aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/include/asm/virt.h5
-rw-r--r--arch/arm/kvm/arm.c3
-rw-r--r--arch/arm64/include/asm/virt.h9
-rw-r--r--arch/s390/kvm/kvm-s390.c4
-rw-r--r--arch/x86/kvm/x86.c3
-rw-r--r--include/kvm/arm_arch_timer.h1
-rw-r--r--virt/kvm/arm/arch_timer.c26
-rw-r--r--virt/kvm/arm/hyp/timer-sr.c33
-rw-r--r--virt/kvm/arm/vgic/vgic-init.c18
-rw-r--r--virt/kvm/arm/vgic/vgic-v2.c2
-rw-r--r--virt/kvm/arm/vgic/vgic-v3.c2
11 files changed, 79 insertions, 27 deletions
diff --git a/arch/arm/include/asm/virt.h b/arch/arm/include/asm/virt.h
index a2e75b84e2ae..6dae1956c74d 100644
--- a/arch/arm/include/asm/virt.h
+++ b/arch/arm/include/asm/virt.h
@@ -80,6 +80,11 @@ static inline bool is_kernel_in_hyp_mode(void)
80 return false; 80 return false;
81} 81}
82 82
83static inline bool has_vhe(void)
84{
85 return false;
86}
87
83/* The section containing the hypervisor idmap text */ 88/* The section containing the hypervisor idmap text */
84extern char __hyp_idmap_text_start[]; 89extern char __hyp_idmap_text_start[];
85extern char __hyp_idmap_text_end[]; 90extern char __hyp_idmap_text_end[];
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 11676787ad49..9d7446456e0c 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -1099,6 +1099,9 @@ static void cpu_init_hyp_mode(void *dummy)
1099 __cpu_init_hyp_mode(pgd_ptr, hyp_stack_ptr, vector_ptr); 1099 __cpu_init_hyp_mode(pgd_ptr, hyp_stack_ptr, vector_ptr);
1100 __cpu_init_stage2(); 1100 __cpu_init_stage2();
1101 1101
1102 if (is_kernel_in_hyp_mode())
1103 kvm_timer_init_vhe();
1104
1102 kvm_arm_init_debug(); 1105 kvm_arm_init_debug();
1103} 1106}
1104 1107
diff --git a/arch/arm64/include/asm/virt.h b/arch/arm64/include/asm/virt.h
index fea10736b11f..439f6b5d31f6 100644
--- a/arch/arm64/include/asm/virt.h
+++ b/arch/arm64/include/asm/virt.h
@@ -47,6 +47,7 @@
47#include <asm/ptrace.h> 47#include <asm/ptrace.h>
48#include <asm/sections.h> 48#include <asm/sections.h>
49#include <asm/sysreg.h> 49#include <asm/sysreg.h>
50#include <asm/cpufeature.h>
50 51
51/* 52/*
52 * __boot_cpu_mode records what mode CPUs were booted in. 53 * __boot_cpu_mode records what mode CPUs were booted in.
@@ -80,6 +81,14 @@ static inline bool is_kernel_in_hyp_mode(void)
80 return read_sysreg(CurrentEL) == CurrentEL_EL2; 81 return read_sysreg(CurrentEL) == CurrentEL_EL2;
81} 82}
82 83
84static inline bool has_vhe(void)
85{
86 if (cpus_have_const_cap(ARM64_HAS_VIRT_HOST_EXTN))
87 return true;
88
89 return false;
90}
91
83#ifdef CONFIG_ARM64_VHE 92#ifdef CONFIG_ARM64_VHE
84extern void verify_cpu_run_el(void); 93extern void verify_cpu_run_el(void);
85#else 94#else
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index bec71e902be3..6484a250021e 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -916,7 +916,7 @@ static int kvm_s390_get_machine(struct kvm *kvm, struct kvm_device_attr *attr)
916 memcpy(&mach->fac_mask, kvm->arch.model.fac_mask, 916 memcpy(&mach->fac_mask, kvm->arch.model.fac_mask,
917 S390_ARCH_FAC_LIST_SIZE_BYTE); 917 S390_ARCH_FAC_LIST_SIZE_BYTE);
918 memcpy((unsigned long *)&mach->fac_list, S390_lowcore.stfle_fac_list, 918 memcpy((unsigned long *)&mach->fac_list, S390_lowcore.stfle_fac_list,
919 S390_ARCH_FAC_LIST_SIZE_BYTE); 919 sizeof(S390_lowcore.stfle_fac_list));
920 if (copy_to_user((void __user *)attr->addr, mach, sizeof(*mach))) 920 if (copy_to_user((void __user *)attr->addr, mach, sizeof(*mach)))
921 ret = -EFAULT; 921 ret = -EFAULT;
922 kfree(mach); 922 kfree(mach);
@@ -1437,7 +1437,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
1437 1437
1438 /* Populate the facility mask initially. */ 1438 /* Populate the facility mask initially. */
1439 memcpy(kvm->arch.model.fac_mask, S390_lowcore.stfle_fac_list, 1439 memcpy(kvm->arch.model.fac_mask, S390_lowcore.stfle_fac_list,
1440 S390_ARCH_FAC_LIST_SIZE_BYTE); 1440 sizeof(S390_lowcore.stfle_fac_list));
1441 for (i = 0; i < S390_ARCH_FAC_LIST_SIZE_U64; i++) { 1441 for (i = 0; i < S390_ARCH_FAC_LIST_SIZE_U64; i++) {
1442 if (i < kvm_s390_fac_list_mask_size()) 1442 if (i < kvm_s390_fac_list_mask_size())
1443 kvm->arch.model.fac_mask[i] &= kvm_s390_fac_list_mask[i]; 1443 kvm->arch.model.fac_mask[i] &= kvm_s390_fac_list_mask[i];
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 57d8a856cdc5..d153be8929a6 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -6171,7 +6171,8 @@ static int emulator_fix_hypercall(struct x86_emulate_ctxt *ctxt)
6171 6171
6172 kvm_x86_ops->patch_hypercall(vcpu, instruction); 6172 kvm_x86_ops->patch_hypercall(vcpu, instruction);
6173 6173
6174 return emulator_write_emulated(ctxt, rip, instruction, 3, NULL); 6174 return emulator_write_emulated(ctxt, rip, instruction, 3,
6175 &ctxt->exception);
6175} 6176}
6176 6177
6177static int dm_request_for_irq_injection(struct kvm_vcpu *vcpu) 6178static int dm_request_for_irq_injection(struct kvm_vcpu *vcpu)
diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h
index b717ed9d2b75..5c970ce67949 100644
--- a/include/kvm/arm_arch_timer.h
+++ b/include/kvm/arm_arch_timer.h
@@ -76,4 +76,5 @@ void kvm_timer_unschedule(struct kvm_vcpu *vcpu);
76 76
77void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu); 77void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu);
78 78
79void kvm_timer_init_vhe(void);
79#endif 80#endif
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index a2dbbccbb6a3..6a084cd57b88 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -24,6 +24,7 @@
24 24
25#include <clocksource/arm_arch_timer.h> 25#include <clocksource/arm_arch_timer.h>
26#include <asm/arch_timer.h> 26#include <asm/arch_timer.h>
27#include <asm/kvm_hyp.h>
27 28
28#include <kvm/arm_vgic.h> 29#include <kvm/arm_vgic.h>
29#include <kvm/arm_arch_timer.h> 30#include <kvm/arm_arch_timer.h>
@@ -89,9 +90,6 @@ static void kvm_timer_inject_irq_work(struct work_struct *work)
89 struct kvm_vcpu *vcpu; 90 struct kvm_vcpu *vcpu;
90 91
91 vcpu = container_of(work, struct kvm_vcpu, arch.timer_cpu.expired); 92 vcpu = container_of(work, struct kvm_vcpu, arch.timer_cpu.expired);
92 vcpu->arch.timer_cpu.armed = false;
93
94 WARN_ON(!kvm_timer_should_fire(vcpu));
95 93
96 /* 94 /*
97 * If the vcpu is blocked we want to wake it up so that it will see 95 * If the vcpu is blocked we want to wake it up so that it will see
@@ -512,3 +510,25 @@ void kvm_timer_init(struct kvm *kvm)
512{ 510{
513 kvm->arch.timer.cntvoff = kvm_phys_timer_read(); 511 kvm->arch.timer.cntvoff = kvm_phys_timer_read();
514} 512}
513
514/*
515 * On VHE system, we only need to configure trap on physical timer and counter
516 * accesses in EL0 and EL1 once, not for every world switch.
517 * The host kernel runs at EL2 with HCR_EL2.TGE == 1,
518 * and this makes those bits have no effect for the host kernel execution.
519 */
520void kvm_timer_init_vhe(void)
521{
522 /* When HCR_EL2.E2H ==1, EL1PCEN and EL1PCTEN are shifted by 10 */
523 u32 cnthctl_shift = 10;
524 u64 val;
525
526 /*
527 * Disallow physical timer access for the guest.
528 * Physical counter access is allowed.
529 */
530 val = read_sysreg(cnthctl_el2);
531 val &= ~(CNTHCTL_EL1PCEN << cnthctl_shift);
532 val |= (CNTHCTL_EL1PCTEN << cnthctl_shift);
533 write_sysreg(val, cnthctl_el2);
534}
diff --git a/virt/kvm/arm/hyp/timer-sr.c b/virt/kvm/arm/hyp/timer-sr.c
index 798866a8d875..63e28dd18bb0 100644
--- a/virt/kvm/arm/hyp/timer-sr.c
+++ b/virt/kvm/arm/hyp/timer-sr.c
@@ -35,10 +35,16 @@ void __hyp_text __timer_save_state(struct kvm_vcpu *vcpu)
35 /* Disable the virtual timer */ 35 /* Disable the virtual timer */
36 write_sysreg_el0(0, cntv_ctl); 36 write_sysreg_el0(0, cntv_ctl);
37 37
38 /* Allow physical timer/counter access for the host */ 38 /*
39 val = read_sysreg(cnthctl_el2); 39 * We don't need to do this for VHE since the host kernel runs in EL2
40 val |= CNTHCTL_EL1PCTEN | CNTHCTL_EL1PCEN; 40 * with HCR_EL2.TGE ==1, which makes those bits have no impact.
41 write_sysreg(val, cnthctl_el2); 41 */
42 if (!has_vhe()) {
43 /* Allow physical timer/counter access for the host */
44 val = read_sysreg(cnthctl_el2);
45 val |= CNTHCTL_EL1PCTEN | CNTHCTL_EL1PCEN;
46 write_sysreg(val, cnthctl_el2);
47 }
42 48
43 /* Clear cntvoff for the host */ 49 /* Clear cntvoff for the host */
44 write_sysreg(0, cntvoff_el2); 50 write_sysreg(0, cntvoff_el2);
@@ -50,14 +56,17 @@ void __hyp_text __timer_restore_state(struct kvm_vcpu *vcpu)
50 struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; 56 struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
51 u64 val; 57 u64 val;
52 58
53 /* 59 /* Those bits are already configured at boot on VHE-system */
54 * Disallow physical timer access for the guest 60 if (!has_vhe()) {
55 * Physical counter access is allowed 61 /*
56 */ 62 * Disallow physical timer access for the guest
57 val = read_sysreg(cnthctl_el2); 63 * Physical counter access is allowed
58 val &= ~CNTHCTL_EL1PCEN; 64 */
59 val |= CNTHCTL_EL1PCTEN; 65 val = read_sysreg(cnthctl_el2);
60 write_sysreg(val, cnthctl_el2); 66 val &= ~CNTHCTL_EL1PCEN;
67 val |= CNTHCTL_EL1PCTEN;
68 write_sysreg(val, cnthctl_el2);
69 }
61 70
62 if (timer->enabled) { 71 if (timer->enabled) {
63 write_sysreg(kvm->arch.timer.cntvoff, cntvoff_el2); 72 write_sysreg(kvm->arch.timer.cntvoff, cntvoff_el2);
diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
index 5114391b7e5a..c737ea0a310a 100644
--- a/virt/kvm/arm/vgic/vgic-init.c
+++ b/virt/kvm/arm/vgic/vgic-init.c
@@ -268,15 +268,11 @@ static void kvm_vgic_dist_destroy(struct kvm *kvm)
268{ 268{
269 struct vgic_dist *dist = &kvm->arch.vgic; 269 struct vgic_dist *dist = &kvm->arch.vgic;
270 270
271 mutex_lock(&kvm->lock);
272
273 dist->ready = false; 271 dist->ready = false;
274 dist->initialized = false; 272 dist->initialized = false;
275 273
276 kfree(dist->spis); 274 kfree(dist->spis);
277 dist->nr_spis = 0; 275 dist->nr_spis = 0;
278
279 mutex_unlock(&kvm->lock);
280} 276}
281 277
282void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu) 278void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu)
@@ -286,7 +282,8 @@ void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu)
286 INIT_LIST_HEAD(&vgic_cpu->ap_list_head); 282 INIT_LIST_HEAD(&vgic_cpu->ap_list_head);
287} 283}
288 284
289void kvm_vgic_destroy(struct kvm *kvm) 285/* To be called with kvm->lock held */
286static void __kvm_vgic_destroy(struct kvm *kvm)
290{ 287{
291 struct kvm_vcpu *vcpu; 288 struct kvm_vcpu *vcpu;
292 int i; 289 int i;
@@ -297,6 +294,13 @@ void kvm_vgic_destroy(struct kvm *kvm)
297 kvm_vgic_vcpu_destroy(vcpu); 294 kvm_vgic_vcpu_destroy(vcpu);
298} 295}
299 296
297void kvm_vgic_destroy(struct kvm *kvm)
298{
299 mutex_lock(&kvm->lock);
300 __kvm_vgic_destroy(kvm);
301 mutex_unlock(&kvm->lock);
302}
303
300/** 304/**
301 * vgic_lazy_init: Lazy init is only allowed if the GIC exposed to the guest 305 * vgic_lazy_init: Lazy init is only allowed if the GIC exposed to the guest
302 * is a GICv2. A GICv3 must be explicitly initialized by the guest using the 306 * is a GICv2. A GICv3 must be explicitly initialized by the guest using the
@@ -348,6 +352,10 @@ int kvm_vgic_map_resources(struct kvm *kvm)
348 ret = vgic_v2_map_resources(kvm); 352 ret = vgic_v2_map_resources(kvm);
349 else 353 else
350 ret = vgic_v3_map_resources(kvm); 354 ret = vgic_v3_map_resources(kvm);
355
356 if (ret)
357 __kvm_vgic_destroy(kvm);
358
351out: 359out:
352 mutex_unlock(&kvm->lock); 360 mutex_unlock(&kvm->lock);
353 return ret; 361 return ret;
diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index 9bab86757fa4..834137e7b83f 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -293,8 +293,6 @@ int vgic_v2_map_resources(struct kvm *kvm)
293 dist->ready = true; 293 dist->ready = true;
294 294
295out: 295out:
296 if (ret)
297 kvm_vgic_destroy(kvm);
298 return ret; 296 return ret;
299} 297}
300 298
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 5c9f9745e6ca..e6b03fd8c374 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -302,8 +302,6 @@ int vgic_v3_map_resources(struct kvm *kvm)
302 dist->ready = true; 302 dist->ready = true;
303 303
304out: 304out:
305 if (ret)
306 kvm_vgic_destroy(kvm);
307 return ret; 305 return ret;
308} 306}
309 307