diff options
author | Sheng Yang <sheng@linux.intel.com> | 2009-02-25 04:22:26 -0500 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2009-06-10 04:48:23 -0400 |
commit | c1e01514296e8a4a43ff0c88dcff635cb90feb5f (patch) | |
tree | 299a54da71c4900fc3b71840e2c6eec98b35f8b4 /virt/kvm | |
parent | bfd349d073b2838a6a031f057d25e266619b7093 (diff) |
KVM: Ioctls for init MSI-X entry
Introduce KVM_SET_MSIX_NR and KVM_SET_MSIX_ENTRY two ioctls.
This two ioctls are used by userspace to specific guest device MSI-X entry
number and correlate MSI-X entry with GSI during the initialization stage.
MSI-X should be well initialzed before enabling.
Don't support change MSI-X entry number for now.
Signed-off-by: Sheng Yang <sheng@linux.intel.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'virt/kvm')
-rw-r--r-- | virt/kvm/kvm_main.c | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 4d0dd390aa50..1ceb96901f32 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
@@ -1593,6 +1593,88 @@ static int kvm_vcpu_ioctl_set_sigmask(struct kvm_vcpu *vcpu, sigset_t *sigset) | |||
1593 | return 0; | 1593 | return 0; |
1594 | } | 1594 | } |
1595 | 1595 | ||
1596 | #ifdef __KVM_HAVE_MSIX | ||
1597 | static int kvm_vm_ioctl_set_msix_nr(struct kvm *kvm, | ||
1598 | struct kvm_assigned_msix_nr *entry_nr) | ||
1599 | { | ||
1600 | int r = 0; | ||
1601 | struct kvm_assigned_dev_kernel *adev; | ||
1602 | |||
1603 | mutex_lock(&kvm->lock); | ||
1604 | |||
1605 | adev = kvm_find_assigned_dev(&kvm->arch.assigned_dev_head, | ||
1606 | entry_nr->assigned_dev_id); | ||
1607 | if (!adev) { | ||
1608 | r = -EINVAL; | ||
1609 | goto msix_nr_out; | ||
1610 | } | ||
1611 | |||
1612 | if (adev->entries_nr == 0) { | ||
1613 | adev->entries_nr = entry_nr->entry_nr; | ||
1614 | if (adev->entries_nr == 0 || | ||
1615 | adev->entries_nr >= KVM_MAX_MSIX_PER_DEV) { | ||
1616 | r = -EINVAL; | ||
1617 | goto msix_nr_out; | ||
1618 | } | ||
1619 | |||
1620 | adev->host_msix_entries = kzalloc(sizeof(struct msix_entry) * | ||
1621 | entry_nr->entry_nr, | ||
1622 | GFP_KERNEL); | ||
1623 | if (!adev->host_msix_entries) { | ||
1624 | r = -ENOMEM; | ||
1625 | goto msix_nr_out; | ||
1626 | } | ||
1627 | adev->guest_msix_entries = kzalloc( | ||
1628 | sizeof(struct kvm_guest_msix_entry) * | ||
1629 | entry_nr->entry_nr, GFP_KERNEL); | ||
1630 | if (!adev->guest_msix_entries) { | ||
1631 | kfree(adev->host_msix_entries); | ||
1632 | r = -ENOMEM; | ||
1633 | goto msix_nr_out; | ||
1634 | } | ||
1635 | } else /* Not allowed set MSI-X number twice */ | ||
1636 | r = -EINVAL; | ||
1637 | msix_nr_out: | ||
1638 | mutex_unlock(&kvm->lock); | ||
1639 | return r; | ||
1640 | } | ||
1641 | |||
1642 | static int kvm_vm_ioctl_set_msix_entry(struct kvm *kvm, | ||
1643 | struct kvm_assigned_msix_entry *entry) | ||
1644 | { | ||
1645 | int r = 0, i; | ||
1646 | struct kvm_assigned_dev_kernel *adev; | ||
1647 | |||
1648 | mutex_lock(&kvm->lock); | ||
1649 | |||
1650 | adev = kvm_find_assigned_dev(&kvm->arch.assigned_dev_head, | ||
1651 | entry->assigned_dev_id); | ||
1652 | |||
1653 | if (!adev) { | ||
1654 | r = -EINVAL; | ||
1655 | goto msix_entry_out; | ||
1656 | } | ||
1657 | |||
1658 | for (i = 0; i < adev->entries_nr; i++) | ||
1659 | if (adev->guest_msix_entries[i].vector == 0 || | ||
1660 | adev->guest_msix_entries[i].entry == entry->entry) { | ||
1661 | adev->guest_msix_entries[i].entry = entry->entry; | ||
1662 | adev->guest_msix_entries[i].vector = entry->gsi; | ||
1663 | adev->host_msix_entries[i].entry = entry->entry; | ||
1664 | break; | ||
1665 | } | ||
1666 | if (i == adev->entries_nr) { | ||
1667 | r = -ENOSPC; | ||
1668 | goto msix_entry_out; | ||
1669 | } | ||
1670 | |||
1671 | msix_entry_out: | ||
1672 | mutex_unlock(&kvm->lock); | ||
1673 | |||
1674 | return r; | ||
1675 | } | ||
1676 | #endif | ||
1677 | |||
1596 | static long kvm_vcpu_ioctl(struct file *filp, | 1678 | static long kvm_vcpu_ioctl(struct file *filp, |
1597 | unsigned int ioctl, unsigned long arg) | 1679 | unsigned int ioctl, unsigned long arg) |
1598 | { | 1680 | { |
@@ -1917,7 +1999,29 @@ static long kvm_vm_ioctl(struct file *filp, | |||
1917 | vfree(entries); | 1999 | vfree(entries); |
1918 | break; | 2000 | break; |
1919 | } | 2001 | } |
2002 | #ifdef __KVM_HAVE_MSIX | ||
2003 | case KVM_ASSIGN_SET_MSIX_NR: { | ||
2004 | struct kvm_assigned_msix_nr entry_nr; | ||
2005 | r = -EFAULT; | ||
2006 | if (copy_from_user(&entry_nr, argp, sizeof entry_nr)) | ||
2007 | goto out; | ||
2008 | r = kvm_vm_ioctl_set_msix_nr(kvm, &entry_nr); | ||
2009 | if (r) | ||
2010 | goto out; | ||
2011 | break; | ||
2012 | } | ||
2013 | case KVM_ASSIGN_SET_MSIX_ENTRY: { | ||
2014 | struct kvm_assigned_msix_entry entry; | ||
2015 | r = -EFAULT; | ||
2016 | if (copy_from_user(&entry, argp, sizeof entry)) | ||
2017 | goto out; | ||
2018 | r = kvm_vm_ioctl_set_msix_entry(kvm, &entry); | ||
2019 | if (r) | ||
2020 | goto out; | ||
2021 | break; | ||
2022 | } | ||
1920 | #endif | 2023 | #endif |
2024 | #endif /* KVM_CAP_IRQ_ROUTING */ | ||
1921 | default: | 2025 | default: |
1922 | r = kvm_arch_vm_ioctl(filp, ioctl, arg); | 2026 | r = kvm_arch_vm_ioctl(filp, ioctl, arg); |
1923 | } | 2027 | } |