KVM: s390: protect VCPU cpu timer with a seqcount
For now, only the owning VCPU thread (that has loaded the VCPU) can get a consistent cpu timer value when calculating the delta. However, other threads might also be interested in a more recent, consistent value. Of special interest will be the timer callback of a VCPU that executes without having the VCPU loaded and could run in parallel with the VCPU thread. The cpu timer has a nice property: it is only updated by the owning VCPU thread. And speaking about accounting, a consistent value can only be calculated by looking at cputm_start and the cpu timer itself in one shot, otherwise the result might be wrong. As we only have one writing thread at a time (owning VCPU thread), we can use a seqcount instead of a seqlock and retry if the VCPU refreshed its cpu timer. This avoids any heavy locking and only introduces a counter update/check plus a handful of smp_wmb(). The owning VCPU thread should never have to retry on reads, and also for other threads this might be a very rare scenario. Please note that we have to use the raw_* variants for locking the seqcount as lockdep will produce false warnings otherwise. The rq->lock held during vcpu_load/put is also acquired from hardirq context. Lockdep cannot know that we avoid potential deadlocks by disabling preemption and thereby disable concurrent write locking attempts (via vcpu_put/load). Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com> Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
This commit is contained in:

committed by
Christian Borntraeger

parent
db0758b297
commit
9c23a1318e
@@ -20,6 +20,7 @@
|
||||
#include <linux/kvm_types.h>
|
||||
#include <linux/kvm_host.h>
|
||||
#include <linux/kvm.h>
|
||||
#include <linux/seqlock.h>
|
||||
#include <asm/debug.h>
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/fpu/api.h>
|
||||
@@ -553,6 +554,13 @@ struct kvm_vcpu_arch {
|
||||
unsigned long pfault_select;
|
||||
unsigned long pfault_compare;
|
||||
bool cputm_enabled;
|
||||
/*
|
||||
* The seqcount protects updates to cputm_start and sie_block.cputm,
|
||||
* this way we can have non-blocking reads with consistent values.
|
||||
* Only the owning VCPU thread (vcpu->cpu) is allowed to change these
|
||||
* values and to start/stop/enable/disable cpu timer accounting.
|
||||
*/
|
||||
seqcount_t cputm_seqcount;
|
||||
__u64 cputm_start;
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user