Skip to content

Commit 609b700

Browse files
committed
Merge tag 'kvm-arm-fixes-for-v4.15-1' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm
KVM/ARM Fixes for v4.15. Fixes: - A number of issues in the vgic discovered using SMATCH - A bit one-off calculation in out stage base address mask (32-bit and 64-bit) - Fixes to single-step debugging instructions that trap for other reasons such as MMMIO aborts - Printing unavailable hyp mode as error - Potential spinlock deadlock in the vgic - Avoid calling vgic vcpu free more than once - Broken bit calculation for big endian systems
2 parents ae64f9b + fc396e0 commit 609b700

File tree

17 files changed

+144
-79
lines changed

17 files changed

+144
-79
lines changed

arch/arm/include/asm/kvm_arm.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,7 @@
161161
#else
162162
#define VTTBR_X (5 - KVM_T0SZ)
163163
#endif
164-
#define VTTBR_BADDR_SHIFT (VTTBR_X - 1)
165-
#define VTTBR_BADDR_MASK (((_AC(1, ULL) << (40 - VTTBR_X)) - 1) << VTTBR_BADDR_SHIFT)
164+
#define VTTBR_BADDR_MASK (((_AC(1, ULL) << (40 - VTTBR_X)) - 1) << VTTBR_X)
166165
#define VTTBR_VMID_SHIFT _AC(48, ULL)
167166
#define VTTBR_VMID_MASK(size) (_AT(u64, (1 << size) - 1) << VTTBR_VMID_SHIFT)
168167

arch/arm/include/asm/kvm_host.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,11 @@ static inline void kvm_arm_init_debug(void) {}
285285
static inline void kvm_arm_setup_debug(struct kvm_vcpu *vcpu) {}
286286
static inline void kvm_arm_clear_debug(struct kvm_vcpu *vcpu) {}
287287
static inline void kvm_arm_reset_debug_ptr(struct kvm_vcpu *vcpu) {}
288+
static inline bool kvm_arm_handle_step_debug(struct kvm_vcpu *vcpu,
289+
struct kvm_run *run)
290+
{
291+
return false;
292+
}
288293

289294
int kvm_arm_vcpu_arch_set_attr(struct kvm_vcpu *vcpu,
290295
struct kvm_device_attr *attr);

arch/arm64/include/asm/kvm_arm.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,8 +170,7 @@
170170
#define VTCR_EL2_FLAGS (VTCR_EL2_COMMON_BITS | VTCR_EL2_TGRAN_FLAGS)
171171
#define VTTBR_X (VTTBR_X_TGRAN_MAGIC - VTCR_EL2_T0SZ_IPA)
172172

173-
#define VTTBR_BADDR_SHIFT (VTTBR_X - 1)
174-
#define VTTBR_BADDR_MASK (((UL(1) << (PHYS_MASK_SHIFT - VTTBR_X)) - 1) << VTTBR_BADDR_SHIFT)
173+
#define VTTBR_BADDR_MASK (((UL(1) << (PHYS_MASK_SHIFT - VTTBR_X)) - 1) << VTTBR_X)
175174
#define VTTBR_VMID_SHIFT (UL(48))
176175
#define VTTBR_VMID_MASK(size) (_AT(u64, (1 << size) - 1) << VTTBR_VMID_SHIFT)
177176

arch/arm64/include/asm/kvm_host.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ void kvm_arm_init_debug(void);
370370
void kvm_arm_setup_debug(struct kvm_vcpu *vcpu);
371371
void kvm_arm_clear_debug(struct kvm_vcpu *vcpu);
372372
void kvm_arm_reset_debug_ptr(struct kvm_vcpu *vcpu);
373+
bool kvm_arm_handle_step_debug(struct kvm_vcpu *vcpu, struct kvm_run *run);
373374
int kvm_arm_vcpu_arch_set_attr(struct kvm_vcpu *vcpu,
374375
struct kvm_device_attr *attr);
375376
int kvm_arm_vcpu_arch_get_attr(struct kvm_vcpu *vcpu,

arch/arm64/kvm/debug.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,3 +221,24 @@ void kvm_arm_clear_debug(struct kvm_vcpu *vcpu)
221221
}
222222
}
223223
}
224+
225+
226+
/*
227+
* After successfully emulating an instruction, we might want to
228+
* return to user space with a KVM_EXIT_DEBUG. We can only do this
229+
* once the emulation is complete, though, so for userspace emulations
230+
* we have to wait until we have re-entered KVM before calling this
231+
* helper.
232+
*
233+
* Return true (and set exit_reason) to return to userspace or false
234+
* if no further action is required.
235+
*/
236+
bool kvm_arm_handle_step_debug(struct kvm_vcpu *vcpu, struct kvm_run *run)
237+
{
238+
if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) {
239+
run->exit_reason = KVM_EXIT_DEBUG;
240+
run->debug.arch.hsr = ESR_ELx_EC_SOFTSTP_LOW << ESR_ELx_EC_SHIFT;
241+
return true;
242+
}
243+
return false;
244+
}

arch/arm64/kvm/handle_exit.c

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <asm/kvm_emulate.h>
2929
#include <asm/kvm_mmu.h>
3030
#include <asm/kvm_psci.h>
31+
#include <asm/debug-monitors.h>
3132

3233
#define CREATE_TRACE_POINTS
3334
#include "trace.h"
@@ -186,15 +187,47 @@ static exit_handle_fn kvm_get_exit_handler(struct kvm_vcpu *vcpu)
186187
return arm_exit_handlers[hsr_ec];
187188
}
188189

190+
/*
191+
* We may be single-stepping an emulated instruction. If the emulation
192+
* has been completed in the kernel, we can return to userspace with a
193+
* KVM_EXIT_DEBUG, otherwise userspace needs to complete its
194+
* emulation first.
195+
*/
196+
static int handle_trap_exceptions(struct kvm_vcpu *vcpu, struct kvm_run *run)
197+
{
198+
int handled;
199+
200+
/*
201+
* See ARM ARM B1.14.1: "Hyp traps on instructions
202+
* that fail their condition code check"
203+
*/
204+
if (!kvm_condition_valid(vcpu)) {
205+
kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
206+
handled = 1;
207+
} else {
208+
exit_handle_fn exit_handler;
209+
210+
exit_handler = kvm_get_exit_handler(vcpu);
211+
handled = exit_handler(vcpu, run);
212+
}
213+
214+
/*
215+
* kvm_arm_handle_step_debug() sets the exit_reason on the kvm_run
216+
* structure if we need to return to userspace.
217+
*/
218+
if (handled > 0 && kvm_arm_handle_step_debug(vcpu, run))
219+
handled = 0;
220+
221+
return handled;
222+
}
223+
189224
/*
190225
* Return > 0 to return to guest, < 0 on error, 0 (and set exit_reason) on
191226
* proper exit to userspace.
192227
*/
193228
int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run,
194229
int exception_index)
195230
{
196-
exit_handle_fn exit_handler;
197-
198231
if (ARM_SERROR_PENDING(exception_index)) {
199232
u8 hsr_ec = ESR_ELx_EC(kvm_vcpu_get_hsr(vcpu));
200233

@@ -220,20 +253,14 @@ int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run,
220253
return 1;
221254
case ARM_EXCEPTION_EL1_SERROR:
222255
kvm_inject_vabt(vcpu);
223-
return 1;
224-
case ARM_EXCEPTION_TRAP:
225-
/*
226-
* See ARM ARM B1.14.1: "Hyp traps on instructions
227-
* that fail their condition code check"
228-
*/
229-
if (!kvm_condition_valid(vcpu)) {
230-
kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
256+
/* We may still need to return for single-step */
257+
if (!(*vcpu_cpsr(vcpu) & DBG_SPSR_SS)
258+
&& kvm_arm_handle_step_debug(vcpu, run))
259+
return 0;
260+
else
231261
return 1;
232-
}
233-
234-
exit_handler = kvm_get_exit_handler(vcpu);
235-
236-
return exit_handler(vcpu, run);
262+
case ARM_EXCEPTION_TRAP:
263+
return handle_trap_exceptions(vcpu, run);
237264
case ARM_EXCEPTION_HYP_GONE:
238265
/*
239266
* EL2 has been reset to the hyp-stub. This happens when a guest

arch/arm64/kvm/hyp/switch.c

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <asm/kvm_emulate.h>
2323
#include <asm/kvm_hyp.h>
2424
#include <asm/fpsimd.h>
25+
#include <asm/debug-monitors.h>
2526

2627
static bool __hyp_text __fpsimd_enabled_nvhe(void)
2728
{
@@ -269,7 +270,11 @@ static bool __hyp_text __populate_fault_info(struct kvm_vcpu *vcpu)
269270
return true;
270271
}
271272

272-
static void __hyp_text __skip_instr(struct kvm_vcpu *vcpu)
273+
/* Skip an instruction which has been emulated. Returns true if
274+
* execution can continue or false if we need to exit hyp mode because
275+
* single-step was in effect.
276+
*/
277+
static bool __hyp_text __skip_instr(struct kvm_vcpu *vcpu)
273278
{
274279
*vcpu_pc(vcpu) = read_sysreg_el2(elr);
275280

@@ -282,6 +287,14 @@ static void __hyp_text __skip_instr(struct kvm_vcpu *vcpu)
282287
}
283288

284289
write_sysreg_el2(*vcpu_pc(vcpu), elr);
290+
291+
if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) {
292+
vcpu->arch.fault.esr_el2 =
293+
(ESR_ELx_EC_SOFTSTP_LOW << ESR_ELx_EC_SHIFT) | 0x22;
294+
return false;
295+
} else {
296+
return true;
297+
}
285298
}
286299

