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 | |
| 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')
| -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 | } |
