History

KVM: arm64: Support stolen time reporting via shared structure

Implement the service call for configuring a shared structure between a VCPU and the hypervisor in which the hypervisor can write the time stolen from the VCPU's execution time by other tasks on the host. User space allocates memory which is placed at an IPA also chosen by user space. The hypervisor then updates the shared structure using kvm_put_guest() to ensure single copy atomicity of the 64-bit value reporting the stolen time in nanoseconds. Whenever stolen time is enabled by the guest, the stolen time counter is reset. The stolen time itself is retrieved from the sched_info structure maintained by the Linux scheduler code. We enable SCHEDSTATS when selecting KVM Kconfig to ensure this value is meaningful.

Steven Price committed 7 years ago

Commit 8564d631 parent cac0f1b7 files · +111 −0Browse files

Unified · Split

7 files
  1. arch/arm/include/asm/kvm_host.h +19 −0
  2. arch/arm64/include/asm/kvm_host.h +20 −0
  3. arch/arm64/kvm/Kconfig +1 −0
  4. include/linux/kvm_types.h +2 −0
  5. virt/kvm/arm/arm.c +11 −0
  6. virt/kvm/arm/hypercalls.c +6 −0
  7. virt/kvm/arm/pvtime.c +52 −0
arch/arm/include/asm/kvm_host.h+19−0
@@ -39,6 +39,7 @@ · 38 unmodified lines
39 KVM_ARCH_REQ_FLAGS(0, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)39 KVM_ARCH_REQ_FLAGS(0, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)
40#define KVM_REQ_IRQ_PENDING KVM_ARCH_REQ(1)40#define KVM_REQ_IRQ_PENDING KVM_ARCH_REQ(1)
41#define KVM_REQ_VCPU_RESET KVM_ARCH_REQ(2)41#define KVM_REQ_VCPU_RESET KVM_ARCH_REQ(2)
42#define KVM_REQ_RECORD_STEAL KVM_ARCH_REQ(3)
42 43
43DECLARE_STATIC_KEY_FALSE(userspace_irqchip_in_use);44DECLARE_STATIC_KEY_FALSE(userspace_irqchip_in_use);
44 45
@@ -329,6 +330,24 @@ static inline long kvm_hypercall_pv_features(struct kvm_vcpu *vcpu) · 284 unmodified lines
329 return SMCCC_RET_NOT_SUPPORTED;330 return SMCCC_RET_NOT_SUPPORTED;
330}331}
331 332
333static inline gpa_t kvm_init_stolen_time(struct kvm_vcpu *vcpu)
334{
335 return GPA_INVALID;
336}
337
338static inline void kvm_update_stolen_time(struct kvm_vcpu *vcpu)
339{
340}
341
342static inline void kvm_arm_pvtime_vcpu_init(struct kvm_vcpu_arch *vcpu_arch)
343{
344}
345
346static inline bool kvm_arm_is_pvtime_enabled(struct kvm_vcpu_arch *vcpu_arch)
347{
348 return false;
349}
350
332void kvm_mmu_wp_memory_region(struct kvm *kvm, int slot);351void kvm_mmu_wp_memory_region(struct kvm *kvm, int slot);
333 352
334struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr);353struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr);
arch/arm64/include/asm/kvm_host.h+20−0
@@ -44,6 +44,7 @@ · 43 unmodified lines
44 KVM_ARCH_REQ_FLAGS(0, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)44 KVM_ARCH_REQ_FLAGS(0, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)
45#define KVM_REQ_IRQ_PENDING KVM_ARCH_REQ(1)45#define KVM_REQ_IRQ_PENDING KVM_ARCH_REQ(1)
46#define KVM_REQ_VCPU_RESET KVM_ARCH_REQ(2)46#define KVM_REQ_VCPU_RESET KVM_ARCH_REQ(2)
47#define KVM_REQ_RECORD_STEAL KVM_ARCH_REQ(3)
47 48
48DECLARE_STATIC_KEY_FALSE(userspace_irqchip_in_use);49DECLARE_STATIC_KEY_FALSE(userspace_irqchip_in_use);
49 50
@@ -338,6 +339,13 @@ struct kvm_vcpu_arch { · 288 unmodified lines
338 /* True when deferrable sysregs are loaded on the physical CPU,339 /* True when deferrable sysregs are loaded on the physical CPU,
339 * see kvm_vcpu_load_sysregs and kvm_vcpu_put_sysregs. */340 * see kvm_vcpu_load_sysregs and kvm_vcpu_put_sysregs. */
340 bool sysregs_loaded_on_cpu;341 bool sysregs_loaded_on_cpu;
342
343 /* Guest PV state */
344 struct {
345 u64 steal;
346 u64 last_steal;
347 gpa_t base;
348 } steal;
341};349};
342 350
343/* Pointer to the vcpu's SVE FFR for sve_{save,load}_state() */351/* Pointer to the vcpu's SVE FFR for sve_{save,load}_state() */
@@ -479,6 +487,18 @@ int kvm_perf_init(void); · 135 unmodified lines
479int kvm_perf_teardown(void);487int kvm_perf_teardown(void);
480 488
481long kvm_hypercall_pv_features(struct kvm_vcpu *vcpu);489long kvm_hypercall_pv_features(struct kvm_vcpu *vcpu);
490gpa_t kvm_init_stolen_time(struct kvm_vcpu *vcpu);
491void kvm_update_stolen_time(struct kvm_vcpu *vcpu);
492
493static inline void kvm_arm_pvtime_vcpu_init(struct kvm_vcpu_arch *vcpu_arch)
494{
495 vcpu_arch->steal.base = GPA_INVALID;
496}
497
498static inline bool kvm_arm_is_pvtime_enabled(struct kvm_vcpu_arch *vcpu_arch)
499{
500 return (vcpu_arch->steal.base != GPA_INVALID);
501}
482 502
483void kvm_set_sei_esr(struct kvm_vcpu *vcpu, u64 syndrome);503void kvm_set_sei_esr(struct kvm_vcpu *vcpu, u64 syndrome);
484 504
arch/arm64/kvm/Kconfig+1−0
@@ -39,6 +39,7 @@ config KVM · 38 unmodified lines
39 select IRQ_BYPASS_MANAGER39 select IRQ_BYPASS_MANAGER
40 select HAVE_KVM_IRQ_BYPASS40 select HAVE_KVM_IRQ_BYPASS
41 select HAVE_KVM_VCPU_RUN_PID_CHANGE41 select HAVE_KVM_VCPU_RUN_PID_CHANGE
42 select SCHEDSTATS
42 ---help---43 ---help---
43 Support hosting virtualized guest machines.44 Support hosting virtualized guest machines.
44 We don't support KVM with 16K page tables yet, due to the multiple45 We don't support KVM with 16K page tables yet, due to the multiple
include/linux/kvm_types.h+2−0
@@ -35,6 +35,8 @@ typedef unsigned long gva_t; · 34 unmodified lines
35typedef u64 gpa_t;35typedef u64 gpa_t;
36typedef u64 gfn_t;36typedef u64 gfn_t;
37 37
38#define GPA_INVALID (~(gpa_t)0)
39
38typedef unsigned long hva_t;40typedef unsigned long hva_t;
39typedef u64 hpa_t;41typedef u64 hpa_t;
40typedef u64 hfn_t;42typedef u64 hfn_t;
virt/kvm/arm/arm.c+11−0
@@ -40,6 +40,10 @@ · 39 unmodified lines
40#include <asm/kvm_coproc.h>40#include <asm/kvm_coproc.h>
41#include <asm/sections.h>41#include <asm/sections.h>
42 42
43#include <kvm/arm_hypercalls.h>
44#include <kvm/arm_pmu.h>
45#include <kvm/arm_psci.h>
46
43#ifdef REQUIRES_VIRT47#ifdef REQUIRES_VIRT
44__asm__(".arch_extension virt");48__asm__(".arch_extension virt");
45#endif49#endif
@@ -351,6 +355,8 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) · 305 unmodified lines
351 355
352 kvm_arm_reset_debug_ptr(vcpu);356 kvm_arm_reset_debug_ptr(vcpu);
353 357
358 kvm_arm_pvtime_vcpu_init(&vcpu->arch);
359
354 return kvm_vgic_vcpu_init(vcpu);360 return kvm_vgic_vcpu_init(vcpu);
355}361}
356 362
@@ -380,6 +386,8 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) · 23 unmodified lines
380 kvm_vcpu_load_sysregs(vcpu);386 kvm_vcpu_load_sysregs(vcpu);
381 kvm_arch_vcpu_load_fp(vcpu);387 kvm_arch_vcpu_load_fp(vcpu);
382 kvm_vcpu_pmu_restore_guest(vcpu);388 kvm_vcpu_pmu_restore_guest(vcpu);
389 if (kvm_arm_is_pvtime_enabled(&vcpu->arch))
390 kvm_make_request(KVM_REQ_RECORD_STEAL, vcpu);
383 391
384 if (single_task_running())392 if (single_task_running())
385 vcpu_clear_wfe_traps(vcpu);393 vcpu_clear_wfe_traps(vcpu);
@@ -645,6 +653,9 @@ static void check_vcpu_requests(struct kvm_vcpu *vcpu) · 259 unmodified lines
645 * that a VCPU sees new virtual interrupts.653 * that a VCPU sees new virtual interrupts.
646 */654 */
647 kvm_check_request(KVM_REQ_IRQ_PENDING, vcpu);655 kvm_check_request(KVM_REQ_IRQ_PENDING, vcpu);
656
657 if (kvm_check_request(KVM_REQ_RECORD_STEAL, vcpu))
658 kvm_update_stolen_time(vcpu);
648 }659 }
649}660}
650 661
virt/kvm/arm/hypercalls.c+6−0
@@ -14,6 +14,7 @@ int kvm_hvc_call_handler(struct kvm_vcpu *vcpu) · 13 unmodified lines
14 u32 func_id = smccc_get_function(vcpu);14 u32 func_id = smccc_get_function(vcpu);
15 long val = SMCCC_RET_NOT_SUPPORTED;15 long val = SMCCC_RET_NOT_SUPPORTED;
16 u32 feature;16 u32 feature;
17 gpa_t gpa;
17 18
18 switch (func_id) {19 switch (func_id) {
19 case ARM_SMCCC_VERSION_FUNC_ID:20 case ARM_SMCCC_VERSION_FUNC_ID:
@@ -56,6 +57,11 @@ int kvm_hvc_call_handler(struct kvm_vcpu *vcpu) · 36 unmodified lines
56 case ARM_SMCCC_HV_PV_TIME_FEATURES:57 case ARM_SMCCC_HV_PV_TIME_FEATURES:
57 val = kvm_hypercall_pv_features(vcpu);58 val = kvm_hypercall_pv_features(vcpu);
58 break;59 break;
60 case ARM_SMCCC_HV_PV_TIME_ST:
61 gpa = kvm_init_stolen_time(vcpu);
62 if (gpa != GPA_INVALID)
63 val = gpa;
64 break;
59 default:65 default:
60 return kvm_psci_call(vcpu);66 return kvm_psci_call(vcpu);
61 }67 }
virt/kvm/arm/pvtime.c+52−0
@@ -3,8 +3,35 @@ · 2 unmodified lines
3 3
4#include <linux/arm-smccc.h>4#include <linux/arm-smccc.h>
5 5
6#include <asm/pvclock-abi.h>
7
6#include <kvm/arm_hypercalls.h>8#include <kvm/arm_hypercalls.h>
7 9
10void kvm_update_stolen_time(struct kvm_vcpu *vcpu)
11{
12 struct kvm *kvm = vcpu->kvm;
13 u64 steal;
14 __le64 steal_le;
15 u64 offset;
16 int idx;
17 u64 base = vcpu->arch.steal.base;
18
19 if (base == GPA_INVALID)
20 return;
21
22 /* Let's do the local bookkeeping */
23 steal = vcpu->arch.steal.steal;
24 steal += current->sched_info.run_delay - vcpu->arch.steal.last_steal;
25 vcpu->arch.steal.last_steal = current->sched_info.run_delay;
26 vcpu->arch.steal.steal = steal;
27
28 steal_le = cpu_to_le64(steal);
29 idx = srcu_read_lock(&kvm->srcu);
30 offset = offsetof(struct pvclock_vcpu_stolen_time, stolen_time);
31 kvm_put_guest(kvm, base + offset, steal_le, u64);
32 srcu_read_unlock(&kvm->srcu, idx);
33}
34
8long kvm_hypercall_pv_features(struct kvm_vcpu *vcpu)35long kvm_hypercall_pv_features(struct kvm_vcpu *vcpu)
9{36{
10 u32 feature = smccc_get_arg1(vcpu);37 u32 feature = smccc_get_arg1(vcpu);
@@ -12,9 +39,34 @@ long kvm_hypercall_pv_features(struct kvm_vcpu *vcpu) · 1 unmodified line
12 39
13 switch (feature) {40 switch (feature) {
14 case ARM_SMCCC_HV_PV_TIME_FEATURES:41 case ARM_SMCCC_HV_PV_TIME_FEATURES:
42 case ARM_SMCCC_HV_PV_TIME_ST:
15 val = SMCCC_RET_SUCCESS;43 val = SMCCC_RET_SUCCESS;
16 break;44 break;
17 }45 }
18 46
19 return val;47 return val;
20}48}
49
50gpa_t kvm_init_stolen_time(struct kvm_vcpu *vcpu)
51{
52 struct pvclock_vcpu_stolen_time init_values = {};
53 struct kvm *kvm = vcpu->kvm;
54 u64 base = vcpu->arch.steal.base;
55 int idx;
56
57 if (base == GPA_INVALID)
58 return base;
59
60 /*
61 * Start counting stolen time from the time the guest requests
62 * the feature enabled.
63 */
64 vcpu->arch.steal.steal = 0;
65 vcpu->arch.steal.last_steal = current->sched_info.run_delay;
66
67 idx = srcu_read_lock(&kvm->srcu);
68 kvm_write_guest(kvm, base, &init_values, sizeof(init_values));
69 srcu_read_unlock(&kvm->srcu, idx);
70
71 return base;
72}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t