mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v11 0/5] KVM: selftests: Add LoongArch support
@ 2025-04-27  6:45 Bibo Mao
  2025-04-27  6:45 ` [PATCH v11 1/5] KVM: selftests: Add VM_MODE_P47V47_16K VM mode Bibo Mao
                   ` (5 more replies)
  0 siblings, 6 replies; 11+ messages in thread
From: Bibo Mao @ 2025-04-27  6:45 UTC (permalink / raw)
  To: Paolo Bonzini, Huacai Chen, Sean Christopherson
  Cc: Shuah Khan, linux-kernel, kvm, linux-kselftest

This patchset adds KVM selftests for LoongArch system, currently only
some common test cases are supported and pass to run. These test cases
are listed as following:
    coalesced_io_test
    demand_paging_test
    dirty_log_perf_test
    dirty_log_test
    guest_print_test
    hardware_disable_test
    kvm_binary_stats_test
    kvm_create_max_vcpus
    kvm_page_table_test
    memslot_modification_stress_test
    memslot_perf_test
    set_memory_region_test

---
Changes in v11:
1. Fix a typo issue in notes of patch 2, it is kvm_util_arch.h rather than
   kvm_util_base.h

Changes in v10:
1. Add PS_64K and remove PS_8K in file include/loongarch/processor.h
2. Fix a typo issue in file lib/loongarch/processor.c
3. Update file MAINTAINERS about LoongArch KVM selftests

Changes in v9:
1. Add vm mode VM_MODE_P47V47_16K, LoongArch VM uses this mode by
   default, rather than VM_MODE_P36V47_16K.
2. Refresh some spelling issues in changelog.

Changes in v8:
1. Porting patch based on the latest version.
2. For macro PC_OFFSET_EXREGS, offsetof() method is used for C header file,
   still hardcoded definition for assemble language.

Changes in v7:
1. Refine code to add LoongArch support in test case
set_memory_region_test.

Changes in v6:
1. Refresh the patch based on latest kernel 6.8-rc1, add LoongArch
support about testcase set_memory_region_test.
2. Add hardware_disable_test test case.
3. Drop modification about macro DEFAULT_GUEST_TEST_MEM, it is problem
of LoongArch binutils, this issue is raised to LoongArch binutils owners.

Changes in v5:
1. In LoongArch kvm self tests, the DEFAULT_GUEST_TEST_MEM could be
0x130000000, it is different from the default value in memstress.h.
So we Move the definition of DEFAULT_GUEST_TEST_MEM into LoongArch
ucall.h, and add 'ifndef' condition for DEFAULT_GUEST_TEST_MEM
in memstress.h.

Changes in v4:
1. Remove the based-on flag, as the LoongArch KVM patch series
have been accepted by Linux kernel, so this can be applied directly
in kernel.

Changes in v3:
1. Improve implementation of LoongArch VM page walk.
2. Add exception handler for LoongArch.
3. Add dirty_log_test, dirty_log_perf_test, guest_print_test
test cases for LoongArch.
4. Add __ASSEMBLER__ macro to distinguish asm file and c file.
5. Move ucall_arch_do_ucall to the header file and make it as
static inline to avoid function calls.
6. Change the DEFAULT_GUEST_TEST_MEM base addr for LoongArch.

Changes in v2:
1. We should use ".balign 4096" to align the assemble code with 4K in
exception.S instead of "align 12".
2. LoongArch only supports 3 or 4 levels page tables, so we remove the
hanlders for 2-levels page table.
3. Remove the DEFAULT_LOONGARCH_GUEST_STACK_VADDR_MIN and use the common
DEFAULT_GUEST_STACK_VADDR_MIN to allocate stack memory in guest.
4. Reorganize the test cases supported by LoongArch.
5. Fix some code comments.
6. Add kvm_binary_stats_test test case into LoongArch KVM selftests.
---
Bibo Mao (5):
  KVM: selftests: Add VM_MODE_P47V47_16K VM mode
  KVM: selftests: Add KVM selftests header files for LoongArch
  KVM: selftests: Add core KVM selftests support for LoongArch
  KVM: selftests: Add ucall test support for LoongArch
  KVM: selftests: Add test cases for LoongArch

 MAINTAINERS                                   |   2 +
 tools/testing/selftests/kvm/Makefile          |   2 +-
 tools/testing/selftests/kvm/Makefile.kvm      |  18 +
 .../testing/selftests/kvm/include/kvm_util.h  |   6 +
 .../kvm/include/loongarch/kvm_util_arch.h     |   7 +
 .../kvm/include/loongarch/processor.h         | 141 ++++++++
 .../selftests/kvm/include/loongarch/ucall.h   |  20 +
 tools/testing/selftests/kvm/lib/kvm_util.c    |   3 +
 .../selftests/kvm/lib/loongarch/exception.S   |  59 +++
 .../selftests/kvm/lib/loongarch/processor.c   | 342 ++++++++++++++++++
 .../selftests/kvm/lib/loongarch/ucall.c       |  38 ++
 .../selftests/kvm/set_memory_region_test.c    |   2 +-
 12 files changed, 638 insertions(+), 2 deletions(-)
 create mode 100644 tools/testing/selftests/kvm/include/loongarch/kvm_util_arch.h
 create mode 100644 tools/testing/selftests/kvm/include/loongarch/processor.h
 create mode 100644 tools/testing/selftests/kvm/include/loongarch/ucall.h
 create mode 100644 tools/testing/selftests/kvm/lib/loongarch/exception.S
 create mode 100644 tools/testing/selftests/kvm/lib/loongarch/processor.c
 create mode 100644 tools/testing/selftests/kvm/lib/loongarch/ucall.c


base-commit: 5bc1018675ec28a8a60d83b378d8c3991faa5a27
-- 
2.39.3


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v11 1/5] KVM: selftests: Add VM_MODE_P47V47_16K VM mode
  2025-04-27  6:45 [PATCH v11 0/5] KVM: selftests: Add LoongArch support Bibo Mao
@ 2025-04-27  6:45 ` Bibo Mao
  2025-04-27  6:45 ` [PATCH v11 2/5] KVM: selftests: Add KVM selftests header files for LoongArch Bibo Mao
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 11+ messages in thread
From: Bibo Mao @ 2025-04-27  6:45 UTC (permalink / raw)
  To: Paolo Bonzini, Huacai Chen, Sean Christopherson
  Cc: Shuah Khan, linux-kernel, kvm, linux-kselftest

On LoongArch system, 16K page is used in general and GVA width is 47 bit
and GPA width is 47 bit also, here add new VM mode VM_MODE_P47V47_16K.

Signed-off-by: Bibo Mao <maobibo@loongson.cn>
---
 tools/testing/selftests/kvm/include/kvm_util.h | 1 +
 tools/testing/selftests/kvm/lib/kvm_util.c     | 3 +++
 2 files changed, 4 insertions(+)

diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing/selftests/kvm/include/kvm_util.h
index 373912464fb4..f8faed8c8024 100644
--- a/tools/testing/selftests/kvm/include/kvm_util.h
+++ b/tools/testing/selftests/kvm/include/kvm_util.h
@@ -177,6 +177,7 @@ enum vm_guest_mode {
 	VM_MODE_P36V48_4K,
 	VM_MODE_P36V48_16K,
 	VM_MODE_P36V48_64K,
+	VM_MODE_P47V47_16K,
 	VM_MODE_P36V47_16K,
 	NUM_VM_MODES,
 };
diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c
index 815bc45dd8dc..5649cf2f40e8 100644
--- a/tools/testing/selftests/kvm/lib/kvm_util.c
+++ b/tools/testing/selftests/kvm/lib/kvm_util.c
@@ -222,6 +222,7 @@ const char *vm_guest_mode_string(uint32_t i)
 		[VM_MODE_P36V48_4K]	= "PA-bits:36,  VA-bits:48,  4K pages",
 		[VM_MODE_P36V48_16K]	= "PA-bits:36,  VA-bits:48, 16K pages",
 		[VM_MODE_P36V48_64K]	= "PA-bits:36,  VA-bits:48, 64K pages",
+		[VM_MODE_P47V47_16K]	= "PA-bits:47,  VA-bits:47, 16K pages",
 		[VM_MODE_P36V47_16K]	= "PA-bits:36,  VA-bits:47, 16K pages",
 	};
 	_Static_assert(sizeof(strings)/sizeof(char *) == NUM_VM_MODES,
@@ -248,6 +249,7 @@ const struct vm_guest_mode_params vm_guest_mode_params[] = {
 	[VM_MODE_P36V48_4K]	= { 36, 48,  0x1000, 12 },
 	[VM_MODE_P36V48_16K]	= { 36, 48,  0x4000, 14 },
 	[VM_MODE_P36V48_64K]	= { 36, 48, 0x10000, 16 },
+	[VM_MODE_P47V47_16K]	= { 47, 47,  0x4000, 14 },
 	[VM_MODE_P36V47_16K]	= { 36, 47,  0x4000, 14 },
 };
 _Static_assert(sizeof(vm_guest_mode_params)/sizeof(struct vm_guest_mode_params) == NUM_VM_MODES,
@@ -319,6 +321,7 @@ struct kvm_vm *____vm_create(struct vm_shape shape)
 	case VM_MODE_P36V48_16K:
 		vm->pgtable_levels = 4;
 		break;
+	case VM_MODE_P47V47_16K:
 	case VM_MODE_P36V47_16K:
 		vm->pgtable_levels = 3;
 		break;
-- 
2.39.3


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v11 2/5] KVM: selftests: Add KVM selftests header files for LoongArch
  2025-04-27  6:45 [PATCH v11 0/5] KVM: selftests: Add LoongArch support Bibo Mao
  2025-04-27  6:45 ` [PATCH v11 1/5] KVM: selftests: Add VM_MODE_P47V47_16K VM mode Bibo Mao
@ 2025-04-27  6:45 ` Bibo Mao
  2025-04-27  6:45 ` [PATCH v11 3/5] KVM: selftests: Add core KVM selftests support " Bibo Mao
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 11+ messages in thread
From: Bibo Mao @ 2025-04-27  6:45 UTC (permalink / raw)
  To: Paolo Bonzini, Huacai Chen, Sean Christopherson
  Cc: Shuah Khan, linux-kernel, kvm, linux-kselftest

Add KVM selftests header files for LoongArch, including processor.h
and kvm_util_arch.h. It mainly contains LoongArch CSR register
and page table entry definition.

Signed-off-by: Bibo Mao <maobibo@loongson.cn>
---
 .../testing/selftests/kvm/include/kvm_util.h  |   5 +
 .../kvm/include/loongarch/kvm_util_arch.h     |   7 +
 .../kvm/include/loongarch/processor.h         | 141 ++++++++++++++++++
 3 files changed, 153 insertions(+)
 create mode 100644 tools/testing/selftests/kvm/include/loongarch/kvm_util_arch.h
 create mode 100644 tools/testing/selftests/kvm/include/loongarch/processor.h

diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing/selftests/kvm/include/kvm_util.h
index f8faed8c8024..93013564428b 100644
--- a/tools/testing/selftests/kvm/include/kvm_util.h
+++ b/tools/testing/selftests/kvm/include/kvm_util.h
@@ -233,6 +233,11 @@ extern enum vm_guest_mode vm_mode_default;
 #define MIN_PAGE_SHIFT			12U
 #define ptes_per_page(page_size)	((page_size) / 8)
 
+#elif defined(__loongarch__)
+#define VM_MODE_DEFAULT			VM_MODE_P47V47_16K
+#define MIN_PAGE_SHIFT			12U
+#define ptes_per_page(page_size)	((page_size) / 8)
+
 #endif
 
 #define VM_SHAPE_DEFAULT	VM_SHAPE(VM_MODE_DEFAULT)
diff --git a/tools/testing/selftests/kvm/include/loongarch/kvm_util_arch.h b/tools/testing/selftests/kvm/include/loongarch/kvm_util_arch.h
new file mode 100644
index 000000000000..e43a57d99b56
--- /dev/null
+++ b/tools/testing/selftests/kvm/include/loongarch/kvm_util_arch.h
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef SELFTEST_KVM_UTIL_ARCH_H
+#define SELFTEST_KVM_UTIL_ARCH_H
+
+struct kvm_vm_arch {};
+
+#endif  // SELFTEST_KVM_UTIL_ARCH_H
diff --git a/tools/testing/selftests/kvm/include/loongarch/processor.h b/tools/testing/selftests/kvm/include/loongarch/processor.h
new file mode 100644
index 000000000000..6427a3275e6a
--- /dev/null
+++ b/tools/testing/selftests/kvm/include/loongarch/processor.h
@@ -0,0 +1,141 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef SELFTEST_KVM_PROCESSOR_H
+#define SELFTEST_KVM_PROCESSOR_H
+
+#ifndef __ASSEMBLER__
+#include "ucall_common.h"
+
+#else
+/* general registers */
+#define zero				$r0
+#define ra				$r1
+#define tp				$r2
+#define sp				$r3
+#define a0				$r4
+#define a1				$r5
+#define a2				$r6
+#define a3				$r7
+#define a4				$r8
+#define a5				$r9
+#define a6				$r10
+#define a7				$r11
+#define t0				$r12
+#define t1				$r13
+#define t2				$r14
+#define t3				$r15
+#define t4				$r16
+#define t5				$r17
+#define t6				$r18
+#define t7				$r19
+#define t8				$r20
+#define u0				$r21
+#define fp				$r22
+#define s0				$r23
+#define s1				$r24
+#define s2				$r25
+#define s3				$r26
+#define s4				$r27
+#define s5				$r28
+#define s6				$r29
+#define s7				$r30
+#define s8				$r31
+#endif
+
+/*
+ * LoongArch page table entry definition
+ * Original header file arch/loongarch/include/asm/loongarch.h
+ */
+#define _PAGE_VALID_SHIFT		0
+#define _PAGE_DIRTY_SHIFT		1
+#define _PAGE_PLV_SHIFT			2  /* 2~3, two bits */
+#define  PLV_KERN			0
+#define  PLV_USER			3
+#define  PLV_MASK			0x3
+#define _CACHE_SHIFT			4  /* 4~5, two bits */
+#define _PAGE_PRESENT_SHIFT		7
+#define _PAGE_WRITE_SHIFT		8
+
+#define _PAGE_VALID			BIT_ULL(_PAGE_VALID_SHIFT)
+#define _PAGE_PRESENT			BIT_ULL(_PAGE_PRESENT_SHIFT)
+#define _PAGE_WRITE			BIT_ULL(_PAGE_WRITE_SHIFT)
+#define _PAGE_DIRTY			BIT_ULL(_PAGE_DIRTY_SHIFT)
+#define _PAGE_USER			(PLV_USER << _PAGE_PLV_SHIFT)
+#define   __READABLE			(_PAGE_VALID)
+#define   __WRITEABLE			(_PAGE_DIRTY | _PAGE_WRITE)
+/* Coherent Cached */
+#define _CACHE_CC			BIT_ULL(_CACHE_SHIFT)
+#define PS_4K				0x0000000c
+#define PS_16K				0x0000000e
+#define PS_64K				0x00000010
+#define PS_DEFAULT_SIZE			PS_16K
+
+/* LoongArch Basic CSR registers */
+#define LOONGARCH_CSR_CRMD		0x0 /* Current mode info */
+#define  CSR_CRMD_PG_SHIFT		4
+#define  CSR_CRMD_PG			BIT_ULL(CSR_CRMD_PG_SHIFT)
+#define  CSR_CRMD_IE_SHIFT		2
+#define  CSR_CRMD_IE			BIT_ULL(CSR_CRMD_IE_SHIFT)
+#define  CSR_CRMD_PLV_SHIFT		0
+#define  CSR_CRMD_PLV_WIDTH		2
+#define  CSR_CRMD_PLV			(0x3UL << CSR_CRMD_PLV_SHIFT)
+#define  PLV_MASK			0x3
+#define LOONGARCH_CSR_PRMD		0x1
+#define LOONGARCH_CSR_EUEN		0x2
+#define LOONGARCH_CSR_ECFG		0x4
+#define LOONGARCH_CSR_ESTAT		0x5  /* Exception status */
+#define LOONGARCH_CSR_ERA		0x6  /* ERA */
+#define LOONGARCH_CSR_BADV		0x7  /* Bad virtual address */
+#define LOONGARCH_CSR_EENTRY		0xc
+#define LOONGARCH_CSR_TLBIDX		0x10 /* TLB Index, EHINV, PageSize */
+#define  CSR_TLBIDX_PS_SHIFT		24
+#define  CSR_TLBIDX_PS_WIDTH		6
+#define  CSR_TLBIDX_PS			(0x3fUL << CSR_TLBIDX_PS_SHIFT)
+#define  CSR_TLBIDX_SIZEM		0x3f000000
+#define  CSR_TLBIDX_SIZE		CSR_TLBIDX_PS_SHIFT
+#define LOONGARCH_CSR_ASID		0x18 /* ASID */
+#define LOONGARCH_CSR_PGDL		0x19
+#define LOONGARCH_CSR_PGDH		0x1a
+/* Page table base */
+#define LOONGARCH_CSR_PGD		0x1b
+#define LOONGARCH_CSR_PWCTL0		0x1c
+#define LOONGARCH_CSR_PWCTL1		0x1d
+#define LOONGARCH_CSR_STLBPGSIZE	0x1e
+#define LOONGARCH_CSR_CPUID		0x20
+#define LOONGARCH_CSR_KS0		0x30
+#define LOONGARCH_CSR_KS1		0x31
+#define LOONGARCH_CSR_TMID		0x40
+#define LOONGARCH_CSR_TCFG		0x41
+/* TLB refill exception entry */
+#define LOONGARCH_CSR_TLBRENTRY		0x88
+#define LOONGARCH_CSR_TLBRSAVE		0x8b
+#define LOONGARCH_CSR_TLBREHI		0x8e
+#define  CSR_TLBREHI_PS_SHIFT		0
+#define  CSR_TLBREHI_PS			(0x3fUL << CSR_TLBREHI_PS_SHIFT)
+
+#define EXREGS_GPRS			(32)
+
+#ifndef __ASSEMBLER__
+void handle_tlb_refill(void);
+void handle_exception(void);
+
+struct ex_regs {
+	unsigned long regs[EXREGS_GPRS];
+	unsigned long pc;
+	unsigned long estat;
+	unsigned long badv;
+};
+
+#define PC_OFFSET_EXREGS		offsetof(struct ex_regs, pc)
+#define ESTAT_OFFSET_EXREGS		offsetof(struct ex_regs, estat)
+#define BADV_OFFSET_EXREGS		offsetof(struct ex_regs, badv)
+#define EXREGS_SIZE			sizeof(struct ex_regs)
+
+#else
+#define PC_OFFSET_EXREGS		((EXREGS_GPRS + 0) * 8)
+#define ESTAT_OFFSET_EXREGS		((EXREGS_GPRS + 1) * 8)
+#define BADV_OFFSET_EXREGS		((EXREGS_GPRS + 2) * 8)
+#define EXREGS_SIZE			((EXREGS_GPRS + 3) * 8)
+#endif
+
+#endif /* SELFTEST_KVM_PROCESSOR_H */
-- 
2.39.3


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v11 3/5] KVM: selftests: Add core KVM selftests support for LoongArch
  2025-04-27  6:45 [PATCH v11 0/5] KVM: selftests: Add LoongArch support Bibo Mao
  2025-04-27  6:45 ` [PATCH v11 1/5] KVM: selftests: Add VM_MODE_P47V47_16K VM mode Bibo Mao
  2025-04-27  6:45 ` [PATCH v11 2/5] KVM: selftests: Add KVM selftests header files for LoongArch Bibo Mao
@ 2025-04-27  6:45 ` Bibo Mao
  2025-05-12  6:53   ` Huacai Chen
  2025-04-27  6:45 ` [PATCH v11 4/5] KVM: selftests: Add ucall test " Bibo Mao
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 11+ messages in thread
From: Bibo Mao @ 2025-04-27  6:45 UTC (permalink / raw)
  To: Paolo Bonzini, Huacai Chen, Sean Christopherson
  Cc: Shuah Khan, linux-kernel, kvm, linux-kselftest

Add core KVM selftests support for LoongArch, it includes exception
handler, mmu page table setup and vCPU startup entry support.

Signed-off-by: Bibo Mao <maobibo@loongson.cn>
---
 .../selftests/kvm/lib/loongarch/exception.S   |  59 +++
 .../selftests/kvm/lib/loongarch/processor.c   | 342 ++++++++++++++++++
 2 files changed, 401 insertions(+)
 create mode 100644 tools/testing/selftests/kvm/lib/loongarch/exception.S
 create mode 100644 tools/testing/selftests/kvm/lib/loongarch/processor.c

diff --git a/tools/testing/selftests/kvm/lib/loongarch/exception.S b/tools/testing/selftests/kvm/lib/loongarch/exception.S
new file mode 100644
index 000000000000..88bfa505c6f5
--- /dev/null
+++ b/tools/testing/selftests/kvm/lib/loongarch/exception.S
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#include "processor.h"
+
+/* address of refill exception should be 4K aligned */
+.balign	4096
+.global handle_tlb_refill
+handle_tlb_refill:
+	csrwr	t0, LOONGARCH_CSR_TLBRSAVE
+	csrrd	t0, LOONGARCH_CSR_PGD
+	lddir	t0, t0, 3
+	lddir	t0, t0, 1
+	ldpte	t0, 0
+	ldpte	t0, 1
+	tlbfill
+	csrrd	t0, LOONGARCH_CSR_TLBRSAVE
+	ertn
+
+	/*
+	 * save and restore all gprs except base register,
+	 * and default value of base register is sp ($r3).
+	 */
+.macro save_gprs base
+	.irp n,1,2,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
+	st.d    $r\n, \base, 8 * \n
+	.endr
+.endm
+
+.macro restore_gprs base
+	.irp n,1,2,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
+	ld.d    $r\n, \base, 8 * \n
+	.endr
+.endm
+
+/* address of general exception should be 4K aligned */
+.balign	4096
+.global handle_exception
+handle_exception:
+	csrwr  sp, LOONGARCH_CSR_KS0
+	csrrd  sp, LOONGARCH_CSR_KS1
+	addi.d sp, sp, -EXREGS_SIZE
+
+	save_gprs sp
+	/* save sp register to stack */
+	csrrd  t0, LOONGARCH_CSR_KS0
+	st.d   t0, sp, 3 * 8
+
+	csrrd  t0, LOONGARCH_CSR_ERA
+	st.d   t0, sp, PC_OFFSET_EXREGS
+	csrrd  t0, LOONGARCH_CSR_ESTAT
+	st.d   t0, sp, ESTAT_OFFSET_EXREGS
+	csrrd  t0, LOONGARCH_CSR_BADV
+	st.d   t0, sp, BADV_OFFSET_EXREGS
+
+	or     a0, sp, zero
+	bl route_exception
+	restore_gprs sp
+	csrrd  sp, LOONGARCH_CSR_KS0
+	ertn
diff --git a/tools/testing/selftests/kvm/lib/loongarch/processor.c b/tools/testing/selftests/kvm/lib/loongarch/processor.c
new file mode 100644
index 000000000000..82d3f041f57a
--- /dev/null
+++ b/tools/testing/selftests/kvm/lib/loongarch/processor.c
@@ -0,0 +1,342 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <assert.h>
+#include <linux/compiler.h>
+
+#include "kvm_util.h"
+#include "processor.h"
+#include "ucall_common.h"
+
+#define LOONGARCH_GUEST_STACK_VADDR_MIN		0x200000
+#define LOONGARCH_PAGE_TABLE_PHYS_MIN		0x200000
+
+static vm_paddr_t invalid_pgtable[4];
+static uint64_t virt_pte_index(struct kvm_vm *vm, vm_vaddr_t gva, int level)
+{
+	unsigned int shift;
+	uint64_t mask;
+
+	shift = level * (vm->page_shift - 3) + vm->page_shift;
+	mask = (1UL << (vm->page_shift - 3)) - 1;
+	return (gva >> shift) & mask;
+}
+
+static uint64_t pte_addr(struct kvm_vm *vm, uint64_t entry)
+{
+	return entry &  ~((0x1UL << vm->page_shift) - 1);
+}
+
+static uint64_t ptrs_per_pte(struct kvm_vm *vm)
+{
+	return 1 << (vm->page_shift - 3);
+}
+
+static void virt_set_pgtable(struct kvm_vm *vm, vm_paddr_t table, vm_paddr_t child)
+{
+	uint64_t *ptep;
+	int i, ptrs_per_pte;
+
+	ptep = addr_gpa2hva(vm, table);
+	ptrs_per_pte = 1 << (vm->page_shift - 3);
+	for (i = 0; i < ptrs_per_pte; i++)
+		WRITE_ONCE(*(ptep + i), child);
+}
+
+void virt_arch_pgd_alloc(struct kvm_vm *vm)
+{
+	int i;
+	vm_paddr_t child, table;
+
+	if (vm->pgd_created)
+		return;
+	child = table = 0;
+	for (i = 0; i < vm->pgtable_levels; i++) {
+		invalid_pgtable[i] = child;
+		table = vm_phy_page_alloc(vm, LOONGARCH_PAGE_TABLE_PHYS_MIN,
+				vm->memslots[MEM_REGION_PT]);
+		TEST_ASSERT(table, "Fail to allocate page tale at level %d\n", i);
+		virt_set_pgtable(vm, table, child);
+		child = table;
+	}
+	vm->pgd = table;
+	vm->pgd_created = true;
+}
+
+static int virt_pte_none(uint64_t *ptep, int level)
+{
+	return *ptep == invalid_pgtable[level];
+}
+
+static uint64_t *virt_populate_pte(struct kvm_vm *vm, vm_vaddr_t gva, int alloc)
+{
+	uint64_t *ptep;
+	vm_paddr_t child;
+	int level;
+
+	if (!vm->pgd_created)
+		goto unmapped_gva;
+
+	level = vm->pgtable_levels - 1;
+	child = vm->pgd;
+	while (level > 0) {
+		ptep = addr_gpa2hva(vm, child) + virt_pte_index(vm, gva, level) * 8;
+		if (virt_pte_none(ptep, level)) {
+			if (alloc) {
+				child = vm_alloc_page_table(vm);
+				virt_set_pgtable(vm, child, invalid_pgtable[level - 1]);
+				WRITE_ONCE(*ptep, child);
+			} else
+				goto unmapped_gva;
+
+		} else
+			child = pte_addr(vm, *ptep);
+		level--;
+	}
+
+	ptep = addr_gpa2hva(vm, child) + virt_pte_index(vm, gva, level) * 8;
+	return ptep;
+
+unmapped_gva:
+	TEST_FAIL("No mapping for vm virtual address, gva: 0x%lx", gva);
+	exit(EXIT_FAILURE);
+}
+
+vm_paddr_t addr_arch_gva2gpa(struct kvm_vm *vm, vm_vaddr_t gva)
+{
+	uint64_t *ptep;
+
+	ptep = virt_populate_pte(vm, gva, 0);
+	TEST_ASSERT(*ptep != 0, "Virtual address vaddr: 0x%lx not mapped\n", gva);
+
+	return pte_addr(vm, *ptep) + (gva & (vm->page_size - 1));
+}
+
+void virt_arch_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr)
+{
+	uint32_t prot_bits;
+	uint64_t *ptep;
+
+	TEST_ASSERT((vaddr % vm->page_size) == 0,
+			"Virtual address not on page boundary,\n"
+			"vaddr: 0x%lx vm->page_size: 0x%x", vaddr, vm->page_size);
+	TEST_ASSERT(sparsebit_is_set(vm->vpages_valid,
+			(vaddr >> vm->page_shift)),
+			"Invalid virtual address, vaddr: 0x%lx", vaddr);
+	TEST_ASSERT((paddr % vm->page_size) == 0,
+			"Physical address not on page boundary,\n"
+			"paddr: 0x%lx vm->page_size: 0x%x", paddr, vm->page_size);
+	TEST_ASSERT((paddr >> vm->page_shift) <= vm->max_gfn,
+			"Physical address beyond maximum supported,\n"
+			"paddr: 0x%lx vm->max_gfn: 0x%lx vm->page_size: 0x%x",
+			paddr, vm->max_gfn, vm->page_size);
+
+	ptep = virt_populate_pte(vm, vaddr, 1);
+	prot_bits = _PAGE_PRESENT | __READABLE | __WRITEABLE | _CACHE_CC;
+	prot_bits |= _PAGE_USER;
+	WRITE_ONCE(*ptep, paddr | prot_bits);
+}
+
+static void pte_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent, uint64_t page, int level)
+{
+	static const char * const type[] = { "pte", "pmd", "pud", "pgd"};
+	uint64_t pte, *ptep;
+
+	if (level < 0)
+		return;
+
+	for (pte = page; pte < page + ptrs_per_pte(vm) * 8; pte += 8) {
+		ptep = addr_gpa2hva(vm, pte);
+		if (virt_pte_none(ptep, level))
+			continue;
+		fprintf(stream, "%*s%s: %lx: %lx at %p\n",
+				indent, "", type[level], pte, *ptep, ptep);
+		pte_dump(stream, vm, indent + 1, pte_addr(vm, *ptep), level--);
+	}
+}
+
+void virt_arch_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent)
+{
+	int level;
+
+	if (!vm->pgd_created)
+		return;
+
+	level = vm->pgtable_levels - 1;
+	pte_dump(stream, vm, indent, vm->pgd, level);
+}
+
+void vcpu_arch_dump(FILE *stream, struct kvm_vcpu *vcpu, uint8_t indent)
+{
+}
+
+void assert_on_unhandled_exception(struct kvm_vcpu *vcpu)
+{
+	struct ucall uc;
+
+	if (get_ucall(vcpu, &uc) != UCALL_UNHANDLED)
+		return;
+
+	TEST_FAIL("Unexpected exception (pc:0x%lx, estat:0x%lx, badv:0x%lx)",
+			uc.args[0], uc.args[1], uc.args[2]);
+}
+
+void route_exception(struct ex_regs *regs)
+{
+	unsigned long pc, estat, badv;
+
+	pc = regs->pc;
+	estat = regs->estat;
+	badv  = regs->badv;
+	ucall(UCALL_UNHANDLED, 3, pc, estat, badv);
+	while (1)
+		;
+}
+
+void vcpu_args_set(struct kvm_vcpu *vcpu, unsigned int num, ...)
+{
+	va_list ap;
+	struct kvm_regs regs;
+	int i;
+
+	TEST_ASSERT(num >= 1 && num <= 8, "Unsupported number of args,\n"
+		    "num: %u\n", num);
+
+	vcpu_regs_get(vcpu, &regs);
+	va_start(ap, num);
+	for (i = 0; i < num; i++)
+		regs.gpr[i + 4] = va_arg(ap, uint64_t);
+	va_end(ap);
+	vcpu_regs_set(vcpu, &regs);
+}
+
+static void loongarch_get_csr(struct kvm_vcpu *vcpu, uint64_t id, void *addr)
+{
+	uint64_t csrid;
+
+	csrid = KVM_REG_LOONGARCH_CSR | KVM_REG_SIZE_U64 | 8 * id;
+	__vcpu_get_reg(vcpu, csrid, addr);
+}
+
+static void loongarch_set_csr(struct kvm_vcpu *vcpu, uint64_t id, uint64_t val)
+{
+	uint64_t csrid;
+
+	csrid = KVM_REG_LOONGARCH_CSR | KVM_REG_SIZE_U64 | 8 * id;
+	vcpu_set_reg(vcpu, csrid, val);
+}
+
+static void loongarch_vcpu_setup(struct kvm_vcpu *vcpu)
+{
+	unsigned long val;
+	int width;
+	struct kvm_vm *vm = vcpu->vm;
+
+	switch (vm->mode) {
+	case VM_MODE_P36V47_16K:
+	case VM_MODE_P47V47_16K:
+		break;
+
+	default:
+		TEST_FAIL("Unknown guest mode, mode: 0x%x", vm->mode);
+	}
+
+	/* user mode and page enable mode */
+	val = PLV_USER | CSR_CRMD_PG;
+	loongarch_set_csr(vcpu, LOONGARCH_CSR_CRMD, val);
+	loongarch_set_csr(vcpu, LOONGARCH_CSR_PRMD, val);
+	loongarch_set_csr(vcpu, LOONGARCH_CSR_EUEN, 1);
+	loongarch_set_csr(vcpu, LOONGARCH_CSR_ECFG, 0);
+	loongarch_set_csr(vcpu, LOONGARCH_CSR_TCFG, 0);
+	loongarch_set_csr(vcpu, LOONGARCH_CSR_ASID, 1);
+
+	width = vm->page_shift - 3;
+	val = 0;
+	switch (vm->pgtable_levels) {
+	case 4:
+		/* pud page shift and width */
+		val = (vm->page_shift + width * 2) << 20 | (width << 25);
+		/* fall throuth */
+	case 3:
+		/* pmd page shift and width */
+		val |= (vm->page_shift + width) << 10 | (width << 15);
+		/* pte page shift and width */
+		val |= vm->page_shift | width << 5;
+		break;
+	default:
+		TEST_FAIL("Got %u page table levels, expected 3 or 4", vm->pgtable_levels);
+	}
+	loongarch_set_csr(vcpu, LOONGARCH_CSR_PWCTL0, val);
+
+	/* PGD page shift and width */
+	val = (vm->page_shift + width * (vm->pgtable_levels - 1)) | width << 6;
+	loongarch_set_csr(vcpu, LOONGARCH_CSR_PWCTL1, val);
+	loongarch_set_csr(vcpu, LOONGARCH_CSR_PGDL, vm->pgd);
+
+	/*
+	 * Refill exception runs on real mode
+	 * Entry address should be physical address
+	 */
+	val = addr_gva2gpa(vm, (unsigned long)handle_tlb_refill);
+	loongarch_set_csr(vcpu, LOONGARCH_CSR_TLBRENTRY, val);
+
+	/*
+	 * General exception runs on page-enabled mode
+	 * Entry address should be virtual address
+	 */
+	val = (unsigned long)handle_exception;
+	loongarch_set_csr(vcpu, LOONGARCH_CSR_EENTRY, val);
+
+	loongarch_get_csr(vcpu, LOONGARCH_CSR_TLBIDX, &val);
+	val &= ~CSR_TLBIDX_SIZEM;
+	val |= PS_DEFAULT_SIZE << CSR_TLBIDX_SIZE;
+	loongarch_set_csr(vcpu, LOONGARCH_CSR_TLBIDX, val);
+
+	loongarch_set_csr(vcpu, LOONGARCH_CSR_STLBPGSIZE, PS_DEFAULT_SIZE);
+
+	/* LOONGARCH_CSR_KS1 is used for exception stack */
+	val = __vm_vaddr_alloc(vm, vm->page_size,
+			LOONGARCH_GUEST_STACK_VADDR_MIN, MEM_REGION_DATA);
+	TEST_ASSERT(val != 0,  "No memory for exception stack");
+	val = val + vm->page_size;
+	loongarch_set_csr(vcpu, LOONGARCH_CSR_KS1, val);
+
+	loongarch_get_csr(vcpu, LOONGARCH_CSR_TLBREHI, &val);
+	val &= ~CSR_TLBREHI_PS;
+	val |= PS_DEFAULT_SIZE << CSR_TLBREHI_PS_SHIFT;
+	loongarch_set_csr(vcpu, LOONGARCH_CSR_TLBREHI, val);
+
+	loongarch_set_csr(vcpu, LOONGARCH_CSR_CPUID, vcpu->id);
+	loongarch_set_csr(vcpu, LOONGARCH_CSR_TMID,  vcpu->id);
+}
+
+struct kvm_vcpu *vm_arch_vcpu_add(struct kvm_vm *vm, uint32_t vcpu_id)
+{
+	size_t stack_size;
+	uint64_t stack_vaddr;
+	struct kvm_regs regs;
+	struct kvm_vcpu *vcpu;
+
+	vcpu = __vm_vcpu_add(vm, vcpu_id);
+	stack_size = vm->page_size;
+	stack_vaddr = __vm_vaddr_alloc(vm, stack_size,
+			LOONGARCH_GUEST_STACK_VADDR_MIN, MEM_REGION_DATA);
+	TEST_ASSERT(stack_vaddr != 0,  "No memory for vm stack");
+
+	loongarch_vcpu_setup(vcpu);
+	/* Setup guest general purpose registers */
+	vcpu_regs_get(vcpu, &regs);
+	regs.gpr[3] = stack_vaddr + stack_size;
+	vcpu_regs_set(vcpu, &regs);
+
+	return vcpu;
+}
+
+void vcpu_arch_set_entry_point(struct kvm_vcpu *vcpu, void *guest_code)
+{
+	struct kvm_regs regs;
+
+	/* Setup guest PC register */
+	vcpu_regs_get(vcpu, &regs);
+	regs.pc = (uint64_t)guest_code;
+	vcpu_regs_set(vcpu, &regs);
+}
-- 
2.39.3


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v11 4/5] KVM: selftests: Add ucall test support for LoongArch
  2025-04-27  6:45 [PATCH v11 0/5] KVM: selftests: Add LoongArch support Bibo Mao
                   ` (2 preceding siblings ...)
  2025-04-27  6:45 ` [PATCH v11 3/5] KVM: selftests: Add core KVM selftests support " Bibo Mao
