Skip to content

Commit 7f71507

Browse files
committed
LoongArch: KVM: Protect kvm_io_bus_{read,write}() with SRCU
When we enable lockdep we get such a warning: ============================= WARNING: suspicious RCU usage 6.12.0-rc7+ #1891 Tainted: G W ----------------------------- arch/loongarch/kvm/../../../virt/kvm/kvm_main.c:5945 suspicious rcu_dereference_check() usage! other info that might help us debug this: rcu_scheduler_active = 2, debug_locks = 1 1 lock held by qemu-system-loo/948: #0: 90000001184a00a8 (&vcpu->mutex){+.+.}-{4:4}, at: kvm_vcpu_ioctl+0xf4/0xe20 [kvm] stack backtrace: CPU: 2 UID: 0 PID: 948 Comm: qemu-system-loo Tainted: G W 6.12.0-rc7+ #1891 Tainted: [W]=WARN Hardware name: Loongson Loongson-3A5000-7A1000-1w-CRB/Loongson-LS3A5000-7A1000-1w-CRB, BIOS vUDK2018-LoongArch-V2.0.0-prebeta9 10/21/2022 Stack : 0000000000000089 9000000005a0db9c 90000000071519c8 900000012c578000 900000012c57b940 0000000000000000 900000012c57b948 9000000007e53788 900000000815bcc8 900000000815bcc0 900000012c57b7b0 0000000000000001 0000000000000001 4b031894b9d6b725 0000000005dec000 9000000100427b00 00000000000003d2 0000000000000001 000000000000002d 0000000000000003 0000000000000030 00000000000003b4 0000000005dec000 0000000000000000 900000000806d000 9000000007e53788 00000000000000b4 0000000000000004 0000000000000004 0000000000000000 0000000000000000 9000000107baf600 9000000008916000 9000000007e53788 9000000005924778 000000001fe001e5 00000000000000b0 0000000000000007 0000000000000000 0000000000071c1d ... Call Trace: [<9000000005924778>] show_stack+0x38/0x180 [<90000000071519c4>] dump_stack_lvl+0x94/0xe4 [<90000000059eb754>] lockdep_rcu_suspicious+0x194/0x240 [<ffff80000221f47c>] kvm_io_bus_read+0x19c/0x1e0 [kvm] [<ffff800002225118>] kvm_emu_mmio_read+0xd8/0x440 [kvm] [<ffff8000022254bc>] kvm_handle_read_fault+0x3c/0xe0 [kvm] [<ffff80000222b3c8>] kvm_handle_exit+0x228/0x480 [kvm] Fix it by protecting kvm_io_bus_{read,write}() with SRCU. Cc: stable@vger.kernel.org Reviewed-by: Bibo Mao <maobibo@loongson.cn> Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
1 parent 589e6cc commit 7f71507

File tree

2 files changed

+26
-11
lines changed

2 files changed

+26
-11
lines changed

arch/loongarch/kvm/exit.c

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ static int kvm_handle_csr(struct kvm_vcpu *vcpu, larch_inst inst)
156156

157157
int kvm_emu_iocsr(larch_inst inst, struct kvm_run *run, struct kvm_vcpu *vcpu)
158158
{
159-
int ret;
159+
int idx, ret;
160160
unsigned long *val;
161161
u32 addr, rd, rj, opcode;
162162

@@ -167,7 +167,6 @@ int kvm_emu_iocsr(larch_inst inst, struct kvm_run *run, struct kvm_vcpu *vcpu)
167167
rj = inst.reg2_format.rj;
168168
opcode = inst.reg2_format.opcode;
169169
addr = vcpu->arch.gprs[rj];
170-
ret = EMULATE_DO_IOCSR;
171170
run->iocsr_io.phys_addr = addr;
172171
run->iocsr_io.is_write = 0;
173172
val = &vcpu->arch.gprs[rd];
@@ -207,20 +206,28 @@ int kvm_emu_iocsr(larch_inst inst, struct kvm_run *run, struct kvm_vcpu *vcpu)
207206
}
208207

209208
if (run->iocsr_io.is_write) {
210-
if (!kvm_io_bus_write(vcpu, KVM_IOCSR_BUS, addr, run->iocsr_io.len, val))
209+
idx = srcu_read_lock(&vcpu->kvm->srcu);
210+
ret = kvm_io_bus_write(vcpu, KVM_IOCSR_BUS, addr, run->iocsr_io.len, val);
211+
srcu_read_unlock(&vcpu->kvm->srcu, idx);
212+
if (ret == 0)
211213
ret = EMULATE_DONE;
212-
else
214+
else {
215+
ret = EMULATE_DO_IOCSR;
213216
/* Save data and let user space to write it */
214217
memcpy(run->iocsr_io.data, val, run->iocsr_io.len);
215-
218+
}
216219
trace_kvm_iocsr(KVM_TRACE_IOCSR_WRITE, run->iocsr_io.len, addr, val);
217220
} else {
218-
if (!kvm_io_bus_read(vcpu, KVM_IOCSR_BUS, addr, run->iocsr_io.len, val))
221+
idx = srcu_read_lock(&vcpu->kvm->srcu);
222+
ret = kvm_io_bus_read(vcpu, KVM_IOCSR_BUS, addr, run->iocsr_io.len, val);
223+
srcu_read_unlock(&vcpu->kvm->srcu, idx);
224+
if (ret == 0)
219225
ret = EMULATE_DONE;
220-
else
226+
else {
227+
ret = EMULATE_DO_IOCSR;
221228
/* Save register id for iocsr read completion */
222229
vcpu->arch.io_gpr = rd;
223-
230+
}
224231
trace_kvm_iocsr(KVM_TRACE_IOCSR_READ, run->iocsr_io.len, addr, NULL);
225232
}
226233

@@ -359,7 +366,7 @@ static int kvm_handle_gspr(struct kvm_vcpu *vcpu)
359366

360367
int kvm_emu_mmio_read(struct kvm_vcpu *vcpu, larch_inst inst)
361368
{
362-
int ret;
369+
int idx, ret;
363370
unsigned int op8, opcode, rd;
364371
struct kvm_run *run = vcpu->run;
365372

@@ -464,8 +471,10 @@ int kvm_emu_mmio_read(struct kvm_vcpu *vcpu, larch_inst inst)
464471
* it need not return to user space to handle the mmio
465472
* exception.
466473
*/
474+
idx = srcu_read_lock(&vcpu->kvm->srcu);
467475
ret = kvm_io_bus_read(vcpu, KVM_MMIO_BUS, vcpu->arch.badv,
468476
run->mmio.len, &vcpu->arch.gprs[rd]);
477+
srcu_read_unlock(&vcpu->kvm->srcu, idx);
469478
if (!ret) {
470479
update_pc(&vcpu->arch);
471480
vcpu->mmio_needed = 0;
@@ -531,7 +540,7 @@ int kvm_complete_mmio_read(struct kvm_vcpu *vcpu, struct kvm_run *run)
531540

532541
int kvm_emu_mmio_write(struct kvm_vcpu *vcpu, larch_inst inst)
533542
{
534-
int ret;
543+
int idx, ret;
535544
unsigned int rd, op8, opcode;
536545
unsigned long curr_pc, rd_val = 0;
537546
struct kvm_run *run = vcpu->run;
@@ -631,7 +640,9 @@ int kvm_emu_mmio_write(struct kvm_vcpu *vcpu, larch_inst inst)
631640
* it need not return to user space to handle the mmio
632641
* exception.
633642
*/
643+
idx = srcu_read_lock(&vcpu->kvm->srcu);
634644
ret = kvm_io_bus_write(vcpu, KVM_MMIO_BUS, vcpu->arch.badv, run->mmio.len, data);
645+
srcu_read_unlock(&vcpu->kvm->srcu, idx);
635646
if (!ret)
636647
return EMULATE_DONE;
637648

arch/loongarch/kvm/intc/ipi.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ static void write_mailbox(struct kvm_vcpu *vcpu, int offset, uint64_t data, int
9898

9999
static int send_ipi_data(struct kvm_vcpu *vcpu, gpa_t addr, uint64_t data)
100100
{
101-
int i, ret;
101+
int i, idx, ret;
102102
uint32_t val = 0, mask = 0;
103103

104104
/*
@@ -107,7 +107,9 @@ static int send_ipi_data(struct kvm_vcpu *vcpu, gpa_t addr, uint64_t data)
107107
*/
108108
if ((data >> 27) & 0xf) {
109109
/* Read the old val */
110+
idx = srcu_read_lock(&vcpu->kvm->srcu);
110111
ret = kvm_io_bus_read(vcpu, KVM_IOCSR_BUS, addr, sizeof(val), &val);
112+
srcu_read_unlock(&vcpu->kvm->srcu, idx);
111113
if (unlikely(ret)) {
112114
kvm_err("%s: : read date from addr %llx failed\n", __func__, addr);
113115
return ret;
@@ -121,7 +123,9 @@ static int send_ipi_data(struct kvm_vcpu *vcpu, gpa_t addr, uint64_t data)
121123
val &= mask;
122124
}
123125
val |= ((uint32_t)(data >> 32) & ~mask);
126+
idx = srcu_read_lock(&vcpu->kvm->srcu);
124127
ret = kvm_io_bus_write(vcpu, KVM_IOCSR_BUS, addr, sizeof(val), &val);
128+
srcu_read_unlock(&vcpu->kvm->srcu, idx);
125129
if (unlikely(ret))
126130
kvm_err("%s: : write date to addr %llx failed\n", __func__, addr);
127131

0 commit comments

Comments
 (0)