Kernel KVM virtualization development
 help / color / mirror / Atom feed
From: Paolo Bonzini <pbonzini@redhat.com>
To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org
Cc: nsaenz@amazon.com, vkuznets@redhat.com, snambakam@linux.microsoft.com
Subject: [PATCH 31/31] KVM: x86: selftests: Introduce memory attributes side-channel tests
Date: Fri, 18 Sep 2026 09:50:30 -0400	[thread overview]
Message-ID: <20260918135030.171564-32-pbonzini@redhat.com> (raw)
In-Reply-To: <20260918135030.171564-1-pbonzini@redhat.com>

Introduce memory attributes selftests to catch any vulnerable
side-channels.

Memory attributes access restrictions are vulnerable to side-channel
attacks. This means that any KVM operation initiated by the guest that
requires guest memory access (which is the case for most
para-virtualised interfaces) needs to consider memory attributes.

The tests confirm this requirement is upheld for a variety of
use-cases, exercising various kinds of guest memory access such as
kvm_read/write_guest(), gfn_to_hva_cache and gfn_to_pfn_cache.

Co-developed-by: Nicolas Saenz Julienne <nsaenz@amazon.com>
Signed-off-by: Nicolas Saenz Julienne <nsaenz@amazon.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 .../testing/selftests/kvm/include/kvm_util.h  |   9 +
 .../selftests/kvm/include/x86/processor.h     |   1 +
 .../testing/selftests/kvm/lib/x86/processor.c |   5 +
 .../testing/selftests/kvm/memory_attributes.c |  51 +++-
 .../selftests/kvm/x86/memory_attributes.c     | 232 ++++++++++++++++++
 5 files changed, 297 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing/selftests/kvm/include/kvm_util.h
index 996909230ac7..b18af4f5f615 100644
--- a/tools/testing/selftests/kvm/include/kvm_util.h
+++ b/tools/testing/selftests/kvm/include/kvm_util.h
@@ -883,6 +883,15 @@ static inline int vcpu_get_stats_fd(struct kvm_vcpu *vcpu)
 	return fd;
 }
 
+static inline struct kvm_translation vcpu_translate(struct kvm_vcpu *vcpu,
+						    u64 gva)
+{
+	struct kvm_translation tr = { .linear_address = gva };
+
+	vcpu_ioctl(vcpu, KVM_TRANSLATE, &tr);
+	return tr;
+}
+
 int __kvm_has_device_attr(int dev_fd, u32 group, u64 attr);
 
 static inline void kvm_has_device_attr(int dev_fd, u32 group, u64 attr)
diff --git a/tools/testing/selftests/kvm/include/x86/processor.h b/tools/testing/selftests/kvm/include/x86/processor.h
index 6e6f70035508..398380157fa1 100644
--- a/tools/testing/selftests/kvm/include/x86/processor.h
+++ b/tools/testing/selftests/kvm/include/x86/processor.h
@@ -1472,6 +1472,7 @@ static inline bool kvm_is_lbrv_enabled(void)
 	return !!get_kvm_amd_param_integer("lbrv");
 }
 
+u64 *vm_get_pte_level(struct kvm_vm *vm, gva_t gva, int *level);
 u64 *vm_get_pte(struct kvm_vm *vm, gva_t gva);
 
 u64 kvm_hypercall(u64 nr, u64 a0, u64 a1, u64 a2, u64 a3);
diff --git a/tools/testing/selftests/kvm/lib/x86/processor.c b/tools/testing/selftests/kvm/lib/x86/processor.c
index d31fa81ea075..f51b4929d668 100644
--- a/tools/testing/selftests/kvm/lib/x86/processor.c
+++ b/tools/testing/selftests/kvm/lib/x86/processor.c
@@ -400,6 +400,11 @@ u64 *tdp_get_pte(struct kvm_vm *vm, u64 l2_gpa)
 	return __vm_get_page_table_entry(vm, &vm->stage2_mmu, l2_gpa, &level);
 }
 
