@@ -333,7 +333,8 @@ void vcpu_write_sys_reg(struct kvm_vcpu *vcpu, u64 val, int reg)
* to reverse-translate virtual EL2 system registers for a
* non-VHE guest hypervisor.
*/
- __vcpu_sys_reg(vcpu, reg) = val;
+ if (reg != HCR_EL2)
+ __vcpu_sys_reg(vcpu, reg) = val;
switch (reg) {
case ELR_EL2:
@@ -370,7 +371,17 @@ void vcpu_write_sys_reg(struct kvm_vcpu *vcpu, u64 val, int reg)
return;
memory_write:
- __vcpu_sys_reg(vcpu, reg) = val;
+ if (reg == HCR_EL2 && vcpu_el2_e2h_is_set(vcpu) && !(val & HCR_E2H)) {
+ preempt_disable();
+ kvm_arch_vcpu_put(vcpu);
+
+ __vcpu_sys_reg(vcpu, reg) = val;
+
+ kvm_arch_vcpu_load(vcpu, smp_processor_id());
+ preempt_enable();
+ } else {
+ __vcpu_sys_reg(vcpu, reg) = val;
+ }
}
/* 3 bits per cache level, as per CLIDR, but non-existent caches always 0 */
arm/selftest.c | 8 ++++++++
1 file changed, 8 insertions(+)
@@ -424,6 +424,14 @@ static void check_el2_cpu(void *data __unused)
report(current_level() == CurrentEL_EL2, "CPU(%3d) Running at EL2", cpu);
report(vhe_supported() && vhe_enabled(),
"CPU(%3d) VHE supported and enabled", cpu);
+
+ disable_vhe();
+ report(current_level() == CurrentEL_EL2 && vhe_supported() && !vhe_enabled(),
+ "CPU(%3d) VHE disable", cpu);
+
+ enable_vhe();
+ report(current_level() == CurrentEL_EL2 && vhe_supported() && vhe_enabled(),
+ "CPU(%3d) VHE re-enable", cpu);
}
static bool psci_check(void);
Check that disabling VHE, then re-enabling it again, works. Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com> --- Disabling VHE is broken with version v1 of the NV patches; to run the tests I use this patch: