mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-06-17 20:25:19 +00:00
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>
This commit is contained in:
parent
bfd349d073
commit
c1e0151429
3 changed files with 132 additions and 0 deletions
|
@ -487,6 +487,10 @@ struct kvm_irq_routing {
|
||||||
#define KVM_REINJECT_CONTROL _IO(KVMIO, 0x71)
|
#define KVM_REINJECT_CONTROL _IO(KVMIO, 0x71)
|
||||||
#define KVM_DEASSIGN_PCI_DEVICE _IOW(KVMIO, 0x72, \
|
#define KVM_DEASSIGN_PCI_DEVICE _IOW(KVMIO, 0x72, \
|
||||||
struct kvm_assigned_pci_dev)
|
struct kvm_assigned_pci_dev)
|
||||||
|
#define KVM_ASSIGN_SET_MSIX_NR \
|
||||||
|
_IOW(KVMIO, 0x73, struct kvm_assigned_msix_nr)
|
||||||
|
#define KVM_ASSIGN_SET_MSIX_ENTRY \
|
||||||
|
_IOW(KVMIO, 0x74, struct kvm_assigned_msix_entry)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ioctls for vcpu fds
|
* ioctls for vcpu fds
|
||||||
|
@ -607,4 +611,18 @@ struct kvm_assigned_irq {
|
||||||
#define KVM_DEV_IRQ_ASSIGN_MSI_ACTION KVM_DEV_IRQ_ASSIGN_ENABLE_MSI
|
#define KVM_DEV_IRQ_ASSIGN_MSI_ACTION KVM_DEV_IRQ_ASSIGN_ENABLE_MSI
|
||||||
#define KVM_DEV_IRQ_ASSIGN_ENABLE_MSI (1 << 0)
|
#define KVM_DEV_IRQ_ASSIGN_ENABLE_MSI (1 << 0)
|
||||||
|
|
||||||
|
struct kvm_assigned_msix_nr {
|
||||||
|
__u32 assigned_dev_id;
|
||||||
|
__u16 entry_nr;
|
||||||
|
__u16 padding;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define KVM_MAX_MSIX_PER_DEV 512
|
||||||
|
struct kvm_assigned_msix_entry {
|
||||||
|
__u32 assigned_dev_id;
|
||||||
|
__u32 gsi;
|
||||||
|
__u16 entry; /* The index of entry in the MSI-X table */
|
||||||
|
__u16 padding[3];
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -319,6 +319,12 @@ struct kvm_irq_ack_notifier {
|
||||||
void (*irq_acked)(struct kvm_irq_ack_notifier *kian);
|
void (*irq_acked)(struct kvm_irq_ack_notifier *kian);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct kvm_guest_msix_entry {
|
||||||
|
u32 vector;
|
||||||
|
u16 entry;
|
||||||
|
u16 flags;
|
||||||
|
};
|
||||||
|
|
||||||
struct kvm_assigned_dev_kernel {
|
struct kvm_assigned_dev_kernel {
|
||||||
struct kvm_irq_ack_notifier ack_notifier;
|
struct kvm_irq_ack_notifier ack_notifier;
|
||||||
struct work_struct interrupt_work;
|
struct work_struct interrupt_work;
|
||||||
|
@ -326,13 +332,17 @@ struct kvm_assigned_dev_kernel {
|
||||||
int assigned_dev_id;
|
int assigned_dev_id;
|
||||||
int host_busnr;
|
int host_busnr;
|
||||||
int host_devfn;
|
int host_devfn;
|
||||||
|
unsigned int entries_nr;
|
||||||
int host_irq;
|
int host_irq;
|
||||||
bool host_irq_disabled;
|
bool host_irq_disabled;
|
||||||
|
struct msix_entry *host_msix_entries;
|
||||||
int guest_irq;
|
int guest_irq;
|
||||||
|
struct kvm_guest_msix_entry *guest_msix_entries;
|
||||||
#define KVM_ASSIGNED_DEV_GUEST_INTX (1 << 0)
|
#define KVM_ASSIGNED_DEV_GUEST_INTX (1 << 0)
|
||||||
#define KVM_ASSIGNED_DEV_GUEST_MSI (1 << 1)
|
#define KVM_ASSIGNED_DEV_GUEST_MSI (1 << 1)
|
||||||
#define KVM_ASSIGNED_DEV_HOST_INTX (1 << 8)
|
#define KVM_ASSIGNED_DEV_HOST_INTX (1 << 8)
|
||||||
#define KVM_ASSIGNED_DEV_HOST_MSI (1 << 9)
|
#define KVM_ASSIGNED_DEV_HOST_MSI (1 << 9)
|
||||||
|
#define KVM_ASSIGNED_DEV_MSIX ((1 << 2) | (1 << 10))
|
||||||
unsigned long irq_requested_type;
|
unsigned long irq_requested_type;
|
||||||
int irq_source_id;
|
int irq_source_id;
|
||||||
int flags;
|
int flags;
|
||||||
|
|
|
@ -1593,6 +1593,88 @@ static int kvm_vcpu_ioctl_set_sigmask(struct kvm_vcpu *vcpu, sigset_t *sigset)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __KVM_HAVE_MSIX
|
||||||
|
static int kvm_vm_ioctl_set_msix_nr(struct kvm *kvm,
|
||||||
|
struct kvm_assigned_msix_nr *entry_nr)
|
||||||
|
{
|
||||||
|
int r = 0;
|
||||||
|
struct kvm_assigned_dev_kernel *adev;
|
||||||
|
|
||||||
|
mutex_lock(&kvm->lock);
|
||||||
|
|
||||||
|
adev = kvm_find_assigned_dev(&kvm->arch.assigned_dev_head,
|
||||||
|
entry_nr->assigned_dev_id);
|
||||||
|
if (!adev) {
|
||||||
|
r = -EINVAL;
|
||||||
|
goto msix_nr_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (adev->entries_nr == 0) {
|
||||||
|
adev->entries_nr = entry_nr->entry_nr;
|
||||||
|
if (adev->entries_nr == 0 ||
|
||||||
|
adev->entries_nr >= KVM_MAX_MSIX_PER_DEV) {
|
||||||
|
r = -EINVAL;
|
||||||
|
goto msix_nr_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
adev->host_msix_entries = kzalloc(sizeof(struct msix_entry) *
|
||||||
|
entry_nr->entry_nr,
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!adev->host_msix_entries) {
|
||||||
|
r = -ENOMEM;
|
||||||
|
goto msix_nr_out;
|
||||||
|
}
|
||||||
|
adev->guest_msix_entries = kzalloc(
|
||||||
|
sizeof(struct kvm_guest_msix_entry) *
|
||||||
|
entry_nr->entry_nr, GFP_KERNEL);
|
||||||
|
if (!adev->guest_msix_entries) {
|
||||||
|
kfree(adev->host_msix_entries);
|
||||||
|
r = -ENOMEM;
|
||||||
|
goto msix_nr_out;
|
||||||
|
}
|
||||||
|
} else /* Not allowed set MSI-X number twice */
|
||||||
|
r = -EINVAL;
|
||||||
|
msix_nr_out:
|
||||||
|
mutex_unlock(&kvm->lock);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int kvm_vm_ioctl_set_msix_entry(struct kvm *kvm,
|
||||||
|
struct kvm_assigned_msix_entry *entry)
|
||||||
|
{
|
||||||
|
int r = 0, i;
|
||||||
|
struct kvm_assigned_dev_kernel *adev;
|
||||||
|
|
||||||
|
mutex_lock(&kvm->lock);
|
||||||
|
|
||||||
|
adev = kvm_find_assigned_dev(&kvm->arch.assigned_dev_head,
|
||||||
|
entry->assigned_dev_id);
|
||||||
|
|
||||||
|
if (!adev) {
|
||||||
|
r = -EINVAL;
|
||||||
|
goto msix_entry_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < adev->entries_nr; i++)
|
||||||
|
if (adev->guest_msix_entries[i].vector == 0 ||
|
||||||
|
adev->guest_msix_entries[i].entry == entry->entry) {
|
||||||
|
adev->guest_msix_entries[i].entry = entry->entry;
|
||||||
|
adev->guest_msix_entries[i].vector = entry->gsi;
|
||||||
|
adev->host_msix_entries[i].entry = entry->entry;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i == adev->entries_nr) {
|
||||||
|
r = -ENOSPC;
|
||||||
|
goto msix_entry_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
msix_entry_out:
|
||||||
|
mutex_unlock(&kvm->lock);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static long kvm_vcpu_ioctl(struct file *filp,
|
static long kvm_vcpu_ioctl(struct file *filp,
|
||||||
unsigned int ioctl, unsigned long arg)
|
unsigned int ioctl, unsigned long arg)
|
||||||
{
|
{
|
||||||
|
@ -1917,7 +1999,29 @@ static long kvm_vm_ioctl(struct file *filp,
|
||||||
vfree(entries);
|
vfree(entries);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#ifdef __KVM_HAVE_MSIX
|
||||||
|
case KVM_ASSIGN_SET_MSIX_NR: {
|
||||||
|
struct kvm_assigned_msix_nr entry_nr;
|
||||||
|
r = -EFAULT;
|
||||||
|
if (copy_from_user(&entry_nr, argp, sizeof entry_nr))
|
||||||
|
goto out;
|
||||||
|
r = kvm_vm_ioctl_set_msix_nr(kvm, &entry_nr);
|
||||||
|
if (r)
|
||||||
|
goto out;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case KVM_ASSIGN_SET_MSIX_ENTRY: {
|
||||||
|
struct kvm_assigned_msix_entry entry;
|
||||||
|
r = -EFAULT;
|
||||||
|
if (copy_from_user(&entry, argp, sizeof entry))
|
||||||
|
goto out;
|
||||||
|
r = kvm_vm_ioctl_set_msix_entry(kvm, &entry);
|
||||||
|
if (r)
|
||||||
|
goto out;
|
||||||
|
break;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#endif /* KVM_CAP_IRQ_ROUTING */
|
||||||
default:
|
default:
|
||||||
r = kvm_arch_vm_ioctl(filp, ioctl, arg);
|
r = kvm_arch_vm_ioctl(filp, ioctl, arg);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue