Skip to content

Commit 948ccbd

Browse files
lixianglaichenhuacai
authored andcommitted
LoongArch: KVM: Add iocsr and mmio bus simulation in kernel
Add iocsr and mmio memory read and write simulation to the kernel. When the VM accesses the device address space through iocsr instructions or mmio, it does not need to return to the qemu user mode but can directly completes the access in the kernel mode. Signed-off-by: Tianrui Zhao <[email protected]> Signed-off-by: Xianglai Li <[email protected]> Signed-off-by: Huacai Chen <[email protected]>
1 parent 2d5404c commit 948ccbd

File tree

3 files changed

+94
-24
lines changed

3 files changed

+94
-24
lines changed

arch/loongarch/kvm/exit.c

Lines changed: 58 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ static int kvm_handle_csr(struct kvm_vcpu *vcpu, larch_inst inst)
157157
int kvm_emu_iocsr(larch_inst inst, struct kvm_run *run, struct kvm_vcpu *vcpu)
158158
{
159159
int ret;
160-
unsigned long val;
160+
unsigned long *val;
161161
u32 addr, rd, rj, opcode;
162162

163163
/*
@@ -170,6 +170,7 @@ int kvm_emu_iocsr(larch_inst inst, struct kvm_run *run, struct kvm_vcpu *vcpu)
170170
ret = EMULATE_DO_IOCSR;
171171
run->iocsr_io.phys_addr = addr;
172172
run->iocsr_io.is_write = 0;
173+
val = &vcpu->arch.gprs[rd];
173174

174175
/* LoongArch is Little endian */
175176
switch (opcode) {
@@ -202,16 +203,25 @@ int kvm_emu_iocsr(larch_inst inst, struct kvm_run *run, struct kvm_vcpu *vcpu)
202203
run->iocsr_io.is_write = 1;
203204
break;
204205
default:
205-
ret = EMULATE_FAIL;
206-
break;
206+
return EMULATE_FAIL;
207207
}
208208

209-
if (ret == EMULATE_DO_IOCSR) {
210-
if (run->iocsr_io.is_write) {
211-
val = vcpu->arch.gprs[rd];
212-
memcpy(run->iocsr_io.data, &val, run->iocsr_io.len);
213-
}
214-
vcpu->arch.io_gpr = rd;
209+
if (run->iocsr_io.is_write) {
210+
if (!kvm_io_bus_write(vcpu, KVM_IOCSR_BUS, addr, run->iocsr_io.len, val))
211+
ret = EMULATE_DONE;
212+
else
213+
/* Save data and let user space to write it */
214+
memcpy(run->iocsr_io.data, val, run->iocsr_io.len);
215+
216+
trace_kvm_iocsr(KVM_TRACE_IOCSR_WRITE, run->iocsr_io.len, addr, val);
217+
} else {
218+
if (!kvm_io_bus_read(vcpu, KVM_IOCSR_BUS, addr, run->iocsr_io.len, val))
219+
ret = EMULATE_DONE;
220+
else
221+
/* Save register id for iocsr read completion */
222+
vcpu->arch.io_gpr = rd;
223+
224+
trace_kvm_iocsr(KVM_TRACE_IOCSR_READ, run->iocsr_io.len, addr, NULL);
215225
}
216226

217227
return ret;
@@ -447,19 +457,33 @@ int kvm_emu_mmio_read(struct kvm_vcpu *vcpu, larch_inst inst)
447457
}
448458

449459
if (ret == EMULATE_DO_MMIO) {
460+
trace_kvm_mmio(KVM_TRACE_MMIO_READ, run->mmio.len, run->mmio.phys_addr, NULL);
461+
462+
/*
463+
* If mmio device such as PCH-PIC is emulated in KVM,
464+
* it need not return to user space to handle the mmio
465+
* exception.
466+
*/
467+
ret = kvm_io_bus_read(vcpu, KVM_MMIO_BUS, vcpu->arch.badv,
468+
run->mmio.len, &vcpu->arch.gprs[rd]);
469+
if (!ret) {
470+
update_pc(&vcpu->arch);
471+
vcpu->mmio_needed = 0;
472+
return EMULATE_DONE;
473+
}
474+
450475
/* Set for kvm_complete_mmio_read() use */
451476
vcpu->arch.io_gpr = rd;
452477
run->mmio.is_write = 0;
453478
vcpu->mmio_is_write = 0;
454-
trace_kvm_mmio(KVM_TRACE_MMIO_READ_UNSATISFIED, run->mmio.len,
455-
run->mmio.phys_addr, NULL);
456-
} else {
457-
kvm_err("Read not supported Inst=0x%08x @%lx BadVaddr:%#lx\n",
458-
inst.word, vcpu->arch.pc, vcpu->arch.badv);
459-
kvm_arch_vcpu_dump_regs(vcpu);
460-
vcpu->mmio_needed = 0;
479+
return EMULATE_DO_MMIO;
461480
}
462481

482+
kvm_err("Read not supported Inst=0x%08x @%lx BadVaddr:%#lx\n",
483+
inst.word, vcpu->arch.pc, vcpu->arch.badv);
484+
kvm_arch_vcpu_dump_regs(vcpu);
485+
vcpu->mmio_needed = 0;
486+
463487
return ret;
464488
}
465489

@@ -600,19 +624,29 @@ int kvm_emu_mmio_write(struct kvm_vcpu *vcpu, larch_inst inst)
600624
}
601625

602626
if (ret == EMULATE_DO_MMIO) {
627+
trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, run->mmio.len, run->mmio.phys_addr, data);
628+
629+
/*
630+
* If mmio device such as PCH-PIC is emulated in KVM,
631+
* it need not return to user space to handle the mmio
632+
* exception.
633+
*/
634+
ret = kvm_io_bus_write(vcpu, KVM_MMIO_BUS, vcpu->arch.badv, run->mmio.len, data);
635+
if (!ret)
636+
return EMULATE_DONE;
637+
603638
run->mmio.is_write = 1;
604639
vcpu->mmio_needed = 1;
605640
vcpu->mmio_is_write = 1;
606-
trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, run->mmio.len,
607-
run->mmio.phys_addr, data);
608-
} else {
609-
vcpu->arch.pc = curr_pc;
610-
kvm_err("Write not supported Inst=0x%08x @%lx BadVaddr:%#lx\n",
611-
inst.word, vcpu->arch.pc, vcpu->arch.badv);
612-
kvm_arch_vcpu_dump_regs(vcpu);
613-
/* Rollback PC if emulation was unsuccessful */
641+
return EMULATE_DO_MMIO;
614642
}
615643

644+
vcpu->arch.pc = curr_pc;
645+
kvm_err("Write not supported Inst=0x%08x @%lx BadVaddr:%#lx\n",
646+
inst.word, vcpu->arch.pc, vcpu->arch.badv);
647+
kvm_arch_vcpu_dump_regs(vcpu);
648+
/* Rollback PC if emulation was unsuccessful */
649+
616650
return ret;
617651
}
618652

include/linux/kvm_host.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ enum kvm_bus {
219219
KVM_PIO_BUS,
220220
KVM_VIRTIO_CCW_NOTIFY_BUS,
221221
KVM_FAST_MMIO_BUS,
222+
KVM_IOCSR_BUS,
222223
KVM_NR_BUSES
223224
};
224225

include/trace/events/kvm.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,41 @@ TRACE_EVENT(kvm_mmio,
236236
__entry->len, __entry->gpa, __entry->val)
237237
);
238238

239+
#define KVM_TRACE_IOCSR_READ_UNSATISFIED 0
240+
#define KVM_TRACE_IOCSR_READ 1
241+
#define KVM_TRACE_IOCSR_WRITE 2
242+
243+
#define kvm_trace_symbol_iocsr \
244+
{ KVM_TRACE_IOCSR_READ_UNSATISFIED, "unsatisfied-read" }, \
245+
{ KVM_TRACE_IOCSR_READ, "read" }, \
246+
{ KVM_TRACE_IOCSR_WRITE, "write" }
247+
248+
TRACE_EVENT(kvm_iocsr,
249+
TP_PROTO(int type, int len, u64 gpa, void *val),
250+
TP_ARGS(type, len, gpa, val),
251+
252+
TP_STRUCT__entry(
253+
__field( u32, type )
254+
__field( u32, len )
255+
__field( u64, gpa )
256+
__field( u64, val )
257+
),
258+
259+
TP_fast_assign(
260+
__entry->type = type;
261+
__entry->len = len;
262+
__entry->gpa = gpa;
263+
__entry->val = 0;
264+
if (val)
265+
memcpy(&__entry->val, val,
266+
min_t(u32, sizeof(__entry->val), len));
267+
),
268+
269+
TP_printk("iocsr %s len %u gpa 0x%llx val 0x%llx",
270+
__print_symbolic(__entry->type, kvm_trace_symbol_iocsr),
271+
__entry->len, __entry->gpa, __entry->val)
272+
);
273+
239274
#define kvm_fpu_load_symbol \
240275
{0, "unload"}, \
241276
{1, "load"}

0 commit comments

Comments
 (0)