Paravirt-spinlock implementation for KVM guests (Version 0)
Subsystems (6)
cover Paravirt-spinlock implementation for KVM guests (Version 0)
This patch-series implements paravirt-spinlock implementation for KVM guests, based heavily on Xen's implementation. I tried to refactor Xen's spinlock implementation to make it common for both Xen and KVM - but found that few differences between Xen and KVM (Xen has the ability to block on a particular event/irq for example) _and_ the fact that the guest kernel can be compiled to support both Xen and KVM hypervisors (CONFIG_XEN and CONFIG_KVM_GUEST can both be turned on) makes the "common" code a eye-sore. There will have to be:
if (xen) {
...
} else if (kvm) {
..
}or possibly:
alternative(NOP, some_xen_specific_call, ....)
type of code in the common implementation.
For the time-being, I have made this KVM-specific only. At somepoint in future, I hope this can be made common between Xen/KVM.
More background and results for this patch below:
What is the Problem being solved?
=================================
Guest operating system can be preempted by hypervisor at any arbitrary point. There is no mechanism (that I know of) where guest OS can disable preemption for certain periods of time. One noticeable effect of this is with regard to locking. Lets say one virtual-cpu of a guest (VCPUA) grabs a spinlock and before it could relinquish the lock is preempted by hypervisor. The time-of-preemption (when the virtual cpu is off the cpu) can be quite large. In that period, if another of guest OS's virtual cpu (VCPUB) tries grabbing the same lock, it could end up spin-waiting a _long_ time, burning cycles unnecessarily. To add to the woes, VCPUB may actually be waiting for VCPUA to yield before it can run on the same (physical) cpu. This is termed as the "lock-holder preemption" (LHP) problem. The effect of it can be quite serious. For ex:
http://lkml.org/lkml/2010/4/11/108 reported 80% performance degradation because of an issue attributed to LHP problem.
Solutions
=========
There are several solutions to this problem.
a. Realize that a lock-holder could have been preempted, and avoid spin-waiting
too long. Instead, yield cycles (to the lock-holder perhaps). This is a common solution adopted by most paravirtualized-guests (Xen, s390, powerpc).
b. Avoid preempting a lock-holder while its holding a (spin-) lock.
In this scheme, guest OS can hint (set some flag in memory shared with hypervisor) whenever its holding a lock and hypervisor could defer preempting the guest vcpu when its holding a lock. With this scheme, we should never have a lock-acquiring vcpu spin on a preempted vcpu to release its lock. If ever it spins, its because somebody *currently running* is holding the lock - and hence it won't have to spin-wait too long. IOW we are pro-actively trying to prevent the LHP problem from occuring in the first place. This should improve job turnaround time for some workloads. [1] has some results based on this approach.
c. Share run-status of vcpu with guests. This could be used to optimize
routines like mutex_spin_on_owner().
Hypervisor could share run-status of vcpus in guest kernel memory. This would allow us to optimize routines like mutex_spin_on_owner() - we don't spin-wait if we relaize that the target vcpu has been preempted.
a) and c) are about dealing with the LHP problem, while b) is about preventing the problem from happening.
This patch-series is along a). Its based against v2.6.35-rc4 kernel for both guest and host.
I have patches for b) and c) as well - want to send them after more thorough experimentation with various workloads.
Results
=======
Machine : IBM x3650 with 2 Dual-core Intel Xeon (5160) CPUs and 4972MB RAM Kernel for host/guest : 2.6.35-rc4
Test :
Spawn a single guest under KVM with 4VCPUs, 3092MB memory, virtio disk Guest runs kernel compile benchmark as:
time -p make -s -j20 bzImage
for 3 times in a loop.
This is repeated under varios over-commitment scenarios and "vcpu/pcpu pinning configurations"
Overcommit scenarios are :
1x : only guest is running
2x : cpu hogs are started such that (hogs + guest vcpu count)/pcpu = 2 3x : cpu hogs are started such that (hogs + guest vcpu count)/pcpu = 3 4x : cpu hogs are started such that (hogs + guest vcpu count)/pcpu = 4
VCPU/PCPU pinning scenarion:
A : Each of the vcpu of the guest is pinned to a separate pcpu B : No pinning. vcpu could run on any pcpu.
C : The 4 VCPUs of guest pinned to run inside a single dual-core CPU
(cpu 2,3 in this case)
Scenario A:
W/o patch W/ Patch Difference Avg (std-dev) Avg. (std-dev)
1: 273.270 (1.051) 251.613 (1.155) 7.9% 2: 541.343 (57.317) 443.400 (2.832) 18.1% 3: 819.160 (9.218) 642.393 (2.646) 21.6%
4: 1020.493 (34.743) 839.327 (0.658) 17.8%
Scenario B:
1: 276.947 (0.644) 248.397 (1.563) 10.3%
2: 500.723 (5.694) 438.957 (6.112) 12.33%
3: 725.687 (5.267) 641.317 (3.902) 11.62%
4: 973.910 (21.712) 836.853 (2.754) 14.07%
Scenario C:
1: 564.610 (12.055) 420.510 (2.598) 25.52% 2: 750.867 (5.139) 618.570 (2.914) 17.61% 3: 950.150 (13.496) 813.803 (1.872) 14.35%
4: 1125.027 (5.337) 1007.63 (5.707) 10.43%
IMO this is good improvement with the patchset applied.
References
==========
1. http://l4ka.org/publications/2004/Towards-Scalable-Multiprocessor-Virtual-Machin
RFC PATCH 1/4 Debugfs support for reading an array of u32-type integers
Debugfs support for reading an array of u32-type integers. This is a rework of what code already exists for Xen.
--- arch/x86/xen/debugfs.c | 104 ---------------------------------------- arch/x86/xen/debugfs.h | 4 - arch/x86/xen/mmu.c | 2 arch/x86/xen/multicalls.c | 6 +- arch/x86/xen/spinlock.c | 6 +- fs/debugfs/file.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++ include/linux/debugfs.h | 11 ++++ 7 files changed, 135 insertions(+), 115 deletions(-)
arch/x86/xen/debugfs.c +0 -104
@@ -18,107 +18,3 @@ struct dentry * __init xen_init_debugfs(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, -}; - -struct dentry *xen_debugfs_create_u32_array (const char *name,mode_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,mode_t mode, -struct dentry *parent, -u32 *array,unsigned elements); -#endif /* _XEN_DEBUGFS_H */
arch/x86/xen/mmu.c +1 -1
@@ -1983,7 +1983,7 @@ static int __init xen_mmu_debugfs(void)debugfs_create_u32 ("mmu_update" ,0444 , d_mmu_debug, &mmu_stats.mmu_update);debugfs_create_u32 ("mmu_update_extended" ,0444 , d_mmu_debug, &mmu_stats.mmu_update_extended); -xen_debugfs_create_u32_array ("mmu_update_histo" ,0444 , d_mmu_debug, +debugfs_create_u32_array ("mmu_update_histo" ,0444 , d_mmu_debug, mmu_stats.mmu_update_histo,20 );debugfs_create_u32 ("set_pte_at" ,0444 , d_mmu_debug, &mmu_stats.set_pte_at);
arch/x86/xen/multicalls.c +3 -3
@@ -269,11 +269,11 @@ static int __init xen_mc_debugfs(void)debugfs_create_u32 ("hypercalls" ,0444 , d_mc_debug, &mc_stats.hypercalls);debugfs_create_u32 ("arg_total" ,0444 , d_mc_debug, &mc_stats.arg_total); -xen_debugfs_create_u32_array ("batch_histo" ,0444 , d_mc_debug, +debugfs_create_u32_array ("batch_histo" ,0444 , d_mc_debug, mc_stats.histo,MC_BATCH ); -xen_debugfs_create_u32_array ("hypercall_histo" ,0444 , d_mc_debug, +debugfs_create_u32_array ("hypercall_histo" ,0444 , d_mc_debug, mc_stats.histo_hypercalls,NHYPERCALLS ); -xen_debugfs_create_u32_array ("flush_reasons" ,0444 , d_mc_debug, +debugfs_create_u32_array ("flush_reasons" ,0444 , d_mc_debug, mc_stats.flush,FL_N_REASONS );return 0 ;
arch/x86/xen/spinlock.c +3 -3
@@ -423,11 +423,11 @@ static int __init xen_spinlock_debugfs(vdebugfs_create_u64 ("time_total" ,0444 , d_spin_debug, &spinlock_stats.time_total); -xen_debugfs_create_u32_array ("histo_total" ,0444 , d_spin_debug, +debugfs_create_u32_array ("histo_total" ,0444 , d_spin_debug, spinlock_stats.histo_spin_total,HISTO_BUCKETS +1 ); -xen_debugfs_create_u32_array ("histo_spinning" ,0444 , d_spin_debug, +debugfs_create_u32_array ("histo_spinning" ,0444 , d_spin_debug, spinlock_stats.histo_spin_spinning,HISTO_BUCKETS +1 ); -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 +117 -0
126 lines not on this page · raw message
include/linux/debugfs.h +11 -0
@@ -74,6 +74,10 @@ struct dentry *debugfs_create_blob(conststruct dentry *parent, struct debugfs_blob_wrapper *blob); +struct dentry *debugfs_create_u32_array (const char *name,mode_t mode, +struct dentry *parent, +u32 *array,unsigned elements); +bool debugfs_initialized (void );#else
@@ -188,6 +192,13 @@ static inline struct dentry *debugfs_crereturn ERR_PTR (-ENODEV ); } +struct dentry *debugfs_create_u32_array (const char *name,mode_t mode, +struct dentry *parent, +u32 *array,unsigned elements) +{ +return ERR_PTR (-ENODEV ); +} +static inline bool debugfs_initialized (void ) {return false;
RFC PATCH 2/4 Add yield hypercall for KVM guests
In reply to Srivatsa VaddagiriAdd KVM hypercall for yielding vcpu timeslice.
--- arch/x86/include/asm/kvm_para.h | 1 + arch/x86/kvm/x86.c | 7 ++++++- include/linux/kvm.h | 1 + include/linux/kvm_para.h | 1 + 4 files changed, 9 insertions(+), 1 deletion(-)
arch/x86/include/asm/kvm_para.h +1 -0
@@ -16,6 +16,7 @@#define KVM_FEATURE_CLOCKSOURCE 0#define KVM_FEATURE_NOP_IO_DELAY 1#define KVM_FEATURE_MMU_OP 2 +#define KVM_FEATURE_YIELD 4/* This indicates that the new set of kvmclock msrs * are available. The use of 0x11 and 0x12 is deprecated */
arch/x86/kvm/x86.c +6 -1
@@ -1618,6 +1618,7 @@ int kvm_dev_ioctl_check_extension(long ecase KVM_CAP_PCI_SEGMENT :case KVM_CAP_DEBUGREGS :case KVM_CAP_X86_ROBUST_SINGLESTEP : +case KVM_CAP_YIELD_HYPERCALL : r =1 ;break ;case KVM_CAP_COALESCED_MMIO :
@@ -1993,7 +1994,8 @@ static void do_cpuid_ent(struct kvm_cpui entry->eax = (1 <<KVM_FEATURE_CLOCKSOURCE ) | (1 <<KVM_FEATURE_NOP_IO_DELAY ) | (1 <<KVM_FEATURE_CLOCKSOURCE2 ) | - (1 <<KVM_FEATURE_CLOCKSOURCE_STABLE_BIT ); + (1 <<KVM_FEATURE_CLOCKSOURCE_STABLE_BIT ) | + (1 <<KVM_FEATURE_YIELD ); entry->ebx =0 ; entry->ecx =0 ; entry->edx =0 ;
@@ -4245,6 +4247,9 @@ int kvm_emulate_hypercall(struct kvm_vcpcase KVM_HC_MMU_OP : r =kvm_pv_mmu_op (vcpu, a0,hc_gpa (vcpu, a1, a2), &ret);break ; +case KVM_HC_YIELD : + ret =0 ; +yield ();default : ret = -KVM_ENOSYS ;break ;
include/linux/kvm.h +1 -0
@@ -524,6 +524,7 @@ struct kvm_enable_cap {#define KVM_CAP_PPC_OSI 52#define KVM_CAP_PPC_UNSET_IRQ 53#define KVM_CAP_ENABLE_CAP 54 +#define KVM_CAP_YIELD_HYPERCALL 55#ifdef KVM_CAP_IRQ_ROUTING
include/linux/kvm_para.h +1 -0
@@ -17,6 +17,7 @@#define KVM_HC_VAPIC_POLL_IRQ 1#define KVM_HC_MMU_OP 2 +#define KVM_HC_YIELD 3/* * hypercalls use architecture specific
Re: [PATCH RFC 2/4] Add yield hypercall for KVM guests
Quoted 1 line · Srivatsa Vaddagiri
Add KVM hypercall for yielding vcpu timeslice.
Can you do a directed yield?
J
Quoted 78 lines
Signed-off-by Srivatsa Vaddagiri<[email protected]>--- arch/x86/include/asm/kvm_para.h | 1 + arch/x86/kvm/x86.c | 7 ++++++- include/linux/kvm.h | 1 + include/linux/kvm_para.h | 1 + 4 files changed, 9 insertions(+), 1 deletion(-)Index:
current/arch/x86/include/asm/kvm_para.h
===================================================================arch/x86/include/asm/kvm_para.h +1
-0@@ -16,6 +16,7 @@#define KVM_FEATURE_CLOCKSOURCE 0#define KVM_FEATURE_NOP_IO_DELAY 1#define KVM_FEATURE_MMU_OP 2 +#define KVM_FEATURE_YIELD 4/* This indicates that the new set of kvmclock msrs * are available. The use of 0x11 and 0x12 is deprecated */ Index:
current/arch/x86/kvm/x86.c
===================================================================arch/x86/kvm/x86.c +6
-1@@ -1618,6 +1618,7 @@ int kvm_dev_ioctl_check_extension(long ecase KVM_CAP_PCI_SEGMENT :case KVM_CAP_DEBUGREGS :case KVM_CAP_X86_ROBUST_SINGLESTEP : +case KVM_CAP_YIELD_HYPERCALL : r =1 ;break ;case KVM_CAP_COALESCED_MMIO :@@ -1993,7 +1994,8 @@ static void do_cpuid_ent(struct kvm_cpui entry->eax = (1 <<KVM_FEATURE_CLOCKSOURCE ) | (1 <<KVM_FEATURE_NOP_IO_DELAY ) | (1 <<KVM_FEATURE_CLOCKSOURCE2 ) | - (1 <<KVM_FEATURE_CLOCKSOURCE_STABLE_BIT ); + (1 <<KVM_FEATURE_CLOCKSOURCE_STABLE_BIT ) | + (1 <<KVM_FEATURE_YIELD ); entry->ebx =0 ; entry->ecx =0 ; entry->edx =0 ;@@ -4245,6 +4247,9 @@ int kvm_emulate_hypercall(struct kvm_vcpcase KVM_HC_MMU_OP : r =kvm_pv_mmu_op (vcpu, a0,hc_gpa (vcpu, a1, a2),&ret);break ; +case KVM_HC_YIELD : + ret =0 ; +yield ();default : ret = -KVM_ENOSYS ;break ;Index:
current/include/linux/kvm.h
===================================================================include/linux/kvm.h +1
-0@@ -524,6 +524,7 @@ struct kvm_enable_cap {#define KVM_CAP_PPC_OSI 52#define KVM_CAP_PPC_UNSET_IRQ 53#define KVM_CAP_ENABLE_CAP 54 +#define KVM_CAP_YIELD_HYPERCALL 55#ifdef KVM_CAP_IRQ_ROUTING Index:
current/include/linux/kvm_para.h
===================================================================include/linux/kvm_para.h +1
-0@@ -17,6 +17,7 @@#define KVM_HC_VAPIC_POLL_IRQ 1#define KVM_HC_MMU_OP 2 +#define KVM_HC_YIELD 3/* * hypercalls use architecture specific
Re: [PATCH RFC 2/4] Add yield hypercall for KVM guests
Quoted 4 lines · Jeremy Fitzhardinge
Quoted 1 line · Srivatsa Vaddagiri
Add KVM hypercall for yielding vcpu timeslice.
Can you do a directed yield?
We don't have that support yet in Linux scheduler. Also I feel it would be more useful when the target vcpu and yielding vcpu are on the same physical cpu, rather than when they are on separate cpus. With latter, yielding (or donating) timeslice need not ensure that target vcpu runs immediately and also I suspect fairness issues needs to be tackled as well (large number of waiters shouldn't boot a lock-holders time slice too much that it gets a larger share).
- vatsa
Re: [PATCH RFC 2/4] Add yield hypercall for KVM guests
Quoted 5 lines · Srivatsa Vaddagiri
Quoted 3 lines · Jeremy Fitzhardinge
Quoted 1 line · Srivatsa Vaddagiri
Add KVM hypercall for yielding vcpu timeslice.
Can you do a directed yield?
We don't have that support yet in Linux scheduler.
If you think it's useful, it would be good to design it into the interface, and fall back to ordinary yield if the host doesn't support it.
A big advantage of directed yield vs yield is that you conserve resources within a VM; a simple yield will cause the guest to drop its share of cpu to other guest.
Made up example:
- 2 vcpu guest with 10% contention
- lock hold time 10us every 100us
- timeslice 1ms
Ideally this guest can consume 190% cpu (sleeping whenever there is contention). But if we yield when we detect contention, then we sleep for 1ms, and utilization drops to around 100%-150% (a vcpu will usually fall asleep soon within a few 100us periods).
Quoted 4 lines
Also I feel it would be more
useful when the target vcpu and yielding vcpu are on the same physical cpu, rather than when they are on separate cpus. With latter, yielding (or donating) timeslice need not ensure that target vcpu runs immediately
Donate at least the amount needed to wake up the other vcpu, we can calculate it during wakeup.
Quoted 3 lines
and also I suspect fairness issues needs to be tackled as well (large number of waiters shouldn't boot a lock-holders time slice too much that it gets a larger share).
I feel ordinary yield suffers from fairness a lot more.
Signature · 1 line
error compiling committee.c: too many arguments to function
Re: [PATCH RFC 2/4] Add yield hypercall for KVM guests
Quoted 10 lines · Avi Kivity
Quoted 2 lines
Quoted 1 line
Can you do a directed yield?
We don't have that support yet in Linux scheduler.
If you think it's useful, it would be good to design it into the interface, and fall back to ordinary yield if the host doesn't support it.
A big advantage of directed yield vs yield is that you conserve resources within a VM; a simple yield will cause the guest to drop its share of cpu to other guest.
Hmm .. I see possibility of modifying yield to reclaim its "lost" timeslice when its scheduled next as well. Basically remember what timeslice we have given up and add that as its "bonus" when it runs next. That would keep the dynamics of yield donation/reclaim local to the (physical) cpu and IMHO is less complex than dealing with directed yield between tasks located across different physical cpus. That would also address the fairness issue with yield you are pointing at?
- vatsa
Re: [PATCH RFC 2/4] Add yield hypercall for KVM guests
Quoted 12 lines · Srivatsa Vaddagiri
Quoted 10 lines · Avi Kivity
Quoted 2 lines
Quoted 1 line
Can you do a directed yield?
We don't have that support yet in Linux scheduler.
If you think it's useful, it would be good to design it into the interface, and fall back to ordinary yield if the host doesn't support it.
A big advantage of directed yield vs yield is that you conserve resources within a VM; a simple yield will cause the guest to drop its share of cpu to other guest.
Quoted 6 lines
Hmm .. I see possibility of modifying yield to reclaim its "lost" timeslice when its scheduled next as well. Basically remember what timeslice we have given up and add that as its "bonus" when it runs next. That would keep the dynamics of yield donation/reclaim local to the (physical) cpu and IMHO is less complex than dealing with directed yield between tasks located across different physical cpus. That would also address the fairness issue with yield you are pointing at?
Basically with directed yield, we need to deal with these issues:
- Timeslice inflation of target (lock-holder) vcpu affecting fair-time of other guests vcpus.
- Intra-VM fairness - different vcpus could get different fair-time, depending on how much of a lock-holder/spinner a vcpu is
By simply educating yield to reclaim its lost share, I feel we can avoid these complexities and get most of the benefit of yield-on-contention.
CCing other shceduler experts for their opinion of directed yield.
- vatsa
Re: [PATCH RFC 2/4] Add yield hypercall for KVM guests
In reply to Jeremy FitzhardingeQuoted 5 lines · Jeremy Fitzhardinge
Quoted 1 line · Srivatsa Vaddagiri
Add KVM hypercall for yielding vcpu timeslice.
Can you do a directed yield?
A problem with directed yield is figuring out who to yield to. One idea is to look for a random vcpu that is not running and donate some runtime to it. In the best case, it's the lock holder and we cause it to start running. Middle case it's not the lock holder, but we lose enough runtime to stop running, so at least we don't waste cpu. Worst case we continue running not having woken the lock holder. Spin again, yield again hoping to find the right vcpu.
Signature · 1 line
error compiling committee.c: too many arguments to function
Re: [PATCH RFC 2/4] Add yield hypercall for KVM guests
Quoted 7 lines · Avi Kivity
Quoted 5 lines · Jeremy Fitzhardinge
Quoted 1 line · Srivatsa Vaddagiri
Add KVM hypercall for yielding vcpu timeslice.
Can you do a directed yield?
Quoted 7 lines
A problem with directed yield is figuring out who to yield to. One idea is to look for a random vcpu that is not running and donate some runtime to it. In the best case, it's the lock holder and we cause it to start running. Middle case it's not the lock holder, but we lose enough runtime to stop running, so at least we don't waste cpu. Worst case we continue running not having woken the lock holder. Spin again, yield again hoping to find the right vcpu.
It's been quite some time, but played with directed yielding for Xen[1] and we were looking to model the POWER directed yield (H_CONFER) where the lock holding vcpu was indiciated in the spinlock. When acquiring the lock, record the vcpu id. When another vcpu attempts to acquire the lock if it can't it can yield its time to the lock holder.
1. http://lists.xensource.com/archives/html/xen-devel/2005-05/msg00776.html
Signature · 4 lines
Ryan Harper Software Engineer; Linux Technology Center IBM Corp., Austin, Tx [email protected]
Re: [PATCH RFC 2/4] Add yield hypercall for KVM guests
Quoted 8 lines · Ryan Harper
Quoted 8 lines
A problem with directed yield is figuring out who to yield to. One idea is to look for a random vcpu that is not running and donate some runtime to it. In the best case, it's the lock holder and we cause it to start running. Middle case it's not the lock holder, but we lose enough runtime to stop running, so at least we don't waste cpu. Worst case we continue running not having woken the lock holder. Spin again, yield again hoping to find the right vcpu.
Quoted 5 lines
It's been quite some time, but played with directed yielding for Xen[1] and we were looking to model the POWER directed yield (
H_CONFER) where the lock holding vcpu was indiciated in the spinlock. When acquiring the lock, record the vcpu id. When another vcpu attempts to acquire the lock if it can't it can yield its time to the lock holder.
No reason why we can't have something similar.
We can take the lock and set the owner atomically:
LOCK_PREFIX "cmpxchg %1, %0"
: "=m"(lock) : "r"(raw_smp_processor_id() | SPIN_LOCK_BIAS),
"a"((u16)0) : "memory"
Signature · 1 line
error compiling committee.c: too many arguments to function
Re: [PATCH RFC 2/4] Add yield hypercall for KVM guests
In reply to Avi KivityQuoted 8 lines · Avi Kivity
Quoted 5 lines · Jeremy Fitzhardinge
Quoted 1 line · Srivatsa Vaddagiri
Add KVM hypercall for yielding vcpu timeslice.
Can you do a directed yield?
A problem with directed yield is figuring out who to yield to. One idea is to look for a random vcpu that is not running and donate some runtime to it. In the best case, it's the lock holder and we cause it to start running. Middle case it's not the lock holder, but we lose enough runtime to stop running, so at least we don't waste cpu. Worst case we continue running not having woken the lock holder. Spin again, yield again hoping to find the right vcpu.
That can help with lockholder preemption, but on unlock you need to wake up exactly the right vcpu - the next in the ticket queue - in order to avoid burning masses of cpu. If each cpu records what lock it is spinning on and what its ticket is in a percpu variable, then the unlocker can search for the next person to kick.
J
RFC PATCH 3/4 Paravirtualized spinlock implementation for KVM guests
In reply to Srivatsa VaddagiriParavirtual spinlock implementation for KVM guests, based heavily on Xen guest's spinlock implementation.
--- arch/x86/Kconfig | 8 + arch/x86/kernel/head64.c | 3 arch/x86/kernel/kvm.c | 293 +++++++++++++++++++++++++++++++++++++++++++++++ include/linux/kvm_para.h | 8 + 4 files changed, 312 insertions(+)
arch/x86/Kconfig +8 -0
@@ -551,6 +551,14 @@ config KVM_GUEST This option enables various optimizations for running under the KVM hypervisor. +config KVM_DEBUG_FS + bool "Enable debug information to be collected for KVM guests" + default n + depends on KVM_GUEST && EXPERIMENTAL + ---help--- + This option will collect various debug information to be collected + and displayed in debugfs of guest kernel. + source "arch/x86/lguest/Kconfig" config PARAVIRT
arch/x86/kernel/head64.c +3 -0
@@ -12,6 +12,7 @@#include <linux/percpu.h> #include <linux/start_kernel.h> #include <linux/io.h> +#include <linux/kvm_para.h> #include <asm/processor.h> #include <asm/proto.h>
@@ -113,6 +114,8 @@ void __init x86_64_start_reservations(chreserve_ebda_region (); +kvm_guest_early_init (); +/* * At this point everything still needed from the boot loader * or BIOS or kernel text should be early reserved or marked not
arch/x86/kernel/kvm.c +293 -0
302 lines not on this page · raw message
include/linux/kvm_para.h +8 -0
@@ -27,8 +27,16 @@#ifdef __KERNEL__#ifdef CONFIG_KVM_GUEST void __init kvm_guest_init (void ); + +#ifdef CONFIG_PARAVIRT_SPINLOCKS +void __init kvm_guest_early_init (void ); +#else +#define kvm_guest_early_init () do { } while (0) +#endif +#else #define kvm_guest_init () do { } while (0) +#define kvm_guest_early_init () do { } while (0)#endif static inline int kvm_para_has_feature (unsigned int feature)
Re: [PATCH RFC 3/4] Paravirtualized spinlock implementation for KVM guests
Quoted 11 lines · Srivatsa Vaddagiri
Paravirtual spinlock implementation for KVM guests, based heavily on Xen guest's spinlock implementation.
arch/x86/kernel/kvm.c +7
-0+ +static struct spinlock_stats +{ + u64 taken; + u32 taken_slow; + + u64 released;
arch/x86/kernel/kvm.c void __init kvm_guest_init(void) · line 263
Quoted 10 lines
arch/x86/kernel/kvm.c +10
-0+ +#define HISTO_BUCKETS 30 +u32 histo_spin_total[HISTO_BUCKETS +1 ]; +u32 histo_spin_spinning[HISTO_BUCKETS +1 ]; +u32 histo_spin_blocked[HISTO_BUCKETS +1 ]; + +u64 time_total; +u64 time_spinning; +u64 time_blocked; +} spinlock_stats;
Could these be replaced by tracepoints when starting to spin/stopping spinning etc? Then userspace can reconstruct the histogram as well as see which locks are involved and what call paths.
Quoted 54 lines
arch/x86/kernel/kvm.c +54
-0+struct kvm_spinlock { +unsigned char lock;/* 0 -> free; 1 -> locked */ +unsigned short spinners;/* count of waiting cpus */ +}; + +/* +* Mark a cpu as interested in a lock. Returns the CPU's previous +* lock of interest, in case we got preempted by an interrupt. +*/ +static inline void spinning_lock (struct kvm_spinlock *pl) +{ + asm(LOCK_PREFIX " incw %0" + :"+m" (pl->spinners) : :"memory" ); +} + +/* +* Mark a cpu as no longer interested in a lock. Restores previous +* lock of interest (NULL for none). +*/ +static inline void unspinning_lock (struct kvm_spinlock *pl) +{ + asm(LOCK_PREFIX " decw %0" + :"+m" (pl->spinners) : :"memory" ); +} + +static int kvm_spin_is_locked (struct arch_spinlock *lock) +{ +struct kvm_spinlock *sl = (struct kvm_spinlock *)lock; + +return sl->lock !=0 ; +} + +static int kvm_spin_is_contended (struct arch_spinlock *lock) +{ +struct kvm_spinlock *sl = (struct kvm_spinlock *)lock; + +/* Not strictly true; this is only the count of contended +lock-takers entering the slow path. */ +return sl->spinners !=0 ; +} + +static int kvm_spin_trylock (struct arch_spinlock *lock) +{ +struct kvm_spinlock *sl = (struct kvm_spinlock *)lock; +u8 old =1 ; + + asm("xchgb %b0,%1" + :"+q" (old),"+m" (sl->lock) : :"memory" ); + +return old ==0 ; +} + +static noinline int kvm_spin_lock_slow(struct arch_spinlock *lock) +{
arch/x86/kernel/kvm.c void __init kvm_guest_init(void) · line 453
Quoted 10 lines
arch/x86/kernel/kvm.c +10
-0+struct kvm_spinlock *sl = (struct kvm_spinlock *)lock; +u64 start; + +ADD_STATS (taken_slow,1 ); + +/* announce we're spinning */ +spinning_lock (sl); + + start =spin_time_start (); +kvm_hypercall0 (KVM_HC_YIELD );
Oh. This isn't really a yield since we expect to be woken up? It's more of a sleep.
We already have a sleep hypercall, it's called HLT. If we can use it, the thing can work on older hosts. It's tricky though:
- if interrupts were enabled before we started spinning, sleep with interrupts enabled. This also allows the spinner to switch to another process if some completion comes along so it's a good idea anyway. Wake up sends an IPI.
- if not, we need to use NMI to wake up. This is somewhat icky since there's no atomic "enable NMI and sleep" instruction, so we have to handle the case of the wake up arriving before HLT (can be done by examining RIP and seeing if it's in the critical section).
Signature · 1 line
error compiling committee.c: too many arguments to function
Re: [PATCH RFC 3/4] Paravirtualized spinlock implementation for KVM guests
Quoted 16 lines · Avi Kivity
Quoted 15 lines · Srivatsa Vaddagiri
Paravirtual spinlock implementation for KVM guests, based heavily on Xen guest's spinlock implementation.
arch/x86/kernel/kvm.c +11
-0+ +static struct spinlock_stats +{ + u64 taken; + u32 taken_slow; + + u64 released; + +#define HISTO_BUCKETS 30 + u32 histo_spin_total[HISTO_BUCKETS+1]; + u32 histo_spin_spinning[HISTO_BUCKETS+1];
Quoted 8 lines
arch/x86/kernel/kvm.c void __init kvm_guest_init(void) · line 263
Quoted 6 lines
arch/x86/kernel/kvm.c +6
-0+u32 histo_spin_blocked[HISTO_BUCKETS +1 ]; + +u64 time_total; +u64 time_spinning; +u64 time_blocked; +} spinlock_stats;Could these be replaced by tracepoints when starting to spin/stopping spinning etc? Then userspace can reconstruct the histogram as well as see which locks are involved and what call paths.
Unfortunately not; the tracing code uses spinlocks.
(TBH I haven't actually tried, but I did give the code an eyeball to this end.)
J
Re: [PATCH RFC 3/4] Paravirtualized spinlock implementation for KVM guests
Quoted 26 lines · Jeremy Fitzhardinge
Quoted 16 lines · Avi Kivity
Quoted 15 lines · Srivatsa Vaddagiri
Paravirtual spinlock implementation for KVM guests, based heavily on Xen guest's spinlock implementation.
arch/x86/kernel/kvm.c +11
-0+ +static struct spinlock_stats +{ + u64 taken; + u32 taken_slow; + + u64 released; + +#define HISTO_BUCKETS 30 + u32 histo_spin_total[HISTO_BUCKETS+1]; + u32 histo_spin_spinning[HISTO_BUCKETS+1];Quoted 8 lines
arch/x86/kernel/kvm.c void __init kvm_guest_init(void) · line 263
Quoted 6 lines
arch/x86/kernel/kvm.c +6
-0+u32 histo_spin_blocked[HISTO_BUCKETS +1 ]; + +u64 time_total; +u64 time_spinning; +u64 time_blocked; +} spinlock_stats;Could these be replaced by tracepoints when starting to spin/stopping spinning etc? Then userspace can reconstruct the histogram as well as see which locks are involved and what call paths.
Quoted 3 lines
Unfortunately not; the tracing code uses spinlocks.
(TBH I haven't actually tried, but I did give the code an eyeball to this end.)
Hm. The tracing code already uses a specialized lock (arch_spinlock_t), perhaps we can make this lock avoid the tracing?
It's really sad, btw, there's all those nice lockless ring buffers and then a spinlock for ftrace_vbprintk(), instead of a per-cpu buffer.
Signature · 2 lines
I have a truly marvellous patch that fixes the bug which this signature is too narrow to contain.
Re: [PATCH RFC 3/4] Paravirtualized spinlock implementation for KVM guests
Quoted 27 lines · Avi Kivity
Quoted 26 lines · Jeremy Fitzhardinge
Quoted 24 lines · Avi Kivity
Quoted 11 lines · Srivatsa Vaddagiri
Paravirtual spinlock implementation for KVM guests, based heavily on Xen guest's spinlock implementation.
arch/x86/kernel/kvm.c +7
-0+ +static struct spinlock_stats +{ + u64 taken; + u32 taken_slow; + + u64 released;arch/x86/kernel/kvm.c void __init kvm_guest_init(void) · line 263
Quoted 10 lines
arch/x86/kernel/kvm.c +10
-0+ +#define HISTO_BUCKETS 30 +u32 histo_spin_total[HISTO_BUCKETS +1 ]; +u32 histo_spin_spinning[HISTO_BUCKETS +1 ]; +u32 histo_spin_blocked[HISTO_BUCKETS +1 ]; + +u64 time_total; +u64 time_spinning; +u64 time_blocked; +} spinlock_stats;Could these be replaced by tracepoints when starting to spin/stopping spinning etc? Then userspace can reconstruct the histogram as well as see which locks are involved and what call paths.
Quoted 5 lines
Quoted 3 lines
Unfortunately not; the tracing code uses spinlocks.
(TBH I haven't actually tried, but I did give the code an eyeball to this end.)
Hm. The tracing code already uses a specialized lock (
arch_spinlock_t), perhaps we can make this lock avoid the tracing?
That's not really a specialized lock; that's just the naked architecture-provided spinlock implementation, without all the lockdep, etc, etc stuff layered on top. All these changes are at a lower level, so giving tracing its own type of spinlock amounts to making the architectures provide two complete spinlock implementations. We could make tracing use, for example, an rwlock so long as we promise not to put tracing in the rwlock implementation - but that's hardly elegant.
Quoted 1 line
It's really sad, btw, there's all those nice lockless ring buffers and then a spinlock for
ftrace_vbprintk(), instead of a per-cpu buffer.
Sad indeed.
J
Re: [PATCH RFC 3/4] Paravirtualized spinlock implementation for KVM guests
In reply to Srivatsa Vaddagiriarch/x86/kernel/kvm.c void __init kvm_guest_init(void) · line 516
Quoted 12 lines · Srivatsa Vaddagiri
Paravirtual spinlock implementation for KVM guests, based heavily on Xen guest's spinlock implementation.
arch/x86/kernel/kvm.c +9
-0+static void kvm_spin_unlock (struct arch_spinlock *lock) +{ +struct kvm_spinlock *sl = (struct kvm_spinlock *)lock; + +ADD_STATS (released,1 ); + +smp_wmb ();/* make sure no writes get moved after unlock */ + sl->lock =0 ;/* release lock */ +}
Wait, no wakeup?
So it is a yield, not a sleep. I'm worried it could seriously impact fairness when one non-contending guest (or non-pv) is overcommitted together with a spin-yield guest.
Signature · 1 line
error compiling committee.c: too many arguments to function
RFC PATCH 4/4 Add yield hypercall support in Qemu
In reply to Srivatsa VaddagiriAdd yield hypercall support in Qemu.
--- kvm/include/linux/kvm.h | 1 + kvm/include/x86/asm/kvm_para.h | 1 + target-i386/kvm.c | 3 +++ 3 files changed, 5 insertions(+)
kvm/include/linux/kvm.h +1 -0
@@ -499,6 +499,7 @@ struct kvm_ioeventfd {#define KVM_CAP_PPC_SEGSTATE 43#define KVM_CAP_PCI_SEGMENT 47 +#define KVM_CAP_YIELD_HYPERCALL 55#ifdef KVM_CAP_IRQ_ROUTING
kvm/include/x86/asm/kvm_para.h +1 -0
@@ -15,6 +15,7 @@#define KVM_FEATURE_CLOCKSOURCE 0#define KVM_FEATURE_NOP_IO_DELAY 1#define KVM_FEATURE_MMU_OP 2 +#define KVM_FEATURE_YIELD 4#define MSR_KVM_WALL_CLOCK 0x11#define MSR_KVM_SYSTEM_TIME 0x12
target-i386/kvm.c +3 -0
@@ -147,6 +147,9 @@ struct kvm_para_features { #ifdef KVM_CAP_PV_MMU { KVM_CAP_PV_MMU, KVM_FEATURE_MMU_OP }, #endif +#ifdef KVM_CAP_YIELD_HYPERCALL + { KVM_CAP_YIELD_HYPERCALL, KVM_FEATURE_YIELD }, +#endif { -1, -1 } };
Quoted 2 lines · Srivatsa Vaddagiri
This patch-series implements paravirt-spinlock implementation for KVM guests, based heavily on Xen's implementation.
Excellent! I think this problem has been ignored for too long.
Quoted 14 lines
I tried to refactor Xen's spinlock
implementation to make it common for both Xen and KVM - but found that few differences between Xen and KVM (Xen has the ability to block on a particular event/irq for example) _and_ the fact that the guest kernel can be compiled to support both Xen and KVM hypervisors (CONFIG_XENandCONFIG_KVM_GUESTcan both be turned on) makes the "common" code a eye-sore. There will have to be:if (xen) { ... } else if (kvm) { .. }
Quoted 5 lines
or possibly:
alternative(NOP, some_xen_specific_call, ....)type of code in the common implementation.
No, that doesn't look like a good approach. It suggests the apparently commonality isn't really there.
Quoted 2 lines
For the time-being, I have made this KVM-specific only. At somepoint in future, I hope this can be made common between Xen/KVM.
Did you see the patch series I posted a couple of weeks ago to revamp pv spinlocks? Specifically, I dropped the notion of pv spinlocks in which the entire spinlock implementation is replaced, and added pv ticketlocks where the ticketlock algorithm is always used for the fastpath, but it calls out to pvop calls for the slowpath (a long spin, or unlocking a lock with waiters). It significantly reduces the amount of hypervisor-specific code.
You can see the current patches in
git://git.kernel.org/pub/scm/linux/kernel/git/jeremy/xen.git
xen/pvticketlock-git
Quoted 5 lines
More background and results for this patch below:
What is the Problem being solved?
=================================
Quoted 13 lines
Guest operating system can be preempted by hypervisor at any arbitrary point. There is no mechanism (that I know of) where guest OS can disable preemption for certain periods of time. One noticeable effect of this is with regard to locking. Lets say one virtual-cpu of a guest (VCPUA) grabs a spinlock and before it could relinquish the lock is preempted by hypervisor. The time-of-preemption (when the virtual cpu is off the cpu) can be quite large. In that period, if another of guest OS's virtual cpu (VCPUB) tries grabbing the same lock, it could end up spin-waiting a _long_ time, burning cycles unnecessarily. To add to the woes, VCPUB may actually be waiting for VCPUA to yield before it can run on the same (physical) cpu. This is termed as the "lock-holder preemption" (LHP) problem. The effect of it can be quite serious. For ex:
http://lkml.org/lkml/2010/4/11/108 reported 80% performance degradation because of an issue attributed to LHP problem.
That's not actually the real problem. It's *a* problem, but insignificant compared to the ticketlock-specific "next-in-line vcpu scheduler bunfight" problem - lock holder preemption is a misnomer. Fortunately the solutions to both are (nearly) the same.
See Thomas Friebel's talk "Prevent Guests from Spinning Around (http://www.xen.org/files/xensummitboston08/LHP.pdf).
Quoted 11 lines
Solutions
=========There are several solutions to this problem.
a. Realize that a lock-holder could have been preempted, and avoid spin-waiting
too long. Instead, yield cycles (to the lock-holder perhaps). This is a common solution adopted by most paravirtualized-guests (Xen, s390, powerpc).b. Avoid preempting a lock-holder while its holding a (spin-) lock.
Quoted 9 lines
In this scheme, guest OS can hint (set some flag in memory shared with hypervisor) whenever its holding a lock and hypervisor could defer preempting the guest vcpu when its holding a lock. With this scheme, we should never have a lock-acquiring vcpu spin on a preempted vcpu to release its lock. If ever it spins, its because somebody *currently running* is holding the lock - and hence it won't have to spin-wait too long. IOW we are pro-actively trying to prevent the LHP problem from occuring in the first place. This should improve job turnaround time for some workloads. [1] has some results based on this approach.
This doesn't actually help the problem mentioned above, because it's not a problem with the lock holder getting preempted, but what happens once the lock has been released.
Quoted 30 lines
c. Share run-status of vcpu with guests. This could be used to optimize
routines likemutex_spin_on_owner().Hypervisor could share run-status of vcpus in guest kernel memory. This would allow us to optimize routines like
mutex_spin_on_owner()- we don't spin-wait if we relaize that the target vcpu has been preempted.a) and c) are about dealing with the LHP problem, while b) is about preventing the problem from happening.
Scenario A:
W/o patch W/ Patch Difference Avg (std-dev) Avg. (std-dev)1: 273.270 (1.051) 251.613 (1.155) 7.9% 2: 541.343 (57.317) 443.400 (2.832) 18.1% 3: 819.160 (9.218) 642.393 (2.646) 21.6%4: 1020.493 (34.743) 839.327 (0.658) 17.8%
Scenario B:
1: 276.947 (0.644) 248.397 (1.563) 10.3%
2: 500.723 (5.694) 438.957 (6.112) 12.33%
3: 725.687 (5.267) 641.317 (3.902) 11.62%
4: 973.910 (21.712) 836.853 (2.754) 14.07%Scenario C:
Quoted 7 lines
1: 564.610 (12.055) 420.510 (2.598) 25.52% 2: 750.867 (5.139) 618.570 (2.914) 17.61% 3: 950.150 (13.496) 813.803 (1.872) 14.35%4: 1125.027 (5.337) 1007.63 (5.707) 10.43%
IMO this is good improvement with the patchset applied.
Those are consistent with the results I get too.
J
Quoted 26 lines · Jeremy Fitzhardinge
Quoted 14 lines
I tried to refactor Xen's spinlock
implementation to make it common for both Xen and KVM - but found that few differences between Xen and KVM (Xen has the ability to block on a particular event/irq for example) _and_ the fact that the guest kernel can be compiled to support both Xen and KVM hypervisors (CONFIG_XENandCONFIG_KVM_GUESTcan both be turned on) makes the "common" code a eye-sore. There will have to be:if (xen) { ... } else if (kvm) { .. }Quoted 5 lines
or possibly:
alternative(NOP, some_xen_specific_call, ....)type of code in the common implementation.
No, that doesn't look like a good approach. It suggests the apparently commonality isn't really there.
Quoted 2 lines
For the time-being, I have made this KVM-specific only. At somepoint in future, I hope this can be made common between Xen/KVM.
Quoted 7 lines
Did you see the patch series I posted a couple of weeks ago to revamp pv spinlocks? Specifically, I dropped the notion of pv spinlocks in which the entire spinlock implementation is replaced, and added pv ticketlocks where the ticketlock algorithm is always used for the fastpath, but it calls out to pvop calls for the slowpath (a long spin, or unlocking a lock with waiters). It significantly reduces the amount of hypervisor-specific code.
Hmmm interesting - I will go thr' it in detail.
Quoted 4 lines
You can see the current patches in
git://git.kernel.org/pub/scm/linux/kernel/git/jeremy/xen.git
xen/pvticketlock-git
[snip]
Quoted 7 lines
That's not actually the real problem. It's *a* problem, but insignificant compared to the ticketlock-specific "next-in-line vcpu scheduler bunfight" problem - lock holder preemption is a misnomer. Fortunately the solutions to both are (nearly) the same.
See Thomas Friebel's talk "Prevent Guests from Spinning Around
(http://www.xen.org/files/xensummitboston08/LHP.pdf).
Yes I had seen Thomas's slides reporting huge degradation in performance with tick spinlock.
Quoted 12 lines
Quoted 11 lines
b. Avoid preempting a lock-holder while its holding a (spin-) lock.
In this scheme, guest OS can hint (set some flag in memory shared with hypervisor) whenever its holding a lock and hypervisor could defer preempting the guest vcpu when its holding a lock. With this scheme, we should never have a lock-acquiring vcpu spin on a preempted vcpu to release its lock. If ever it spins, its because somebody *currently running* is holding the lock - and hence it won't have to spin-wait too long. IOW we are pro-actively trying to prevent the LHP problem from occuring in the first place. This should improve job turnaround time for some workloads. [1] has some results based on this approach.
Quoted 3 lines
This doesn't actually help the problem mentioned above, because it's not a problem with the lock holder getting preempted, but what happens once the lock has been released.
Good point. I agree that the latter problem needs more attention, given a ticket-type implementation of spinlocks. Have you considered possible solutions for unmodified guests, which have similar ticket-type lock implementations? Not sure if that's important enough to investigate solutions like gang scheduling ..
- vatsa
Quoted 15 lines · Srivatsa Vaddagiri
This patch-series implements paravirt-spinlock implementation for KVM guests, based heavily on Xen's implementation. I tried to refactor Xen's spinlock implementation to make it common for both Xen and KVM - but found that few differences between Xen and KVM (Xen has the ability to block on a particular event/irq for example) _and_ the fact that the guest kernel can be compiled to support both Xen and KVM hypervisors (
CONFIG_XENandCONFIG_KVM_GUESTcan both be turned on) makes the "common" code a eye-sore. There will have to be:if (xen) { ... } else if (kvm) { .. }
Quoted 3 lines
or possibly:
alternative(NOP, some_xen_specific_call, ....)
Why not utilize the pvops path?
Quoted 16 lines · Konrad Rzeszutek Wilk
Quoted 15 lines · Srivatsa Vaddagiri
This patch-series implements paravirt-spinlock implementation for KVM guests, based heavily on Xen's implementation. I tried to refactor Xen's spinlock implementation to make it common for both Xen and KVM - but found that few differences between Xen and KVM (Xen has the ability to block on a particular event/irq for example) _and_ the fact that the guest kernel can be compiled to support both Xen and KVM hypervisors (
CONFIG_XENandCONFIG_KVM_GUESTcan both be turned on) makes the "common" code a eye-sore. There will have to be:if (xen) { ... } else if (kvm) { .. }
Quoted 5 lines
Quoted 3 lines
or possibly:
alternative(NOP, some_xen_specific_call, ....)Why not utilize the pvops path?
Duh. You did use it. Sorry about the noise.
Quoted 15 lines · Srivatsa Vaddagiri
This patch-series implements paravirt-spinlock implementation for KVM guests, based heavily on Xen's implementation. I tried to refactor Xen's spinlock implementation to make it common for both Xen and KVM - but found that few differences between Xen and KVM (Xen has the ability to block on a particular event/irq for example) _and_ the fact that the guest kernel can be compiled to support both Xen and KVM hypervisors (
CONFIG_XENandCONFIG_KVM_GUESTcan both be turned on) makes the "common" code a eye-sore. There will have to be:if (xen) { ... } else if (kvm) { .. }
Quoted 5 lines
or possibly:
alternative(NOP, some_xen_specific_call, ....)type of code in the common implementation.
I do think things are pretty common. If that is the only issue, you can use a plain function vector, no?
Signature · 1 line
error compiling committee.c: too many arguments to function