kvm : Paravirt-spinlock support for KVM guests
Subsystems (8)
v5 cover kvm : Paravirt-spinlock support for KVM guests
The 6-patch series to follow this email extends KVM-hypervisor and Linux guest running on KVM-hypervisor to support pv-ticket spinlocks, based on Xen's implementation.
One hypercall is introduced in KVM hypervisor,that allows a vcpu to kick another vcpu out of halt state.
The blocking of vcpu is done using halt() in (lock_spinning) slowpath. one MSR is added to aid live migration.
Changes in V5:
- rebased to 3.3-rc6
- added PV_UNHALT_MSR that would help in live migration (Avi)
- removed PV_LOCK_KICK vcpu request and pv_unhalt flag (re)added.
- Changed hypercall documentaion (Alex).
- mode_t changed to umode_t in debugfs.
- MSR related documentation added.
- rename PV_LOCK_KICK to PV_UNHALT.
- host and guest patches not mixed. (Marcelo, Alex)
- kvm_kick_cpu now takes cpu so it can be used by flush_tlb_ipi_other paravirtualization (Nikunj)
- coding style changes in variable declarion etc (Srikar)
Changes in V4:
- reabsed to 3.2.0 pre.
- use APIC ID for kicking the vcpu and use kvm_apic_match_dest for matching (Avi)
- fold vcpu->kicked flag into vcpu->requests (KVM_REQ_PVLOCK_KICK) and related changes for UNHALT path to make pv ticket spinlock migration friendly(Avi, Marcello)
- Added Documentation for CPUID, Hypercall (KVM_HC_KICK_CPU)
and capabilty (KVM_CAP_PVLOCK_KICK) (Avi)
- Remove unneeded kvm_arch_vcpu_ioctl_set_mpstate call. (Marcello)
- cumulative variable type changed (int ==> u32) in add_stat (Konrad)
- remove unneeded kvm_guest_init for !CONFIG_KVM_GUEST case
Changes in V3:
- rebased to 3.2-rc1
- use halt() instead of wait for kick hypercall.
- modify kick hyper call to do wakeup halted vcpu.
- hook kvm_spinlock_init to smp_prepare_cpus call (moved the call out of head##.c).
- fix the potential race when zero_stat is read.
- export debugfs_create_32 and add documentation to API.
- use static inline and enum instead of ADDSTAT macro.
- add barrier() in after setting kick_vcpu.
- empty static inline function for kvm_spinlock_init.
- combine the patches one and two readuce overhead.
- make KVM_DEBUGFS depends on DEBUGFS.
- include debugfs header unconditionally.
Changes in V2:
- rebased patchesto -rc9
- synchronization related changes based on Jeremy's changes (Jeremy Fitzhardinge <[email protected]>) pointed by Stephan Diestelhorst <[email protected]>
- enabling 32 bit guests
- splitted patches into two more chunks
Test Set up :
The BASE patch is 3.3.0-rc6 + jumplabel split patch (https://lkml.org/lkml/2012/2/21/167)
+ ticketlock cleanup patch (https://lkml.org/lkml/2012/3/21/161)
Results:
The performance gain is mainly because of reduced busy-wait time. From the results we can see that patched kernel performance is similar to BASE when there is no lock contention. But once we start seeing more contention, patched kernel outperforms BASE.
3 guests with 8VCPU, 8GB RAM, 1 used for kernbench (kernbench -f -H -M -o 20) other for cpuhog (shell script while true with an instruction)
1x: no hogs
2x: 8hogs in one guest
3x: 8hogs each in two guest
1) kernbench
Machine : IBM xSeries with Intel(R) Xeon(R) x5570 2.93GHz CPU with 8 core , 64GB RAM
BASE BASE+patch %improvement
mean (sd) mean (sd)
case 1x: 38.1033 (43.502) 38.09 (43.4269) 0.0349051
case 2x: 778.622 (1092.68) 129.342 (156.324) 83.3883
case 3x: 2399.11 (3548.32) 114.913 (139.5) 95.2102
2) pgbench:
pgbench version: http://www.postgresql.org/ftp/snapshot/dev/
tool used for benchmarking: git://git.postgresql.org/git/pgbench-tools.git
Ananlysis is done using ministat.
Test is done for 1x overcommit to check overhead of pv spinlock. There is small performance penalty in non contention scenario (note BASE is jeremy's ticketlock). But with increase in number of threads, improvement is seen.
guest: 64bit 8 vCPU and 8GB RAM
shared buffer size = 2GB
x base_kernel
+ patched_kernel
N Min Max Median Avg Stddev
+--------------------- NRCLIENT = 1 ----------------------------------------+ x 10 7468.0719 7774.0026 7529.9217 7594.9696 128.7725 + 10 7280.413 7650.6619 7425.7968 7434.9344 144.59127 Difference at 95.0% confidence -160.035 +/- 128.641 -2.10712% +/- 1.69376% +--------------------- NRCLIENT = 2 ----------------------------------------+ x 10 14604.344 14849.358 14725.845 14724.722 76.866294 + 10 14070.064 14246.013 14125.556 14138.169 60.556379 Difference at 95.0% confidence -586.553 +/- 65.014 -3.98346% +/- 0.441529% +--------------------- NRCLIENT = 4 ----------------------------------------+ x 10 27891.073 28305.466 28059.892 28060.231 115.65612 + 10 27237.685 27639.645 27297.79 27375.966 145.31006 Difference at 95.0% confidence -684.265 +/- 123.39 -2.43856% +/- 0.439734% +--------------------- NRCLIENT = 8 ----------------------------------------+ x 10 53063.509 53498.677 53343.24 53309.697 138.77983 + 10 51705.708 52208.274 52030.06 51987.067 156.65323 Difference at 95.0% confidence -1322.63 +/- 139.048 -2.48103% +/- 0.26083% +--------------------- NRCLIENT = 16 ---------------------------------------+ x 10 50043.347 52701.253 52235.978 51993.466 817.44911 + 10 51562.772 52272.412 51905.317 51946.557 228.54314 No difference proven at 95.0% confidence +--------------------- NRCLIENT = 32 --------------------------------------+ x 10 49178.789 51284.599 50288.185 50275.212 616.80154 + 10 50722.097 52145.041 51551.112 51512.423 469.18898 Difference at 95.0% confidence 1237.21 +/- 514.888 2.46088% +/- 1.02414%
+--------------------------------------------------------------------------+
Let me know if you have any sugestion/comments...
---
V4 kernel changes:
https://lkml.org/lkml/2012/1/14/66
Qemu changes for V4:
http://www.mail-archive.com/[email protected]/msg66450.html
V3 kernel Changes:
https://lkml.org/lkml/2011/11/30/62
V2 kernel changes :
https://lkml.org/lkml/2011/10/23/207
Previous discussions : (posted by Srivatsa V).
https://lkml.org/lkml/2010/7/26/24
https://lkml.org/lkml/2011/1/19/212
Qemu patch for V3:
http://lists.gnu.org/archive/html/qemu-devel/2011-12/msg00397.html
Srivatsa Vaddagiri, Suzuki Poulose, Raghavendra K T (6):
Add debugfs support to print u32-arrays in debugfs
Add a hypercall to KVM hypervisor to support pv-ticketlocks Add unhalt msr to aid migration
Added configuration support to enable debug information for KVM Guests pv-ticketlock support for linux guests running on KVM hypervisor Add documentation on Hypercalls and features used for PV spinlock
Documentation/virtual/kvm/api.txt | 7 + Documentation/virtual/kvm/cpuid.txt | 4 + Documentation/virtual/kvm/hypercalls.txt | 59 +++++++ Documentation/virtual/kvm/msr.txt | 9 + arch/x86/Kconfig | 9 + arch/x86/include/asm/kvm_para.h | 18 ++- arch/x86/kernel/kvm.c | 254 ++++++++++++++++++++++++++++++ arch/x86/kvm/cpuid.c | 3 +- arch/x86/kvm/x86.c | 40 +++++- arch/x86/xen/debugfs.c | 104 ------------ arch/x86/xen/debugfs.h | 4 - arch/x86/xen/spinlock.c | 2 +- fs/debugfs/file.c | 128 +++++++++++++++ include/linux/debugfs.h | 11 ++ include/linux/kvm.h | 1 + include/linux/kvm_host.h | 1 + include/linux/kvm_para.h | 1 + virt/kvm/kvm_main.c | 4 + 18 files changed, 545 insertions(+), 114 deletions(-)
RFC PATCH v5 1/6 debugfs: Add support to print u32 array in debugfs
From: Srivatsa Vaddagiri <[email protected]>
Move the code from Xen to debugfs to make the code common for other users as well.
---
arch/x86/xen/debugfs.c +0 -104
@@ -19,107 +19,3 @@ struct dentry * __init xen_init_debugfs(void)return d_xen_debug; } -struct array_data -{ -void *array; -unsigned elements; -}; - -static int u32_array_open (struct inode *inode,struct file *file) -{ - file->private_data =NULL ; -return nonseekable_open (inode, file); -} - -static size_t format_array (char *buf,size_t bufsize,const char *fmt, -u32 *array,unsigned array_size) -{ -size_t ret =0 ; -unsigned i; - -for (i =0 ; i < array_size; i++) { -size_t len; - - len =snprintf (buf, bufsize, fmt, array[i]); - len++;/* ' ' or '\n' */ - ret += len; - -if (buf) { - buf += len; - bufsize -= len; - buf[-1 ] = (i == array_size-1 ) ?'\n' :' ' ; - } - } - - ret++;/* \0 */ -if (buf) - *buf ='\0' ; - -return ret; -} - -static char *format_array_alloc (const char *fmt,u32 *array,unsigned array_size) -{ -size_t len =format_array (NULL ,0 , fmt, array, array_size); -char *ret; - - ret =kmalloc (len,GFP_KERNEL ); -if (ret ==NULL ) -return NULL ; - -format_array (ret, len, fmt, array, array_size); -return ret; -} - -static ssize_t u32_array_read (struct file *file,char __user *buf,size_t len, -loff_t *ppos) -{ -struct inode *inode = file->f_path.dentry->d_inode; -struct array_data *data = inode->i_private; -size_t size; - -if (*ppos ==0 ) { -if (file->private_data) { -kfree (file->private_data); - file->private_data =NULL ; - } - - file->private_data =format_array_alloc ("%u" , data->array, data->elements); - } - - size =0 ; -if (file->private_data) - size =strlen (file->private_data); - -return simple_read_from_buffer (buf, len, ppos, file->private_data, size); -} - -static int xen_array_release (struct inode *inode,struct file *file) -{ -kfree (file->private_data); - -return 0 ; -} - -static const struct file_operations u32_array_fops = { - .owner =THIS_MODULE , - .open = u32_array_open, - .release= xen_array_release, - .read = u32_array_read, - .llseek = no_llseek, -}; - -struct dentry *xen_debugfs_create_u32_array (const char *name,umode_t mode, -struct dentry *parent, -u32 *array,unsigned elements) -{ -struct array_data *data =kmalloc (sizeof (*data),GFP_KERNEL ); - -if (data ==NULL ) -return NULL ; - - data->array = array; - data->elements = elements; - -return debugfs_create_file (name, mode, parent, data, &u32_array_fops); -}
arch/x86/xen/debugfs.h +0 -4
@@ -3,8 +3,4 @@struct dentry *__init xen_init_debugfs (void ); -struct dentry *xen_debugfs_create_u32_array (const char *name,umode_t mode, -struct dentry *parent, -u32 *array,unsigned elements); -#endif /* _XEN_DEBUGFS_H */
arch/x86/xen/spinlock.c +1 -1
@@ -314,7 +314,7 @@ static int __init xen_spinlock_debugfs(void)debugfs_create_u64 ("time_blocked" ,0444 , d_spin_debug, &spinlock_stats.time_blocked); -xen_debugfs_create_u32_array ("histo_blocked" ,0444 , d_spin_debug, +debugfs_create_u32_array ("histo_blocked" ,0444 , d_spin_debug, spinlock_stats.histo_spin_blocked,HISTO_BUCKETS +1 );return 0 ;
fs/debugfs/file.c +128 -0
140 lines not on this page · raw message
include/linux/debugfs.h +11 -0
@@ -93,6 +93,10 @@ struct dentry *debugfs_create_regset32(const char *name, mode_t mode,int debugfs_print_regs32 (struct seq_file *s,const struct debugfs_reg32 *regs,int nregs,void __iomem *base,char *prefix); +struct dentry *debugfs_create_u32_array (const char *name,umode_t mode, +struct dentry *parent, +u32 *array,u32 elements); +bool debugfs_initialized (void );#else
@@ -219,6 +223,13 @@ static inline bool debugfs_initialized(void)return false; } +struct dentry *debugfs_create_u32_array (const char *name,umode_t mode, +struct dentry *parent, +u32 *array,u32 elements) +{ +return ERR_PTR (-ENODEV ); +} +#endif #endif
Re: [Xen-devel] [PATCH RFC V5 1/6] debugfs: Add support to print u32 array in debugfs
Quoted 9 lines · Raghavendra K T
From: Srivatsa Vaddagiri <[email protected]>
Move the code from Xen to debugfs to make the code common for other users as well.
Signed-off-by Srivatsa Vaddagiri <[email protected]>Signed-off-by Suzuki Poulose <[email protected]>Signed-off-by Raghavendra K T <[email protected]>Signed-off-by Konrad Rzeszutek Wilk <[email protected]>
Greg,
I was thinking to stick this patch in my queue, but I need your OK since it touches fs/debugfs/file.c.
Quoted 320 lines
---
arch/x86/xen/debugfs.c +0
-104@@ -19,107 +19,3 @@ struct dentry * __init xen_init_debugfs(void)return d_xen_debug; } -struct array_data -{ -void *array; -unsigned elements; -}; - -static int u32_array_open (struct inode *inode,struct file *file) -{ - file->private_data =NULL ; -return nonseekable_open (inode, file); -} - -static size_t format_array (char *buf,size_t bufsize,const char *fmt, -u32 *array,unsigned array_size) -{ -size_t ret =0 ; -unsigned i; - -for (i =0 ; i < array_size; i++) { -size_t len; - - len =snprintf (buf, bufsize, fmt, array[i]); - len++;/* ' ' or '\n' */ - ret += len; - -if (buf) { - buf += len; - bufsize -= len; - buf[-1 ] = (i == array_size-1 ) ?'\n' :' ' ; - } - } - - ret++;/* \0 */ -if (buf) - *buf ='\0' ; - -return ret; -} - -static char *format_array_alloc (const char *fmt,u32 *array,unsigned array_size) -{ -size_t len =format_array (NULL ,0 , fmt, array, array_size); -char *ret; - - ret =kmalloc (len,GFP_KERNEL ); -if (ret ==NULL ) -return NULL ; - -format_array (ret, len, fmt, array, array_size); -return ret; -} - -static ssize_t u32_array_read (struct file *file,char __user *buf,size_t len, -loff_t *ppos) -{ -struct inode *inode = file->f_path.dentry->d_inode; -struct array_data *data = inode->i_private; -size_t size; - -if (*ppos ==0 ) { -if (file->private_data) { -kfree (file->private_data); - file->private_data =NULL ; - } - - file->private_data =format_array_alloc ("%u" , data->array, data->elements); - } - - size =0 ; -if (file->private_data) - size =strlen (file->private_data); - -return simple_read_from_buffer (buf, len, ppos, file->private_data, size); -} - -static int xen_array_release (struct inode *inode,struct file *file) -{ -kfree (file->private_data); - -return 0 ; -} - -static const struct file_operations u32_array_fops = { - .owner =THIS_MODULE , - .open = u32_array_open, - .release= xen_array_release, - .read = u32_array_read, - .llseek = no_llseek, -}; - -struct dentry *xen_debugfs_create_u32_array (const char *name,umode_t mode, -struct dentry *parent, -u32 *array,unsigned elements) -{ -struct array_data *data =kmalloc (sizeof (*data),GFP_KERNEL ); - -if (data ==NULL ) -return NULL ; - - data->array = array; - data->elements = elements; - -return debugfs_create_file (name, mode, parent, data, &u32_array_fops); -}arch/x86/xen/debugfs.h +0
-4@@ -3,8 +3,4 @@struct dentry *__init xen_init_debugfs (void ); -struct dentry *xen_debugfs_create_u32_array (const char *name,umode_t mode, -struct dentry *parent, -u32 *array,unsigned elements); -#endif /* _XEN_DEBUGFS_H */ arch/x86/xen/spinlock.c +1
-1@@ -314,7 +314,7 @@ static int __init xen_spinlock_debugfs(void)debugfs_create_u64 ("time_blocked" ,0444 , d_spin_debug, &spinlock_stats.time_blocked); -xen_debugfs_create_u32_array ("histo_blocked" ,0444 , d_spin_debug, +debugfs_create_u32_array ("histo_blocked" ,0444 , d_spin_debug, spinlock_stats.histo_spin_blocked,HISTO_BUCKETS +1 );return 0 ;fs/debugfs/file.c +128
-0@@ -20,6 +20,7 @@#include <linux/namei.h> #include <linux/debugfs.h> #include <linux/io.h> +#include <linux/slab.h> static ssize_t default_read_file (struct file *file,char __user *buf,size_t count,loff_t *ppos)@@ -528,6 +529,133 @@ struct dentry *debugfs_create_blob(const char *name, umode_t mode, }EXPORT_SYMBOL_GPL (debugfs_create_blob); +struct array_data { +void *array; +u32 elements; +}; + +static int u32_array_open (struct inode *inode,struct file *file) +{ + file->private_data =NULL ; +return nonseekable_open (inode, file); +} + +static size_t format_array (char *buf,size_t bufsize,const char *fmt, +u32 *array,u32 array_size) +{ +size_t ret =0 ; +u32 i; + +for (i =0 ; i < array_size; i++) { +size_t len; + + len =snprintf (buf, bufsize, fmt, array[i]); + len++;/* ' ' or '\n' */ + ret += len; + +if (buf) { + buf += len; + bufsize -= len; + buf[-1 ] = (i == array_size-1 ) ?'\n' :' ' ; + } + } + + ret++;/* \0 */ +if (buf) + *buf ='\0' ; + +return ret; +} + +static char *format_array_alloc (const char *fmt,u32 *array, +u32 array_size) +{ +size_t len =format_array (NULL ,0 , fmt, array, array_size); +char *ret; + + ret =kmalloc (len,GFP_KERNEL ); +if (ret ==NULL ) +return NULL ; + +format_array (ret, len, fmt, array, array_size); +return ret; +} + +static ssize_t u32_array_read (struct file *file,char __user *buf,size_t len, +loff_t *ppos) +{ +struct inode *inode = file->f_path.dentry->d_inode; +struct array_data *data = inode->i_private; +size_t size; + +if (*ppos ==0 ) { +if (file->private_data) { +kfree (file->private_data); + file->private_data =NULL ; + } + + file->private_data =format_array_alloc ("%u" , data->array, + data->elements); + } + + size =0 ; +if (file->private_data) + size =strlen (file->private_data); + +return simple_read_from_buffer (buf, len, ppos, + file->private_data, size); +} + +static int u32_array_release (struct inode *inode,struct file *file) +{ +kfree (file->private_data); + +return 0 ; +} + +static const struct file_operations u32_array_fops = { + .owner =THIS_MODULE , + .open = u32_array_open, + .release = u32_array_release, + .read = u32_array_read, + .llseek = no_llseek, +}; + +/** +* debugfs_create_u32_array - create a debugfs file that is used to read u32 +* array. +* @name: a pointer to a string containing the name of the file to create. +* @mode: the permission that the file should have. +* @parent: a pointer to the parent dentry for this file. This should be a +* directory dentry if set. If this parameter is %NULL, then the +* file will be created in the root of the debugfs filesystem. +* @array: u32 array that provides data. +* @elements: total number of elements in the array. +* +* This function creates a file in debugfs with the given name that exports +* @array as data. If the @mode variable is so set it can be read from. +* Writing is not supported. Seek within the file is also not supported. +* Once array is created its size can not be changed. +* +* The function returns a pointer to dentry on success. If debugfs is not +* enabled in the kernel, the value -%ENODEV will be returned. +*/ +struct dentry *debugfs_create_u32_array (const char *name,umode_t mode, +struct dentry *parent, +u32 *array,u32 elements) +{ +struct array_data *data =kmalloc (sizeof (*data),GFP_KERNEL ); + +if (data ==NULL ) +return NULL ; + + data->array = array; + data->elements = elements; + +return debugfs_create_file (name, mode, parent, data, &u32_array_fops); +} +EXPORT_SYMBOL_GPL (debugfs_create_u32_array); +#ifdef CONFIG_HAS_IOMEM /* include/linux/debugfs.h +11
-0@@ -93,6 +93,10 @@ struct dentry *debugfs_create_regset32(const char *name, mode_t mode,int debugfs_print_regs32 (struct seq_file *s,const struct debugfs_reg32 *regs,int nregs,void __iomem *base,char *prefix); +struct dentry *debugfs_create_u32_array (const char *name,umode_t mode, +struct dentry *parent, +u32 *array,u32 elements); +bool debugfs_initialized (void );#else @@ -219,6 +223,13 @@ static inline bool debugfs_initialized(void)return false; } +struct dentry *debugfs_create_u32_array (const char *name,umode_t mode, +struct dentry *parent, +u32 *array,u32 elements) +{ +return ERR_PTR (-ENODEV ); +} +#endif #endif _______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xen.org/xen-devel
Re: [Xen-devel] [PATCH RFC V5 1/6] debugfs: Add support to print u32 array in debugfs
Quoted 11 lines · Konrad Rzeszutek Wilk
Quoted 9 lines · Raghavendra K T
From: Srivatsa Vaddagiri <[email protected]>
Move the code from Xen to debugfs to make the code common for other users as well.
Signed-off-by Srivatsa Vaddagiri <[email protected]>Signed-off-by Suzuki Poulose <[email protected]>Signed-off-by Raghavendra K T <[email protected]>Signed-off-by Konrad Rzeszutek Wilk <[email protected]>
Quoted 4 lines
Greg,
I was thinking to stick this patch in my queue, but I need your OK since it touches
fs/debugfs/file.c.
That's fine with me:
Re: [Xen-devel] [PATCH RFC V5 1/6] debugfs: Add support to print u32 array in debugfs
In reply to Konrad Rzeszutek WilkQuoted 11 lines · Konrad Rzeszutek Wilk
Quoted 9 lines · Raghavendra K T
From: Srivatsa Vaddagiri <[email protected]>
Move the code from Xen to debugfs to make the code common for other users as well.
Signed-off-by Srivatsa Vaddagiri <[email protected]>Signed-off-by Suzuki Poulose <[email protected]>Signed-off-by Raghavendra K T <[email protected]>Signed-off-by Konrad Rzeszutek Wilk <[email protected]>
Quoted 4 lines
Greg,
I was thinking to stick this patch in my queue, but I need your OK since it touches
fs/debugfs/file.c.
That's fine with me:
RFC PATCH v5 2/6 kvm hypervisor : Add a hypercall to KVM hypervisor to support pv-ticketlocks
In reply to Raghavendra K TFrom: Srivatsa Vaddagiri <[email protected]>
KVM_HC_KICK_CPU allows the calling vcpu to kick another vcpu out of halt state.
The presence of these hypercalls is indicated to guest via KVM_FEATURE_PV_UNHALT/KVM_CAP_PV_UNHALT.
---
arch/x86/include/asm/kvm_para.h +3 -0
@@ -16,12 +16,14 @@#define KVM_FEATURE_CLOCKSOURCE 0#define KVM_FEATURE_NOP_IO_DELAY 1#define KVM_FEATURE_MMU_OP 2 +/* This indicates that the new set of kvmclock msrs * are available. The use of 0x11 and 0x12 is deprecated */ #define KVM_FEATURE_CLOCKSOURCE2 3#define KVM_FEATURE_ASYNC_PF 4#define KVM_FEATURE_STEAL_TIME 5 +#define KVM_FEATURE_PV_UNHALT 6/* The last 8 bits are used to indicate how to interpret the flags field * in pvclock structure. If no bits are set, all flags are ignored.
@@ -32,6 +34,7 @@#define MSR_KVM_SYSTEM_TIME 0x12#define KVM_MSR_ENABLED 1 +/* Custom MSRs falls in the range 0x4b564d00-0x4b564dff */ #define MSR_KVM_WALL_CLOCK_NEW 0x4b564d00#define MSR_KVM_SYSTEM_TIME_NEW 0x4b564d01
arch/x86/kvm/cpuid.c +2 -1
@@ -408,7 +408,8 @@ static int do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function, (1 <<KVM_FEATURE_NOP_IO_DELAY ) | (1 <<KVM_FEATURE_CLOCKSOURCE2 ) | (1 <<KVM_FEATURE_ASYNC_PF ) | - (1 <<KVM_FEATURE_CLOCKSOURCE_STABLE_BIT ); + (1 <<KVM_FEATURE_CLOCKSOURCE_STABLE_BIT ) | + (1 <<KVM_FEATURE_PV_UNHALT );if (sched_info_on ()) entry->eax |= (1 <<KVM_FEATURE_STEAL_TIME );
arch/x86/kvm/x86.c +30 -0
@@ -2079,6 +2079,7 @@ int kvm_dev_ioctl_check_extension(long ext)case KVM_CAP_XSAVE :case KVM_CAP_ASYNC_PF :case KVM_CAP_GET_TSC_KHZ : +case KVM_CAP_PV_UNHALT : r =1 ;break ;case KVM_CAP_COALESCED_MMIO :
@@ -4913,6 +4914,30 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)return 1 ; } +/* +* kvm_pv_kick_cpu_op: Kick a vcpu. +* +* @apicid - apicid of vcpu to be kicked. +*/ +static void kvm_pv_kick_cpu_op (struct kvm *kvm,int apicid) +{ +struct kvm_vcpu *vcpu =NULL ; +int i; + +kvm_for_each_vcpu (i, vcpu, kvm) { +if (!kvm_apic_present (vcpu)) +continue ; + +if (kvm_apic_match_dest (vcpu,0 ,0 , apicid,0 )) +break ; + } +if (vcpu) { + vcpu->pv_unhalted =1 ; +smp_mb (); +kvm_vcpu_kick (vcpu); + } +} +int kvm_emulate_hypercall (struct kvm_vcpu *vcpu) {unsigned long nr, a0, a1, a2, a3, ret;
@@ -4946,6 +4971,10 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)case KVM_HC_VAPIC_POLL_IRQ : ret =0 ;break ; +case KVM_HC_KICK_CPU : +kvm_pv_kick_cpu_op (vcpu->kvm, a0); + ret =0 ; +break ;default : ret = -KVM_ENOSYS ;break ;
@@ -6174,6 +6203,7 @@ int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu) !vcpu->arch.apf.halted) || !list_empty_careful (&vcpu->async_pf.done) || vcpu->arch.mp_state ==KVM_MP_STATE_SIPI_RECEIVED + || vcpu->pv_unhalted ||atomic_read (&vcpu->arch.nmi_queued) || (kvm_arch_interrupt_allowed (vcpu) &&kvm_cpu_has_interrupt (vcpu));
include/linux/kvm.h +1 -0
@@ -558,6 +558,7 @@ struct kvm_ppc_pvinfo {#define KVM_CAP_PPC_PAPR 68#define KVM_CAP_S390_GMAP 71#define KVM_CAP_TSC_DEADLINE_TIMER 72 +#define KVM_CAP_PV_UNHALT 73#ifdef KVM_CAP_IRQ_ROUTING
include/linux/kvm_host.h +1 -0
@@ -158,6 +158,7 @@ struct kvm_vcpu {#endif struct kvm_vcpu_arch arch; +int pv_unhalted; };static inline int kvm_vcpu_exiting_guest_mode (struct kvm_vcpu *vcpu)
include/linux/kvm_para.h +1 -0
@@ -19,6 +19,7 @@#define KVM_HC_MMU_OP 2#define KVM_HC_FEATURES 3#define KVM_HC_PPC_MAP_MAGIC_PAGE 4 +#define KVM_HC_KICK_CPU 5/* * hypercalls use architecture specific
virt/kvm/kvm_main.c +4 -0
@@ -226,6 +226,7 @@ int kvm_vcpu_init(struct kvm_vcpu *vcpu, struct kvm *kvm, unsigned id) vcpu->kvm = kvm; vcpu->vcpu_id = id; vcpu->pid =NULL ; + vcpu->pv_unhalted =0 ;init_waitqueue_head (&vcpu->wq);kvm_async_pf_vcpu_init (vcpu);
@@ -1567,6 +1568,9 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)prepare_to_wait (&vcpu->wq, &wait,TASK_INTERRUPTIBLE );if (kvm_arch_vcpu_runnable (vcpu)) { + vcpu->pv_unhalted =0 ; +/* preventing reordering should be enough here */ +barrier ();kvm_make_request (KVM_REQ_UNHALT , vcpu);break ; }
Re: [PATCH RFC V5 2/6] kvm hypervisor : Add a hypercall to KVM hypervisor to support pv-ticketlocks
Quoted 163 lines · Raghavendra K T
From: Srivatsa Vaddagiri <[email protected]>
KVM_HC_KICK_CPUallows the calling vcpu to kick another vcpu out of halt state.The presence of these hypercalls is indicated to guest via KVM_FEATURE_PV_UNHALT/KVM_CAP_PV_UNHALT.
Signed-off-by Srivatsa Vaddagiri <[email protected]>Signed-off-by Suzuki Poulose <[email protected]>Signed-off-by Raghavendra K T <[email protected]>---
arch/x86/include/asm/kvm_para.h +3
-0@@ -16,12 +16,14 @@#define KVM_FEATURE_CLOCKSOURCE 0#define KVM_FEATURE_NOP_IO_DELAY 1#define KVM_FEATURE_MMU_OP 2 +/* This indicates that the new set of kvmclock msrs * are available. The use of 0x11 and 0x12 is deprecated */ #define KVM_FEATURE_CLOCKSOURCE2 3#define KVM_FEATURE_ASYNC_PF 4#define KVM_FEATURE_STEAL_TIME 5 +#define KVM_FEATURE_PV_UNHALT 6/* The last 8 bits are used to indicate how to interpret the flags field * in pvclock structure. If no bits are set, all flags are ignored. @@ -32,6 +34,7 @@#define MSR_KVM_SYSTEM_TIME 0x12#define KVM_MSR_ENABLED 1 +/* Custom MSRs falls in the range 0x4b564d00-0x4b564dff */ #define MSR_KVM_WALL_CLOCK_NEW 0x4b564d00#define MSR_KVM_SYSTEM_TIME_NEW 0x4b564d01arch/x86/kvm/cpuid.c +2
-1@@ -408,7 +408,8 @@ static int do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function, (1 <<KVM_FEATURE_NOP_IO_DELAY ) | (1 <<KVM_FEATURE_CLOCKSOURCE2 ) | (1 <<KVM_FEATURE_ASYNC_PF ) | - (1 <<KVM_FEATURE_CLOCKSOURCE_STABLE_BIT ); + (1 <<KVM_FEATURE_CLOCKSOURCE_STABLE_BIT ) | + (1 <<KVM_FEATURE_PV_UNHALT );if (sched_info_on ()) entry->eax |= (1 <<KVM_FEATURE_STEAL_TIME );arch/x86/kvm/x86.c +30
-0@@ -2079,6 +2079,7 @@ int kvm_dev_ioctl_check_extension(long ext)case KVM_CAP_XSAVE :case KVM_CAP_ASYNC_PF :case KVM_CAP_GET_TSC_KHZ : +case KVM_CAP_PV_UNHALT : r =1 ;break ;case KVM_CAP_COALESCED_MMIO :@@ -4913,6 +4914,30 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)return 1 ; } +/* +* kvm_pv_kick_cpu_op: Kick a vcpu. +* +* @apicid - apicid of vcpu to be kicked. +*/ +static void kvm_pv_kick_cpu_op (struct kvm *kvm,int apicid) +{ +struct kvm_vcpu *vcpu =NULL ; +int i; + +kvm_for_each_vcpu (i, vcpu, kvm) { +if (!kvm_apic_present (vcpu)) +continue ; + +if (kvm_apic_match_dest (vcpu,0 ,0 , apicid,0 )) +break ; + } +if (vcpu) { + vcpu->pv_unhalted =1 ; +smp_mb (); +kvm_vcpu_kick (vcpu); + } +} +int kvm_emulate_hypercall (struct kvm_vcpu *vcpu) {unsigned long nr, a0, a1, a2, a3, ret;@@ -4946,6 +4971,10 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)case KVM_HC_VAPIC_POLL_IRQ : ret =0 ;break ; +case KVM_HC_KICK_CPU : +kvm_pv_kick_cpu_op (vcpu->kvm, a0); + ret =0 ; +break ;default : ret = -KVM_ENOSYS ;break ;@@ -6174,6 +6203,7 @@ int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu) !vcpu->arch.apf.halted) || !list_empty_careful (&vcpu->async_pf.done) || vcpu->arch.mp_state ==KVM_MP_STATE_SIPI_RECEIVED + || vcpu->pv_unhalted ||atomic_read (&vcpu->arch.nmi_queued) || (kvm_arch_interrupt_allowed (vcpu) &&kvm_cpu_has_interrupt (vcpu));include/linux/kvm.h +1
-0@@ -558,6 +558,7 @@ struct kvm_ppc_pvinfo {#define KVM_CAP_PPC_PAPR 68#define KVM_CAP_S390_GMAP 71#define KVM_CAP_TSC_DEADLINE_TIMER 72 +#define KVM_CAP_PV_UNHALT 73#ifdef KVM_CAP_IRQ_ROUTING include/linux/kvm_host.h +1
-0@@ -158,6 +158,7 @@ struct kvm_vcpu {#endif struct kvm_vcpu_arch arch; +int pv_unhalted; };static inline int kvm_vcpu_exiting_guest_mode (struct kvm_vcpu *vcpu)include/linux/kvm_para.h +1
-0@@ -19,6 +19,7 @@#define KVM_HC_MMU_OP 2#define KVM_HC_FEATURES 3#define KVM_HC_PPC_MAP_MAGIC_PAGE 4 +#define KVM_HC_KICK_CPU 5/* * hypercalls use architecture specific virt/kvm/kvm_main.c +1
-0@@ -226,6 +226,7 @@ int kvm_vcpu_init(struct kvm_vcpu *vcpu, struct kvm *kvm, unsigned id) vcpu->kvm = kvm; vcpu->vcpu_id = id; vcpu->pid =NULL ; + vcpu->pv_unhalted =0 ;init_waitqueue_head (&vcpu->wq);kvm_async_pf_vcpu_init (vcpu);
virt/kvm/kvm_main.c void kvm_vcpu_block(struct kvm_vcpu *vcpu) · line 1573
Quoted 6 lines
virt/kvm/kvm_main.c +3
-0@@ -1567,6 +1568,9 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)prepare_to_wait (&vcpu->wq, &wait,TASK_INTERRUPTIBLE );if (kvm_arch_vcpu_runnable (vcpu)) { + vcpu->pv_unhalted =0 ; +/* preventing reordering should be enough here */ +barrier ();
Is it always OK to erase the notification, even in case an unrelated event such as interrupt was the source of wakeup?
It would be easier to verify that notifications are not lost with atomic
test_and_clear(pv_unhalted).
Also x86 specific code should remain in arch/x86/kvm/
Re: [PATCH RFC V5 2/6] kvm hypervisor : Add a hypercall to KVM hypervisor to support pv-ticketlocks
Quoted 166 lines · Marcelo Tosatti
Quoted 165 lines · Raghavendra K T
From: Srivatsa Vaddagiri <[email protected]>
KVM_HC_KICK_CPUallows the calling vcpu to kick another vcpu out of halt state.The presence of these hypercalls is indicated to guest via KVM_FEATURE_PV_UNHALT/KVM_CAP_PV_UNHALT.
Signed-off-by Srivatsa Vaddagiri <[email protected]>Signed-off-by Suzuki Poulose <[email protected]>Signed-off-by Raghavendra K T <[email protected]>---
arch/x86/include/asm/kvm_para.h +3
-0@@ -16,12 +16,14 @@#define KVM_FEATURE_CLOCKSOURCE 0#define KVM_FEATURE_NOP_IO_DELAY 1#define KVM_FEATURE_MMU_OP 2 +/* This indicates that the new set of kvmclock msrs * are available. The use of 0x11 and 0x12 is deprecated */ #define KVM_FEATURE_CLOCKSOURCE2 3#define KVM_FEATURE_ASYNC_PF 4#define KVM_FEATURE_STEAL_TIME 5 +#define KVM_FEATURE_PV_UNHALT 6/* The last 8 bits are used to indicate how to interpret the flags field * in pvclock structure. If no bits are set, all flags are ignored. @@ -32,6 +34,7 @@#define MSR_KVM_SYSTEM_TIME 0x12#define KVM_MSR_ENABLED 1 +/* Custom MSRs falls in the range 0x4b564d00-0x4b564dff */ #define MSR_KVM_WALL_CLOCK_NEW 0x4b564d00#define MSR_KVM_SYSTEM_TIME_NEW 0x4b564d01arch/x86/kvm/cpuid.c +2
-1@@ -408,7 +408,8 @@ static int do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function, (1 <<KVM_FEATURE_NOP_IO_DELAY ) | (1 <<KVM_FEATURE_CLOCKSOURCE2 ) | (1 <<KVM_FEATURE_ASYNC_PF ) | - (1 <<KVM_FEATURE_CLOCKSOURCE_STABLE_BIT ); + (1 <<KVM_FEATURE_CLOCKSOURCE_STABLE_BIT ) | + (1 <<KVM_FEATURE_PV_UNHALT );if (sched_info_on ()) entry->eax |= (1 <<KVM_FEATURE_STEAL_TIME );arch/x86/kvm/x86.c +30
-0@@ -2079,6 +2079,7 @@ int kvm_dev_ioctl_check_extension(long ext)case KVM_CAP_XSAVE :case KVM_CAP_ASYNC_PF :case KVM_CAP_GET_TSC_KHZ : +case KVM_CAP_PV_UNHALT : r =1 ;break ;case KVM_CAP_COALESCED_MMIO :@@ -4913,6 +4914,30 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)return 1 ; } +/* +* kvm_pv_kick_cpu_op: Kick a vcpu. +* +* @apicid - apicid of vcpu to be kicked. +*/ +static void kvm_pv_kick_cpu_op (struct kvm *kvm,int apicid) +{ +struct kvm_vcpu *vcpu =NULL ; +int i; + +kvm_for_each_vcpu (i, vcpu, kvm) { +if (!kvm_apic_present (vcpu)) +continue ; + +if (kvm_apic_match_dest (vcpu,0 ,0 , apicid,0 )) +break ; + } +if (vcpu) { + vcpu->pv_unhalted =1 ; +smp_mb (); +kvm_vcpu_kick (vcpu); + } +} +int kvm_emulate_hypercall (struct kvm_vcpu *vcpu) {unsigned long nr, a0, a1, a2, a3, ret;@@ -4946,6 +4971,10 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)case KVM_HC_VAPIC_POLL_IRQ : ret =0 ;break ; +case KVM_HC_KICK_CPU : +kvm_pv_kick_cpu_op (vcpu->kvm, a0); + ret =0 ; +break ;default : ret = -KVM_ENOSYS ;break ;@@ -6174,6 +6203,7 @@ int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu) !vcpu->arch.apf.halted) || !list_empty_careful (&vcpu->async_pf.done) || vcpu->arch.mp_state ==KVM_MP_STATE_SIPI_RECEIVED + || vcpu->pv_unhalted ||atomic_read (&vcpu->arch.nmi_queued) || (kvm_arch_interrupt_allowed (vcpu) &&kvm_cpu_has_interrupt (vcpu));include/linux/kvm.h +1
-0@@ -558,6 +558,7 @@ struct kvm_ppc_pvinfo {#define KVM_CAP_PPC_PAPR 68#define KVM_CAP_S390_GMAP 71#define KVM_CAP_TSC_DEADLINE_TIMER 72 +#define KVM_CAP_PV_UNHALT 73#ifdef KVM_CAP_IRQ_ROUTING include/linux/kvm_host.h +1
-0@@ -158,6 +158,7 @@ struct kvm_vcpu {#endif struct kvm_vcpu_arch arch; +int pv_unhalted; };static inline int kvm_vcpu_exiting_guest_mode (struct kvm_vcpu *vcpu)include/linux/kvm_para.h +1
-0@@ -19,6 +19,7 @@#define KVM_HC_MMU_OP 2#define KVM_HC_FEATURES 3#define KVM_HC_PPC_MAP_MAGIC_PAGE 4 +#define KVM_HC_KICK_CPU 5/* * hypercalls use architecture specific virt/kvm/kvm_main.c +1
-0@@ -226,6 +226,7 @@ int kvm_vcpu_init(struct kvm_vcpu *vcpu, struct kvm *kvm, unsigned id) vcpu->kvm = kvm; vcpu->vcpu_id = id; vcpu->pid =NULL ; + vcpu->pv_unhalted =0 ;init_waitqueue_head (&vcpu->wq);kvm_async_pf_vcpu_init (vcpu);@@ -1567,6 +1568,9 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)prepare_to_wait (&vcpu->wq, &wait,TASK_INTERRUPTIBLE );
Quoted 7 lines
virt/kvm/kvm_main.c void kvm_vcpu_block(struct kvm_vcpu *vcpu) · line 1573
Quoted 4 lines
virt/kvm/kvm_main.c +3
-0if (kvm_arch_vcpu_runnable (vcpu)) { + vcpu->pv_unhalted =0 ; +/* preventing reordering should be enough here */ +barrier ();Is it always OK to erase the notification, even in case an unrelated event such as interrupt was the source of wakeup?
Note i am only asking whether it is OK to lose a notification, not requesting a change to atomic test-and-clear.
It would be nice to have a comment explaining it.
Quoted 6 lines
It would be easier to verify that notifications are not lost with atomic
test_and_clear(pv_unhalted).Also x86 specific code should remain in
arch/x86/kvm/
Re: [PATCH RFC V5 2/6] kvm hypervisor : Add a hypercall to KVM hypervisor to support pv-ticketlocks
Quoted 4 lines · Marcelo Tosatti
Quoted 3 lines · Marcelo Tosatti
Quoted 2 lines · Raghavendra K T
From: Srivatsa Vaddagiri<[email protected]>
[...]
barrier();
Quoted 6 lines
Quoted 3 lines
Is it always OK to erase the notification, even in case an unrelated event such as interrupt was the source of wakeup?
Note i am only asking whether it is OK to lose a notification, not requesting a change to atomic test-and-clear.
Yes.. got your point.
IMO, this is the only (safe) place where it can clear kicked(pv_unhalted) flag. Since it is going to be runnable.
and you are also right in having concern on unwanted clear of flag since that would result in vcpu /vm hangs eventually.
Hope I did not miss anything.
Quoted 3 lines
It would be nice to have a comment explaining it.
Sure will do that
Quoted 1 line
Quoted 1 line
Re: [PATCH RFC V5 2/6] kvm hypervisor : Add a hypercall to KVM hypervisor to support pv-ticketlocks
In reply to Marcelo TosattiQuoted 4 lines · Marcelo Tosatti
Quoted 3 lines · Marcelo Tosatti
Quoted 2 lines · Raghavendra K T
From: Srivatsa Vaddagiri<[email protected]>
[...]
barrier();
Quoted 6 lines
Quoted 3 lines
Is it always OK to erase the notification, even in case an unrelated event such as interrupt was the source of wakeup?
Note i am only asking whether it is OK to lose a notification, not requesting a change to atomic test-and-clear.
Yes.. got your point.
IMO, this is the only (safe) place where it can clear kicked(pv_unhalted) flag. Since it is going to be runnable.
and you are also right in having concern on unwanted clear of flag since that would result in vcpu /vm hangs eventually.
Hope I did not miss anything.
Quoted 3 lines
It would be nice to have a comment explaining it.
Sure will do that
Quoted 1 line
Quoted 1 line
Re: [PATCH RFC V5 2/6] kvm hypervisor : Add a hypercall to KVM hypervisor to support pv-ticketlocks
In reply to Marcelo TosattiSorry for late reply,
was on vacation for a week (without IMAP access :( )
Quoted 2 lines · Marcelo Tosatti
Quoted 1 line · Raghavendra K T
From: Srivatsa Vaddagiri<[email protected]>
[snip]
Quoted 10 lines
virt/kvm/kvm_main.c void kvm_vcpu_block(struct kvm_vcpu *vcpu) · line 1573
Quoted 7 lines
virt/kvm/kvm_main.c +3
-0@@ -1567,6 +1568,9 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)prepare_to_wait (&vcpu->wq,&wait,TASK_INTERRUPTIBLE );if (kvm_arch_vcpu_runnable (vcpu)) { + vcpu->pv_unhalted =0 ; +/* preventing reordering should be enough here */ +barrier ();Is it always OK to erase the notification, even in case an unrelated event such as interrupt was the source of wakeup?
Erasing notification is not good, But I think in this case,
kvm_make_request(KVM_REQ_UNHALT, vcpu);
below this would take care of the rest.
Quoted 4 lines
It would be easier to verify that notifications are not lost with atomic
test_and_clear(pv_unhalted).
true, I 'll verify that (with pv_unhalt as atomic variable). my heart says current code is just fine, since we are about to unblock.
Quoted 3 lines
Also x86 specific code should remain in
arch/x86/kvm/
I agree. 'll have clear function in arch/x86/kvm and add stub to rest of the archs
Quoted 1 line
Re: [PATCH RFC V5 2/6] kvm hypervisor : Add a hypercall to KVM hypervisor to support pv-ticketlocks
In reply to Marcelo TosattiSorry for late reply,
was on vacation for a week (without IMAP access :( )
Quoted 2 lines · Marcelo Tosatti
Quoted 1 line · Raghavendra K T
From: Srivatsa Vaddagiri<[email protected]>
[snip]
Quoted 10 lines
virt/kvm/kvm_main.c void kvm_vcpu_block(struct kvm_vcpu *vcpu) · line 1573
Quoted 7 lines
virt/kvm/kvm_main.c +3
-0@@ -1567,6 +1568,9 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)prepare_to_wait (&vcpu->wq,&wait,TASK_INTERRUPTIBLE );if (kvm_arch_vcpu_runnable (vcpu)) { + vcpu->pv_unhalted =0 ; +/* preventing reordering should be enough here */ +barrier ();Is it always OK to erase the notification, even in case an unrelated event such as interrupt was the source of wakeup?
Erasing notification is not good, But I think in this case,
kvm_make_request(KVM_REQ_UNHALT, vcpu);
below this would take care of the rest.
Quoted 4 lines
It would be easier to verify that notifications are not lost with atomic
test_and_clear(pv_unhalted).
true, I 'll verify that (with pv_unhalt as atomic variable). my heart says current code is just fine, since we are about to unblock.
Quoted 3 lines
Also x86 specific code should remain in
arch/x86/kvm/
I agree. 'll have clear function in arch/x86/kvm and add stub to rest of the archs
Quoted 1 line
RFC PATCH v5 3/6 kvm : Add unhalt msr to aid (live) migration
In reply to Raghavendra K TFrom: Raghavendra K T <[email protected]>
Currently guest does not need to know pv_unhalt state and intended to be used via GET/SET_MSR ioctls during migration.
---
arch/x86/include/asm/kvm_para.h +1 -0
@@ -40,6 +40,7 @@#define MSR_KVM_SYSTEM_TIME_NEW 0x4b564d01#define MSR_KVM_ASYNC_PF_EN 0x4b564d02#define MSR_KVM_STEAL_TIME 0x4b564d03 +#define MSR_KVM_PV_UNHALT 0x4b564d04struct kvm_steal_time {__u64 steal;
arch/x86/kvm/x86.c +8 -2
@@ -784,12 +784,13 @@ EXPORT_SYMBOL_GPL(kvm_rdpmc);* kvm-specific. Those are put in the beginning of the list. */ -#define KVM_SAVE_MSRS_BEGIN 9 +#define KVM_SAVE_MSRS_BEGIN 10static u32 msrs_to_save[] = {MSR_KVM_SYSTEM_TIME ,MSR_KVM_WALL_CLOCK ,MSR_KVM_SYSTEM_TIME_NEW ,MSR_KVM_WALL_CLOCK_NEW ,HV_X64_MSR_GUEST_OS_ID ,HV_X64_MSR_HYPERCALL ,HV_X64_MSR_APIC_ASSIST_PAGE ,MSR_KVM_ASYNC_PF_EN ,MSR_KVM_STEAL_TIME , +MSR_KVM_PV_UNHALT ,MSR_IA32_SYSENTER_CS ,MSR_IA32_SYSENTER_ESP ,MSR_IA32_SYSENTER_EIP ,MSR_STAR , #ifdef CONFIG_X86_64
@@ -1606,7 +1607,9 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)kvm_make_request (KVM_REQ_STEAL_UPDATE , vcpu);break ; - +case MSR_KVM_PV_UNHALT : + vcpu->pv_unhalted = (u32 ) data; +break ;case MSR_IA32_MCG_CTL :case MSR_IA32_MCG_STATUS : case MSR_IA32_MC0_CTL ... MSR_IA32_MC0_CTL + 4 * KVM_MAX_MCE_BANKS - 1:
@@ -1917,6 +1920,9 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)case MSR_KVM_STEAL_TIME : data = vcpu->arch.st.msr_val;break ; +case MSR_KVM_PV_UNHALT : + data = (u64 )vcpu->pv_unhalted; +break ;case MSR_IA32_P5_MC_ADDR :case MSR_IA32_P5_MC_TYPE :case MSR_IA32_MCG_CAP :
Re: [PATCH RFC V5 3/6] kvm : Add unhalt msr to aid (live) migration
Quoted 50 lines · Raghavendra K T
From: Raghavendra K T <[email protected]>
Currently guest does not need to know
pv_unhaltstate and intended to be used via GET/SET_MSR ioctls during migration.Signed-off-by Raghavendra K T <[email protected]>---
arch/x86/include/asm/kvm_para.h +1
-0@@ -40,6 +40,7 @@#define MSR_KVM_SYSTEM_TIME_NEW 0x4b564d01#define MSR_KVM_ASYNC_PF_EN 0x4b564d02#define MSR_KVM_STEAL_TIME 0x4b564d03 +#define MSR_KVM_PV_UNHALT 0x4b564d04struct kvm_steal_time {__u64 steal;arch/x86/kvm/x86.c +5
-2@@ -784,12 +784,13 @@ EXPORT_SYMBOL_GPL(kvm_rdpmc);* kvm-specific. Those are put in the beginning of the list. */ -#define KVM_SAVE_MSRS_BEGIN 9 +#define KVM_SAVE_MSRS_BEGIN 10static u32 msrs_to_save[] = {MSR_KVM_SYSTEM_TIME ,MSR_KVM_WALL_CLOCK ,MSR_KVM_SYSTEM_TIME_NEW ,MSR_KVM_WALL_CLOCK_NEW ,HV_X64_MSR_GUEST_OS_ID ,HV_X64_MSR_HYPERCALL ,HV_X64_MSR_APIC_ASSIST_PAGE ,MSR_KVM_ASYNC_PF_EN ,MSR_KVM_STEAL_TIME , +MSR_KVM_PV_UNHALT ,MSR_IA32_SYSENTER_CS ,MSR_IA32_SYSENTER_ESP ,MSR_IA32_SYSENTER_EIP ,MSR_STAR , #ifdef CONFIG_X86_64@@ -1606,7 +1607,9 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)kvm_make_request (KVM_REQ_STEAL_UPDATE , vcpu);break ; - +case MSR_KVM_PV_UNHALT : + vcpu->pv_unhalted = (u32 ) data; +break ;case MSR_IA32_MCG_CTL :case MSR_IA32_MCG_STATUS : case MSR_IA32_MC0_CTL ... MSR_IA32_MC0_CTL + 4 * KVM_MAX_MCE_BANKS - 1:
arch/x86/kvm/x86.c int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata) · line 1928
Quoted 9 lines
arch/x86/kvm/x86.c +3
-0@@ -1917,6 +1920,9 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)case MSR_KVM_STEAL_TIME : data = vcpu->arch.st.msr_val;break ; +case MSR_KVM_PV_UNHALT : + data = (u64 )vcpu->pv_unhalted; +break ;case MSR_IA32_P5_MC_ADDR :case MSR_IA32_P5_MC_TYPE :case MSR_IA32_MCG_CAP :
Unless there is a reason to use an MSR, should use a normal ioctl such as KVM_{GET,SET}_MP_STATE.
Re: [PATCH RFC V5 3/6] kvm : Add unhalt msr to aid (live) migration
Quoted 3 lines · Marcelo Tosatti
Quoted 2 lines · Raghavendra K T
From: Raghavendra K T<[email protected]>
[...]
Quoted 5 lines
Unless there is a reason to use an MSR, should use a normal ioctl such as KVM_{GET,SET}_MP_STATE.
I agree with you. In the current implementation, since we are not doing any communication between host/guest (on this flag), I too felt MSR is an overkill for this.
IMO, patch like below should do the job, which I am planning to include in next version of patch.
Let me know if you foresee any side-effects.
---
arch/x86/kvm/x86.c +3 -1
@@ -5691,7 +5691,9 @@ int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,int kvm_arch_vcpu_ioctl_get_mpstate (struct kvm_vcpu *vcpu,struct kvm_mp_state *mp_state) { - mp_state->mp_state = vcpu->arch.mp_state; + mp_state->mp_state = (vcpu->arch.mp_state ==KVM_MP_STATE_HALTED && + vcpu->pv_unhalted)? +KVM_MP_STATE_RUNNABLE : vcpu->arch.mp_state;return 0 ; }
Re: [PATCH RFC V5 3/6] kvm : Add unhalt msr to aid (live) migration
In reply to Marcelo TosattiQuoted 3 lines · Marcelo Tosatti
Quoted 2 lines · Raghavendra K T
From: Raghavendra K T<[email protected]>
[...]
Quoted 5 lines
Unless there is a reason to use an MSR, should use a normal ioctl such as KVM_{GET,SET}_MP_STATE.
I agree with you. In the current implementation, since we are not doing any communication between host/guest (on this flag), I too felt MSR is an overkill for this.
IMO, patch like below should do the job, which I am planning to include in next version of patch.
Let me know if you foresee any side-effects.
---
arch/x86/kvm/x86.c +3 -1
@@ -5691,7 +5691,9 @@ int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,int kvm_arch_vcpu_ioctl_get_mpstate (struct kvm_vcpu *vcpu,struct kvm_mp_state *mp_state) { - mp_state->mp_state = vcpu->arch.mp_state; + mp_state->mp_state = (vcpu->arch.mp_state ==KVM_MP_STATE_HALTED && + vcpu->pv_unhalted)? +KVM_MP_STATE_RUNNABLE : vcpu->arch.mp_state;return 0 ; }
RFC PATCH v5 4/6 kvm guest : Added configuration support to enable debug information for KVM Guests
In reply to Raghavendra K TFrom: Srivatsa Vaddagiri <[email protected]>
---
arch/x86/Kconfig +9 -0
@@ -600,6 +600,15 @@ config KVM_GUEST This option enables various optimizations for running under the KVM hypervisor. +config KVM_DEBUG_FS + bool "Enable debug information for KVM Guests in debugfs" + depends on KVM_GUEST && DEBUG_FS + default n + ---help--- + This option enables collection of various statistics for KVM guest. + Statistics are displayed in debugfs filesystem. Enabling this option + may incur significant overhead. + source "arch/x86/lguest/Kconfig" config PARAVIRT
RFC PATCH v5 5/6 kvm : pv-ticketlocks support for linux guests running on KVM hypervisor
In reply to Raghavendra K TFrom: Srivatsa Vaddagiri <[email protected]>
During smp_boot_cpus paravirtualied KVM guest detects if the hypervisor has required feature (KVM_FEATURE_PV_UNHALT) to support pv-ticketlocks. If so,
support for pv-ticketlocks is registered via pv_lock_ops.
Use KVM_HC_KICK_CPU hypercall to wakeup waiting/halted vcpu.
---
arch/x86/include/asm/kvm_para.h +12 -2
@@ -197,10 +197,20 @@ void kvm_async_pf_task_wait(u32 token);void kvm_async_pf_task_wake (u32 token);u32 kvm_read_and_reset_pf_reason (void );extern void kvm_disable_steal_time (void ); -#else -#define kvm_guest_init () do { } while (0) + +#ifdef CONFIG_PARAVIRT_SPINLOCKS +void __init kvm_spinlock_init (void ); +#else /* !CONFIG_PARAVIRT_SPINLOCKS */ +static void kvm_spinlock_init (void ) +{ +} +#endif /* CONFIG_PARAVIRT_SPINLOCKS */ + +#else /* CONFIG_KVM_GUEST */ +#define kvm_guest_init () do {} while (0)#define kvm_async_pf_task_wait (T ) do {} while(0)#define kvm_async_pf_task_wake (T ) do {} while(0) +static inline u32 kvm_read_and_reset_pf_reason (void ) {return 0 ;
arch/x86/kernel/kvm.c +254 -0
269 lines not on this page · raw message
RFC PATCH v5 6/6 Documentation/kvm : Add documentation on Hypercalls and features used for PV spinlock
In reply to Raghavendra K TFrom: Raghavendra K T <[email protected]>
KVM_HC_KICK_CPU hypercall added to wakeup halted vcpu in paravirtual spinlock enabled guest.
KVM_FEATURE_PV_UNHALT enables guest to check whether pv spinlock can be enabled in guest. support in host is queried via ioctl(KVM_CHECK_EXTENSION, KVM_CAP_PV_UNHALT)
Thanks Alex for KVM_HC_FEATURES inputs and Vatsa for rewriting KVM_HC_KICK_CPU
---
Documentation/virtual/kvm/api.txt +7 -0
@@ -1109,6 +1109,13 @@ support. Instead it is reported via if that returns true and you use KVM_CREATE_IRQCHIP, or if you emulate the feature in userspace, then you can enable the feature for KVM_SET_CPUID2. +Paravirtualized ticket spinlocks can be enabled in guest by checking whether +support exists in host via, + + ioctl(KVM_CHECK_EXTENSION, KVM_CAP_PV_UNHALT) + +if this call return true, guest can use the feature. + 4.47 KVM_PPC_GET_PVINFO Capability: KVM_CAP_PPC_GET_PVINFO
Documentation/virtual/kvm/cpuid.txt +4 -0
@@ -39,6 +39,10 @@ KVM_FEATURE_CLOCKSOURCE2 || 3 || kvmclock available at msrs KVM_FEATURE_ASYNC_PF || 4 || async pf can be enabled by || || writing to msr 0x4b564d02 ------------------------------------------------------------------------------ +KVM_FEATURE_PV_UNHALT || 6 || guest checks this feature bit + || || before enabling paravirtualized + || || spinlock support. +------------------------------------------------------------------------------ KVM_FEATURE_CLOCKSOURCE_STABLE_BIT || 24 || host will warn if no guest-side || || per-cpu warps are expected in || || kvmclock.
Documentation/virtual/kvm/hypercalls.txt new file +59 -0
59 lines not on this page · raw message
Documentation/virtual/kvm/msr.txt +9 -0
@@ -219,3 +219,12 @@ MSR_KVM_STEAL_TIME: 0x4b564d03 steal: the amount of time in which this vCPU did not run, in nanoseconds. Time during which the vcpu is idle, will not be reported as steal time. + +MSR_KVM_PV_UNHALT: 0x4b564d04 + data: 32 bit flag indicating the paravirtual unhalt state of the VCPU. + This data is not expected to reside in guest memory. The unhalt state + indicates that corresponding VCPU (halted for some reason) is ready for + unhalt operation. + + This data is expected to be filled only via ioctl. This is needed for + live migration of virtual machine.
Quoted 9 lines · Raghavendra K T
The 6-patch series to follow this email extends KVM-hypervisor and Linux guest running on KVM-hypervisor to support pv-ticket spinlocks, based on Xen's implementation.
One hypercall is introduced in KVM hypervisor,that allows a vcpu to kick another vcpu out of halt state.
The blocking of vcpu is done usinghalt()in (lock_spinning) slowpath. one MSR is added to aid live migration.
Quoted 4 lines
Changes in V5:
- rebased to 3.3-rc6
- addedPV_UNHALT_MSRthat would help in live migration (Avi)
- removedPV_LOCK_KICKvcpu request andpv_unhaltflag (re)added.
Sorry for pinging
I know it is busy time. But I hope to get response on these patches in your free time, so that I can target next merge window for this. (whether it has reached some good state or it is heading in reverse direction!). it would really boost my morale. especially MSR stuff and dropping vcpu request bit for PV unhalt.
- Raghu
Quoted 15 lines · Raghavendra K T
Quoted 9 lines · Raghavendra K T
The 6-patch series to follow this email extends KVM-hypervisor and Linux guest running on KVM-hypervisor to support pv-ticket spinlocks, based on Xen's implementation.
One hypercall is introduced in KVM hypervisor,that allows a vcpu to kick another vcpu out of halt state.
The blocking of vcpu is done usinghalt()in (lock_spinning) slowpath. one MSR is added to aid live migration.Quoted 4 lines
Changes in V5:
- rebased to 3.3-rc6
- addedPV_UNHALT_MSRthat would help in live migration (Avi)
- removedPV_LOCK_KICKvcpu request andpv_unhaltflag (re)added.
Quoted 8 lines
Sorry for pinging
I know it is busy time. But I hope to get response on these patches in your free time, so that I can target next merge window for this. (whether it has reached some good state or it is heading in reverse direction!). it would really boost my morale.
especially MSR stuff and dropping vcpu request bit for PV unhalt.- Raghu
Looks good. Only the MSR appears an abuse, since there is no need to expose the info to the guest.