@ 2025-04-27  6:45 ` Bibo Mao
  2025-04-27  6:45 ` [PATCH v11 5/5] KVM: selftests: Add test cases " Bibo Mao
  2025-05-12  6:53 ` [PATCH v11 0/5] KVM: selftests: Add LoongArch support Huacai Chen
  5 siblings, 0 replies; 11+ messages in thread
From: Bibo Mao @ 2025-04-27  6:45 UTC (permalink / raw)
  To: Paolo Bonzini, Huacai Chen, Sean Christopherson
  Cc: Shuah Khan, linux-kernel, kvm, linux-kselftest

Add ucall test support for LoongArch, ucall method on LoongArch uses
undefined mmio area. It will cause vCPU exiting to hypervisor so that
hypervisor can communicate with vCPU.

Signed-off-by: Bibo Mao <maobibo@loongson.cn>
---
 .../selftests/kvm/include/loongarch/ucall.h   | 20 ++++++++++
 .../selftests/kvm/lib/loongarch/ucall.c       | 38 +++++++++++++++++++
 2 files changed, 58 insertions(+)
 create mode 100644 tools/testing/selftests/kvm/include/loongarch/ucall.h
 create mode 100644 tools/testing/selftests/kvm/lib/loongarch/ucall.c

diff --git a/tools/testing/selftests/kvm/include/loongarch/ucall.h b/tools/testing/selftests/kvm/include/loongarch/ucall.h
new file mode 100644
index 000000000000..4ec801f37f00
--- /dev/null
+++ b/tools/testing/selftests/kvm/include/loongarch/ucall.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef SELFTEST_KVM_UCALL_H
+#define SELFTEST_KVM_UCALL_H
+
+#include "kvm_util.h"
+
+#define UCALL_EXIT_REASON       KVM_EXIT_MMIO
+
+/*
+ * ucall_exit_mmio_addr holds per-VM values (global data is duplicated by each
+ * VM), it must not be accessed from host code.
+ */
+extern vm_vaddr_t *ucall_exit_mmio_addr;
+
+static inline void ucall_arch_do_ucall(vm_vaddr_t uc)
+{
+	WRITE_ONCE(*ucall_exit_mmio_addr, uc);
+}
+
+#endif
diff --git a/tools/testing/selftests/kvm/lib/loongarch/ucall.c b/tools/testing/selftests/kvm/lib/loongarch/ucall.c
new file mode 100644
index 000000000000..fc6cbb50573f
--- /dev/null
+++ b/tools/testing/selftests/kvm/lib/loongarch/ucall.c
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ucall support. A ucall is a "hypercall to userspace".
+ *
+ */
+#include "kvm_util.h"
+
+/*
+ * ucall_exit_mmio_addr holds per-VM values (global data is duplicated by each
+ * VM), it must not be accessed from host code.
+ */
+vm_vaddr_t *ucall_exit_mmio_addr;
+
+void ucall_arch_init(struct kvm_vm *vm, vm_paddr_t mmio_gpa)
+{
+	vm_vaddr_t mmio_gva = vm_vaddr_unused_gap(vm, vm->page_size, KVM_UTIL_MIN_VADDR);
+
+	virt_map(vm, mmio_gva, mmio_gpa, 1);
+
+	vm->ucall_mmio_addr = mmio_gpa;
+
+	write_guest_global(vm, ucall_exit_mmio_addr, (vm_vaddr_t *)mmio_gva);
+}
+
+void *ucall_arch_get_ucall(struct kvm_vcpu *vcpu)
+{
+	struct kvm_run *run = vcpu->run;
+
+	if (run->exit_reason == KVM_EXIT_MMIO &&
+	    run->mmio.phys_addr == vcpu->vm->ucall_mmio_addr) {
+		TEST_ASSERT(run->mmio.is_write && run->mmio.len == sizeof(uint64_t),
+			    "Unexpected ucall exit mmio address access");
+
+		return (void *)(*((uint64_t *)run->mmio.data));
+	}
+
+	return NULL;
+}
-- 
2.39.3


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v11 5/5] KVM: selftests: Add test cases for LoongArch
  2025-04-27  6:45 [PATCH v11 0/5] KVM: selftests: Add LoongArch support Bibo Mao
                   ` (3 preceding siblings ...)
  2025-04-27  6:45 ` [PATCH v11 4/5] KVM: selftests: Add ucall test " Bibo Mao
@ 2025-04-27  6:45 ` Bibo Mao
  2025-05-12  6:54   ` Huacai Chen
  2025-05-12  6:53 ` [PATCH v11 0/5] KVM: selftests: Add LoongArch support Huacai Chen
  5 siblings, 1 reply; 11+ messages in thread
