Commit bccf2150 authored by Avi Kivity's avatar Avi Kivity

KVM: Per-vcpu inodes

Allocate a distinct inode for every vcpu in a VM.  This has the following
benefits:

 - the filp cachelines are no longer bounced when f_count is incremented on
   every ioctl()
 - the API and internal code are distinctly clearer; for example, on the
   KVM_GET_REGS ioctl, there is no need to copy the vcpu number from
   userspace and then copy the registers back; the vcpu identity is derived
   from the fd used to make the call

Right now the performance benefits are completely theoretical since (a) we
don't support more than one vcpu per VM and (b) virtualization hardware
inefficiencies completely everwhelm any cacheline bouncing effects.  But
both of these will change, and we need to prepare the API today.
Signed-off-by: default avatarAvi Kivity <avi@qumranet.com>
parent c5ea7660
...@@ -309,6 +309,7 @@ struct kvm { ...@@ -309,6 +309,7 @@ struct kvm {
int busy; int busy;
unsigned long rmap_overflow; unsigned long rmap_overflow;
struct list_head vm_list; struct list_head vm_list;
struct file *filp;
}; };
struct kvm_stat { struct kvm_stat {
...@@ -343,7 +344,7 @@ struct kvm_arch_ops { ...@@ -343,7 +344,7 @@ struct kvm_arch_ops {
int (*vcpu_create)(struct kvm_vcpu *vcpu); int (*vcpu_create)(struct kvm_vcpu *vcpu);
void (*vcpu_free)(struct kvm_vcpu *vcpu); void (*vcpu_free)(struct kvm_vcpu *vcpu);
struct kvm_vcpu *(*vcpu_load)(struct kvm_vcpu *vcpu); void (*vcpu_load)(struct kvm_vcpu *vcpu);
void (*vcpu_put)(struct kvm_vcpu *vcpu); void (*vcpu_put)(struct kvm_vcpu *vcpu);
void (*vcpu_decache)(struct kvm_vcpu *vcpu); void (*vcpu_decache)(struct kvm_vcpu *vcpu);
......
This diff is collapsed.
...@@ -600,10 +600,9 @@ static void svm_free_vcpu(struct kvm_vcpu *vcpu) ...@@ -600,10 +600,9 @@ static void svm_free_vcpu(struct kvm_vcpu *vcpu)
kfree(vcpu->svm); kfree(vcpu->svm);
} }
static struct kvm_vcpu *svm_vcpu_load(struct kvm_vcpu *vcpu) static void svm_vcpu_load(struct kvm_vcpu *vcpu)
{ {
get_cpu(); get_cpu();
return vcpu;
} }
static void svm_vcpu_put(struct kvm_vcpu *vcpu) static void svm_vcpu_put(struct kvm_vcpu *vcpu)
......
...@@ -204,7 +204,7 @@ static void vmcs_write64(unsigned long field, u64 value) ...@@ -204,7 +204,7 @@ static void vmcs_write64(unsigned long field, u64 value)
* Switches to specified vcpu, until a matching vcpu_put(), but assumes * Switches to specified vcpu, until a matching vcpu_put(), but assumes
* vcpu mutex is already taken. * vcpu mutex is already taken.
*/ */
static struct kvm_vcpu *vmx_vcpu_load(struct kvm_vcpu *vcpu) static void vmx_vcpu_load(struct kvm_vcpu *vcpu)
{ {
u64 phys_addr = __pa(vcpu->vmcs); u64 phys_addr = __pa(vcpu->vmcs);
int cpu; int cpu;
...@@ -242,7 +242,6 @@ static struct kvm_vcpu *vmx_vcpu_load(struct kvm_vcpu *vcpu) ...@@ -242,7 +242,6 @@ static struct kvm_vcpu *vmx_vcpu_load(struct kvm_vcpu *vcpu)
rdmsrl(MSR_IA32_SYSENTER_ESP, sysenter_esp); rdmsrl(MSR_IA32_SYSENTER_ESP, sysenter_esp);
vmcs_writel(HOST_IA32_SYSENTER_ESP, sysenter_esp); /* 22.2.3 */ vmcs_writel(HOST_IA32_SYSENTER_ESP, sysenter_esp); /* 22.2.3 */
} }
return vcpu;
} }
static void vmx_vcpu_put(struct kvm_vcpu *vcpu) static void vmx_vcpu_put(struct kvm_vcpu *vcpu)
......
...@@ -52,11 +52,10 @@ enum kvm_exit_reason { ...@@ -52,11 +52,10 @@ enum kvm_exit_reason {
/* for KVM_RUN */ /* for KVM_RUN */
struct kvm_run { struct kvm_run {
/* in */ /* in */
__u32 vcpu;
__u32 emulated; /* skip current instruction */ __u32 emulated; /* skip current instruction */
__u32 mmio_completed; /* mmio request completed */ __u32 mmio_completed; /* mmio request completed */
__u8 request_interrupt_window; __u8 request_interrupt_window;
__u8 padding1[3]; __u8 padding1[7];
/* out */ /* out */
__u32 exit_type; __u32 exit_type;
...@@ -111,10 +110,6 @@ struct kvm_run { ...@@ -111,10 +110,6 @@ struct kvm_run {
/* for KVM_GET_REGS and KVM_SET_REGS */ /* for KVM_GET_REGS and KVM_SET_REGS */
struct kvm_regs { struct kvm_regs {
/* in */
__u32 vcpu;
__u32 padding;
/* out (KVM_GET_REGS) / in (KVM_SET_REGS) */ /* out (KVM_GET_REGS) / in (KVM_SET_REGS) */
__u64 rax, rbx, rcx, rdx; __u64 rax, rbx, rcx, rdx;
__u64 rsi, rdi, rsp, rbp; __u64 rsi, rdi, rsp, rbp;
...@@ -141,10 +136,6 @@ struct kvm_dtable { ...@@ -141,10 +136,6 @@ struct kvm_dtable {
/* for KVM_GET_SREGS and KVM_SET_SREGS */ /* for KVM_GET_SREGS and KVM_SET_SREGS */
struct kvm_sregs { struct kvm_sregs {
/* in */
__u32 vcpu;
__u32 padding;
/* out (KVM_GET_SREGS) / in (KVM_SET_SREGS) */ /* out (KVM_GET_SREGS) / in (KVM_SET_SREGS) */
struct kvm_segment cs, ds, es, fs, gs, ss; struct kvm_segment cs, ds, es, fs, gs, ss;
struct kvm_segment tr, ldt; struct kvm_segment tr, ldt;
...@@ -163,8 +154,8 @@ struct kvm_msr_entry { ...@@ -163,8 +154,8 @@ struct kvm_msr_entry {
/* for KVM_GET_MSRS and KVM_SET_MSRS */ /* for KVM_GET_MSRS and KVM_SET_MSRS */
struct kvm_msrs { struct kvm_msrs {
__u32 vcpu;
__u32 nmsrs; /* number of msrs in entries */ __u32 nmsrs; /* number of msrs in entries */
__u32 pad;
struct kvm_msr_entry entries[0]; struct kvm_msr_entry entries[0];
}; };
...@@ -179,8 +170,6 @@ struct kvm_msr_list { ...@@ -179,8 +170,6 @@ struct kvm_msr_list {
struct kvm_translation { struct kvm_translation {
/* in */ /* in */
__u64 linear_address; __u64 linear_address;
__u32 vcpu;
__u32 padding;
/* out */ /* out */
__u64 physical_address; __u64 physical_address;
...@@ -193,7 +182,6 @@ struct kvm_translation { ...@@ -193,7 +182,6 @@ struct kvm_translation {
/* for KVM_INTERRUPT */ /* for KVM_INTERRUPT */
struct kvm_interrupt { struct kvm_interrupt {
/* in */ /* in */
__u32 vcpu;
__u32 irq; __u32 irq;
}; };
...@@ -206,8 +194,8 @@ struct kvm_breakpoint { ...@@ -206,8 +194,8 @@ struct kvm_breakpoint {
/* for KVM_DEBUG_GUEST */ /* for KVM_DEBUG_GUEST */
struct kvm_debug_guest { struct kvm_debug_guest {
/* int */ /* int */
__u32 vcpu;
__u32 enabled; __u32 enabled;
__u32 pad;
struct kvm_breakpoint breakpoints[4]; struct kvm_breakpoint breakpoints[4];
__u32 singlestep; __u32 singlestep;
}; };
...@@ -234,18 +222,26 @@ struct kvm_dirty_log { ...@@ -234,18 +222,26 @@ struct kvm_dirty_log {
/* /*
* ioctls for VM fds * ioctls for VM fds
*/ */
#define KVM_SET_MEMORY_REGION _IOW(KVMIO, 10, struct kvm_memory_region)
/*
* KVM_CREATE_VCPU receives as a parameter the vcpu slot, and returns
* a vcpu fd.
*/
#define KVM_CREATE_VCPU _IOW(KVMIO, 11, int)
#define KVM_GET_DIRTY_LOG _IOW(KVMIO, 12, struct kvm_dirty_log)
/*
* ioctls for vcpu fds
*/
#define KVM_RUN _IOWR(KVMIO, 2, struct kvm_run) #define KVM_RUN _IOWR(KVMIO, 2, struct kvm_run)
#define KVM_GET_REGS _IOWR(KVMIO, 3, struct kvm_regs) #define KVM_GET_REGS _IOR(KVMIO, 3, struct kvm_regs)
#define KVM_SET_REGS _IOW(KVMIO, 4, struct kvm_regs) #define KVM_SET_REGS _IOW(KVMIO, 4, struct kvm_regs)
#define KVM_GET_SREGS _IOWR(KVMIO, 5, struct kvm_sregs) #define KVM_GET_SREGS _IOR(KVMIO, 5, struct kvm_sregs)
#define KVM_SET_SREGS _IOW(KVMIO, 6, struct kvm_sregs) #define KVM_SET_SREGS _IOW(KVMIO, 6, struct kvm_sregs)
#define KVM_TRANSLATE _IOWR(KVMIO, 7, struct kvm_translation) #define KVM_TRANSLATE _IOWR(KVMIO, 7, struct kvm_translation)
#define KVM_INTERRUPT _IOW(KVMIO, 8, struct kvm_interrupt) #define KVM_INTERRUPT _IOW(KVMIO, 8, struct kvm_interrupt)
#define KVM_DEBUG_GUEST _IOW(KVMIO, 9, struct kvm_debug_guest) #define KVM_DEBUG_GUEST _IOW(KVMIO, 9, struct kvm_debug_guest)
#define KVM_SET_MEMORY_REGION _IOW(KVMIO, 10, struct kvm_memory_region)
#define KVM_CREATE_VCPU _IOW(KVMIO, 11, int /* vcpu_slot */)
#define KVM_GET_DIRTY_LOG _IOW(KVMIO, 12, struct kvm_dirty_log)
#define KVM_GET_MSRS _IOWR(KVMIO, 13, struct kvm_msrs) #define KVM_GET_MSRS _IOWR(KVMIO, 13, struct kvm_msrs)
#define KVM_SET_MSRS _IOWR(KVMIO, 14, struct kvm_msrs) #define KVM_SET_MSRS _IOW(KVMIO, 14, struct kvm_msrs)
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment