Re: [PATCH 2/2] KVM: LoongArch: selftests: Add in-kernel MMIO read fast path test
Bibo Mao <[email protected]> Fri, 24 Jul 2026 09:27:44 +0800
| Newsgroups | dev.linux.lists.loongarch,org.kernel.vger.kvm,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
On 2026/7/23 下午7:16, Zeng Chi wrote: > From: Zeng Chi <[email protected]> > > Add a test that exercises the in-kernel MMIO read fast path of > kvm_emu_mmio_read(). The guest performs an MMIO read from an in-kernel > emulated PCH-PIC, immediately followed by a marker instruction, and the > test verifies that the marker instruction is executed, i.e. that the PC > advances by exactly one instruction instead of skipping the instruction > after the MMIO read. > > The test skips gracefully when the host KVM cannot create a PCH-PIC > device. > > Signed-off-by: Zeng Chi <[email protected]> > --- > tools/testing/selftests/kvm/Makefile.kvm | 3 +- > .../selftests/kvm/loongarch/mmio_read_test.c | 89 +++++++++++++++++++ > 2 files changed, 91 insertions(+), 1 deletion(-) > create mode 100644 tools/testing/selftests/kvm/loongarch/mmio_read_test.c > > diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selftests/kvm/Makefile.kvm > index 6fc34e9bf8e1..4daf90caaabc 100644 > --- a/tools/testing/selftests/kvm/Makefile.kvm > +++ b/tools/testing/selftests/kvm/Makefile.kvm > @@ -228,7 +228,8 @@ TEST_GEN_PROGS_riscv += mmu_stress_test > TEST_GEN_PROGS_riscv += rseq_test > TEST_GEN_PROGS_riscv += steal_time > > -TEST_GEN_PROGS_loongarch = loongarch/pmu_test > +TEST_GEN_PROGS_loongarch = loongarch/mmio_read_test > +TEST_GEN_PROGS_loongarch += loongarch/pmu_test > TEST_GEN_PROGS_loongarch += arch_timer > TEST_GEN_PROGS_loongarch += coalesced_io_test > TEST_GEN_PROGS_loongarch += demand_paging_test > diff --git a/tools/testing/selftests/kvm/loongarch/mmio_read_test.c b/tools/testing/selftests/kvm/loongarch/mmio_read_test.c > new file mode 100644 > index 000000000000..7f64ca91ca8f > --- /dev/null > +++ b/tools/testing/selftests/kvm/loongarch/mmio_read_test.c > @@ -0,0 +1,89 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * LoongArch KVM in-kernel MMIO read fast path test > + * > + * When an MMIO read hits a device emulated inside KVM (such as the > + * PCH-PIC), kvm_emu_mmio_read() completes the access without returning > + * to user space and advances the guest PC by one instruction. > + * > + * This test issues such an in-kernel MMIO read immediately followed by > + * a marker instruction and checks that the marker instruction actually > + * runs, i.e. that the PC advanced by exactly one instruction (4 bytes) > + * rather than skipping the instruction after the MMIO read. > + */ > +#include "kvm_util.h" > +#include "processor.h" > +#include "test_util.h" > +#include "loongarch/processor.h" > + > +/* Physical base the in-kernel PCH-PIC is mapped at (no memslot backs it) */ > +#define PCH_PIC_BASE 0x10000000UL > + > +static void guest_code(void) > +{ > + unsigned long marker = 0; > + unsigned int val = 0; > + > + /* > + * 'ld.w' faults out as an MMIO read and is emulated in kernel. > + * The following 'addi.d' must execute; it is skipped if the MMIO > + * read fast path advances the PC twice (by 8 instead of 4). > + */ > + asm volatile( > + "ld.w %[val], %[base], 0\n\t" > + "addi.d %[marker], %[marker], 1\n\t" > + : [val] "=&r" (val), [marker] "+&r" (marker) > + : [base] "r" (PCH_PIC_BASE) > + : "memory"); By my understanding, the kvm selftest is mainly to test function. It will be better if it is to verify irq handling with in-kernel PCH-PIC irqchip. Regards Bibo Mao > + > + GUEST_PRINTF("mmio read val=0x%x, marker=%lu\n", val, marker); > + GUEST_ASSERT_EQ(marker, 1); > + GUEST_DONE(); > +} > + > +int main(int argc, char *argv[]) > +{ > + struct kvm_vcpu *vcpu; > + struct kvm_vm *vm; > + struct ucall uc; > + uint64_t addr = PCH_PIC_BASE; > + int dev_fd; > + > + vm = vm_create(VM_MODE_P47V47_16K); > + vcpu = vm_vcpu_add(vm, 0, guest_code); > + > + /* Create the in-kernel PCH-PIC and map it at PCH_PIC_BASE */ > + dev_fd = __kvm_create_device(vm, KVM_DEV_TYPE_LOONGARCH_PCHPIC); > + if (dev_fd < 0) { > + print_skip("PCH-PIC device not supported by host KVM"); > + kvm_vm_free(vm); > + return KSFT_SKIP; > + } > + kvm_device_attr_set(dev_fd, KVM_DEV_LOONGARCH_PCH_PIC_GRP_CTRL, > + KVM_DEV_LOONGARCH_PCH_PIC_CTRL_INIT, &addr); > + close(dev_fd); > + > + /* Identity-map the MMIO page so the guest can reach the device */ > + virt_map(vm, PCH_PIC_BASE, PCH_PIC_BASE, 1); > + > + while (1) { > + vcpu_run(vcpu); > + switch (get_ucall(vcpu, &uc)) { > + case UCALL_PRINTF: > + pr_info("%s", uc.buffer); > + break; > + case UCALL_DONE: > + goto done; > + case UCALL_ABORT: > + REPORT_GUEST_ASSERT(uc); > + goto done; > + default: > + TEST_FAIL("Unexpected exit: %s", > + exit_reason_str(vcpu->run->exit_reason)); > + } > + } > + > +done: > + kvm_vm_free(vm); > + return 0; > +} >