287300
int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu)
@@ -342,13 +355,21 @@ int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu)
342355
int ret = __vgic_v2_perform_cpuif_access(vcpu);
343356

344357
if (ret == 1) {
345-
__skip_instr(vcpu);
346-
goto again;
358+
if (__skip_instr(vcpu))
359+
goto again;
360+
else
361+
exit_code = ARM_EXCEPTION_TRAP;
347362
}
348363

349364
if (ret == -1) {
350-
/* Promote an illegal access to an SError */
351-
__skip_instr(vcpu);
365+
/* Promote an illegal access to an
366+
* SError. If we would be returning
367+
* due to single-step clear the SS
368+
* bit so handle_exit knows what to
369+
* do after dealing with the error.
370+
*/
371+
if (!__skip_instr(vcpu))
372+
*vcpu_cpsr(vcpu) &= ~DBG_SPSR_SS;
352373
exit_code = ARM_EXCEPTION_EL1_SERROR;
353374
}
354375

@@ -363,8 +384,10 @@ int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu)
363384
int ret = __vgic_v3_perform_cpuif_access(vcpu);
364385

365386
if (ret == 1) {
366-
__skip_instr(vcpu);
367-
goto again;
387+
if (__skip_instr(vcpu))
388+
goto again;
389+
else
390+
exit_code = ARM_EXCEPTION_TRAP;
368391
}
369392

370393
/* 0 falls through to be handled out of EL2 */

include/kvm/arm_arch_timer.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,4 @@ void kvm_timer_init_vhe(void);
9393
#define vcpu_vtimer(v) (&(v)->arch.timer_cpu.vtimer)
9494
#define vcpu_ptimer(v) (&(v)->arch.timer_cpu.ptimer)
9595

96-
void enable_el1_phys_timer_access(void);
97-
void disable_el1_phys_timer_access(void);
98-
9996
#endif

virt/kvm/arm/arch_timer.c

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -479,9 +479,6 @@ void kvm_timer_vcpu_load(struct kvm_vcpu *vcpu)
479479

480480
vtimer_restore_state(vcpu);
481481

482-
if (has_vhe())
483-
disable_el1_phys_timer_access();
484-
485482
/* Set the background timer for the physical timer emulation. */
486483
phys_timer_emulate(vcpu);
487484
}
@@ -510,9 +507,6 @@ void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu)
510507
if (unlikely(!timer->enabled))
511508
return;
512509

513-
if (has_vhe())
514-
enable_el1_phys_timer_access();
515-
516510
vtimer_save_state(vcpu);
517511