+u64 *vm_get_pte_level(struct kvm_vm *vm, gva_t gva, int *level)
+{
+	return __vm_get_page_table_entry(vm, &vm->mmu, gva, level);
+}
+
 u64 *vm_get_pte(struct kvm_vm *vm, gva_t gva)
 {
 	int level = PG_LEVEL_4K;
diff --git a/tools/testing/selftests/kvm/memory_attributes.c b/tools/testing/selftests/kvm/memory_attributes.c
index c703c5586d43..63dec49c2888 100644
--- a/tools/testing/selftests/kvm/memory_attributes.c
+++ b/tools/testing/selftests/kvm/memory_attributes.c
@@ -22,6 +22,8 @@
 #define TEST_MEM_SLOT	1
 #define TEST_MEM_GPA	0x80000000
 
+#define HV_STATUS_INVALID_HYPERCALL_INPUT	3
+
 #define MMIO_GPA	0x700000000
 #define MMIO_GVA	MMIO_GPA
 
@@ -29,12 +31,35 @@
 #define PT_ACCESSED_MASK	BIT_ULL(5)
 #define PTE_VADDR		0x1000000000
 
+static volatile uint64_t ipis_rcvd;
+
+static pthread_t vcpu_thread;
+
+struct hv_vpset {
+	u64 format;
+	u64 valid_bank_mask;
+	u64 bank_contents[2];
+};
+
+enum HV_GENERIC_SET_FORMAT {
+	HV_GENERIC_SET_SPARSE_4K,
+	HV_GENERIC_SET_ALL,
+};
+
+struct hv_send_ipi_ex {
+	u32 vector;
+	u32 reserved;
+	struct hv_vpset vp_set;
+};
+
 enum {
 	TEST_OP_NOP,
 	TEST_OP_READ,
 	TEST_OP_WRITE,
 	TEST_OP_EXEC,
 	TEST_OP_INVPLG,
+	TEST_OP_HYPERV_HYPERCALL_INPUT,
+	TEST_OP_MONITOR_ADDRESS,
 	TEST_OP_EXIT,
 };
 
@@ -44,6 +69,8 @@ const char *test_op_names[] =
 	[TEST_OP_WRITE] = "Write",
 	[TEST_OP_EXEC] = "Exec",
 	[TEST_OP_INVPLG] = "Invplg",
+	[TEST_OP_HYPERV_HYPERCALL_INPUT] = "HvHcall input",
+	[TEST_OP_MONITOR_ADDRESS] = "Monitor address",
 	[TEST_OP_EXIT] = "Exit",
 };
 