From: Bibo Mao @ 2025-04-27  6:45 UTC (permalink / raw)
  To: Paolo Bonzini, Huacai Chen, Sean Christopherson
  Cc: Shuah Khan, linux-kernel, kvm, linux-kselftest

Some common KVM test cases are supported on LoongArch now as following:
  coalesced_io_test
  demand_paging_test
  dirty_log_perf_test
  dirty_log_test
  guest_print_test
  hardware_disable_test
  kvm_binary_stats_test
  kvm_create_max_vcpus
  kvm_page_table_test
  memslot_modification_stress_test
  memslot_perf_test
  set_memory_region_test
And other test cases are not supported by LoongArch such as rseq_test,
since it is not supported on LoongArch physical machine either.

Signed-off-by: Bibo Mao <maobibo@loongson.cn>
---
 MAINTAINERS                                    |  2 ++
 tools/testing/selftests/kvm/Makefile           |  2 +-
 tools/testing/selftests/kvm/Makefile.kvm       | 18 ++++++++++++++++++
 .../selftests/kvm/set_memory_region_test.c     |  2 +-
 4 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 3cbf9ac0d83f..20cb455e0821 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -13043,6 +13043,8 @@ F:	Documentation/virt/kvm/loongarch/
 F:	arch/loongarch/include/asm/kvm*
 F:	arch/loongarch/include/uapi/asm/kvm*
 F:	arch/loongarch/kvm/
+F:	tools/testing/selftests/kvm/*/loongarch/
+F:	tools/testing/selftests/kvm/lib/loongarch/
 
 KERNEL VIRTUAL MACHINE FOR MIPS (KVM/mips)
 M:	Huacai Chen <chenhuacai@kernel.org>
diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile
index 20af35a91d6f..d9fffe06d3ea 100644
--- a/tools/testing/selftests/kvm/Makefile
+++ b/tools/testing/selftests/kvm/Makefile
@@ -3,7 +3,7 @@ top_srcdir = ../../../..
 include $(top_srcdir)/scripts/subarch.include
 ARCH            ?= $(SUBARCH)
 
-ifeq ($(ARCH),$(filter $(ARCH),arm64 s390 riscv x86 x86_64))
+ifeq ($(ARCH),$(filter $(ARCH),arm64 s390 riscv x86 x86_64 loongarch))
 # Top-level selftests allows ARCH=x86_64 :-(
 ifeq ($(ARCH),x86_64)
 	ARCH := x86
diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selftests/kvm/Makefile.kvm
index f62b0a5aba35..7985bb42d2c1 100644
--- a/tools/testing/selftests/kvm/Makefile.kvm
+++ b/tools/testing/selftests/kvm/Makefile.kvm
@@ -47,6 +47,10 @@ LIBKVM_riscv += lib/riscv/handlers.S
 LIBKVM_riscv += lib/riscv/processor.c
 LIBKVM_riscv += lib/riscv/ucall.c
 
+LIBKVM_loongarch += lib/loongarch/processor.c
+LIBKVM_loongarch += lib/loongarch/ucall.c
+LIBKVM_loongarch += lib/loongarch/exception.S
+
 # Non-compiled test targets
 TEST_PROGS_x86 += x86/nx_huge_pages_test.sh
 
@@ -190,6 +194,20 @@ TEST_GEN_PROGS_riscv += coalesced_io_test
 TEST_GEN_PROGS_riscv += get-reg-list
 TEST_GEN_PROGS_riscv += steal_time
 
+TEST_GEN_PROGS_loongarch += coalesced_io_test
+TEST_GEN_PROGS_loongarch += demand_paging_test
+TEST_GEN_PROGS_loongarch += dirty_log_perf_test
+TEST_GEN_PROGS_loongarch += dirty_log_test
+TEST_GEN_PROGS_loongarch += demand_paging_test
+TEST_GEN_PROGS_loongarch += guest_print_test
+TEST_GEN_PROGS_loongarch += hardware_disable_test
+TEST_GEN_PROGS_loongarch += kvm_binary_stats_test
+TEST_GEN_PROGS_loongarch += kvm_create_max_vcpus
+TEST_GEN_PROGS_loongarch += kvm_page_table_test
+TEST_GEN_PROGS_loongarch += memslot_modification_stress_test
+TEST_GEN_PROGS_loongarch += memslot_perf_test
+TEST_GEN_PROGS_loongarch += set_memory_region_test
+
 SPLIT_TESTS += arch_timer
 SPLIT_TESTS += get-reg-list
 
diff --git a/tools/testing/selftests/kvm/set_memory_region_test.c b/tools/testing/selftests/kvm/set_memory_region_test.c
index bc440d5aba57..ce3ac0fd6dfb 100644
--- a/tools/testing/selftests/kvm/set_memory_region_test.c
+++ b/tools/testing/selftests/kvm/set_memory_region_test.c
@@ -350,7 +350,7 @@ static void test_invalid_memory_region_flags(void)
 	struct kvm_vm *vm;
 	int r, i;
 
-#if defined __aarch64__ || defined __riscv || defined __x86_64__
+#if defined __aarch64__ || defined __riscv || defined __x86_64__ || defined __loongarch__
 	supported_flags |= KVM_MEM_READONLY;
 #endif
 
-- 
2.39.3


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v11 0/5] KVM: selftests: Add LoongArch support
  2025-04-27  6:45 [PATCH v11 0/5] KVM: selftests: Add LoongArch support Bibo Mao
                   ` (4 preceding siblings ...)
  2025-04-27  6:45 ` [PATCH v11 5/5] KVM: selftests: Add test cases " Bibo Mao
@ 2025-05-12  6:53 ` Huacai Chen
  2025-05-19  7:50   ` Bibo Mao
  2025-05-19  9:42   ` Bibo Mao
  5 siblings, 2 replies; 11+ messages in thread
From: Huacai Chen @ 2025-05-12  6:53 UTC (permalink / raw)
  To: Bibo Mao
  Cc: Paolo Bonzini, Sean Christopherson, Shuah Khan, linux-kernel,
	kvm, linux-kselftest

Hi, Bibo,

On Sun, Apr 27, 2025 at 2:45 PM Bibo Mao <maobibo@loongson.cn> wrote:
>
> This patchset adds KVM selftests for LoongArch system, currently only
> some common test cases are supported and pass to run. These test cases
> are listed as following:
>     coalesced_io_test
>     demand_paging_test
>     dirty_log_perf_test
>     dirty_log_test
>     guest_print_test
>     hardware_disable_test
>     kvm_binary_stats_test
>     kvm_create_max_vcpus
>     kvm_page_table_test
>     memslot_modification_stress_test
>     memslot_perf_test
>     set_memory_region_test
I have applied this series [1] but with some modifications (see
comments in other patches). You can test it to see if everything is
OK.

And if it's OK, it is better to fetch the patches from [1] and then send V12.

[1] https://github.com/chenhuacai/linux/commits/loongarch-next



Huacai

>
> ---
> Changes in v11:
> 1. Fix a typo issue in notes of patch 2, it is kvm_util_arch.h rather than
>    kvm_util_base.h
>
> Changes in v10:
> 1. Add PS_64K and remove PS_8K in file include/loongarch/processor.h
> 2. Fix a typo issue in file lib/loongarch/processor.c
> 3. Update file MAINTAINERS about LoongArch KVM selftests
>
> Changes in v9:
> 1. Add vm mode VM_MODE_P47V47_16K, LoongArch VM uses this mode by
>    default, rather than VM_MODE_P36V47_16K.
> 2. Refresh some spelling issues in changelog.
>
> Changes in v8:
> 1. Porting patch based on the latest version.
> 2. For macro PC_OFFSET_EXREGS, offsetof() method is used for C header file,
>    still hardcoded definition for assemble language.
>
> Changes in v7:
> 1. Refine code to add LoongArch support in test case
> set_memory_region_test.
>
> Changes in v6:
> 1. Refresh the patch based on latest kernel 6.8-rc1, add LoongArch
> support about testcase set_memory_region_test.
> 2. Add hardware_disable_test test case.
> 3. Drop modification about macro DEFAULT_GUEST_TEST_MEM, it is problem
> of LoongArch binutils, this issue is raised to LoongArch binutils owners.
>
> Changes in v5:
> 1. In LoongArch kvm self tests, the DEFAULT_GUEST_TEST_MEM could be
> 0x130000000, it is different from the default value in memstress.h.
> So we Move the definition of DEFAULT_GUEST_TEST_MEM into LoongArch
> ucall.h, and add 'ifndef' condition for DEFAULT_GUEST_TEST_MEM
> in memstress.h.
>
> Changes in v4:
> 1. Remove the based-on flag, as the LoongArch KVM patch series
> have been accepted by Linux kernel, so this can be applied directly
> in kernel.
>
> Changes in v3:
> 1. Improve implementation of LoongArch VM page walk.
> 2. Add exception handler for LoongArch.
> 3. Add dirty_log_test, dirty_log_perf_test, guest_print_test
> test cases for LoongArch.
> 4. Add __ASSEMBLER__ macro to distinguish asm file and c file.
> 5. Move ucall_arch_do_ucall to the header file and make it as
> static inline to avoid function calls.
> 6. Change the DEFAULT_GUEST_TEST_MEM base addr for LoongArch.
>
> Changes in v2:
> 1. We should use ".balign 4096" to align the assemble code with 4K in
> exception.S instead of "align 12".
> 2. LoongArch only supports 3 or 4 levels page tables, so we remove the
> hanlders for 2-levels page table.
> 3. Remove the DEFAULT_LOONGARCH_GUEST_STACK_VADDR_MIN and use the common
> DEFAULT_GUEST_STACK_VADDR_MIN to allocate stack memory in guest.
> 4. Reorganize the test cases supported by LoongArch.
> 5. Fix some code comments.
> 6. Add kvm_binary_stats_test test case into LoongArch KVM selftests.
> ---
> Bibo Mao (5):
>   KVM: selftests: Add VM_MODE_P47V47_16K VM mode
>   KVM: selftests: Add KVM selftests header files for LoongArch
>   KVM: selftests: Add core KVM selftests support for LoongArch
>   KVM: selftests: Add ucall test support for LoongArch
>   KVM: selftests: Add test cases for LoongArch
>
>  MAINTAINERS                                   |   2 +
>  tools/testing/selftests/kvm/Makefile          |   2 +-
>  tools/testing/selftests/kvm/Makefile.kvm      |  18 +
>  .../testing/selftests/kvm/include/kvm_util.h  |   6 +
>  .../kvm/include/loongarch/kvm_util_arch.h     |   7 +
>  .../kvm/include/loongarch/processor.h         | 141 ++++++++
>  .../selftests/kvm/include/loongarch/ucall.h   |  20 +
>  tools/testing/selftests/kvm/lib/kvm_util.c    |   3 +
>  .../selftests/kvm/lib/loongarch/exception.S   |  59 +++
>  .../selftests/kvm/lib/loongarch/processor.c   | 342 ++++++++++++++++++
>  .../selftests/kvm/lib/loongarch/ucall.c       |  38 ++
>  .../selftests/kvm/set_memory_region_test.c    |   2 +-
>  12 files changed, 638 insertions(+), 2 deletions(-)
>  create mode 100644 tools/testing/selftests/kvm/include/loongarch/kvm_util_arch.h
>  create mode 100644 tools/testing/selftests/kvm/include/loongarch/processor.h
>  create mode 100644 tools/testing/selftests/kvm/include/loongarch/ucall.h
>  create mode 100644 tools/testing/selftests/kvm/lib/loongarch/exception.S
>  create mode 100644 tools/testing/selftests/kvm/lib/loongarch/processor.c
>  create mode 100644 tools/testing/selftests/kvm/lib/loongarch/ucall.c
>
>
> base-commit: 5bc1018675ec28a8a60d83b378d8c3991faa5a27
> --
> 2.39.3
>

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v11 3/5] KVM: selftests: Add core KVM selftests support for LoongArch
  2025-04-27  6:45 ` [PATCH v11 3/5] KVM: selftests: Add core KVM selftests support " Bibo Mao
@ 2025-05-12  6:53   ` Huacai Chen
  0 siblings, 0 replies; 11+ messages in thread
From: Huacai Chen @ 2025-05-12  6:53 UTC (permalink / raw)
  To: Bibo Mao
  Cc: Paolo Bonzini, Sean Christopherson, Shuah Khan, linux-kernel,
	kvm, linux-kselftest

Hi, Bibo,

On Sun, Apr 27, 2025 at 2:45 PM Bibo Mao <maobibo@loongson.cn> wrote:
>
> Add core KVM selftests support for LoongArch, it includes exception
> handler, mmu page table setup and vCPU startup entry support.
>
> Signed-off-by: Bibo Mao <maobibo@loongson.cn>
> ---
>  .../selftests/kvm/lib/loongarch/exception.S   |  59 +++
>  .../selftests/kvm/lib/loongarch/processor.c   | 342 ++++++++++++++++++
>  2 files changed, 401 insertions(+)
>  create mode 100644 tools/testing/selftests/kvm/lib/loongarch/exception.S
>  create mode 100644 tools/testing/selftests/kvm/lib/loongarch/processor.c
>
> diff --git a/tools/testing/selftests/kvm/lib/loongarch/exception.S b/tools/testing/selftests/kvm/lib/loongarch/exception.S
> new file mode 100644
> index 000000000000..88bfa505c6f5
> --- /dev/null
> +++ b/tools/testing/selftests/kvm/lib/loongarch/exception.S
> @@ -0,0 +1,59 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +
> +#include "processor.h"
> +
> +/* address of refill exception should be 4K aligned */
> +.balign        4096
> +.global handle_tlb_refill
> +handle_tlb_refill:
> +       csrwr   t0, LOONGARCH_CSR_TLBRSAVE
> +       csrrd   t0, LOONGARCH_CSR_PGD
> +       lddir   t0, t0, 3
> +       lddir   t0, t0, 1
> +       ldpte   t0, 0
> +       ldpte   t0, 1
> +       tlbfill
> +       csrrd   t0, LOONGARCH_CSR_TLBRSAVE
> +       ertn
> +
> +       /*
> +        * save and restore all gprs except base register,
> +        * and default value of base register is sp ($r3).
> +        */
> +.macro save_gprs base
> +       .irp n,1,2,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
> +       st.d    $r\n, \base, 8 * \n
> +       .endr
> +.endm
> +
> +.macro restore_gprs base
> +       .irp n,1,2,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
> +       ld.d    $r\n, \base, 8 * \n
> +       .endr
> +.endm
> +
> +/* address of general exception should be 4K aligned */
> +.balign        4096
> +.global handle_exception
> +handle_exception:
> +       csrwr  sp, LOONGARCH_CSR_KS0
> +       csrrd  sp, LOONGARCH_CSR_KS1
> +       addi.d sp, sp, -EXREGS_SIZE
> +
> +       save_gprs sp
> +       /* save sp register to stack */
> +       csrrd  t0, LOONGARCH_CSR_KS0
> +       st.d   t0, sp, 3 * 8
> +
> +       csrrd  t0, LOONGARCH_CSR_ERA
> +       st.d   t0, sp, PC_OFFSET_EXREGS
> +       csrrd  t0, LOONGARCH_CSR_ESTAT
> +       st.d   t0, sp, ESTAT_OFFSET_EXREGS
> +       csrrd  t0, LOONGARCH_CSR_BADV
> +       st.d   t0, sp, BADV_OFFSET_EXREGS
> +
> +       or     a0, sp, zero
> +       bl route_exception
> +       restore_gprs sp
> +       csrrd  sp, LOONGARCH_CSR_KS0
> +       ertn
> diff --git a/tools/testing/selftests/kvm/lib/loongarch/processor.c b/tools/testing/selftests/kvm/lib/loongarch/processor.c
> new file mode 100644
> index 000000000000..82d3f041f57a
> --- /dev/null
> +++ b/tools/testing/selftests/kvm/lib/loongarch/processor.c
> @@ -0,0 +1,342 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#include <assert.h>
> +#include <linux/compiler.h>
> +
> +#include "kvm_util.h"
> +#include "processor.h"
> +#include "ucall_common.h"
> +
> +#define LOONGARCH_GUEST_STACK_VADDR_MIN                0x200000
> +#define LOONGARCH_PAGE_TABLE_PHYS_MIN          0x200000
> +
> +static vm_paddr_t invalid_pgtable[4];
> +static uint64_t virt_pte_index(struct kvm_vm *vm, vm_vaddr_t gva, int level)
> +{
> +       unsigned int shift;
> +       uint64_t mask;
> +
> +       shift = level * (vm->page_shift - 3) + vm->page_shift;
> +       mask = (1UL << (vm->page_shift - 3)) - 1;
> +       return (gva >> shift) & mask;
> +}
> +
> +static uint64_t pte_addr(struct kvm_vm *vm, uint64_t entry)
> +{
> +       return entry &  ~((0x1UL << vm->page_shift) - 1);
> +}
> +
> +static uint64_t ptrs_per_pte(struct kvm_vm *vm)
> +{
> +       return 1 << (vm->page_shift - 3);
> +}
> +
> +static void virt_set_pgtable(struct kvm_vm *vm, vm_paddr_t table, vm_paddr_t child)
> +{
> +       uint64_t *ptep;
> +       int i, ptrs_per_pte;
> +
> +       ptep = addr_gpa2hva(vm, table);
> +       ptrs_per_pte = 1 << (vm->page_shift - 3);
> +       for (i = 0; i < ptrs_per_pte; i++)
> +               WRITE_ONCE(*(ptep + i), child);
> +}
> +
> +void virt_arch_pgd_alloc(struct kvm_vm *vm)
> +{
> +       int i;
> +       vm_paddr_t child, table;
> +
> +       if (vm->pgd_created)
> +               return;
> +       child = table = 0;
> +       for (i = 0; i < vm->pgtable_levels; i++) {
> +               invalid_pgtable[i] = child;
> +               table = vm_phy_page_alloc(vm, LOONGARCH_PAGE_TABLE_PHYS_MIN,
> +                               vm->memslots[MEM_REGION_PT]);
> +               TEST_ASSERT(table, "Fail to allocate page tale at level %d\n", i);
> +               virt_set_pgtable(vm, table, child);
> +               child = table;
> +       }
> +       vm->pgd = table;
> +       vm->pgd_created = true;
> +}
> +
> +static int virt_pte_none(uint64_t *ptep, int level)
> +{
> +       return *ptep == invalid_pgtable[level];
> +}
> +
> +static uint64_t *virt_populate_pte(struct kvm_vm *vm, vm_vaddr_t gva, int alloc)
> +{
> +       uint64_t *ptep;
> +       vm_paddr_t child;
> +       int level;
> +
> +       if (!vm->pgd_created)
> +               goto unmapped_gva;
> +
> +       level = vm->pgtable_levels - 1;
> +       child = vm->pgd;
> +       while (level > 0) {
> +               ptep = addr_gpa2hva(vm, child) + virt_pte_index(vm, gva, level) * 8;
> +               if (virt_pte_none(ptep, level)) {
> +                       if (alloc) {
> +                               child = vm_alloc_page_table(vm);
> +                               virt_set_pgtable(vm, child, invalid_pgtable[level - 1]);
> +                               WRITE_ONCE(*ptep, child);
> +                       } else
> +                               goto unmapped_gva;
> +
> +               } else
> +                       child = pte_addr(vm, *ptep);
> +               level--;
> +       }
> +
> +       ptep = addr_gpa2hva(vm, child) + virt_pte_index(vm, gva, level) * 8;
> +       return ptep;
> +
> +unmapped_gva:
> +       TEST_FAIL("No mapping for vm virtual address, gva: 0x%lx", gva);
> +       exit(EXIT_FAILURE);
> +}
> +
> +vm_paddr_t addr_arch_gva2gpa(struct kvm_vm *vm, vm_vaddr_t gva)
> +{
> +       uint64_t *ptep;
> +
> +       ptep = virt_populate_pte(vm, gva, 0);
> +       TEST_ASSERT(*ptep != 0, "Virtual address vaddr: 0x%lx not mapped\n", gva);
> +
> +       return pte_addr(vm, *ptep) + (gva & (vm->page_size - 1));
> +}
> +
> +void virt_arch_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr)
> +{
> +       uint32_t prot_bits;
> +       uint64_t *ptep;
> +
> +       TEST_ASSERT((vaddr % vm->page_size) == 0,
> +                       "Virtual address not on page boundary,\n"
> +                       "vaddr: 0x%lx vm->page_size: 0x%x", vaddr, vm->page_size);
> +       TEST_ASSERT(sparsebit_is_set(vm->vpages_valid,
> +                       (vaddr >> vm->page_shift)),
> +                       "Invalid virtual address, vaddr: 0x%lx", vaddr);
> +       TEST_ASSERT((paddr % vm->page_size) == 0,
> +                       "Physical address not on page boundary,\n"
> +                       "paddr: 0x%lx vm->page_size: 0x%x", paddr, vm->page_size);
> +       TEST_ASSERT((paddr >> vm->page_shift) <= vm->max_gfn,
> +                       "Physical address beyond maximum supported,\n"
> +                       "paddr: 0x%lx vm->max_gfn: 0x%lx vm->page_size: 0x%x",
> +                       paddr, vm->max_gfn, vm->page_size);
> +
> +       ptep = virt_populate_pte(vm, vaddr, 1);
> +       prot_bits = _PAGE_PRESENT | __READABLE | __WRITEABLE | _CACHE_CC;
> +       prot_bits |= _PAGE_USER;
We can calculate prot_bits in one statement.

> +       WRITE_ONCE(*ptep, paddr | prot_bits);
> +}
> +
> +static void pte_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent, uint64_t page, int level)
> +{
> +       static const char * const type[] = { "pte", "pmd", "pud", "pgd"};
> +       uint64_t pte, *ptep;
> +
> +       if (level < 0)
> +               return;
> +
> +       for (pte = page; pte < page + ptrs_per_pte(vm) * 8; pte += 8) {
> +               ptep = addr_gpa2hva(vm, pte);
> +               if (virt_pte_none(ptep, level))
> +                       continue;
> +               fprintf(stream, "%*s%s: %lx: %lx at %p\n",
> +                               indent, "", type[level], pte, *ptep, ptep);
> +               pte_dump(stream, vm, indent + 1, pte_addr(vm, *ptep), level--);
> +       }
> +}
> +
> +void virt_arch_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent)
> +{
> +       int level;
> +
> +       if (!vm->pgd_created)
> +               return;
> +
> +       level = vm->pgtable_levels - 1;
> +       pte_dump(stream, vm, indent, vm->pgd, level);
> +}
> +
> +void vcpu_arch_dump(FILE *stream, struct kvm_vcpu *vcpu, uint8_t indent)
> +{
> +}
> +
> +void assert_on_unhandled_exception(struct kvm_vcpu *vcpu)
> +{
> +       struct ucall uc;
> +
> +       if (get_ucall(vcpu, &uc) != UCALL_UNHANDLED)
> +               return;
> +
> +       TEST_FAIL("Unexpected exception (pc:0x%lx, estat:0x%lx, badv:0x%lx)",
> +                       uc.args[0], uc.args[1], uc.args[2]);
> +}
> +
> +void route_exception(struct ex_regs *regs)
> +{
> +       unsigned long pc, estat, badv;
> +
> +       pc = regs->pc;
> +       estat = regs->estat;
> +       badv  = regs->badv;
> +       ucall(UCALL_UNHANDLED, 3, pc, estat, badv);
> +       while (1)
> +               ;
> +}
> +
> +void vcpu_args_set(struct kvm_vcpu *vcpu, unsigned int num, ...)
> +{
> +       va_list ap;
> +       struct kvm_regs regs;
> +       int i;
> +
> +       TEST_ASSERT(num >= 1 && num <= 8, "Unsupported number of args,\n"
> +                   "num: %u\n", num);
> +
> +       vcpu_regs_get(vcpu, &regs);
> +       va_start(ap, num);
> +       for (i = 0; i < num; i++)
> +               regs.gpr[i + 4] = va_arg(ap, uint64_t);
> +       va_end(ap);
> +       vcpu_regs_set(vcpu, &regs);
> +}
> +
> +static void loongarch_get_csr(struct kvm_vcpu *vcpu, uint64_t id, void *addr)
> +{
> +       uint64_t csrid;
> +
> +       csrid = KVM_REG_LOONGARCH_CSR | KVM_REG_SIZE_U64 | 8 * id;
> +       __vcpu_get_reg(vcpu, csrid, addr);
> +}
> +
> +static void loongarch_set_csr(struct kvm_vcpu *vcpu, uint64_t id, uint64_t val)
> +{
> +       uint64_t csrid;
> +
> +       csrid = KVM_REG_LOONGARCH_CSR | KVM_REG_SIZE_U64 | 8 * id;
> +       vcpu_set_reg(vcpu, csrid, val);
For symmetry with loongarch_get_csr(), maybe we can replace
vcpu_set_reg() with __vcpu_set_reg() here.


Huacai

> +}
> +
> +static void loongarch_vcpu_setup(struct kvm_vcpu *vcpu)
> +{
> +       unsigned long val;
> +       int width;
> +       struct kvm_vm *vm = vcpu->vm;
> +
> +       switch (vm->mode) {
> +       case VM_MODE_P36V47_16K:
> +       case VM_MODE_P47V47_16K:
> +               break;
> +
> +       default:
> +               TEST_FAIL("Unknown guest mode, mode: 0x%x", vm->mode);
> +       }
> +
> +       /* user mode and page enable mode */
> +       val = PLV_USER | CSR_CRMD_PG;
> +       loongarch_set_csr(vcpu, LOONGARCH_CSR_CRMD, val);
> +       loongarch_set_csr(vcpu, LOONGARCH_CSR_PRMD, val);
> +       loongarch_set_csr(vcpu, LOONGARCH_CSR_EUEN, 1);
> +       loongarch_set_csr(vcpu, LOONGARCH_CSR_ECFG, 0);
> +       loongarch_set_csr(vcpu, LOONGARCH_CSR_TCFG, 0);
> +       loongarch_set_csr(vcpu, LOONGARCH_CSR_ASID, 1);
> +
> +       width = vm->page_shift - 3;
> +       val = 0;
> +       switch (vm->pgtable_levels) {
> +       case 4:
> +               /* pud page shift and width */
> +               val = (vm->page_shift + width * 2) << 20 | (width << 25);
> +               /* fall throuth */
> +       case 3:
> +               /* pmd page shift and width */
> +               val |= (vm->page_shift + width) << 10 | (width << 15);
> +               /* pte page shift and width */
> +               val |= vm->page_shift | width << 5;
> +               break;
> +       default:
> +               TEST_FAIL("Got %u page table levels, expected 3 or 4", vm->pgtable_levels);
> +       }
> +       loongarch_set_csr(vcpu, LOONGARCH_CSR_PWCTL0, val);
> +
> +       /* PGD page shift and width */
> +       val = (vm->page_shift + width * (vm->pgtable_levels - 1)) | width << 6;
> +       loongarch_set_csr(vcpu, LOONGARCH_CSR_PWCTL1, val);
> +       loongarch_set_csr(vcpu, LOONGARCH_CSR_PGDL, vm->pgd);
> +
> +       /*
> +        * Refill exception runs on real mode
> +        * Entry address should be physical address
> +        */
> +       val = addr_gva2gpa(vm, (unsigned long)handle_tlb_refill);
> +       loongarch_set_csr(vcpu, LOONGARCH_CSR_TLBRENTRY, val);
> +
> +       /*
> +        * General exception runs on page-enabled mode
> +        * Entry address should be virtual address
> +        */
> +       val = (unsigned long)handle_exception;
> +       loongarch_set_csr(vcpu, LOONGARCH_CSR_EENTRY, val);
> +
> +       loongarch_get_csr(vcpu, LOONGARCH_CSR_TLBIDX, &val);
> +       val &= ~CSR_TLBIDX_SIZEM;
> +       val |= PS_DEFAULT_SIZE << CSR_TLBIDX_SIZE;
> +       loongarch_set_csr(vcpu, LOONGARCH_CSR_TLBIDX, val);
> +
> +       loongarch_set_csr(vcpu, LOONGARCH_CSR_STLBPGSIZE, PS_DEFAULT_SIZE);
> +
> +       /* LOONGARCH_CSR_KS1 is used for exception stack */
> +       val = __vm_vaddr_alloc(vm, vm->page_size,
> +                       LOONGARCH_GUEST_STACK_VADDR_MIN, MEM_REGION_DATA);
> +       TEST_ASSERT(val != 0,  "No memory for exception stack");
> +       val = val + vm->page_size;
> +       loongarch_set_csr(vcpu, LOONGARCH_CSR_KS1, val);
> +
> +       loongarch_get_csr(vcpu, LOONGARCH_CSR_TLBREHI, &val);
> +       val &= ~CSR_TLBREHI_PS;
> +       val |= PS_DEFAULT_SIZE << CSR_TLBREHI_PS_SHIFT;
> +       loongarch_set_csr(vcpu, LOONGARCH_CSR_TLBREHI, val);
> +
> +       loongarch_set_csr(vcpu, LOONGARCH_CSR_CPUID, vcpu->id);
> +       loongarch_set_csr(vcpu, LOONGARCH_CSR_TMID,  vcpu->id);
> +}
> +
> +struct kvm_vcpu *vm_arch_vcpu_add(struct kvm_vm *vm, uint32_t vcpu_id)
> +{
> +       size_t stack_size;
> +       uint64_t stack_vaddr;
> +       struct kvm_regs regs;
> +       struct kvm_vcpu *vcpu;
> +
> +       vcpu = __vm_vcpu_add(vm, vcpu_id);
> +       stack_size = vm->page_size;
> +       stack_vaddr = __vm_vaddr_alloc(vm, stack_size,
> +                       LOONGARCH_GUEST_STACK_VADDR_MIN, MEM_REGION_DATA);
> +       TEST_ASSERT(stack_vaddr != 0,  "No memory for vm stack");
> +
> +       loongarch_vcpu_setup(vcpu);
> +       /* Setup guest general purpose registers */
> +       vcpu_regs_get(vcpu, &regs);
> +       regs.gpr[3] = stack_vaddr + stack_size;
> +       vcpu_regs_set(vcpu, &regs);
> +
> +       return vcpu;
> +}
> +
> +void vcpu_arch_set_entry_point(struct kvm_vcpu *vcpu, void *guest_code)
> +{
> +       struct kvm_regs regs;
> +
> +       /* Setup guest PC register */
> +       vcpu_regs_get(vcpu, &regs);
> +       regs.pc = (uint64_t)guest_code;
> +       vcpu_regs_set(vcpu, &regs);
> +}
> --
> 2.39.3
>

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v11 5/5] KVM: selftests: Add test cases for LoongArch
  2025-04-27  6:45 ` [PATCH v11 5/5] KVM: selftests: Add test cases " Bibo Mao
@ 2025-05-12  6:54   ` Huacai Chen
  0 siblings, 0 replies; 11+ messages in thread