518512
/*
@@ -841,7 +835,10 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu)
841835
no_vgic:
842836
preempt_disable();
843837
timer->enabled = 1;
844-
kvm_timer_vcpu_load_vgic(vcpu);
838+
if (!irqchip_in_kernel(vcpu->kvm))
839+
kvm_timer_vcpu_load_user(vcpu);
840+
else
841+
kvm_timer_vcpu_load_vgic(vcpu);
845842
preempt_enable();
846843

847844
return 0;

virt/kvm/arm/arm.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
188188
kvm->vcpus[i] = NULL;
189189
}
190190
}
191+
atomic_set(&kvm->online_vcpus, 0);
191192
}
192193

193194
int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
@@ -296,7 +297,6 @@ void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu)
296297
{
297298
kvm_mmu_free_memory_caches(vcpu);
298299
kvm_timer_vcpu_terminate(vcpu);
299-
kvm_vgic_vcpu_destroy(vcpu);
300300
kvm_pmu_vcpu_destroy(vcpu);
301301
kvm_vcpu_uninit(vcpu);
302302
kmem_cache_free(kvm_vcpu_cache, vcpu);
@@ -627,6 +627,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
627627
ret = kvm_handle_mmio_return(vcpu, vcpu->run);
628628
if (ret)
629629
return ret;
630+
if (kvm_arm_handle_step_debug(vcpu, vcpu->run))
631+
return 0;
632+
630633
}
631634

632635
if (run->immediate_exit)
@@ -1502,7 +1505,7 @@ int kvm_arch_init(void *opaque)
15021505
bool in_hyp_mode;
15031506

15041507
if (!is_hyp_mode_available()) {
1505-
kvm_err("HYP mode not available\n");
1508+
kvm_info("HYP mode not available\n");
15061509
return -ENODEV;
15071510
}
15081511

virt/kvm/arm/hyp/timer-sr.c

Lines changed: 20 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -27,42 +27,34 @@ void __hyp_text __kvm_timer_set_cntvoff(u32 cntvoff_low, u32 cntvoff_high)
2727
write_sysreg(cntvoff, cntvoff_el2);
2828
}
2929

30-
void __hyp_text enable_el1_phys_timer_access(void)
31-
{
32-
u64 val;
33-
34-
/* Allow physical timer/counter access for the host */
35-
val = read_sysreg(cnthctl_el2);
36-
val |= CNTHCTL_EL1PCTEN | CNTHCTL_EL1PCEN;
37-
write_sysreg(val, cnthctl_el2);
38-
}
39-
40-
void __hyp_text disable_el1_phys_timer_access(void)
41-
{
42-
u64 val;
43-
44-
/*
45-
* Disallow physical timer access for the guest
46-
* Physical counter access is allowed
47-
*/
48-
val = read_sysreg(cnthctl_el2);
49-
val &= ~CNTHCTL_EL1PCEN;
50-
val |= CNTHCTL_EL1PCTEN;
51-
write_sysreg(val, cnthctl_el2);
52-
}
53-
5430
void __hyp_text __timer_disable_traps(struct kvm_vcpu *vcpu)
5531
{
5632
/*
5733
* We don't need to do this for VHE since the host kernel runs in EL2
5834
* with HCR_EL2.TGE ==1, which makes those bits have no impact.
5935
*/
60-
if (!has_vhe())
61-
enable_el1_phys_timer_access();
36+
if (!has_vhe()) {
37+
u64 val;
38+
39+
/* Allow physical timer/counter access for the host */
40+
val = read_sysreg(cnthctl_el2);
41+
val |= CNTHCTL_EL1PCTEN | CNTHCTL_EL1PCEN;
42+
write_sysreg(val, cnthctl_el2);
43+
}
6244
}
6345

6446
void __hyp_text __timer_enable_traps(struct kvm_vcpu *vcpu)
6547
{
66-
if (!has_vhe())
67-
disable_el1_phys_timer_access();
48+
if (!has_vhe()) {
49+
u64 val;
50+
51+
/*
52+
* Disallow physical timer access for the guest
53+
* Physical counter access is allowed
54+
*/
55+
val = read_sysreg(cnthctl_el2);
56+
val &= ~CNTHCTL_EL1PCEN;
57+
val |= CNTHCTL_EL1PCTEN;
58+
write_sysreg(val, cnthctl_el2);
59+
}
6860
}

virt/kvm/arm/hyp/vgic-v2-sr.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,7 @@ static void __hyp_text save_elrsr(struct kvm_vcpu *vcpu, void __iomem *base)
3434
else
3535
elrsr1 = 0;
3636

37-
#ifdef CONFIG_CPU_BIG_ENDIAN
38-
cpu_if->vgic_elrsr = ((u64)elrsr0 << 32) | elrsr1;
39-
#else
4037
cpu_if->vgic_elrsr = ((u64)elrsr1 << 32) | elrsr0;
41-
#endif
4238
}
4339

4440
static void __hyp_text save_lrs(struct kvm_vcpu *vcpu, void __iomem *base)

virt/kvm/arm/vgic/vgic-irqfd.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,7 @@ int kvm_vgic_setup_default_irq_routing(struct kvm *kvm)
112112
u32 nr = dist->nr_spis;
113113
int i, ret;
114114

115-
entries = kcalloc(nr, sizeof(struct kvm_kernel_irq_routing_entry),
116-
GFP_KERNEL);
115+
entries = kcalloc(nr, sizeof(*entries), GFP_KERNEL);
117116
if (!entries)
118117
return -ENOMEM;
119118

0 commit comments

Comments
 (0)