@@ -51,6 +78,8 @@ struct test_data {
 	uint8_t op;
 	int stage;
 	gva_t vaddr;
+	gpa_t paddr;
+	uint8_t confirm_read;
 	uint64_t expected_val;
 
 	struct kvm_vcpu *vcpu;
@@ -63,19 +92,26 @@ static void arch_controlled_write(gva_t addr, uint64_t val);
 static void arch_controlled_exec(gva_t addr);
 static void arch_write_return_insn(struct kvm_vm *vm, gpa_t paddr);
 static bool arch_test_op(struct test_data *test_data);
+static void arch_guest_init(void);
 
 static void guest_code(void *data)
 {
 	struct test_data *test_data = data;
 	int stage = 1;
 
+	arch_guest_init();
+
 	while (true) {
 		uint64_t expected_val = READ_ONCE(test_data->expected_val);
+		bool confirm_read = READ_ONCE(test_data->confirm_read);
 		gva_t vaddr = READ_ONCE(test_data->vaddr);
+		u64 val;
 
 		switch(READ_ONCE(test_data->op)) {
 		case TEST_OP_READ:
-			(void) arch_controlled_read(vaddr);
+			val = arch_controlled_read(vaddr);
+			if (confirm_read)
+				GUEST_ASSERT_EQ(expected_val, val);
 			GUEST_SYNC(stage++);
 			break;
 		case TEST_OP_WRITE:
@@ -86,6 +122,14 @@ static void guest_code(void *data)
 			arch_controlled_exec(vaddr);
 			GUEST_SYNC(stage++);
 			break;
+		case TEST_OP_MONITOR_ADDRESS: {
+			if (arch_controlled_read(vaddr) != expected_val)
+				GUEST_SYNC(stage++);
+			break;
+		}
+		case TEST_OP_NOP:
+			GUEST_SYNC(stage++);
+			break;
 		default:
 			if (!arch_test_op(test_data))
 				goto exit;
@@ -145,6 +189,7 @@ static void test_page_restricted(struct kvm_vcpu *vcpu, int op,
 
 	test_data->op = op;
 	test_data->vaddr = vaddr;
+	test_data->paddr = fault_paddr;
 
 	rc = _vcpu_run(vcpu);
 	TEST_ASSERT(rc == -1 && errno == EFAULT,
@@ -390,12 +435,16 @@ int main(int argc, char *argv[])
 	test_mem = vm_alloc_pages(vm, pages);
 	virt_map(vcpu->vm, MMIO_GVA, MMIO_GPA, 1);
 	test_data = init_test_data(vcpu);
+#ifdef __x86_64__
+	vcpu_set_hv_cpuid(vcpu);
+#endif
 
 	test_input_validation(vm);
 	test_memory_access(vcpu, test_mem, size);
 	test_memattrs_ignore_mmio(vcpu);
 #ifdef __x86_64__
 	arch_test_memory_access_pte(vcpu, test_mem);
+	arch_test_side_channels(vcpu, test_mem, size);
 #endif
 	test_finalize(vcpu);
 
diff --git a/tools/testing/selftests/kvm/x86/memory_attributes.c b/tools/testing/selftests/kvm/x86/memory_attributes.c
index 12395feb6ac7..36e788be0e05 100644
--- a/tools/testing/selftests/kvm/x86/memory_attributes.c
+++ b/tools/testing/selftests/kvm/x86/memory_attributes.c
@@ -45,17 +45,28 @@ void arch_write_return_insn(struct kvm_vm *vm, gpa_t paddr)
 bool arch_test_op(struct test_data *test_data)
 {
 	gva_t vaddr = READ_ONCE(test_data->vaddr);
+	gpa_t paddr = READ_ONCE(test_data->paddr);
 
 	switch(READ_ONCE(test_data->op)) {
 	case TEST_OP_INVPLG:
 		asm volatile("invlpg (%0)"
 			     :: "b" (vaddr): "memory");
 		return true;
+	case TEST_OP_HYPERV_HYPERCALL_INPUT:
+		hyperv_hypercall(HVCALL_SEND_IPI_EX, paddr, 0);
+		asm volatile ("sti; hlt; cli;");
+		GUEST_ASSERT_EQ(ipis_rcvd, 1);
+		return true;
 	default:
 		return false;
 	}
 }
 
+void arch_guest_init(void)
+{
+	x2apic_enable();
+}
+
 /*
  * This test validates that, during a page walk, if the page a PTE is placed in
  * is read-only the accesss and dirty bits will not be written. Note There's a
@@ -181,3 +192,224 @@ static void arch_test_memory_access_pte(struct kvm_vcpu *vcpu, gva_t vaddr)
 	test_memory_access_pte_ro(vcpu, vaddr);
 	test_memory_access_sync_spte(vcpu, vaddr);
 }
+
+#define IPI_VECTOR	 0xfe
+
+static void guest_ipi_handler_hv(struct ex_regs *regs)
+{
+	ipis_rcvd++;
+	wrmsr(HV_X64_MSR_EOI, 1);
+}
+
+/*
+ * This test verifies that the Hyper-V hypercall exit handler takes memory
+ * attributes into account before accessing input data. It coordinates with the
+ * guest through the 'TEST_OP_HYPERV_HYPERCALL_INPUT' operation and instructs
+ * the guest to issue two PV IPIs. The first PV IPI fails because the input
+ * data is held in read-protected memory. Subsequently, the memory protection
+ * is lifted, and the second PV IPI succeeds.
+ */
+static void test_side_channel_hyperv_hypercall_inputs(struct kvm_vcpu *vcpu,
+						      gva_t vaddr,
+						      size_t size)
+{
+	struct kvm_vm *vm = vcpu->vm;
+	struct hv_send_ipi_ex *ipi_ex = addr_gva2hva(vm, vaddr);
+	gpa_t paddr = addr_gva2gpa(vm, vaddr);
+
+	if (!kvm_has_cap(KVM_CAP_HYPERV_SEND_IPI) ||
+	    !kvm_has_cap(KVM_CAP_HCALL_FAULT_EXIT))
+		return;
+
+	vm_enable_cap(vcpu->vm, KVM_CAP_HCALL_FAULT_EXIT, 1);
+
+	ipis_rcvd = 0;
+	vm_install_exception_handler(vm, IPI_VECTOR, guest_ipi_handler_hv);
+	vcpu_set_msr(vcpu, HV_X64_MSR_GUEST_OS_ID, HYPERV_LINUX_OS_ID);
+
+	*ipi_ex = (struct hv_send_ipi_ex){
+		.vector = IPI_VECTOR,
+		.vp_set.format = HV_GENERIC_SET_ALL,
+	};
+
+	vm_set_memory_attributes(vm, paddr, vm->page_size, KVM_MEMORY_ATTRIBUTE_NO_ACCESS);
+	test_page_restricted(vcpu, TEST_OP_HYPERV_HYPERCALL_INPUT, vaddr, paddr,
+			     KVM_MEMORY_EXIT_FLAG_READ);
+	vm_set_memory_attributes(vm, paddr, vm->page_size, 0);
+	vcpu_run_and_inc_stage(vcpu);
+}
+
+/*
+ * Verifies that the guest page table walker fails the walk if it encounters a
+ * page table entry address read-protected by a memory attribute.
+ */
+static void test_side_channel_emul_page_walks(struct kvm_vcpu *vcpu,
+					      gva_t test_vm_addr,
+					      size_t size)
+{
+	const uint64_t pte_addr_mask = GENMASK(51, 12);
+	struct kvm_vm *vm = vcpu->vm;
+	struct kvm_translation tr;
+	int level = PG_LEVEL_1G;
+	gpa_t paddr;
+	uint64_t *pte;
+
+	pte = vm_get_pte_level(vm, test_vm_addr, &level);
+	TEST_ASSERT_EQ(level, PG_LEVEL_1G);
+	paddr = *pte & pte_addr_mask;
+
+	tr = vcpu_translate(vcpu, test_vm_addr);
+	TEST_ASSERT_EQ(tr.valid, true);
+	TEST_ASSERT_EQ(tr.physical_address, addr_gva2gpa(vm, test_vm_addr));
+
+	vm_set_memory_attributes(vm, paddr, vm->page_size, KVM_MEMORY_ATTRIBUTE_NO_ACCESS);
+	tr = vcpu_translate(vcpu, test_vm_addr);
+	TEST_ASSERT_EQ(tr.valid, false);
+
+	vm_set_memory_attributes(vm, paddr, vm->page_size, 0);
+}
+
+static void vm_set_vapic_addr(struct kvm_vcpu *vcpu, uint64_t addr)
+{
+	struct kvm_vapic_addr va;
+
+	va.vapic_addr = addr;
+	vcpu_ioctl(vcpu, KVM_SET_VAPIC_ADDR, &va);
+}
+
+/*
+ * Perform a dummy regs update to issue a KVM_REQ_EVENT. This forces
+ * vapic to be synced before entering the guest.
+ */
+static void vcpu_force_vapic_update(struct kvm_vcpu *vcpu)
+{
+	struct kvm_regs regs;
+
+	vcpu_regs_get(vcpu, &regs);
+	vcpu_regs_set(vcpu, &regs);
+}
+
+/*
+ * Setup the vapic address on a GPA that is write-protected. Force an vapic
+ * update and validate its contents were not changes. Then, lift the write
+ * restriction and validate the page's contents are updated.
+ */
+static void test_side_channel_vapic_addr(struct kvm_vcpu *vcpu)
+{
+	struct kvm_vm *vm = vcpu->vm;
+	gva_t vaddr = vm_alloc_page(vm);
+	gpa_t paddr = addr_gva2gpa(vm, vaddr);
+
+	vm_set_vapic_addr(vcpu, paddr);
+	test_data->op = TEST_OP_READ;
+	test_data->vaddr = vaddr;
+	test_data->confirm_read = 1;
+	test_data->expected_val = ~0ULL >> 32;
+	memset(addr_gva2hva(vm, vaddr), 0xff, sizeof(uint32_t));
+	vm_set_memory_attributes(vm, paddr, vm->page_size, KVM_MEMORY_ATTRIBUTE_NW);
+	vcpu_run_and_inc_stage(vcpu);
+
+	vm_set_memory_attributes(vm, paddr, vm->page_size, 0);
+	vcpu_force_vapic_update(vcpu);
+	test_data->expected_val = 0ULL;
+	vcpu_run_and_inc_stage(vcpu);
+
+	vm_set_vapic_addr(vcpu, 0);
+	test_data->confirm_read = 0;
+}
+
+static void *vcpu_worker(void *data)
+{
+	struct test_data *test_data = data;
+	struct kvm_vcpu *vcpu = test_data->vcpu;
+
+	vcpu_run_and_inc_stage(vcpu);
+
+	return NULL;
+}
+
+/*
+ * Set up the pvclock page and validate that KVM periodically updates the
+ * 'version' field. Subsequently, make the pvclock page non-writable and
+ * verify that the 'version' field is no longer updated.
+ */
+static void test_side_channel_pvclock(struct kvm_vcpu *vcpu)
+{
+	struct kvm_vm *vm = vcpu->vm;
+	gva_t vaddr = vm_alloc_page(vm);
+	gpa_t paddr = addr_gva2gpa(vm, vaddr);
+	struct pvclock_vcpu_time_info *pvclock = addr_gpa2hva(vm, paddr);
+
+	pvclock->version = 0;
+
+	test_data->op = TEST_OP_MONITOR_ADDRESS;
+	test_data->vaddr = vaddr + offsetof(struct pvclock_vcpu_time_info, version);
+	test_data->expected_val = pvclock->version;
+
+	vcpu_set_msr(vcpu, MSR_KVM_SYSTEM_TIME_NEW, paddr | 0x1);
+	pthread_create(&vcpu_thread, NULL, vcpu_worker, test_data);
+	usleep(msecs_to_usecs(1000));
+	TEST_ASSERT_EQ(pthread_tryjoin_np(vcpu_thread, NULL), 0);
+	vcpu_set_msr(vcpu, MSR_KVM_SYSTEM_TIME_NEW, 0);
+
+	test_data->expected_val = pvclock->version;
+	vm_set_memory_attributes(vm, paddr, vm->page_size, KVM_MEMORY_ATTRIBUTE_NW);
+	vcpu_set_msr(vcpu, MSR_KVM_SYSTEM_TIME_NEW, paddr | 0x1);
+	pthread_create(&vcpu_thread, NULL, vcpu_worker, test_data);
+	usleep(msecs_to_usecs(1000));
+	TEST_ASSERT_EQ(pthread_tryjoin_np(vcpu_thread, NULL), EBUSY);
+
+	/* Force the 'monitor_address' guest operation to finish */
+	test_data->op = TEST_OP_NOP;
+	TEST_ASSERT_EQ(pthread_join(vcpu_thread, NULL), 0);
+	vm_set_memory_attributes(vm, paddr, vm->page_size, 0);
+	vcpu_set_msr(vcpu, MSR_KVM_SYSTEM_TIME_NEW, 0);
+}
+
+/*
+ * Write to MSR_KVM_WALL_CLOCK_NEW and verify that the struct's 'version' field
+ * is updated. Subsequently, make the target guest physical address
+ * non-writable, and verify the 'version' field isn't updated anymore.
+ */
+static void test_side_channel_wallclock(struct kvm_vcpu *vcpu)
+{
+	struct kvm_vm *vm = vcpu->vm;
+	gva_t vaddr = vm_alloc_page(vm);
+	gpa_t paddr = addr_gva2gpa(vm, vaddr);
+	struct pvclock_wall_clock *wc = addr_gva2hva(vm, vaddr);
+
+	wc->version = 0x0;
+	vcpu_set_msr(vcpu, MSR_KVM_WALL_CLOCK_NEW, paddr);
+	TEST_ASSERT_EQ(READ_ONCE(wc->version), 2);
+
+	vm_set_memory_attributes(vm, paddr, vm->page_size, KVM_MEMORY_ATTRIBUTE_NW);
+	vcpu_set_msr(vcpu, MSR_KVM_WALL_CLOCK_NEW, paddr);
+	TEST_ASSERT_EQ(READ_ONCE(wc->version), 2);
+
+	vm_set_memory_attributes(vm, paddr, vm->page_size, 0);
+}
+
+/*
+ * Memory attributes are vulnerable to side-channel attacks. This means that
+ * any KVM operation initiated by the guest that requires guest memory access
+ * (which is the case for most pv-interfaces) needs to consider memory
+ * attributes.
+ *
+ * The following tests validate that this requirement is upheld for a variety
+ * of use-cases. These test cases were selected to exercise specific approaches
+ * to accessing guest memory, including:
+ *
+ *  - kvm_read/write_guest()
+ *  - gfn_to_hva_cache
+ *  - gfn_to_pfn_cache
+ *  - Guest page walker
+ */
+static void arch_test_side_channels(struct kvm_vcpu *vcpu, gva_t test_vm_addr,
+			            size_t size)
+{
+	test_side_channel_hyperv_hypercall_inputs(vcpu, test_vm_addr, size);
+	test_side_channel_emul_page_walks(vcpu, test_vm_addr, size);
+	test_side_channel_vapic_addr(vcpu);
+	test_side_channel_wallclock(vcpu);
+	test_side_channel_pvclock(vcpu);
+}
-- 
2.52.0


  parent reply	other threads:[~2026-09-18 13:51 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-18 13:49 [PATCH v3 00/28] KVM: x86: Introduce memory protection attributes Paolo Bonzini
2026-09-18 13:50 ` [PATCH 01/31] KVM: x86/hyperv: do not overwrite hc->ingpa for slow SIGNAL_EVENT hypercall Paolo Bonzini
2026-09-18 13:50 ` [PATCH 02/31] KVM: selftests: Take into account mixed memory fault flags Paolo Bonzini
2026-09-18 13:50 ` [PATCH 03/31] KVM: Define and communicate KVM_EXIT_MEMORY_FAULT RWX flags to userspace Paolo Bonzini
2026-09-18 13:50 ` [PATCH 04/31] KVM: selftests: Test address translation for Hyper-V direct L2 hypercalls Paolo Bonzini
2026-09-18 13:50 ` [PATCH 05/31] KVM: apply nGPA->GPA translation to KVM_HC_CLOCK_PAIRING Paolo Bonzini
2026-09-18 13:50 ` [PATCH 06/31] KVM: x86: Introduce memory fault on invalid hypercalls reads/writes Paolo Bonzini
2026-09-18 14:11   ` sashiko-bot
2026-09-21 16:56   ` Vitaly Kuznetsov
2026-09-18 13:50 ` [PATCH 07/31] KVM: selftests: test hypercall memory fault exits Paolo Bonzini
2026-09-18 13:50 ` [PATCH 08/31] KVM: x86/mmu: intersect writability from __kvm_faultin_pfn with fault->map_writable Paolo Bonzini
2026-09-18 13:50 ` [PATCH 09/31] KVM: x86/mmu: Extend map_writable to a full ACC_* mask Paolo Bonzini
2026-09-18 13:50 ` [PATCH 10/31] KVM: x86/mmu: Init memslot hugepage information for non-private_mem VMs too Paolo Bonzini
2026-09-18 13:50 ` [PATCH 11/31] KVM: pass kvm == NULL case to kvm_arch_has_private_mem Paolo Bonzini
2026-09-18 13:50 ` [PATCH 12/31] KVM: adjust for presence of more than one attribute Paolo Bonzini
2026-09-18 13:50 ` [PATCH 13/31] KVM: Introduce NR/NW/NX memory attributes Paolo Bonzini
2026-09-18 13:50 ` [PATCH 14/31] KVM: Include memory protections in result of gfn->hva conversion Paolo Bonzini
2026-09-18 13:50 ` [PATCH 15/31] KVM: Introduce kvm_fetch_guest_page() and use it for x86 Paolo Bonzini
2026-09-18 13:50 ` [PATCH 16/31] KVM: Take memory protections into account for memory read/write/fetch Paolo Bonzini
2026-09-18 13:50 ` [PATCH 17/31] KVM: Take memory protections into account for __kvm_vcpu_map Paolo Bonzini
2026-09-18 13:50 ` [PATCH 18/31] KVM: Encapsulate memattrs array into anonymous struct Paolo Bonzini
2026-09-18 13:50 ` [PATCH 19/31] KVM: loongarch: do full validity check on the gfn-to-hva cache Paolo Bonzini
2026-09-18 13:50 ` [PATCH 20/31] KVM: Introduce kvm_check_gen()/kvm_memslots_check_gen() Paolo Bonzini
2026-09-18 14:26   ` sashiko-bot
2026-09-18 13:50 ` [PATCH 21/31] KVM: Introduce a generation number for memory attributes Paolo Bonzini
2026-09-18 14:42   ` sashiko-bot
2026-09-18 13:50 ` [PATCH 22/31] KVM: Take memory protections into account for accesses with cached gfn->hva Paolo Bonzini
2026-09-18 14:42   ` sashiko-bot
2026-09-18 13:50 ` [PATCH 23/31] KVM: pfncache: Fail to refresh if it contains memory protections Paolo Bonzini
2026-09-18 13:50 ` [PATCH 24/31] KVM: x86/mmu: Do not prefetch sptes on gfns backed by memory attributes Paolo Bonzini
2026-09-18 13:50 ` [PATCH 25/31] KVM: x86/mmu: Take memory protection attributes into account during faults Paolo Bonzini
2026-09-18 14:57   ` sashiko-bot
2026-09-18 13:50 ` [PATCH 26/31] KVM: x86/mmu: Issue memory fault exit if walk failed due to memory attribute Paolo Bonzini
2026-09-18 14:46   ` sashiko-bot
2026-09-18 13:50 ` [PATCH 27/31] KVM: let kvm_arch_post_set_memory_attributes drop mmu_lock Paolo Bonzini
2026-09-18 13:50 ` [PATCH 28/31] KVM: x86/mmu: Obsolete all roots if memattr contains gPTEs Paolo Bonzini
2026-09-18 14:57   ` sashiko-bot
2026-09-18 13:50 ` [PATCH 29/31] KVM: x86: selftests: Introduce memory protection attributes test Paolo Bonzini
2026-09-18 13:50 ` [PATCH 30/31] KVM: x86: selftests: Introduce memory attributes PTE test Paolo Bonzini
2026-09-18 13:50 ` Paolo Bonzini [this message]
2026-09-18 14:56   ` [PATCH 31/31] KVM: x86: selftests: Introduce memory attributes side-channel tests sashiko-bot
2026-09-18 15:20 ` [PATCH v3 00/28] KVM: x86: Introduce memory protection attributes Paolo Bonzini
2026-09-21 16:56 ` Vitaly Kuznetsov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260918135030.171564-32-pbonzini@redhat.com \
    --to=pbonzini@redhat.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=nsaenz@amazon.com \
    --cc=snambakam@linux.microsoft.com \
    --cc=vkuznets@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox