diff options
| -rw-r--r-- | arch/arm/include/asm/virt.h | 5 | ||||
| -rw-r--r-- | arch/arm/kvm/arm.c | 3 | ||||
| -rw-r--r-- | arch/arm64/include/asm/virt.h | 9 | ||||
| -rw-r--r-- | arch/s390/kvm/kvm-s390.c | 4 | ||||
| -rw-r--r-- | arch/x86/kvm/x86.c | 3 | ||||
| -rw-r--r-- | include/kvm/arm_arch_timer.h | 1 | ||||
| -rw-r--r-- | virt/kvm/arm/arch_timer.c | 26 | ||||
| -rw-r--r-- | virt/kvm/arm/hyp/timer-sr.c | 33 | ||||
| -rw-r--r-- | virt/kvm/arm/vgic/vgic-init.c | 18 | ||||
| -rw-r--r-- | virt/kvm/arm/vgic/vgic-v2.c | 2 | ||||
| -rw-r--r-- | virt/kvm/arm/vgic/vgic-v3.c | 2 |
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 | ||
| 83 | static 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 */ |
| 84 | extern char __hyp_idmap_text_start[]; | 89 | extern char __hyp_idmap_text_start[]; |
| 85 | extern char __hyp_idmap_text_end[]; | 90 | extern 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 | ||
| 84 | static 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 |
| 84 | extern void verify_cpu_run_el(void); | 93 | extern 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 | ||
| 6177 | static int dm_request_for_irq_injection(struct kvm_vcpu *vcpu) | 6178 | static 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 | ||
| 77 | void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu); | 77 | void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu); |
| 78 | 78 | ||
| 79 | void 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 | */ | ||
| 520 | void 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 | ||
| 282 | void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu) | 278 | void 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 | ||
| 289 | void kvm_vgic_destroy(struct kvm *kvm) | 285 | /* To be called with kvm->lock held */ |
| 286 | static 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 | ||
| 297 | void 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 | |||
| 351 | out: | 359 | out: |
| 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 | ||
| 295 | out: | 295 | out: |
| 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 | ||
| 304 | out: | 304 | out: |
| 305 | if (ret) | ||
| 306 | kvm_vgic_destroy(kvm); | ||
| 307 | return ret; | 305 | return ret; |
| 308 | } | 306 | } |
| 309 | 307 | ||