From: Huacai Chen @ 2025-05-12  6:54 UTC (permalink / raw)
  To: Bibo Mao
  Cc: Paolo Bonzini, Sean Christopherson, Shuah Khan, linux-kernel,
	kvm, linux-kselftest

Hi, Bibo,

On Sun, Apr 27, 2025 at 2:45 PM Bibo Mao <maobibo@loongson.cn> wrote:
>
> Some common KVM test cases are supported on LoongArch now as following:
>   coalesced_io_test
>   demand_paging_test
>   dirty_log_perf_test
>   dirty_log_test
>   guest_print_test
>   hardware_disable_test
>   kvm_binary_stats_test
>   kvm_create_max_vcpus
>   kvm_page_table_test
>   memslot_modification_stress_test
>   memslot_perf_test
>   set_memory_region_test
> And other test cases are not supported by LoongArch such as rseq_test,
> since it is not supported on LoongArch physical machine either.
>
> Signed-off-by: Bibo Mao <maobibo@loongson.cn>
> ---
>  MAINTAINERS                                    |  2 ++
>  tools/testing/selftests/kvm/Makefile           |  2 +-
>  tools/testing/selftests/kvm/Makefile.kvm       | 18 ++++++++++++++++++
>  .../selftests/kvm/set_memory_region_test.c     |  2 +-
>  4 files changed, 22 insertions(+), 2 deletions(-)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 3cbf9ac0d83f..20cb455e0821 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -13043,6 +13043,8 @@ F:      Documentation/virt/kvm/loongarch/
>  F:     arch/loongarch/include/asm/kvm*
>  F:     arch/loongarch/include/uapi/asm/kvm*
>  F:     arch/loongarch/kvm/
> +F:     tools/testing/selftests/kvm/*/loongarch/
> +F:     tools/testing/selftests/kvm/lib/loongarch/
>
>  KERNEL VIRTUAL MACHINE FOR MIPS (KVM/mips)
>  M:     Huacai Chen <chenhuacai@kernel.org>
> diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile
> index 20af35a91d6f..d9fffe06d3ea 100644
> --- a/tools/testing/selftests/kvm/Makefile
> +++ b/tools/testing/selftests/kvm/Makefile
> @@ -3,7 +3,7 @@ top_srcdir = ../../../..
>  include $(top_srcdir)/scripts/subarch.include
>  ARCH            ?= $(SUBARCH)
>
> -ifeq ($(ARCH),$(filter $(ARCH),arm64 s390 riscv x86 x86_64))
> +ifeq ($(ARCH),$(filter $(ARCH),arm64 s390 riscv x86 x86_64 loongarch))
>  # Top-level selftests allows ARCH=x86_64 :-(
>  ifeq ($(ARCH),x86_64)
>         ARCH := x86
> diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selftests/kvm/Makefile.kvm
> index f62b0a5aba35..7985bb42d2c1 100644
> --- a/tools/testing/selftests/kvm/Makefile.kvm
> +++ b/tools/testing/selftests/kvm/Makefile.kvm
> @@ -47,6 +47,10 @@ LIBKVM_riscv += lib/riscv/handlers.S
>  LIBKVM_riscv += lib/riscv/processor.c
>  LIBKVM_riscv += lib/riscv/ucall.c
>
> +LIBKVM_loongarch += lib/loongarch/processor.c
> +LIBKVM_loongarch += lib/loongarch/ucall.c
> +LIBKVM_loongarch += lib/loongarch/exception.S
> +
>  # Non-compiled test targets
>  TEST_PROGS_x86 += x86/nx_huge_pages_test.sh
>
> @@ -190,6 +194,20 @@ TEST_GEN_PROGS_riscv += coalesced_io_test
>  TEST_GEN_PROGS_riscv += get-reg-list
>  TEST_GEN_PROGS_riscv += steal_time
>
> +TEST_GEN_PROGS_loongarch += coalesced_io_test
> +TEST_GEN_PROGS_loongarch += demand_paging_test
> +TEST_GEN_PROGS_loongarch += dirty_log_perf_test
> +TEST_GEN_PROGS_loongarch += dirty_log_test
> +TEST_GEN_PROGS_loongarch += demand_paging_test
This line is duplicated.


Huacai

> +TEST_GEN_PROGS_loongarch += guest_print_test
> +TEST_GEN_PROGS_loongarch += hardware_disable_test
> +TEST_GEN_PROGS_loongarch += kvm_binary_stats_test
> +TEST_GEN_PROGS_loongarch += kvm_create_max_vcpus
> +TEST_GEN_PROGS_loongarch += kvm_page_table_test
> +TEST_GEN_PROGS_loongarch += memslot_modification_stress_test
> +TEST_GEN_PROGS_loongarch += memslot_perf_test
> +TEST_GEN_PROGS_loongarch += set_memory_region_test
> +
>  SPLIT_TESTS += arch_timer
>  SPLIT_TESTS += get-reg-list
>
> diff --git a/tools/testing/selftests/kvm/set_memory_region_test.c b/tools/testing/selftests/kvm/set_memory_region_test.c
> index bc440d5aba57..ce3ac0fd6dfb 100644
> --- a/tools/testing/selftests/kvm/set_memory_region_test.c
> +++ b/tools/testing/selftests/kvm/set_memory_region_test.c
> @@ -350,7 +350,7 @@ static void test_invalid_memory_region_flags(void)
>         struct kvm_vm *vm;
>         int r, i;
>
> -#if defined __aarch64__ || defined __riscv || defined __x86_64__
> +#if defined __aarch64__ || defined __riscv || defined __x86_64__ || defined __loongarch__
>         supported_flags |= KVM_MEM_READONLY;
>  #endif
>
> --
> 2.39.3
>

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v11 0/5] KVM: selftests: Add LoongArch support
  2025-05-12  6:53 ` [PATCH v11 0/5] KVM: selftests: Add LoongArch support Huacai Chen
@ 2025-05-19  7:50   ` Bibo Mao
  2025-05-19  9:42   ` Bibo Mao
  1 sibling, 0 replies; 11+ messages in thread
From: Bibo Mao @ 2025-05-19  7:50 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Paolo Bonzini, Sean Christopherson, Shuah Khan, linux-kernel,
	kvm, linux-kselftest



On 2025/5/12 下午2:53, Huacai Chen wrote:
> Hi, Bibo,
> 
> On Sun, Apr 27, 2025 at 2:45 PM Bibo Mao <maobibo@loongson.cn> wrote:
>>
>> This patchset adds KVM selftests for LoongArch system, currently only
>> some common test cases are supported and pass to run. These test cases
>> are listed as following:
>>      coalesced_io_test
>>      demand_paging_test
>>      dirty_log_perf_test
>>      dirty_log_test
>>      guest_print_test
>>      hardware_disable_test
>>      kvm_binary_stats_test
>>      kvm_create_max_vcpus
>>      kvm_page_table_test
>>      memslot_modification_stress_test
>>      memslot_perf_test
>>      set_memory_region_test
> I have applied this series [1] but with some modifications (see
> comments in other patches). You can test it to see if everything is
> OK.
> 
> And if it's OK, it is better to fetch the patches from [1] and then send V12.
> 
> [1] https://github.com/chenhuacai/linux/commits/loongarch-next
That is ok for me. Will send V12 soon.

Regards
Bibo Mao
> 
> 
> 
> Huacai
> 
>>
>> ---
>> Changes in v11:
>> 1. Fix a typo issue in notes of patch 2, it is kvm_util_arch.h rather than
>>     kvm_util_base.h
>>
>> Changes in v10:
>> 1. Add PS_64K and remove PS_8K in file include/loongarch/processor.h
>> 2. Fix a typo issue in file lib/loongarch/processor.c
>> 3. Update file MAINTAINERS about LoongArch KVM selftests
>>
>> Changes in v9:
>> 1. Add vm mode VM_MODE_P47V47_16K, LoongArch VM uses this mode by
>>     default, rather than VM_MODE_P36V47_16K.
>> 2. Refresh some spelling issues in changelog.
>>
>> Changes in v8:
>> 1. Porting patch based on the latest version.
>> 2. For macro PC_OFFSET_EXREGS, offsetof() method is used for C header file,
>>     still hardcoded definition for assemble language.
>>
>> Changes in v7:
>> 1. Refine code to add LoongArch support in test case
>> set_memory_region_test.
>>
>> Changes in v6:
>> 1. Refresh the patch based on latest kernel 6.8-rc1, add LoongArch
>> support about testcase set_memory_region_test.
>> 2. Add hardware_disable_test test case.
>> 3. Drop modification about macro DEFAULT_GUEST_TEST_MEM, it is problem
>> of LoongArch binutils, this issue is raised to LoongArch binutils owners.
>>
>> Changes in v5:
>> 1. In LoongArch kvm self tests, the DEFAULT_GUEST_TEST_MEM could be
>> 0x130000000, it is different from the default value in memstress.h.
>> So we Move the definition of DEFAULT_GUEST_TEST_MEM into LoongArch
>> ucall.h, and add 'ifndef' condition for DEFAULT_GUEST_TEST_MEM
>> in memstress.h.
>>
>> Changes in v4:
>> 1. Remove the based-on flag, as the LoongArch KVM patch series
>> have been accepted by Linux kernel, so this can be applied directly
>> in kernel.
>>
>> Changes in v3:
>> 1. Improve implementation of LoongArch VM page walk.
>> 2. Add exception handler for LoongArch.
>> 3. Add dirty_log_test, dirty_log_perf_test, guest_print_test
>> test cases for LoongArch.
>> 4. Add __ASSEMBLER__ macro to distinguish asm file and c file.
>> 5. Move ucall_arch_do_ucall to the header file and make it as
>> static inline to avoid function calls.
>> 6. Change the DEFAULT_GUEST_TEST_MEM base addr for LoongArch.
>>
>> Changes in v2:
>> 1. We should use ".balign 4096" to align the assemble code with 4K in
>> exception.S instead of "align 12".
>> 2. LoongArch only supports 3 or 4 levels page tables, so we remove the
>> hanlders for 2-levels page table.
>> 3. Remove the DEFAULT_LOONGARCH_GUEST_STACK_VADDR_MIN and use the common
>> DEFAULT_GUEST_STACK_VADDR_MIN to allocate stack memory in guest.
>> 4. Reorganize the test cases supported by LoongArch.
>> 5. Fix some code comments.
>> 6. Add kvm_binary_stats_test test case into LoongArch KVM selftests.
>> ---
>> Bibo Mao (5):
>>    KVM: selftests: Add VM_MODE_P47V47_16K VM mode
>>    KVM: selftests: Add KVM selftests header files for LoongArch
>>    KVM: selftests: Add core KVM selftests support for LoongArch
>>    KVM: selftests: Add ucall test support for LoongArch
>>    KVM: selftests: Add test cases for LoongArch
>>
>>   MAINTAINERS                                   |   2 +
>>   tools/testing/selftests/kvm/Makefile          |   2 +-
>>   tools/testing/selftests/kvm/Makefile.kvm      |  18 +
>>   .../testing/selftests/kvm/include/kvm_util.h  |   6 +
>>   .../kvm/include/loongarch/kvm_util_arch.h     |   7 +
>>   .../kvm/include/loongarch/processor.h         | 141 ++++++++
>>   .../selftests/kvm/include/loongarch/ucall.h   |  20 +
>>   tools/testing/selftests/kvm/lib/kvm_util.c    |   3 +
>>   .../selftests/kvm/lib/loongarch/exception.S   |  59 +++
>>   .../selftests/kvm/lib/loongarch/processor.c   | 342 ++++++++++++++++++
>>   .../selftests/kvm/lib/loongarch/ucall.c       |  38 ++
>>   .../selftests/kvm/set_memory_region_test.c    |   2 +-
>>   12 files changed, 638 insertions(+), 2 deletions(-)
>>   create mode 100644 tools/testing/selftests/kvm/include/loongarch/kvm_util_arch.h
>>   create mode 100644 tools/testing/selftests/kvm/include/loongarch/processor.h
>>   create mode 100644 tools/testing/selftests/kvm/include/loongarch/ucall.h
>>   create mode 100644 tools/testing/selftests/kvm/lib/loongarch/exception.S
>>   create mode 100644 tools/testing/selftests/kvm/lib/loongarch/processor.c
>>   create mode 100644 tools/testing/selftests/kvm/lib/loongarch/ucall.c
>>
>>
>> base-commit: 5bc1018675ec28a8a60d83b378d8c3991faa5a27
>> --
>> 2.39.3
>>


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v11 0/5] KVM: selftests: Add LoongArch support
  2025-05-12  6:53 ` [PATCH v11 0/5] KVM: selftests: Add LoongArch support Huacai Chen
  2025-05-19  7:50   ` Bibo Mao
@ 2025-05-19  9:42   ` Bibo Mao
  1 sibling, 0 replies; 11+ messages in thread
From: Bibo Mao @ 2025-05-19  9:42 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Paolo Bonzini, Sean Christopherson, Shuah Khan, linux-kernel,
	kvm, linux-kselftest



On 2025/5/12 下午2:53, Huacai Chen wrote:
> Hi, Bibo,
> 
> On Sun, Apr 27, 2025 at 2:45 PM Bibo Mao <maobibo@loongson.cn> wrote:
>>
>> This patchset adds KVM selftests for LoongArch system, currently only
>> some common test cases are supported and pass to run. These test cases
>> are listed as following:
>>      coalesced_io_test
>>      demand_paging_test
>>      dirty_log_perf_test
>>      dirty_log_test
>>      guest_print_test
>>      hardware_disable_test
>>      kvm_binary_stats_test
>>      kvm_create_max_vcpus
>>      kvm_page_table_test
>>      memslot_modification_stress_test
>>      memslot_perf_test
>>      set_memory_region_test
> I have applied this series [1] but with some modifications (see
> comments in other patches). You can test it to see if everything is
> OK.
> 
> And if it's OK, it is better to fetch the patches from [1] and then send V12.
There is error reporting with checkpatch as followings:
ERROR: trailing statements should be on next line
#281: FILE: tools/testing/selftests/kvm/lib/loongarch/processor.c:192:
+       while (1) ;

This is already solved in V9, which patch does [1] come from?
+void route_exception(struct ex_regs *regs)
+{
+       unsigned long pc, estat, badv;
+
+       pc = regs->pc;
+       estat = regs->estat;
+       badv  = regs->badv;
+       ucall(UCALL_UNHANDLED, 3, pc, estat, badv);
+       while (1)
+               ;
+}

Regards
Bibo Mao
> 
> [1] https://github.com/chenhuacai/linux/commits/loongarch-next
> 
> 
> 
> Huacai
> 
>>
>> ---
>> Changes in v11:
>> 1. Fix a typo issue in notes of patch 2, it is kvm_util_arch.h rather than
>>     kvm_util_base.h
>>
>> Changes in v10:
>> 1. Add PS_64K and remove PS_8K in file include/loongarch/processor.h
>> 2. Fix a typo issue in file lib/loongarch/processor.c
>> 3. Update file MAINTAINERS about LoongArch KVM selftests
>>
>> Changes in v9:
>> 1. Add vm mode VM_MODE_P47V47_16K, LoongArch VM uses this mode by
>>     default, rather than VM_MODE_P36V47_16K.
>> 2. Refresh some spelling issues in changelog.
>>
>> Changes in v8:
>> 1. Porting patch based on the latest version.
>> 2. For macro PC_OFFSET_EXREGS, offsetof() method is used for C header file,
>>     still hardcoded definition for assemble language.
>>
>> Changes in v7:
>> 1. Refine code to add LoongArch support in test case
>> set_memory_region_test.
>>
>> Changes in v6:
>> 1. Refresh the patch based on latest kernel 6.8-rc1, add LoongArch
>> support about testcase set_memory_region_test.
>> 2. Add hardware_disable_test test case.
>> 3. Drop modification about macro DEFAULT_GUEST_TEST_MEM, it is problem
>> of LoongArch binutils, this issue is raised to LoongArch binutils owners.
>>
>> Changes in v5:
>> 1. In LoongArch kvm self tests, the DEFAULT_GUEST_TEST_MEM could be
>> 0x130000000, it is different from the default value in memstress.h.
>> So we Move the definition of DEFAULT_GUEST_TEST_MEM into LoongArch
>> ucall.h, and add 'ifndef' condition for DEFAULT_GUEST_TEST_MEM
>> in memstress.h.
>>
>> Changes in v4:
>> 1. Remove the based-on flag, as the LoongArch KVM patch series
>> have been accepted by Linux kernel, so this can be applied directly
>> in kernel.
>>
>> Changes in v3:
>> 1. Improve implementation of LoongArch VM page walk.
>> 2. Add exception handler for LoongArch.
>> 3. Add dirty_log_test, dirty_log_perf_test, guest_print_test
>> test cases for LoongArch.
>> 4. Add __ASSEMBLER__ macro to distinguish asm file and c file.
>> 5. Move ucall_arch_do_ucall to the header file and make it as
>> static inline to avoid function calls.
>> 6. Change the DEFAULT_GUEST_TEST_MEM base addr for LoongArch.
>>
>> Changes in v2:
>> 1. We should use ".balign 4096" to align the assemble code with 4K in
>> exception.S instead of "align 12".
>> 2. LoongArch only supports 3 or 4 levels page tables, so we remove the
>> hanlders for 2-levels page table.
>> 3. Remove the DEFAULT_LOONGARCH_GUEST_STACK_VADDR_MIN and use the common
>> DEFAULT_GUEST_STACK_VADDR_MIN to allocate stack memory in guest.
>> 4. Reorganize the test cases supported by LoongArch.
>> 5. Fix some code comments.
>> 6. Add kvm_binary_stats_test test case into LoongArch KVM selftests.
>> ---
>> Bibo Mao (5):
>>    KVM: selftests: Add VM_MODE_P47V47_16K VM mode
>>    KVM: selftests: Add KVM selftests header files for LoongArch
>>    KVM: selftests: Add core KVM selftests support for LoongArch
>>    KVM: selftests: Add ucall test support for LoongArch
>>    KVM: selftests: Add test cases for LoongArch
>>
>>   MAINTAINERS                                   |   2 +
>>   tools/testing/selftests/kvm/Makefile          |   2 +-
>>   tools/testing/selftests/kvm/Makefile.kvm      |  18 +
>>   .../testing/selftests/kvm/include/kvm_util.h  |   6 +
>>   .../kvm/include/loongarch/kvm_util_arch.h     |   7 +
>>   .../kvm/include/loongarch/processor.h         | 141 ++++++++
>>   .../selftests/kvm/include/loongarch/ucall.h   |  20 +
>>   tools/testing/selftests/kvm/lib/kvm_util.c    |   3 +
>>   .../selftests/kvm/lib/loongarch/exception.S   |  59 +++
>>   .../selftests/kvm/lib/loongarch/processor.c   | 342 ++++++++++++++++++
>>   .../selftests/kvm/lib/loongarch/ucall.c       |  38 ++
>>   .../selftests/kvm/set_memory_region_test.c    |   2 +-
>>   12 files changed, 638 insertions(+), 2 deletions(-)
>>   create mode 100644 tools/testing/selftests/kvm/include/loongarch/kvm_util_arch.h
>>   create mode 100644 tools/testing/selftests/kvm/include/loongarch/processor.h
>>   create mode 100644 tools/testing/selftests/kvm/include/loongarch/ucall.h
>>   create mode 100644 tools/testing/selftests/kvm/lib/loongarch/exception.S
>>   create mode 100644 tools/testing/selftests/kvm/lib/loongarch/processor.c
>>   create mode 100644 tools/testing/selftests/kvm/lib/loongarch/ucall.c
>>
>>
>> base-commit: 5bc1018675ec28a8a60d83b378d8c3991faa5a27
>> --
>> 2.39.3
>>


^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2025-05-19  9:43 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-04-27  6:45 [PATCH v11 0/5] KVM: selftests: Add LoongArch support Bibo Mao
2025-04-27  6:45 ` [PATCH v11 1/5] KVM: selftests: Add VM_MODE_P47V47_16K VM mode Bibo Mao
2025-04-27  6:45 ` [PATCH v11 2/5] KVM: selftests: Add KVM selftests header files for LoongArch Bibo Mao
2025-04-27  6:45 ` [PATCH v11 3/5] KVM: selftests: Add core KVM selftests support " Bibo Mao
2025-05-12  6:53   ` Huacai Chen
2025-04-27  6:45 ` [PATCH v11 4/5] KVM: selftests: Add ucall test " Bibo Mao
2025-04-27  6:45 ` [PATCH v11 5/5] KVM: selftests: Add test cases " Bibo Mao
2025-05-12  6:54   ` Huacai Chen
2025-05-12  6:53 ` [PATCH v11 0/5] KVM: selftests: Add LoongArch support Huacai Chen
2025-05-19  7:50   ` Bibo Mao
2025-05-19  9:42   ` Bibo Mao

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®