From nobody Thu Apr 16 19:18:20 2026 Received: from jpms-ob02.noc.sony.co.jp (jpms-ob02.noc.sony.co.jp [211.125.140.165]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D420038F921; Thu, 26 Feb 2026 07:35:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=211.125.140.165 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772091329; cv=none; b=hsfyvzXsnhQ4mW4/OiyhEFnqpryhqatM/i0BMyzPGCGVSFH9f9FcNETt3cwlditFQJaZzs16ujIjqLjFzAWgvNeuSb7yaMQCnPgoUNta5pWHs+II/SmGvVOEUDq9YeQalrBxzRBbNzfzLAxwhrvZVkB1ukkcnpIhGNANpXlYgNs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772091329; c=relaxed/simple; bh=P8+TGDnvkg7gufbIf6sOV2gE+oWXesLj+BT+qqAjWd0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KxR2AFQyMuRrBLtIOpT/44wZfXkX+yBQ+an49vxHABjkBaXA5fm6hbryBLy3AECSnAvwRT400reFxduWPZTnJC/+PhUj+kmjaMN4qGJZf7VUt0aEhEknH/u6RgxpcHsAkRfl2OWyKUprQHgPuvFF8OQbFCtZkVd7/5xoRvRflIQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=sony.com; spf=pass smtp.mailfrom=sony.com; dkim=pass (2048-bit key) header.d=sony.com header.i=@sony.com header.b=KcYHtes9; arc=none smtp.client-ip=211.125.140.165 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=sony.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=sony.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=sony.com header.i=@sony.com header.b="KcYHtes9" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sony.com; s=s1jp; t=1772091326; x=1803627326; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=okgIaffSuE7iTDSP0gw48/bn86X3WVAG8sCQHMc54fQ=; b=KcYHtes9avrkA27FxmBskqP1CAajtqUObEK+T86A2EN7bhIZiqcDj+Iv /FQ+Zl7eFu0aL/NCf4FPv9IJsMG/pSHvEcNpnaPZUBHkhG7ye7CGQpFmT HNEU740zbTws79IFkZdYNkfS4goNN80PAmmkFwaepmIDjJOMZuWvPesog o933GmG+9/iWpx2+MTc8djPU7/7QWNHYbsF51RUxSqLv5fWPSegXoQKui 4E41Q//nTrbKknDif1nRH34HZxFSEfYd7+2j9nY7tWYeU4pUEbGIJmD5U 0rL8ORX/PPetVQ/9CQsptgB62s+JjFccF0mtQ32c/u3SQwfYF12KmyFxN Q==; Received: from unknown (HELO jpmta-ob1.noc.sony.co.jp) ([IPv6:2001:cf8:0:6e7::6]) by jpms-ob02.noc.sony.co.jp with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Feb 2026 16:35:24 +0900 X-IronPort-AV: E=Sophos;i="6.21,311,1763391600"; d="scan'208";a="616141560" Received: from unknown (HELO asagi..) ([43.11.56.84]) by jpmta-ob1.noc.sony.co.jp with ESMTP; 26 Feb 2026 16:35:23 +0900 From: Yohei Kojima To: Paolo Bonzini , Shuah Khan Cc: Yohei Kojima , Daniel Palmer , Tim Bird , kvm@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 1/2] KVM: selftests: Extract memslot setup code from spawn_vm() Date: Thu, 26 Feb 2026 16:37:14 +0900 Message-ID: <57c05d4d7db845be9250b7a4f6537e98636d70ca.1772090306.git.yohei.kojima@sony.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add vm_userspace_mem_region_add_map() function to set up memslot, and update spawn_vm() to use it. This helps the test cases to create additional memslots easily. Signed-off-by: Yohei Kojima --- .../selftests/kvm/set_memory_region_test.c | 47 ++++++++++++------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/tools/testing/selftests/kvm/set_memory_region_test.c b/tools/t= esting/selftests/kvm/set_memory_region_test.c index 7fe427ff9b38..8d4fd713347c 100644 --- a/tools/testing/selftests/kvm/set_memory_region_test.c +++ b/tools/testing/selftests/kvm/set_memory_region_test.c @@ -107,31 +107,42 @@ static void wait_for_vcpu(void) usleep(100000); } =20 +static void vm_userspace_mem_region_add_map(struct kvm_vm *vm, + uint64_t addr, uint32_t slot, size_t size, uint32_t flags) +{ + uint64_t *hva; + uint64_t gpa; + + vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS_THP, + addr, slot, + size / getpagesize(), flags); + + /* + * Allocate and map two pages so that the GPA accessed by guest_code() + * stays valid across the memslot move. + */ + gpa =3D vm_phy_pages_alloc(vm, 2, addr, slot); + TEST_ASSERT(gpa =3D=3D addr, "Failed vm_phy_pages_alloc\n"); + + virt_map(vm, addr, addr, 2); + + /* Ditto for the host mapping so that both pages can be zeroed. */ + hva =3D addr_gpa2hva(vm, MEM_REGION_GPA); + memset(hva, 0, 2 * 4096); +} + static struct kvm_vm *spawn_vm(struct kvm_vcpu **vcpu, pthread_t *vcpu_thr= ead, void *guest_code) { struct kvm_vm *vm; - uint64_t *hva; - uint64_t gpa; =20 vm =3D vm_create_with_one_vcpu(vcpu, guest_code); =20 - vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS_THP, - MEM_REGION_GPA, MEM_REGION_SLOT, - MEM_REGION_SIZE / getpagesize(), 0); - - /* - * Allocate and map two pages so that the GPA accessed by guest_code() - * stays valid across the memslot move. - */ - gpa =3D vm_phy_pages_alloc(vm, 2, MEM_REGION_GPA, MEM_REGION_SLOT); - TEST_ASSERT(gpa =3D=3D MEM_REGION_GPA, "Failed vm_phy_pages_alloc\n"); - - virt_map(vm, MEM_REGION_GPA, MEM_REGION_GPA, 2); - - /* Ditto for the host mapping so that both pages can be zeroed. */ - hva =3D addr_gpa2hva(vm, MEM_REGION_GPA); - memset(hva, 0, 2 * 4096); + vm_userspace_mem_region_add_map(vm, + MEM_REGION_GPA, + MEM_REGION_SLOT, + MEM_REGION_SIZE, + 0); =20 pthread_create(vcpu_thread, NULL, vcpu_worker, *vcpu); =20 --=20 2.43.0 From nobody Thu Apr 16 19:18:20 2026 Received: from jpms-ob01.noc.sony.co.jp (jpms-ob01.noc.sony.co.jp [211.125.140.164]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AFD5F18DF9D; Thu, 26 Feb 2026 07:45:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=211.125.140.164 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772091944; cv=none; b=vE/eKxJsGXwcE3di6I0RdTTE3lINQBk3IKonQe5tP/NwdzQ82IGNxE1F5tK7s+1jxHFjx/pOb8bosZA5omYa2/nhZs9IJ2syRPcXsrwTIGfTUg3/lNZuKO54O1rJr8UeCMSR6OQCu9Cr272zEHOgkYQATsMyv3FqqU1eymVk4Nw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772091944; c=relaxed/simple; bh=XlyfTKQvT+attS79aJv44qTZ3vo2uGVzMyVcldJbDmk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=aUC6+P5AEXP7qNJZMsXWBLzqOSK6z7lwB4VHKWcAop3WJDkMSyZAxD3s+h9GQeK4PQ6XAynB1s4hMauREq2usH5Q72vfYrJ6rxI64essZxM5L+kPp9KGL+PqAA9t6dKD8ODKT+ciJ5Y2EJfdOJ/wMZyeU6am2bs08EKaPiT2oZQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=sony.com; spf=pass smtp.mailfrom=sony.com; dkim=pass (2048-bit key) header.d=sony.com header.i=@sony.com header.b=BL1V1/0k; arc=none smtp.client-ip=211.125.140.164 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=sony.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=sony.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=sony.com header.i=@sony.com header.b="BL1V1/0k" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sony.com; s=s1jp; t=1772091943; x=1803627943; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=PmAhxaglJ4zsFHlpniPU1qeRT9pDBq4QRgL4uv1x7B0=; b=BL1V1/0k7ie0QEns3iHWFd4tkRfrVCoQ7QGI/yh40m2DwH9NbxXbA38S pvBU2aMEUnUy4LQww46glPRJkOJG57TzDLYw5kII7iJNA5+CYftqeJevT w6jTQKpvUpb5mAfDJp7CvZ2Dk54vIxNWittuC1iT63IwSDJhCNpwK7olV 4KxVmtXAIeH5iOZ3e0L11m+YhS+mj5I7OZm8Cd5GG1aWWLaFMuxvYcYlj wCrkqAIu5jRgBfL6oC8hVQv+Fa5FEYS83PM4NU4k0Vs9AGBLxL26a85wo 8v/jh/P2FdMjM2Pn5IGOfcjtb5J/rRqI/6BIWLJVMnUPEwnZF17gEIaFS g==; Received: from unknown (HELO jpmta-ob1.noc.sony.co.jp) ([IPv6:2001:cf8:0:6e7::6]) by jpms-ob01.noc.sony.co.jp with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Feb 2026 16:35:33 +0900 X-IronPort-AV: E=Sophos;i="6.21,311,1763391600"; d="scan'208";a="616141614" Received: from unknown (HELO asagi..) ([43.11.56.84]) by jpmta-ob1.noc.sony.co.jp with ESMTP; 26 Feb 2026 16:35:32 +0900 From: Yohei Kojima To: Paolo Bonzini , Shuah Khan Cc: Yohei Kojima , Daniel Palmer , Tim Bird , kvm@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 2/2] KVM: selftests: Add test case for readonly memslots on x86 Date: Thu, 26 Feb 2026 16:37:15 +0900 Message-ID: <26c1ddd4c80498bfba17ade1f9c88a04cf77779e.1772090306.git.yohei.kojima@sony.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Extend set_memory_region_test to verify the following properties: * read on RO-memslot succeeds, * execute on RO-memslot backed by executable memory succeeds, and * write on RO-memslot fails with mmio fault. Signed-off-by: Yohei Kojima --- .../selftests/kvm/set_memory_region_test.c | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/tools/testing/selftests/kvm/set_memory_region_test.c b/tools/t= esting/selftests/kvm/set_memory_region_test.c index 8d4fd713347c..2f21bfcbc821 100644 --- a/tools/testing/selftests/kvm/set_memory_region_test.c +++ b/tools/testing/selftests/kvm/set_memory_region_test.c @@ -28,7 +28,10 @@ * Somewhat arbitrary location and slot, intended to not overlap anything. */ #define MEM_REGION_GPA 0xc0000000 +#define MEM_REGION_RO_GPA 0xd0000000 + #define MEM_REGION_SLOT 10 +#define MEM_REGION_RO_SLOT 11 =20 static const uint64_t MMIO_VAL =3D 0xbeefull; =20 @@ -49,6 +52,8 @@ static inline uint64_t guest_spin_on_val(uint64_t spin_va= l) return val; } =20 +static int allow_mmio_fault; + static void *vcpu_worker(void *data) { struct kvm_vcpu *vcpu =3D data; @@ -76,6 +81,13 @@ static void *vcpu_worker(void *data) if (run->exit_reason !=3D KVM_EXIT_MMIO) break; =20 + if (allow_mmio_fault && run->mmio.is_write) + /* + * in this case, skip checking mmio-related assertions + * and exit status + */ + return NULL; + TEST_ASSERT(!run->mmio.is_write, "Unexpected exit mmio write"); TEST_ASSERT(run->mmio.len =3D=3D 8, "Unexpected exit mmio size =3D %u", run->mmio.len); @@ -336,6 +348,92 @@ static void test_delete_memory_region(bool disable_slo= t_zap_quirk) kvm_vm_free(vm); } =20 +static void guest_code_ro_memory_region(void) +{ + uint64_t val; + unsigned char c; + void *instruction_addr; + + GUEST_SYNC(0); + + val =3D guest_spin_on_val(0); + __GUEST_ASSERT(val =3D=3D 1, "Expected '1', got '%lx'", val); + + /* RO memory read; should succeed if the backing memory is readable */ + c =3D *(unsigned char *)MEM_REGION_RO_GPA; + __GUEST_ASSERT(c =3D=3D 0xab, "Expected '0xab', got '0x%x'", c); + + /* RO memory exec; should succeed if the backing memory is executable */ + instruction_addr =3D ((unsigned char *)MEM_REGION_RO_GPA) + 8; + val =3D ((uint32_t (*)(void))instruction_addr)(); + __GUEST_ASSERT(val =3D=3D 0xbeef, + "Expected 0xbeef, but got '%lx'", val); + + /* Spin until the mmio fault is allowed for RO-memslot write */ + val =3D guest_spin_on_val(1); + __GUEST_ASSERT(val =3D=3D 2, "Expected '2', got '%lx'", val); + + /* RO memory write; should fail */ + WRITE_ONCE(*((uint64_t *)MEM_REGION_RO_GPA), 0x12); + __GUEST_ASSERT(0, "RO memory write is expected to fail, but it didn't"); +} + +/* + * On x86 environment, write access to the readonly memslots are trapped as + * a special MMIO fault. This test verifies that write access on the reado= nly + * memslot is blocked, and read/exec access isn't. + */ +static void test_ro_memory_region(void) +{ + pthread_t vcpu_thread; + uint64_t *hva, *hva_ro; + struct kvm_vcpu *vcpu; + struct kvm_vm *vm; + + /* + * Equivalent C function (assuming SysV ABI): + * uint32_t some_function(void) { + * return 0xbeef; + * } + */ + unsigned char inst_bytes[] =3D { + 0x48, 0xc7, 0xc0, 0xef, 0xbe, 0x00, 0x00, // mov %eax, $0xbeef + 0xc3, // ret + }; + + pr_info("Testing write on RO memslot\n"); + + vm =3D spawn_vm(&vcpu, &vcpu_thread, guest_code_ro_memory_region); + + vm_userspace_mem_region_add_map(vm, + MEM_REGION_RO_GPA, + MEM_REGION_RO_SLOT, + MEM_REGION_SIZE, + KVM_MEM_READONLY); + + hva =3D addr_gpa2hva(vm, MEM_REGION_GPA); + hva_ro =3D addr_gpa2hva(vm, MEM_REGION_RO_GPA); + + memset(hva_ro, 0xcccccccc, 0x2000); + WRITE_ONCE(*hva_ro, 0xab); + memcpy(((unsigned char *)hva_ro) + 8, inst_bytes, sizeof(inst_bytes)); + + WRITE_ONCE(*hva, 1); + + /* Wait the vcpu thread to complete read/exec on ro memory */ + usleep(100000); + + allow_mmio_fault =3D true; + WRITE_ONCE(*hva, 2); + + wait_for_vcpu(); + + pthread_join(vcpu_thread, NULL); + + kvm_vm_free(vm); + allow_mmio_fault =3D false; +} + static void test_zero_memory_regions(void) { struct kvm_vcpu *vcpu; @@ -629,6 +727,8 @@ int main(int argc, char *argv[]) */ test_zero_memory_regions(); test_mmio_during_vectoring(); + + test_ro_memory_region(); #endif =20 test_invalid_memory_region_flags(); --=20 2.43.0