Re: [PATCH 2/2] KVM: LoongArch: selftests: Add in-kernel MMIO read fast path test

Huacai Chen <[email protected]> Sat, 25 Jul 2026 17:41:10 +0800
Newsgroups dev.linux.lists.loongarch,org.kernel.vger.kvm,org.kernel.vger.linux-kernel
Message-ID <CAAhV-H7pLEUeKWGmCZqDdF+2vr=2aexOFVCMa_UxTrDpUY+gvA@mail.gmail.com>
On Fri, Jul 24, 2026 at 9:28=E2=80=AFAM Bibo Mao <[email protected]> wrot=
e:
>
>
>
> On 2026/7/23 =E4=B8=8B=E5=8D=887: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_te=
st.c
> >
> > diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/s=
elftests/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 +=3D mmu_stress_test
> >   TEST_GEN_PROGS_riscv +=3D rseq_test
> >   TEST_GEN_PROGS_riscv +=3D steal_time
> >
> > -TEST_GEN_PROGS_loongarch =3D loongarch/pmu_test
> > +TEST_GEN_PROGS_loongarch =3D loongarch/mmio_read_test
> > +TEST_GEN_PROGS_loongarch +=3D loongarch/pmu_test
> >   TEST_GEN_PROGS_loongarch +=3D arch_timer
> >   TEST_GEN_PROGS_loongarch +=3D coalesced_io_test
> >   TEST_GEN_PROGS_loongarch +=3D demand_paging_test
> > diff --git a/tools/testing/selftests/kvm/loongarch/mmio_read_test.c b/t=
ools/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 returnin=
g
> > + * to user space and advances the guest PC by one instruction.
> > + *
> > + * This test issues such an in-kernel MMIO read immediately followed b=
y
> > + * a marker instruction and checks that the marker instruction actuall=
y
> > + * 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 =3D 0;
> > +     unsigned int val =3D 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] "=3D&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.
I think the fist patch is just enough. :)

Huacai

>
> Regards
> Bibo Mao
> > +
> > +     GUEST_PRINTF("mmio read val=3D0x%x, marker=3D%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 =3D PCH_PIC_BASE;
> > +     int dev_fd;
> > +
> > +     vm =3D vm_create(VM_MODE_P47V47_16K);
> > +     vcpu =3D vm_vcpu_add(vm, 0, guest_code);
> > +
> > +     /* Create the in-kernel PCH-PIC and map it at PCH_PIC_BASE */
> > +     dev_fd =3D __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;
> > +}
> >
>