* [PATCH 0/5] KVM: selftests: Reserve memslot 1 for ucall MMIO
@ 2026-10-17 11:02 Tharit Tangkijwanichakul
2026-10-17 11:02 ` [PATCH 1/5] KVM: selftests: Introduce a shared base for test memslots Tharit Tangkijwanichakul
` (4 more replies)
0 siblings, 5 replies; 7+ messages in thread
From: Tharit Tangkijwanichakul @ 2026-10-17 11:02 UTC (permalink / raw)
To: Paolo Bonzini, Sean Christopherson
Cc: Shuah Khan, Marc Zyngier, Oliver Upton, Fuad Tabba, Joey Gouly,
Steffen Eiden, Suzuki K Poulose, Zenghui Yu, Anup Patel,
Atish Patra, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, kvm, linux-kernel, linux-kselftest,
linux-arm-kernel, kvmarm, kvm-riscv, linux-riscv,
linux-kernel-mentees, skhan, me, jkoolstra,
Tharit Tangkijwanichakul
This series addresses the TODO in __vm_create() to reserve memslot 1
for the ucall MMIO region. It introduces a shared base for test
memslots, migrates existing test users, and adds a read-only region to
prevent overlapping allocations.
A regression test verifies overlap rejection and continued ucall
operation.
Testing:
- Intel Core i5-10210U and Rockchip RK3588 (arm64).
These tests are changed but not tested:
- arm64/sea_to_user.c: not enough memory allocation.
- x86/nested_vmsave_vmload_test.c: requires X86_FEATURE_SVM.
- riscv/sbi_pmu_test.c: riscv hardware unavailability.
The following test failures reproduce on both the unmodified base
<8edffbc1f6272db167037e1a8c49b99e9cd04803> with host kernel
7.3.0-rc1-gd4b7fb647204 on RK3588 and with this series applied:
- arm64/vgic_its_save.c
- arm64/hypercalls.c
These failures are unchanged by this series.
Tharit Tangkijwanichakul (5):
KVM: selftests: Introduce a shared base for test memslots
KVM: selftests: Use the shared memslot base in memslot_perf_test
KVM: selftests: Use the shared memslot base in memstress
KVM: selftests: Reserve memslot 1 for the ucall MMIO address
KVM: selftests: Test protection of the ucall MMIO region
tools/testing/selftests/kvm/Makefile.kvm | 1 +
.../testing/selftests/kvm/arm64/hypercalls.c | 3 +-
.../testing/selftests/kvm/arm64/sea_to_user.c | 2 +-
.../kvm/arm64/stage2_block_transitions.c | 2 +-
.../selftests/kvm/arm64/vgic_its_save.c | 2 +-
.../selftests/kvm/arm64/vgic_lpi_stress.c | 2 +-
tools/testing/selftests/kvm/dirty_log_test.c | 2 +-
.../testing/selftests/kvm/guest_memfd_test.c | 2 +-
.../testing/selftests/kvm/include/kvm_util.h | 1 +
.../testing/selftests/kvm/include/memstress.h | 2 +-
.../selftests/kvm/kvm_page_table_test.c | 2 +-
tools/testing/selftests/kvm/lib/kvm_util.c | 19 ++++--
.../testing/selftests/kvm/memslot_perf_test.c | 62 +++++++++++--------
tools/testing/selftests/kvm/mmu_stress_test.c | 2 +-
.../selftests/kvm/reserved_slot_test.c | 61 ++++++++++++++++++
.../selftests/kvm/riscv/sbi_pmu_test.c | 3 +-
tools/testing/selftests/kvm/steal_time.c | 3 +-
.../selftests/kvm/x86/nested_dirty_log_test.c | 2 +-
.../kvm/x86/nested_vmsave_vmload_test.c | 2 +-
19 files changed, 128 insertions(+), 47 deletions(-)
create mode 100644 tools/testing/selftests/kvm/reserved_slot_test.c
--
2.53.0
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 1/5] KVM: selftests: Introduce a shared base for test memslots
2026-10-17 11:02 [PATCH 0/5] KVM: selftests: Reserve memslot 1 for ucall MMIO Tharit Tangkijwanichakul
@ 2026-10-17 11:02 ` Tharit Tangkijwanichakul
2026-10-17 11:02 ` [PATCH 2/5] KVM: selftests: Use the shared memslot base in memslot_perf_test Tharit Tangkijwanichakul
` (3 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Tharit Tangkijwanichakul @ 2026-10-17 11:02 UTC (permalink / raw)
To: Paolo Bonzini, Sean Christopherson
Cc: Shuah Khan, Marc Zyngier, Oliver Upton, Fuad Tabba, Joey Gouly,
Steffen Eiden, Suzuki K Poulose, Zenghui Yu, Anup Patel,
Atish Patra, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, kvm, linux-kernel, linux-kselftest,
linux-arm-kernel, kvmarm, kvm-riscv, linux-riscv,
linux-kernel-mentees, skhan, me, jkoolstra,
Tharit Tangkijwanichakul
Replace hardcoded slot 1 assignments with TEST_MEM_SLOT_BASE
This prepares tests for reserving slot 1 for library use.
Signed-off-by: Tharit Tangkijwanichakul <tharitt97@gmail.com>
---
tools/testing/selftests/kvm/arm64/hypercalls.c | 3 ++-
tools/testing/selftests/kvm/arm64/sea_to_user.c | 2 +-
tools/testing/selftests/kvm/arm64/stage2_block_transitions.c | 2 +-
tools/testing/selftests/kvm/arm64/vgic_its_save.c | 2 +-
tools/testing/selftests/kvm/arm64/vgic_lpi_stress.c | 2 +-
tools/testing/selftests/kvm/dirty_log_test.c | 2 +-
tools/testing/selftests/kvm/guest_memfd_test.c | 2 +-
tools/testing/selftests/kvm/include/kvm_util.h | 1 +
tools/testing/selftests/kvm/kvm_page_table_test.c | 2 +-
tools/testing/selftests/kvm/mmu_stress_test.c | 2 +-
tools/testing/selftests/kvm/riscv/sbi_pmu_test.c | 3 ++-
tools/testing/selftests/kvm/steal_time.c | 3 ++-
tools/testing/selftests/kvm/x86/nested_dirty_log_test.c | 2 +-
tools/testing/selftests/kvm/x86/nested_vmsave_vmload_test.c | 2 +-
14 files changed, 17 insertions(+), 13 deletions(-)
diff --git a/tools/testing/selftests/kvm/arm64/hypercalls.c b/tools/testing/selftests/kvm/arm64/hypercalls.c
index 391e2ba58b0b..ff7c21738a96 100644
--- a/tools/testing/selftests/kvm/arm64/hypercalls.c
+++ b/tools/testing/selftests/kvm/arm64/hypercalls.c
@@ -191,7 +191,8 @@ static void steal_time_init(struct kvm_vcpu *vcpu)
unsigned int gpages;
gpages = vm_calc_num_guest_pages(VM_MODE_DEFAULT, STEAL_TIME_SIZE);
- vm_userspace_mem_region_add(vcpu->vm, VM_MEM_SRC_ANONYMOUS, ST_GPA_BASE, 1, gpages, 0);
+ vm_userspace_mem_region_add(vcpu->vm, VM_MEM_SRC_ANONYMOUS, ST_GPA_BASE,
+ TEST_MEM_SLOT_BASE, gpages, 0);
vcpu_device_attr_set(vcpu, KVM_ARM_VCPU_PVTIME_CTRL,
KVM_ARM_VCPU_PVTIME_IPA, &st_ipa);
diff --git a/tools/testing/selftests/kvm/arm64/sea_to_user.c b/tools/testing/selftests/kvm/arm64/sea_to_user.c
index d4af6e0eed28..bb552debc61c 100644
--- a/tools/testing/selftests/kvm/arm64/sea_to_user.c
+++ b/tools/testing/selftests/kvm/arm64/sea_to_user.c
@@ -323,7 +323,7 @@ static struct kvm_vm *vm_create_with_sea_handler(struct kvm_vcpu **vcpu)
/*vm=*/vm,
/*src_type=*/src_type,
/*gpa=*/start_gpa,
- /*slot=*/1,
+ /*slot=*/TEST_MEM_SLOT_BASE,
/*npages=*/num_guest_pages,
/*flags=*/0);
diff --git a/tools/testing/selftests/kvm/arm64/stage2_block_transitions.c b/tools/testing/selftests/kvm/arm64/stage2_block_transitions.c
index 5fd47f4ada1f..0e23d7b55782 100644
--- a/tools/testing/selftests/kvm/arm64/stage2_block_transitions.c
+++ b/tools/testing/selftests/kvm/arm64/stage2_block_transitions.c
@@ -41,7 +41,7 @@
#include "test_util.h"
#include "ucall.h"
-#define DATA_SLOT 1
+#define DATA_SLOT TEST_MEM_SLOT_BASE
#define TEST_GVA 0xc0000000UL
#define BLOCK_SIZE SZ_2M
diff --git a/tools/testing/selftests/kvm/arm64/vgic_its_save.c b/tools/testing/selftests/kvm/arm64/vgic_its_save.c
index 864da01539f3..e858a4aa741d 100644
--- a/tools/testing/selftests/kvm/arm64/vgic_its_save.c
+++ b/tools/testing/selftests/kvm/arm64/vgic_its_save.c
@@ -29,7 +29,7 @@
#include "ucall.h"
#include "vgic.h"
-#define TEST_MEMSLOT_INDEX 1
+#define TEST_MEMSLOT_INDEX TEST_MEM_SLOT_BASE
/* All three ITS table entry sizes are 8 bytes in ABI 0. */
#define ESZ 8
diff --git a/tools/testing/selftests/kvm/arm64/vgic_lpi_stress.c b/tools/testing/selftests/kvm/arm64/vgic_lpi_stress.c
index 9a69c439a0f8..1d5c56481053 100644
--- a/tools/testing/selftests/kvm/arm64/vgic_lpi_stress.c
+++ b/tools/testing/selftests/kvm/arm64/vgic_lpi_stress.c
@@ -18,7 +18,7 @@
#include "ucall.h"
#include "vgic.h"
-#define TEST_MEMSLOT_INDEX 1
+#define TEST_MEMSLOT_INDEX TEST_MEM_SLOT_BASE
#define GIC_LPI_OFFSET 8192
diff --git a/tools/testing/selftests/kvm/dirty_log_test.c b/tools/testing/selftests/kvm/dirty_log_test.c
index af5eb0334a74..75084fe3bec6 100644
--- a/tools/testing/selftests/kvm/dirty_log_test.c
+++ b/tools/testing/selftests/kvm/dirty_log_test.c
@@ -26,7 +26,7 @@
#define PAGE_SHIFT_4K 12
/* The memory slot index to track dirty pages */
-#define TEST_MEM_SLOT_INDEX 1
+#define TEST_MEM_SLOT_INDEX TEST_MEM_SLOT_BASE
/* Default guest test virtual memory offset */
#define DEFAULT_GUEST_TEST_MEM 0xc0000000
diff --git a/tools/testing/selftests/kvm/guest_memfd_test.c b/tools/testing/selftests/kvm/guest_memfd_test.c
index 2233d871a38f..231bfe238e31 100644
--- a/tools/testing/selftests/kvm/guest_memfd_test.c
+++ b/tools/testing/selftests/kvm/guest_memfd_test.c
@@ -510,7 +510,7 @@ static void test_guest_memfd_guest(void)
* the PCI hole and other MMIO regions that need to be avoided.
*/
const gpa_t gpa = SZ_4G;
- const int slot = 1;
+ const int slot = TEST_MEM_SLOT_BASE;
struct kvm_vcpu *vcpu;
struct kvm_vm *vm;
diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing/selftests/kvm/include/kvm_util.h
index 5a7a455b5387..759d604d44ce 100644
--- a/tools/testing/selftests/kvm/include/kvm_util.h
+++ b/tools/testing/selftests/kvm/include/kvm_util.h
@@ -30,6 +30,7 @@
#define KVM_DEV_PATH "/dev/kvm"
#define KVM_MAX_VCPUS 512
+#define TEST_MEM_SLOT_BASE 1
#define NSEC_PER_SEC 1000000000L
diff --git a/tools/testing/selftests/kvm/kvm_page_table_test.c b/tools/testing/selftests/kvm/kvm_page_table_test.c
index 974813ea8953..f18720109319 100644
--- a/tools/testing/selftests/kvm/kvm_page_table_test.c
+++ b/tools/testing/selftests/kvm/kvm_page_table_test.c
@@ -20,7 +20,7 @@
#include "guest_modes.h"
#include "ucall_common.h"
-#define TEST_MEM_SLOT_INDEX 1
+#define TEST_MEM_SLOT_INDEX TEST_MEM_SLOT_BASE
/* Default size(1GB) of the memory for testing */
#define DEFAULT_TEST_MEM_SIZE (1 << 30)
diff --git a/tools/testing/selftests/kvm/mmu_stress_test.c b/tools/testing/selftests/kvm/mmu_stress_test.c
index 741e343962ed..b965a8b9d214 100644
--- a/tools/testing/selftests/kvm/mmu_stress_test.c
+++ b/tools/testing/selftests/kvm/mmu_stress_test.c
@@ -273,7 +273,7 @@ int main(int argc, char *argv[])
* 1gb-3gb,but it's simpler to skip straight to 4gb.
*/
const u64 start_gpa = SZ_4G;
- const int first_slot = 1;
+ const int first_slot = TEST_MEM_SLOT_BASE;
struct timespec time_start, time_run1, time_reset, time_run2, time_ro, time_rw;
u64 max_gpa, gpa, slot_size, max_mem, i;
diff --git a/tools/testing/selftests/kvm/riscv/sbi_pmu_test.c b/tools/testing/selftests/kvm/riscv/sbi_pmu_test.c
index 20388f0b959d..6abd74870e01 100644
--- a/tools/testing/selftests/kvm/riscv/sbi_pmu_test.c
+++ b/tools/testing/selftests/kvm/riscv/sbi_pmu_test.c
@@ -605,7 +605,8 @@ static void test_vm_events_test(void *guest_code)
static void test_vm_setup_snapshot_mem(struct kvm_vm *vm, struct kvm_vcpu *vcpu)
{
/* PMU Snapshot requires single page only */
- vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS, PMU_SNAPSHOT_GPA_BASE, 1, 1, 0);
+ vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS, PMU_SNAPSHOT_GPA_BASE,
+ TEST_MEM_SLOT_BASE, 1, 0);
/* PMU_SNAPSHOT_GPA_BASE is identity mapped */
virt_map(vm, PMU_SNAPSHOT_GPA_BASE, PMU_SNAPSHOT_GPA_BASE, 1);
diff --git a/tools/testing/selftests/kvm/steal_time.c b/tools/testing/selftests/kvm/steal_time.c
index 785d19f9ee8f..e386580ef540 100644
--- a/tools/testing/selftests/kvm/steal_time.c
+++ b/tools/testing/selftests/kvm/steal_time.c
@@ -509,7 +509,8 @@ static struct kvm_vm *vm_create_steal_time(u32 nr_vcpus, void *guest_code,
/* Create a VM and an identity mapped memslot for the steal time structure */
vm = vm_create_with_vcpus(nr_vcpus, guest_code, vcpus);
gpages = vm_calc_num_guest_pages(VM_MODE_DEFAULT, STEAL_TIME_SIZE * nr_vcpus);
- vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS, ST_GPA_BASE, 1, gpages, 0);
+ vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS, ST_GPA_BASE,
+ TEST_MEM_SLOT_BASE, gpages, 0);
virt_map(vm, ST_GPA_BASE, ST_GPA_BASE, gpages);
return vm;
diff --git a/tools/testing/selftests/kvm/x86/nested_dirty_log_test.c b/tools/testing/selftests/kvm/x86/nested_dirty_log_test.c
index 26b474bf1353..e86d625b3e89 100644
--- a/tools/testing/selftests/kvm/x86/nested_dirty_log_test.c
+++ b/tools/testing/selftests/kvm/x86/nested_dirty_log_test.c
@@ -16,7 +16,7 @@
#include "vmx.h"
/* The memory slot index to track dirty pages */
-#define TEST_MEM_SLOT_INDEX 1
+#define TEST_MEM_SLOT_INDEX TEST_MEM_SLOT_BASE
/*
* Allocate four pages total. Two pages are used to verify that the KVM marks
diff --git a/tools/testing/selftests/kvm/x86/nested_vmsave_vmload_test.c b/tools/testing/selftests/kvm/x86/nested_vmsave_vmload_test.c
index a130759f39a1..4bc57e5e40e3 100644
--- a/tools/testing/selftests/kvm/x86/nested_vmsave_vmload_test.c
+++ b/tools/testing/selftests/kvm/x86/nested_vmsave_vmload_test.c
@@ -17,7 +17,7 @@
* interpreted as a direct L1 GPA or translated using NPT as an L2 GPA, depends
* on which VMCB is accessed.
*/
-#define TEST_MEM_SLOT_INDEX 1
+#define TEST_MEM_SLOT_INDEX TEST_MEM_SLOT_BASE
#define TEST_MEM_PAGES 2
#define TEST_MEM_BASE 0xc0000000
--
2.53.0
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/5] KVM: selftests: Use the shared memslot base in memslot_perf_test
2026-10-17 11:02 [PATCH 0/5] KVM: selftests: Reserve memslot 1 for ucall MMIO Tharit Tangkijwanichakul
2026-10-17 11:02 ` [PATCH 1/5] KVM: selftests: Introduce a shared base for test memslots Tharit Tangkijwanichakul
@ 2026-10-17 11:02 ` Tharit Tangkijwanichakul
2026-10-17 11:02 ` [PATCH 3/5] KVM: selftests: Use the shared memslot base in memstress Tharit Tangkijwanichakul
` (2 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Tharit Tangkijwanichakul @ 2026-10-17 11:02 UTC (permalink / raw)
To: Paolo Bonzini, Sean Christopherson
Cc: Shuah Khan, Marc Zyngier, Oliver Upton, Fuad Tabba, Joey Gouly,
Steffen Eiden, Suzuki K Poulose, Zenghui Yu, Anup Patel,
Atish Patra, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, kvm, linux-kernel, linux-kselftest,
linux-arm-kernel, kvmarm, kvm-riscv, linux-riscv,
linux-kernel-mentees, skhan, me, jkoolstra,
Tharit Tangkijwanichakul
Use TEST_MEM_SLOT_BASE for test memslot IDs and account for the
reserved slots when calculating the available slot count. This
prepares memslot_perf_test for reserving slot 1 for library use.
Signed-off-by: Tharit Tangkijwanichakul <tharitt97@gmail.com>
---
.../testing/selftests/kvm/memslot_perf_test.c | 62 +++++++++++--------
1 file changed, 35 insertions(+), 27 deletions(-)
diff --git a/tools/testing/selftests/kvm/memslot_perf_test.c b/tools/testing/selftests/kvm/memslot_perf_test.c
index e1299611be32..cbb900ab58af 100644
--- a/tools/testing/selftests/kvm/memslot_perf_test.c
+++ b/tools/testing/selftests/kvm/memslot_perf_test.c
@@ -60,7 +60,7 @@
* other memslot(s).
*
* We have different number of memory slots, excluding the reserved
- * memory slot 0, on various architectures and configurations. The
+ * memory slots 0 and 1, on various architectures and configurations. The
* memory size in this test is calculated by picking the maximal
* last memory slot's memory size, with alignment to the largest
* supported page size (64KB). In this way, the selected memory
@@ -68,9 +68,9 @@
*
* architecture slots memory-per-slot memory-on-last-slot
* --------------------------------------------------------------
- * x86-4KB 32763 16KB 160KB
- * arm64-4KB 32766 16KB 112KB
- * arm64-16KB 32766 16KB 112KB
+ * x86-4KB 32762 16KB 176KB
+ * arm64-4KB 32765 16KB 128KB
+ * arm64-16KB 32765 16KB 128KB
* arm64-64KB 8192 64KB 128KB
*/
#define MEM_TEST_MOVE_SIZE (3 * SZ_64K)
@@ -276,7 +276,7 @@ static u64 get_max_slots(struct vm_data *data, u32 host_page_size)
rempages = mempages % pages_per_slot;
if (check_slot_pages(host_page_size, guest_page_size,
pages_per_slot, rempages))
- return slots + 1; /* slot 0 is reserved */
+ return slots + TEST_MEM_SLOT_BASE;
}
return 0;
@@ -313,38 +313,42 @@ static bool prepare_vm(struct vm_data *data, int nslots, u64 *maxslots,
data->hva_slots = malloc(sizeof(*data->hva_slots) * data->nslots);
TEST_ASSERT(data->hva_slots, "malloc() fail");
- pr_info_v("Adding slots 1..%i, each slot with %"PRIu64" pages + %"PRIu64" extra pages last\n",
- data->nslots, data->pages_per_slot, rempages);
+ pr_info_v("Adding slots %u..%u, each slot with %" PRIu64
+ " pages + %" PRIu64 " extra pages last\n",
+ (u32)TEST_MEM_SLOT_BASE,
+ TEST_MEM_SLOT_BASE + data->nslots - 1,
+ data->pages_per_slot, rempages);
clock_gettime(CLOCK_MONOTONIC, &tstart);
- for (slot = 1, guest_addr = MEM_GPA; slot <= data->nslots; slot++) {
+ for (slot = 0, guest_addr = MEM_GPA; slot < data->nslots; slot++) {
u64 npages;
npages = data->pages_per_slot;
- if (slot == data->nslots)
+ if (slot == data->nslots - 1)
npages += rempages;
vm_userspace_mem_region_add(data->vm, VM_MEM_SRC_ANONYMOUS,
- guest_addr, slot, npages,
- 0);
+ guest_addr, TEST_MEM_SLOT_BASE + slot,
+ npages, 0);
guest_addr += npages * guest_page_size;
}
*slot_runtime = timespec_elapsed(tstart);
- for (slot = 1, guest_addr = MEM_GPA; slot <= data->nslots; slot++) {
+ for (slot = 0, guest_addr = MEM_GPA; slot < data->nslots; slot++) {
u64 npages;
gpa_t gpa;
npages = data->pages_per_slot;
- if (slot == data->nslots)
+ if (slot == data->nslots - 1)
npages += rempages;
- gpa = vm_phy_pages_alloc(data->vm, npages, guest_addr, slot);
+ gpa = vm_phy_pages_alloc(data->vm, npages, guest_addr,
+ TEST_MEM_SLOT_BASE + slot);
TEST_ASSERT(gpa == guest_addr,
"vm_phy_pages_alloc() failed");
- data->hva_slots[slot - 1] = addr_gpa2hva(data->vm, guest_addr);
- memset(data->hva_slots[slot - 1], 0, npages * guest_page_size);
+ data->hva_slots[slot] = addr_gpa2hva(data->vm, guest_addr);
+ memset(data->hva_slots[slot], 0, npages * guest_page_size);
guest_addr += npages * guest_page_size;
}
@@ -631,9 +635,10 @@ static void test_memslot_move_loop(struct vm_data *data, struct sync_area *sync)
u64 movesrcgpa;
movesrcgpa = vm_slot2gpa(data, data->nslots - 1);
- vm_mem_region_move(data->vm, data->nslots - 1 + 1,
+ vm_mem_region_move(data->vm, TEST_MEM_SLOT_BASE + data->nslots - 1,
MEM_TEST_MOVE_GPA_DEST);
- vm_mem_region_move(data->vm, data->nslots - 1 + 1, movesrcgpa);
+ vm_mem_region_move(data->vm, TEST_MEM_SLOT_BASE + data->nslots - 1,
+ movesrcgpa);
}
static void test_memslot_do_unmap(struct vm_data *data,
@@ -988,8 +993,10 @@ static bool parse_args(int argc, char *argv[],
#endif
case 's':
targs->nslots = atoi_paranoid(optarg);
- if (targs->nslots <= 1 && targs->nslots != -1) {
- pr_info("Slot count cap must be larger than 1 or -1 for no cap\n");
+ if (targs->nslots <= TEST_MEM_SLOT_BASE &&
+ targs->nslots != -1) {
+ pr_info("Slot count cap must be larger than %d or -1 for no cap\n",
+ TEST_MEM_SLOT_BASE);
return false;
}
break;
@@ -1027,20 +1034,21 @@ static bool parse_args(int argc, char *argv[],
}
max_mem_slots = kvm_check_cap(KVM_CAP_NR_MEMSLOTS);
- if (max_mem_slots <= 1) {
- pr_info("KVM_CAP_NR_MEMSLOTS should be greater than 1\n");
+ if (max_mem_slots <= TEST_MEM_SLOT_BASE) {
+ pr_info("KVM_CAP_NR_MEMSLOTS should be greater than %d\n",
+ TEST_MEM_SLOT_BASE);
return false;
}
- /* Memory slot 0 is reserved */
+ /* Memory slots below TEST_MEM_SLOT_BASE are reserved. */
if (targs->nslots == -1)
- targs->nslots = max_mem_slots - 1;
+ targs->nslots = max_mem_slots - TEST_MEM_SLOT_BASE;
else
- targs->nslots = min_t(int, targs->nslots, max_mem_slots) - 1;
+ targs->nslots = min_t(int, targs->nslots, max_mem_slots)
+ - TEST_MEM_SLOT_BASE;
pr_info_v("Allowed Number of memory slots: %"PRIu32"\n",
- targs->nslots + 1);
-
+ (u32)(targs->nslots + TEST_MEM_SLOT_BASE));
return true;
}
--
2.53.0
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 3/5] KVM: selftests: Use the shared memslot base in memstress
2026-10-17 11:02 [PATCH 0/5] KVM: selftests: Reserve memslot 1 for ucall MMIO Tharit Tangkijwanichakul
2026-10-17 11:02 ` [PATCH 1/5] KVM: selftests: Introduce a shared base for test memslots Tharit Tangkijwanichakul
2026-10-17 11:02 ` [PATCH 2/5] KVM: selftests: Use the shared memslot base in memslot_perf_test Tharit Tangkijwanichakul
@ 2026-10-17 11:02 ` Tharit Tangkijwanichakul
2026-10-17 11:02 ` [PATCH 4/5] KVM: selftests: Reserve memslot 1 for the ucall MMIO address Tharit Tangkijwanichakul
2026-10-17 11:02 ` [PATCH 5/5] KVM: selftests: Test protection of the ucall MMIO region Tharit Tangkijwanichakul
4 siblings, 0 replies; 7+ messages in thread
From: Tharit Tangkijwanichakul @ 2026-10-17 11:02 UTC (permalink / raw)
To: Paolo Bonzini, Sean Christopherson
Cc: Shuah Khan, Marc Zyngier, Oliver Upton, Fuad Tabba, Joey Gouly,
Steffen Eiden, Suzuki K Poulose, Zenghui Yu, Anup Patel,
Atish Patra, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, kvm, linux-kernel, linux-kselftest,
linux-arm-kernel, kvmarm, kvm-riscv, linux-riscv,
linux-kernel-mentees, skhan, me, jkoolstra,
Tharit Tangkijwanichakul
Define MEMSTRESS_MEM_SLOT_INDEX using TEST_MEM_SLOT_BASE so
memstress and its users follow the library's reserved-slot
convention.
The tests affected but require no change are:
dirty_log_perf_test.c
demand_paging_test.c
access_tracking_perf_test.c
memslot_modification_stress_test.c
x86/dirty_log_page_splitting_test.c
Signed-off-by: Tharit Tangkijwanichakul <tharitt97@gmail.com>
---
tools/testing/selftests/kvm/include/memstress.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/testing/selftests/kvm/include/memstress.h b/tools/testing/selftests/kvm/include/memstress.h
index 0d1d6230cc05..4da03541e805 100644
--- a/tools/testing/selftests/kvm/include/memstress.h
+++ b/tools/testing/selftests/kvm/include/memstress.h
@@ -17,7 +17,7 @@
#define DEFAULT_PER_VCPU_MEM_SIZE (1 << 30) /* 1G */
-#define MEMSTRESS_MEM_SLOT_INDEX 1
+#define MEMSTRESS_MEM_SLOT_INDEX TEST_MEM_SLOT_BASE
struct memstress_vcpu_args {
gpa_t gpa;
--
2.53.0
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 4/5] KVM: selftests: Reserve memslot 1 for the ucall MMIO address
2026-10-17 11:02 [PATCH 0/5] KVM: selftests: Reserve memslot 1 for ucall MMIO Tharit Tangkijwanichakul
` (2 preceding siblings ...)
2026-10-17 11:02 ` [PATCH 3/5] KVM: selftests: Use the shared memslot base in memstress Tharit Tangkijwanichakul
@ 2026-10-17 11:02 ` Tharit Tangkijwanichakul
2026-10-17 11:02 ` [PATCH 5/5] KVM: selftests: Test protection of the ucall MMIO region Tharit Tangkijwanichakul
4 siblings, 0 replies; 7+ messages in thread
From: Tharit Tangkijwanichakul @ 2026-10-17 11:02 UTC (permalink / raw)
To: Paolo Bonzini, Sean Christopherson
Cc: Shuah Khan, Marc Zyngier, Oliver Upton, Fuad Tabba, Joey Gouly,
Steffen Eiden, Suzuki K Poulose, Zenghui Yu, Anup Patel,
Atish Patra, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, kvm, linux-kernel, linux-kselftest,
linux-arm-kernel, kvmarm, kvm-riscv, linux-riscv,
linux-kernel-mentees, skhan, me, jkoolstra,
Tharit Tangkijwanichakul
Back the ucall MMIO address with a read-only region in slot 1
when KVM_CAP_READONLY_MEM is available. Writes still exit as
MMIO, while overlapping memslot creation is rejected.
Start test memslots at slot 2, leaving slot 1 reserved by
convention even when read-only memory is unsupported.
Signed-off-by: Tharit Tangkijwanichakul <tharitt97@gmail.com>
---
.../testing/selftests/kvm/include/kvm_util.h | 2 +-
tools/testing/selftests/kvm/lib/kvm_util.c | 19 +++++++++++++------
2 files changed, 14 insertions(+), 7 deletions(-)
diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing/selftests/kvm/include/kvm_util.h
index 759d604d44ce..4dbb2ef332fc 100644
--- a/tools/testing/selftests/kvm/include/kvm_util.h
+++ b/tools/testing/selftests/kvm/include/kvm_util.h
@@ -30,7 +30,7 @@
#define KVM_DEV_PATH "/dev/kvm"
#define KVM_MAX_VCPUS 512
-#define TEST_MEM_SLOT_BASE 1
+#define TEST_MEM_SLOT_BASE 2
#define NSEC_PER_SEC 1000000000L
diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c
index 9ddc047d5c27..73e28814a226 100644
--- a/tools/testing/selftests/kvm/lib/kvm_util.c
+++ b/tools/testing/selftests/kvm/lib/kvm_util.c
@@ -20,6 +20,7 @@
#include <linux/kernel.h>
#define KVM_UTIL_MIN_PFN 2
+#define KVM_UCALL_MEMSLOT 1
u32 kvm_random_seed;
struct kvm_random_state kvm_rng;
@@ -492,6 +493,7 @@ struct kvm_vm *__vm_create(struct vm_shape shape, u32 nr_runnable_vcpus,
struct userspace_mem_region *slot0;
struct kvm_vm *vm;
int i, flags;
+ gpa_t mmio_gpa;
kvm_set_files_rlimit(nr_runnable_vcpus);
@@ -514,14 +516,19 @@ struct kvm_vm *__vm_create(struct vm_shape shape, u32 nr_runnable_vcpus,
kvm_vm_elf_load(vm, program_invocation_name);
- /*
- * TODO: Add proper defines to protect the library's memslots, and then
- * carve out memslot1 for the ucall MMIO address. KVM treats writes to
- * read-only memslots as MMIO, and creating a read-only memslot for the
- * MMIO region would prevent silently clobbering the MMIO region.
+ /* KVM treats writes to read-only memslots as MMIO, and creating
+ * a read-only memslot for the MMIO region would prevent silently
+ * clobbering the MMIO region.
*/
slot0 = memslot2region(vm, 0);
- ucall_init(vm, slot0->region.guest_phys_addr + slot0->region.memory_size);
+ mmio_gpa = slot0->region.guest_phys_addr + slot0->region.memory_size;
+ ucall_init(vm, mmio_gpa);
+
+ if (vm_check_cap(vm, KVM_CAP_READONLY_MEM))
+ vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS,
+ mmio_gpa, KVM_UCALL_MEMSLOT,
+ vm_adjust_num_guest_pages(vm->mode, 1),
+ KVM_MEM_READONLY);
if (kvm_random_seed != last_kvm_seed)
kvm_seed_rng(kvm_random_seed);
--
2.53.0
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 5/5] KVM: selftests: Test protection of the ucall MMIO region
2026-10-17 11:02 [PATCH 0/5] KVM: selftests: Reserve memslot 1 for ucall MMIO Tharit Tangkijwanichakul
` (3 preceding siblings ...)
2026-10-17 11:02 ` [PATCH 4/5] KVM: selftests: Reserve memslot 1 for the ucall MMIO address Tharit Tangkijwanichakul
@ 2026-10-17 11:02 ` Tharit Tangkijwanichakul
2026-10-17 15:25 ` Tharit Tangkijwanichakul
4 siblings, 1 reply; 7+ messages in thread
From: Tharit Tangkijwanichakul @ 2026-10-17 11:02 UTC (permalink / raw)
To: Paolo Bonzini, Sean Christopherson
Cc: Shuah Khan, Marc Zyngier, Oliver Upton, Fuad Tabba, Joey Gouly,
Steffen Eiden, Suzuki K Poulose, Zenghui Yu, Anup Patel,
Atish Patra, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, kvm, linux-kernel, linux-kselftest,
linux-arm-kernel, kvmarm, kvm-riscv, linux-riscv,
linux-kernel-mentees, skhan, me, jkoolstra,
Tharit Tangkijwanichakul
Verify that creating a memslot overlapping the ucall MMIO region
fails with EEXIST and that ucalls work before and after the
attempt. Skip when MMIO ucalls or read-only memory are unsupported.
Signed-off-by: Tharit Tangkijwanichakul <tharitt97@gmail.com>
---
tools/testing/selftests/kvm/Makefile.kvm | 1 +
.../selftests/kvm/reserved_slot_test.c | 61 +++++++++++++++++++
2 files changed, 62 insertions(+)
create mode 100644 tools/testing/selftests/kvm/reserved_slot_test.c
diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selftests/kvm/Makefile.kvm
index 1f4bc2a1322d..ff4a5e9733e9 100644
--- a/tools/testing/selftests/kvm/Makefile.kvm
+++ b/tools/testing/selftests/kvm/Makefile.kvm
@@ -68,6 +68,7 @@ TEST_GEN_PROGS_COMMON += set_memory_region_test
TEST_GEN_PROGS_COMMON += memslot_modification_stress_test
TEST_GEN_PROGS_COMMON += memslot_perf_test
TEST_GEN_PROGS_COMMON += vm_types_test
+TEST_GEN_PROGS_COMMON += reserved_slot_test
# Compiled test targets
TEST_GEN_PROGS_x86 = $(TEST_GEN_PROGS_COMMON)
diff --git a/tools/testing/selftests/kvm/reserved_slot_test.c b/tools/testing/selftests/kvm/reserved_slot_test.c
new file mode 100644
index 000000000000..4a908017ca73
--- /dev/null
+++ b/tools/testing/selftests/kvm/reserved_slot_test.c
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0
+#include "kvm_util.h"
+#include "processor.h"
+#include "test_util.h"
+
+#define CLOBBERED_SLOT TEST_MEM_SLOT_BASE
+
+static void guest_code(void)
+{
+ GUEST_SYNC(1);
+ GUEST_SYNC(2);
+}
+
+static void test_slot1_protected(void)
+{
+ struct kvm_vcpu *vcpu;
+ struct kvm_run *run;
+ struct kvm_vm *vm;
+ struct ucall uc;
+ u32 nr_pages;
+ size_t slot_size;
+ void *slot_mem;
+ int ret;
+
+ vm = vm_create_with_one_vcpu(&vcpu, guest_code);
+ nr_pages = vm_adjust_num_guest_pages(vm->mode, 1);
+ slot_size = (size_t)nr_pages * vm->page_size;
+
+ run = vcpu->run;
+ vcpu_run(vcpu);
+ TEST_ASSERT(run->exit_reason == KVM_EXIT_MMIO,
+ "Unexpected exit reason = %u", run->exit_reason);
+ TEST_ASSERT(get_ucall(vcpu, &uc) == UCALL_SYNC && uc.args[1] == 1,
+ "Expected the first sync before clobbering the ucall GPA");
+
+ slot_mem = kvm_mmap(slot_size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1);
+ ret = __vm_set_user_memory_region2(vm, CLOBBERED_SLOT, 0,
+ vm->ucall_mmio_addr, slot_size, slot_mem, 0, 0);
+ TEST_ASSERT(ret == -1 && errno == EEXIST,
+ "Expected the ucall GPA overlap to be rejected: ret=%d errno=%d",
+ ret, errno);
+
+ vcpu_run(vcpu);
+ TEST_ASSERT(run->exit_reason == KVM_EXIT_MMIO,
+ "Unexpected exit reason = %u", run->exit_reason);
+ TEST_ASSERT(get_ucall(vcpu, &uc) == UCALL_SYNC && uc.args[1] == 2,
+ "Expected the second sync after attempting to clobber the ucall GPA");
+
+ kvm_vm_free(vm);
+ TEST_ASSERT(!munmap(slot_mem, slot_size), "munmap() failed, errno=%d", errno);
+}
+
+int main(void)
+{
+ TEST_REQUIRE(UCALL_EXIT_REASON == KVM_EXIT_MMIO);
+ TEST_REQUIRE(kvm_has_cap(KVM_CAP_READONLY_MEM));
+
+ test_slot1_protected();
+ return 0;
+}
--
2.53.0
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 5/5] KVM: selftests: Test protection of the ucall MMIO region
2026-10-17 11:02 ` [PATCH 5/5] KVM: selftests: Test protection of the ucall MMIO region Tharit Tangkijwanichakul
@ 2026-10-17 15:25 ` Tharit Tangkijwanichakul
0 siblings, 0 replies; 7+ messages in thread
From: Tharit Tangkijwanichakul @ 2026-10-17 15:25 UTC (permalink / raw)
To: Paolo Bonzini, Sean Christopherson
Cc: Shuah Khan, Marc Zyngier, Oliver Upton, Fuad Tabba, Joey Gouly,
Steffen Eiden, Suzuki K Poulose, Zenghui Yu, Anup Patel,
Atish Patra, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, kvm, linux-kernel, linux-kselftest,
linux-arm-kernel, kvmarm, kvm-riscv, linux-riscv,
linux-kernel-mentees, skhan, me, jkoolstra
> +#define CLOBBERED_SLOT TEST_MEM_SLOT_BASE
Upon self-review, this should have been hardcoded to 1 (to clobber the
reserved ucal mmio).
> + ret = __vm_set_user_memory_region2(vm, CLOBBERED_SLOT, 0,
> + vm->ucall_mmio_addr, slot_size, slot_mem, 0, 0);
> + TEST_ASSERT(ret == -1 && errno == EEXIST,
> + "Expected the ucall GPA overlap to be rejected: ret=%d errno=%d",
> + ret, errno);
This should have been errno == EINVAL check to catch writing to the
exiting read-only slot.
The earlier test accidentally passed because it used a different slot
ID (=2, not reserved) and received EEXIST for overlapping the reserved
ucall GPA. It therefore tested GPA overlap rejection, not the intended
rejection of overwriting slot 1.
I will fix it in v2
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-10-17 15:25 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-17 11:02 [PATCH 0/5] KVM: selftests: Reserve memslot 1 for ucall MMIO Tharit Tangkijwanichakul
2026-10-17 11:02 ` [PATCH 1/5] KVM: selftests: Introduce a shared base for test memslots Tharit Tangkijwanichakul
2026-10-17 11:02 ` [PATCH 2/5] KVM: selftests: Use the shared memslot base in memslot_perf_test Tharit Tangkijwanichakul
2026-10-17 11:02 ` [PATCH 3/5] KVM: selftests: Use the shared memslot base in memstress Tharit Tangkijwanichakul
2026-10-17 11:02 ` [PATCH 4/5] KVM: selftests: Reserve memslot 1 for the ucall MMIO address Tharit Tangkijwanichakul
2026-10-17 11:02 ` [PATCH 5/5] KVM: selftests: Test protection of the ucall MMIO region Tharit Tangkijwanichakul
2026-10-17 15:25 ` Tharit Tangkijwanichakul
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox