Skip to contentSkip to conversation

KVM: selftests: add powerpc support

PATCH RESEND Superseded Ritesh Harjani (IBM) 3 participants 25 messages Jun 10 – Jun 24

Subsystems (8)
KVM Kselftest RISC-V KVM arm64 +4 more subsystems

v3 of 7 Superseded Latest is v7 →

lore
Share & tools
lore
#0 lore raw

v3 cover KVM: selftests: add powerpc support

RFCv3 -> PATCH v3:
==================
- resend and dropped RFC tag.

Hi All,

This series primarly adds KVM selftests support for powerpc (64-bit, BookS, radix MMU).

This patch series is originally Nick's work. I have mainly only rebased it on the latest upstream tree. Since the rebase required few changes to all the four patches (Patch 1-4), I have dropped the earlier Acked-by from Michael Ellerman.

Since the last series was posted three years ago [1], I am resetting the version to RFC. This rebase was done as part of a larger effort to improve the selftests infrastructure for Linux on PowerPC tree. Thanks to Harsh and Maddy for their help on this.

Testing Updates:
================
1. Tested this on PowerNV P9 with Radix mode. (all selftests passes)
2. Tested this on LPAR (KVM on PowerVM) case. (all selftests except-1 passes). The failed testcase (kvm_create_max_vcpus) is because H_GUEST_CREATE_VCPU (PAPR HCALL) only supports vcpu_ids 0-2047 i.e. max 2048 vcpus. However, kernel always returns NR_CPUS for the KVM_CAP_MAX_VCPUS extension. So if the LPAR kernel is built using NR_CPUS=8192, then kvm_create_max_vcpus can fail in __vm_vcpu_add(). This failure needs to be handled separately, mostly as fix in kernel.
3. Tested these selftests changes inside x86 kvm guest - no new failures seen.

RFCv2 -> RFC v3:
===============
1. Relaxed strict pte permission checking in patch-3 (Sashiko)
2. Fixed errno from getting clobbered in patch-5 (Sashiko)
3. Added PATCH 6-9 to handle the type conversion (e.g. uint64_t to u64) as was done earlier with other kvm selftests. Kept these patches separate to keep the review & changelog simpler.
4. Added PATCH 10, which replaces u64 gpa/gva to use gpa_t and gva_t and converts the vaddr variable to gva as done by some previous commits for other kvm selftests. Kept this patch separate to keep the review & changelog simpler.

RFC v1 -> RFC v2
================
(mostly Sashiko review comments)
1. Fixed x86's stage-2 mmu handling in patch-1 - commit msg has more description
2. Added "cc" into the clobber list for hcalls in patch-3
3. Fixed the size calculation in kvm_arch_vm_post_create in patch-3 for allocating 2 pages for 4K pagesize
4. Added patch-5 which prints vcpu_id in case of an error

[RFCv2]: https://lore.kernel.org/all/[email protected]/
[RFCv1]: https://lore.kernel.org/linuxppc-dev/[email protected]/
[1]: https://lore.kernel.org/all/[email protected]/

Nicholas Piggin (4):
KVM: selftests: Move pgd_created check into virt_pgd_alloc
KVM: selftests: Add aligned guest physical page allocator
KVM: PPC: selftests: add support for powerpc
KVM: PPC: selftests: powerpc enable kvm_create_max_vcpus test

Ritesh Harjani (IBM) (6):
KVM: selftests: Print the vcpu_id when KVM_CREATE_VCPU ioctl fails
KVM: PPC: selftests: Use u64 instead of uint64_t
KVM: PPC: selftests: Use s64 instead of int64_t
KVM: PPC: selftests: Use u32 instead of uint32_t
KVM: PPC: selftests: Use u8 instead of uint8_t
KVM: PPC: selftests: Replace u64 gpa, u64 gva|vaddr with gpa_t and
gva_t

 MAINTAINERS                                   |   2 +
 tools/testing/selftests/kvm/Makefile          |   2 +-
 tools/testing/selftests/kvm/Makefile.kvm      |  10 +
 .../testing/selftests/kvm/include/kvm_util.h  |  34 +-
 .../selftests/kvm/include/powerpc/hcall.h     |  17 +
 .../kvm/include/powerpc/kvm_util_arch.h       |  22 +
 .../selftests/kvm/include/powerpc/ppc_asm.h   |  32 ++
 .../selftests/kvm/include/powerpc/processor.h |  39 ++
 .../selftests/kvm/include/powerpc/ucall.h     |  21 +
 .../selftests/kvm/kvm_create_max_vcpus.c      |   9 +
 .../selftests/kvm/lib/arm64/processor.c       |   4 -
 tools/testing/selftests/kvm/lib/guest_modes.c |  20 +-
 tools/testing/selftests/kvm/lib/kvm_util.c    |  48 +-
 .../selftests/kvm/lib/loongarch/processor.c   |   4 -
 .../selftests/kvm/lib/powerpc/handlers.S      |  93 ++++
 .../testing/selftests/kvm/lib/powerpc/hcall.c |  45 ++
 .../selftests/kvm/lib/powerpc/processor.c     | 483 ++++++++++++++++++
 .../testing/selftests/kvm/lib/powerpc/ucall.c |  22 +
 .../selftests/kvm/lib/riscv/processor.c       |   4 -
 .../selftests/kvm/lib/s390/processor.c        |   4 -
 20 files changed, 876 insertions(+), 39 deletions(-)
 create mode 100644 tools/testing/selftests/kvm/include/powerpc/hcall.h
 create mode 100644 tools/testing/selftests/kvm/include/powerpc/kvm_util_arch.h
 create mode 100644 tools/testing/selftests/kvm/include/powerpc/ppc_asm.h
 create mode 100644 tools/testing/selftests/kvm/include/powerpc/processor.h
 create mode 100644 tools/testing/selftests/kvm/include/powerpc/ucall.h
 create mode 100644 tools/testing/selftests/kvm/lib/powerpc/handlers.S
 create mode 100644 tools/testing/selftests/kvm/lib/powerpc/hcall.c
 create mode 100644 tools/testing/selftests/kvm/lib/powerpc/processor.c
 create mode 100644 tools/testing/selftests/kvm/lib/powerpc/ucall.c

--
2.50.1 (Apple Git-155)

#1 lore raw

PATCH RESEND v3 1/10 KVM: selftests: Move pgd_created check into virt_pgd_alloc

From: Nicholas Piggin <[email protected]>

virt_arch_pgd_alloc all do the same test and set pgd_created. Move this into common code -
except for x86's virt_arch_pgd_alloc() -> virt_mmu_init() - because this can also be called from it's tdp_mmu_init() call for setting up it's stage-2 mmu.

[Rebased to latest mainline tree and removed x86 case]
---
 tools/testing/selftests/kvm/include/kvm_util.h        | 5 +++++
 tools/testing/selftests/kvm/lib/arm64/processor.c     | 4 ----
 tools/testing/selftests/kvm/lib/loongarch/processor.c | 4 ----
 tools/testing/selftests/kvm/lib/riscv/processor.c     | 4 ----
 tools/testing/selftests/kvm/lib/s390/processor.c      | 4 ----
 5 files changed, 5 insertions(+), 16 deletions(-)
tools/testing/selftests/kvm/include/kvm_util.h +5 -0
index 2ecaaa0e9965..3666a8530f31 100644
@@ -1197,7 +1197,12 @@ void virt_arch_pgd_alloc(struct kvm_vm *vm);
 
 static inline void virt_pgd_alloc(struct kvm_vm *vm)
 {
+	if (vm->mmu.pgd_created)
+		return;
+
 	virt_arch_pgd_alloc(vm);
+
+	vm->mmu.pgd_created = true;
 }
 
 /*
tools/testing/selftests/kvm/lib/arm64/processor.c +0 -4
index 01325bf4d36f..498fbcb0ea16 100644
@@ -112,13 +112,9 @@ void virt_arch_pgd_alloc(struct kvm_vm *vm)
 {
 	size_t nr_pages = vm_page_align(vm, ptrs_per_pgd(vm) * 8) / vm->page_size;
 
-	if (vm->mmu.pgd_created)
-		return;
-
 	vm->mmu.pgd = vm_phy_pages_alloc(vm, nr_pages,
 					 KVM_GUEST_PAGE_TABLE_MIN_PADDR,
 					 vm->memslots[MEM_REGION_PT]);
-	vm->mmu.pgd_created = true;
 }
 
 static void _virt_pg_map(struct kvm_vm *vm, gva_t gva, gpa_t gpa,
tools/testing/selftests/kvm/lib/loongarch/processor.c +0 -4
index 64d91fb76522..207055db5f5d 100644
@@ -51,9 +51,6 @@ void virt_arch_pgd_alloc(struct kvm_vm *vm)
 	int i;
 	gpa_t child, table;
 
-	if (vm->mmu.pgd_created)
-		return;
-
 	child = table = 0;
 	for (i = 0; i < vm->mmu.pgtable_levels; i++) {
 		invalid_pgtable[i] = child;
@@ -64,7 +61,6 @@ void virt_arch_pgd_alloc(struct kvm_vm *vm)
 		child = table;
 	}
 	vm->mmu.pgd = table;
-	vm->mmu.pgd_created = true;
 }
 
 static int virt_pte_none(u64 *ptep, int level)
tools/testing/selftests/kvm/lib/riscv/processor.c +0 -4
index ded5429f3448..75a5d4c46001 100644
@@ -66,13 +66,9 @@ void virt_arch_pgd_alloc(struct kvm_vm *vm)
 {
 	size_t nr_pages = vm_page_align(vm, ptrs_per_pte(vm) * 8) / vm->page_size;
 
-	if (vm->mmu.pgd_created)
-		return;
-
 	vm->mmu.pgd = vm_phy_pages_alloc(vm, nr_pages,
 					 KVM_GUEST_PAGE_TABLE_MIN_PADDR,
 					 vm->memslots[MEM_REGION_PT]);
-	vm->mmu.pgd_created = true;
 }
 
 void virt_arch_pg_map(struct kvm_vm *vm, gva_t gva, gpa_t gpa)
tools/testing/selftests/kvm/lib/s390/processor.c +0 -4
index a9adb3782b35..342b7c92463e 100644
@@ -17,16 +17,12 @@ void virt_arch_pgd_alloc(struct kvm_vm *vm)
 	TEST_ASSERT(vm->page_size == PAGE_SIZE, "Unsupported page size: 0x%x",
 		    vm->page_size);
 
-	if (vm->mmu.pgd_created)
-		return;
-
 	gpa = vm_phy_pages_alloc(vm, PAGES_PER_REGION,
 				   KVM_GUEST_PAGE_TABLE_MIN_PADDR,
 				   vm->memslots[MEM_REGION_PT]);
 	memset(addr_gpa2hva(vm, gpa), 0xff, PAGES_PER_REGION * vm->page_size);
 
 	vm->mmu.pgd = gpa;
-	vm->mmu.pgd_created = true;
 }
 
 /*
Signature · 1 line
2.50.1 (Apple Git-155)
#2 lore raw

PATCH RESEND v3 2/10 KVM: selftests: Add aligned guest physical page allocator

In reply to Ritesh Harjani (IBM)

From: Nicholas Piggin <[email protected]>

powerpc will require this to allocate MMU tables in guest memory that are larger than guest base page size.

[Rebased to latest mainline tree]
---
 .../testing/selftests/kvm/include/kvm_util.h  | 20 +++++++++--
 tools/testing/selftests/kvm/lib/kvm_util.c    | 33 +++++++++----------
 2 files changed, 33 insertions(+), 20 deletions(-)
tools/testing/selftests/kvm/include/kvm_util.h +17 -3
index 3666a8530f31..c515c918c2c9 100644
@@ -991,8 +991,8 @@ void kvm_gsi_routing_write(struct kvm_vm *vm, struct kvm_irq_routing *routing);
 const char *exit_reason_str(unsigned int exit_reason);
 
 gpa_t vm_phy_page_alloc(struct kvm_vm *vm, gpa_t min_gpa, u32 memslot);
-gpa_t __vm_phy_pages_alloc(struct kvm_vm *vm, size_t num, gpa_t min_gpa,
-			   u32 memslot, bool protected);
+gpa_t __vm_phy_pages_alloc(struct kvm_vm *vm, size_t num, size_t align,
+			   gpa_t min_gpa, u32 memslot, bool protected);
 gpa_t vm_alloc_page_table(struct kvm_vm *vm);
 
 static inline gpa_t vm_phy_pages_alloc(struct kvm_vm *vm, size_t num,
@@ -1003,10 +1003,24 @@ static inline gpa_t vm_phy_pages_alloc(struct kvm_vm *vm, size_t num,
 	 * protected memory, as the majority of memory for such VMs is
 	 * protected, i.e. using shared memory is effectively opt-in.
 	 */
-	return __vm_phy_pages_alloc(vm, num, min_gpa, memslot,
+	return __vm_phy_pages_alloc(vm, num, 1, min_gpa, memslot,
 				    vm_arch_has_protected_memory(vm));
 }
 
+static inline gpa_t vm_phy_pages_alloc_align(struct kvm_vm *vm, size_t num,
+					     size_t align, gpa_t min_gpa,
+					     u32 memslot)
+{
+	/*
+	 * By default, allocate memory as protected for VMs that support
+	 * protected memory, as the majority of memory for such VMs is
+	 * protected, i.e. using shared memory is effectively opt-in.
+	 */
+	return __vm_phy_pages_alloc(vm, num, align, min_gpa, memslot,
+				    vm_arch_has_protected_memory(vm));
+}
+
+
 /*
  * ____vm_create() does KVM_CREATE_VM and little else.  __vm_create() also
  * loads the test binary into guest memory and creates an IRQ chip (x86 only).
tools/testing/selftests/kvm/lib/kvm_util.c +16 -17
index e08967ef7b7b..ac7215824203 100644
@@ -1442,7 +1442,7 @@ static gva_t ____vm_alloc(struct kvm_vm *vm, size_t sz, gva_t min_gva,
 	u64 pages = (sz >> vm->page_shift) + ((sz % vm->page_size) != 0);
 
 	virt_pgd_alloc(vm);
-	gpa_t gpa = __vm_phy_pages_alloc(vm, pages,
+	gpa_t gpa = __vm_phy_pages_alloc(vm, pages, 1,
 					   KVM_UTIL_MIN_PFN * vm->page_size,
 					   vm->memslots[type], protected);
 
@@ -2021,7 +2021,7 @@ const char *exit_reason_str(unsigned int exit_reason)
  * and their base address is returned. A TEST_ASSERT failure occurs if
  * not enough pages are available at or above min_gpa.
  */
-gpa_t __vm_phy_pages_alloc(struct kvm_vm *vm, size_t num,
+gpa_t __vm_phy_pages_alloc(struct kvm_vm *vm, size_t num, size_t align,
 			   gpa_t min_gpa, u32 memslot,
 			   bool protected)
 {
@@ -2039,23 +2039,22 @@ gpa_t __vm_phy_pages_alloc(struct kvm_vm *vm, size_t num,
 	TEST_ASSERT(!protected || region->protected_phy_pages,
 		    "Region doesn't support protected memory");
 
-	base = pg = min_gpa >> vm->page_shift;
-	do {
-		for (; pg < base + num; ++pg) {
-			if (!sparsebit_is_set(region->unused_phy_pages, pg)) {
-				base = pg = sparsebit_next_set(region->unused_phy_pages, pg);
-				break;
+	base = min_gpa >> vm->page_shift;
+again:
+	base = (base + align - 1) & ~(align - 1);
+	for (pg = base; pg < base + num; ++pg) {
+		if (!sparsebit_is_set(region->unused_phy_pages, pg)) {
+			base = sparsebit_next_set(region->unused_phy_pages, pg);
+			if (!base) {
+				fprintf(stderr, "No guest physical page available, "
+					"min_gpa: 0x%lx page_size: 0x%x memslot: %u\n",
+					min_gpa, vm->page_size, memslot);
+				fputs("---- vm dump ----\n", stderr);
+				vm_dump(stderr, vm, 2);
+				abort();
 			}
+			goto again;
 		}
-	} while (pg && pg != base + num);
-
-	if (pg == 0) {
-		fprintf(stderr, "No guest physical page available, "
-			"min_gpa: 0x%lx page_size: 0x%x memslot: %u\n",
-			min_gpa, vm->page_size, memslot);
-		fputs("---- vm dump ----\n", stderr);
-		vm_dump(stderr, vm, 2);
-		abort();
 	}
 
 	for (pg = base; pg < base + num; ++pg) {
Signature · 1 line
2.50.1 (Apple Git-155)
#3 lore raw

Re: [PATCH v3 RESEND 02/10] KVM: selftests: Add aligned guest physical page allocator

Quoted 30 lines · Ritesh Harjani (IBM)

From: Nicholas Piggin <[email protected]>

powerpc will require this to allocate MMU tables in guest memory that are larger than guest base page size.

[Rebased to latest mainline tree]
---
 .../testing/selftests/kvm/include/kvm_util.h  | 20 +++++++++--
 tools/testing/selftests/kvm/lib/kvm_util.c    | 33 +++++++++----------
 2 files changed, 33 insertions(+), 20 deletions(-)
tools/testing/selftests/kvm/include/kvm_util.h +2 -2
index 3666a8530f31..c515c918c2c9 100644
@@ -991,8 +991,8 @@ void kvm_gsi_routing_write(struct kvm_vm *vm, struct kvm_irq_routing *routing);
 const char *exit_reason_str(unsigned int exit_reason);
 
 gpa_t vm_phy_page_alloc(struct kvm_vm *vm, gpa_t min_gpa, u32 memslot);
-gpa_t __vm_phy_pages_alloc(struct kvm_vm *vm, size_t num, gpa_t min_gpa,
-			   u32 memslot, bool protected);
+gpa_t __vm_phy_pages_alloc(struct kvm_vm *vm, size_t num, size_t align,
+			   gpa_t min_gpa, u32 memslot, bool protected);
 gpa_t vm_alloc_page_table(struct kvm_vm *vm);
 
 static inline gpa_t vm_phy_pages_alloc(struct kvm_vm *vm, size_t num,
@@ -1003,10 +1003,24 @@ static inline gpa_t vm_phy_pages_alloc(struct kvm_vm *vm, size_t num,
 	 * protected memory, as the majority of memory for such VMs is

tools/testing/selftests/kvm/include/kvm_util.h static inline gpa_t vm_phy_pages_alloc(struct kvm_vm *vm, size_t num, · line 1012

Quoted 10 lines
tools/testing/selftests/kvm/include/kvm_util.h +4 -1
 	 * protected, i.e. using shared memory is effectively opt-in.
 	 */
-	return __vm_phy_pages_alloc(vm, num, min_gpa, memslot,
+	return __vm_phy_pages_alloc(vm, num, 1, min_gpa, memslot,
 				    vm_arch_has_protected_memory(vm));
 }
 
+static inline gpa_t vm_phy_pages_alloc_align(struct kvm_vm *vm, size_t num,
+					     size_t align, gpa_t min_gpa,
+					     u32 memslot)

Given that the PPC usage is all for naturally aligned allocations, I think it makes sense for that to be the API, i.e. have "bool naturally_aligned" instead of an arbitrary alignment.

tools/testing/selftests/kvm/include/kvm_util.h static inline gpa_t vm_phy_pages_alloc(struct kvm_vm *vm, size_t num, · line 1018

Quoted 6 lines
tools/testing/selftests/kvm/include/kvm_util.h +6 -0
+{
+	/*
+	 * By default, allocate memory as protected for VMs that support
+	 * protected memory, as the majority of memory for such VMs is
+	 * protected, i.e. using shared memory is effectively opt-in.
+	 */

Duplicating this big comment is very ugly. In general, these APIs could use some love. E.g. taking in @memslot is essentially a historical wart that isn't necessary except for literally just memslot_perf_test.c, which allocates memory in a huge number of memslots.

If we rework the APIs to take the memory region type instead of the memslot, then we can kill many birds with one stone. It takes quite a bit of cleanup to throw that one stone, but I think the end result can be quite nice.

Compile tested only at this point, but I now have a series of ~17 patches to yield:

__weak bool kvm_arch_needs_naturally_aligned_page_tables(void)

  {
	return false;

}

gpa_t __vm_phy_pages_alloc(struct kvm_vm *vm, size_t nr_pages,
enum kvm_mem_region_type type, bool protected)

  {
	struct userspace_mem_region *region = vm_get_mem_region(vm, type);
	bool naturally_aligned = false;
	gpa_t min_gpa;

	TEST_ASSERT(region, "No region for type '%u', memslot '%u'",
		    type, vm->memslots[type]);

	switch (type) {
	case MEM_REGION_CODE:
	case MEM_REGION_DATA:
	case MEM_REGION_TEST_DATA:
		/*
		 * If the region is backed by the default memslot (id=0), use
		 * selftests' hardcoded minimum PFN, otherwise use the base of
		 * the custom memory slot that backs the region.
		 */
		if (!vm->memslots[type])
			min_gpa = KVM_UTIL_MIN_PFN * vm->page_size;
		else
			min_gpa = region->region.guest_phys_addr;
		break;
	case MEM_REGION_PT:
		min_gpa = KVM_GUEST_PAGE_TABLE_MIN_PADDR;
		naturally_aligned = kvm_arch_needs_naturally_aligned_page_tables();
		break;
	case MEM_REGION_TEST_EXTRA:
		min_gpa = region->region.guest_phys_addr;
		break;
	default:
		TEST_FAIL("Invalid memory region type '%u'", type);
		break;
	}

	return ____vm_phy_pages_alloc(vm, nr_pages, min_gpa, vm->memslots[type],
				      protected, naturally_aligned);

}

with convenience wrappers:

static inline gpa_t vm_phy_pages_alloc(struct kvm_vm *vm, size_t nr_pages,
enum kvm_mem_region_type type)
{
/*
* By default, allocate memory as protected for VMs that support
* protected memory, as the majority of memory for such VMs is
* protected, i.e. using shared memory is effectively opt-in. */
return __vm_phy_pages_alloc(vm, nr_pages, type,
vm_arch_has_protected_memory(vm));
}

static inline gpa_t vm_phy_page_alloc(struct kvm_vm *vm,
enum kvm_mem_region_type type)

  {
	return vm_phy_pages_alloc(vm, 1, type);

}

static inline gpa_t vm_alloc_page_table_pages(struct kvm_vm *vm, size_t nr_pages)

  {
	return vm_phy_page_alloc(vm, MEM_REGION_PT);

}

static inline gpa_t vm_alloc_page_table(struct kvm_vm *vm)

  {
	return vm_alloc_page_table_pages(vm, 1);

}

That way we don't need to add yet another rarely used param to the APIs, and PPC just needs to define kvm_arch_needs_naturally_aligned_page_tables(). The bonus is that @min_gpa goes away too.

It'll probably take me a few days/weeks, but I'll try get a series posted before the 7.2 merge window closes, so that you can build on top to get the PPC selftests support landed in 7.3.

Quoted 26 lines
tools/testing/selftests/kvm/include/kvm_util.h +14 -6
@@ -2039,23 +2039,22 @@ gpa_t __vm_phy_pages_alloc(struct kvm_vm *vm, size_t num,
 	TEST_ASSERT(!protected || region->protected_phy_pages,
 		    "Region doesn't support protected memory");
 
-	base = pg = min_gpa >> vm->page_shift;
-	do {
-		for (; pg < base + num; ++pg) {
-			if (!sparsebit_is_set(region->unused_phy_pages, pg)) {
-				base = pg = sparsebit_next_set(region->unused_phy_pages, pg);
-				break;
+	base = min_gpa >> vm->page_shift;
+again:
+	base = (base + align - 1) & ~(align - 1);
+	for (pg = base; pg < base + num; ++pg) {
+		if (!sparsebit_is_set(region->unused_phy_pages, pg)) {
+			base = sparsebit_next_set(region->unused_phy_pages, pg);
+			if (!base) {
+				fprintf(stderr, "No guest physical page available, "
+					"min_gpa: 0x%lx page_size: 0x%x memslot: %u\n",
+					min_gpa, vm->page_size, memslot);
+				fputs("---- vm dump ----\n", stderr);
+				vm_dump(stderr, vm, 2);
+				abort();
 			}
+			goto again;
 		}

tools/testing/selftests/kvm/include/kvm_util.h gpa_t __vm_phy_pages_alloc(struct kvm_vm *vm, size_t num, · line 2058

Quoted 10 lines
tools/testing/selftests/kvm/include/kvm_util.h +0 -9
-	} while (pg && pg != base + num);
-
-	if (pg == 0) {
-		fprintf(stderr, "No guest physical page available, "
-			"min_gpa: 0x%lx page_size: 0x%x memslot: %u\n",
-			min_gpa, vm->page_size, memslot);
-		fputs("---- vm dump ----\n", stderr);
-		vm_dump(stderr, vm, 2);
-		abort();
 	}

This is unnecessary churn. I'm not saying the current code is pretty or anything, but unless I'm missing something, this can simply be:

@@ -2025,7 +2027,7 @@ gpa_t __vm_phy_pages_alloc(struct kvm_vm *vm, size_t nr_pages, gpa_t min_gpa,

        TEST_ASSERT(!protected || region->protected_phy_pages,
                    "Region doesn't support protected memory");

- base = pg = min_gpa >> vm->page_shift;

+       base = pg = ALIGN(min_gpa >> vm->page_shift, alignment);
        do {
                for (; pg < base + nr_pages; ++pg) {
                        if (!sparsebit_is_set(region->unused_phy_pages, pg)) {
Quoted 5 lines
tools/testing/selftests/kvm/include/kvm_util.h +0 -1
 	for (pg = base; pg < base + num; ++pg) {
-- 

2.50.1 (Apple Git-155)

#4 lore raw

Re: [PATCH v3 RESEND 02/10] KVM: selftests: Add aligned guest physical page allocator

Quoted 38 lines · Sean Christopherson
Quoted 37 lines · Ritesh Harjani (IBM)

From: Nicholas Piggin <[email protected]>

powerpc will require this to allocate MMU tables in guest memory that are larger than guest base page size.

[Rebased to latest mainline tree]
---
 .../testing/selftests/kvm/include/kvm_util.h  | 20 +++++++++--
 tools/testing/selftests/kvm/lib/kvm_util.c    | 33 +++++++++----------
 2 files changed, 33 insertions(+), 20 deletions(-)
tools/testing/selftests/kvm/include/kvm_util.h +3 -3
index 3666a8530f31..c515c918c2c9 100644
@@ -991,8 +991,8 @@ void kvm_gsi_routing_write(struct kvm_vm *vm, struct kvm_irq_routing *routing);
 const char *exit_reason_str(unsigned int exit_reason);
 
 gpa_t vm_phy_page_alloc(struct kvm_vm *vm, gpa_t min_gpa, u32 memslot);
-gpa_t __vm_phy_pages_alloc(struct kvm_vm *vm, size_t num, gpa_t min_gpa,
-			   u32 memslot, bool protected);
+gpa_t __vm_phy_pages_alloc(struct kvm_vm *vm, size_t num, size_t align,
+			   gpa_t min_gpa, u32 memslot, bool protected);
 gpa_t vm_alloc_page_table(struct kvm_vm *vm);
 
 static inline gpa_t vm_phy_pages_alloc(struct kvm_vm *vm, size_t num,
@@ -1003,10 +1003,24 @@ static inline gpa_t vm_phy_pages_alloc(struct kvm_vm *vm, size_t num,
 	 * protected memory, as the majority of memory for such VMs is
 	 * protected, i.e. using shared memory is effectively opt-in.
 	 */
-	return __vm_phy_pages_alloc(vm, num, min_gpa, memslot,
+	return __vm_phy_pages_alloc(vm, num, 1, min_gpa, memslot,
 				    vm_arch_has_protected_memory(vm));
 }
 
Quoted 8 lines

tools/testing/selftests/kvm/include/kvm_util.h static inline gpa_t vm_phy_pages_alloc(struct kvm_vm *vm, size_t num, · line 1012

Quoted 3 lines
tools/testing/selftests/kvm/include/kvm_util.h +3 -0
+static inline gpa_t vm_phy_pages_alloc_align(struct kvm_vm *vm, size_t num,
+					     size_t align, gpa_t min_gpa,
+					     u32 memslot)

Given that the PPC usage is all for naturally aligned allocations, I think it makes sense for that to be the API, i.e. have "bool naturally_aligned" instead of an arbitrary alignment.

I would still prefer passing an explicit align value to the allocator, because IMHO that's a useful allocator interface to have.

However, if we do want to go down this road than I don't have any strong objection either, since as you mentioned powerpc mostly just needs natual alignment for it's page table region. So alignment can be extracted from the region type as you described below, so no need to pass it all the time.

Quoted 8 lines

tools/testing/selftests/kvm/include/kvm_util.h static inline gpa_t vm_phy_pages_alloc(struct kvm_vm *vm, size_t num, · line 1018

Quoted 6 lines
tools/testing/selftests/kvm/include/kvm_util.h +6 -0
+{
+	/*
+	 * By default, allocate memory as protected for VMs that support
+	 * protected memory, as the majority of memory for such VMs is
+	 * protected, i.e. using shared memory is effectively opt-in.
+	 */

Duplicating this big comment is very ugly.

yes, my bad. I should have removed one copy of the comment.

Quoted 81 lines

In general, these APIs could use
some love. E.g. taking in @memslot is essentially a historical wart that isn't necessary except for literally just memslot_perf_test.c, which allocates memory in a huge number of memslots.

If we rework the APIs to take the memory region type instead of the memslot, then we can kill many birds with one stone. It takes quite a bit of cleanup to throw that one stone, but I think the end result can be quite nice.

Compile tested only at this point, but I now have a series of ~17 patches to yield:

__weak bool kvm_arch_needs_naturally_aligned_page_tables(void)

  {
	return false;

}

gpa_t __vm_phy_pages_alloc(struct kvm_vm *vm, size_t nr_pages,
enum kvm_mem_region_type type, bool protected)

  {
	struct userspace_mem_region *region = vm_get_mem_region(vm, type);
	bool naturally_aligned = false;
	gpa_t min_gpa;

	TEST_ASSERT(region, "No region for type '%u', memslot '%u'",
		    type, vm->memslots[type]);

	switch (type) {
	case MEM_REGION_CODE:
	case MEM_REGION_DATA:
	case MEM_REGION_TEST_DATA:
		/*
		 * If the region is backed by the default memslot (id=0), use
		 * selftests' hardcoded minimum PFN, otherwise use the base of
		 * the custom memory slot that backs the region.
		 */
		if (!vm->memslots[type])
			min_gpa = KVM_UTIL_MIN_PFN * vm->page_size;
		else
			min_gpa = region->region.guest_phys_addr;
		break;
	case MEM_REGION_PT:
		min_gpa = KVM_GUEST_PAGE_TABLE_MIN_PADDR;
		naturally_aligned = kvm_arch_needs_naturally_aligned_page_tables();
		break;
	case MEM_REGION_TEST_EXTRA:
		min_gpa = region->region.guest_phys_addr;
		break;
	default:
		TEST_FAIL("Invalid memory region type '%u'", type);
		break;
	}

	return ____vm_phy_pages_alloc(vm, nr_pages, min_gpa, vm->memslots[type],
				      protected, naturally_aligned);

}

with convenience wrappers:

static inline gpa_t vm_phy_pages_alloc(struct kvm_vm *vm, size_t nr_pages,
enum kvm_mem_region_type type)
{
/*
* By default, allocate memory as protected for VMs that support
* protected memory, as the majority of memory for such VMs is
* protected, i.e. using shared memory is effectively opt-in. */
return __vm_phy_pages_alloc(vm, nr_pages, type,
vm_arch_has_protected_memory(vm));
}

static inline gpa_t vm_phy_page_alloc(struct kvm_vm *vm,
enum kvm_mem_region_type type)

  {
	return vm_phy_pages_alloc(vm, 1, type);

}

static inline gpa_t vm_alloc_page_table_pages(struct kvm_vm *vm, size_t nr_pages)

  {
	return vm_phy_page_alloc(vm, MEM_REGION_PT);

}

Quoted 8 lines

static inline gpa_t vm_alloc_page_table(struct kvm_vm *vm)

  {
	return vm_alloc_page_table_pages(vm, 1);

}

That way we don't need to add yet another rarely used param to the APIs, and PPC just needs to define kvm_arch_needs_naturally_aligned_page_tables().

yup, looks good.

Quoted 1 line

The bonus is that @min_gpa goes away too.

powerpc needs min_gpa for it's exception handling pages. see.

	excp_paddr = vm_phy_pages_alloc(vm, excp_pages, 0,
					vm->memslots[MEM_REGION_DATA]);

	TEST_ASSERT(excp_paddr == 0,
		    "Interrupt vectors not allocated at gPA address 0: (0x%lx)",
		    excp_paddr);

So, will arch still have an access to the API for passing min_gpa = 0 for cases like above?

Quoted 5 lines

It'll probably take me a few days/weeks, but I'll try get a series posted before the 7.2 merge window closes, so that you can build on top to get the PPC selftests support landed in 7.3.

Thanks Sean for your help! Yes, landing kvm selftests for powerpc will be definitely helpful to verify against any kvm regressions.

BTW, I was thinking whether landing powerpc first will be easier for you to consider all the API requirements from all users / usecases? But either way is fine please. I can work on top of your changes too and if something is missing for powerpc, we can add / modify on top, once your series is finished.

Quoted 31 lines
Quoted 31 lines
tools/testing/selftests/kvm/include/kvm_util.h +14 -11
@@ -2039,23 +2039,22 @@ gpa_t __vm_phy_pages_alloc(struct kvm_vm *vm, size_t num,
 	TEST_ASSERT(!protected || region->protected_phy_pages,
 		    "Region doesn't support protected memory");
 
-	base = pg = min_gpa >> vm->page_shift;
-	do {
-		for (; pg < base + num; ++pg) {
-			if (!sparsebit_is_set(region->unused_phy_pages, pg)) {
-				base = pg = sparsebit_next_set(region->unused_phy_pages, pg);
-				break;
+	base = min_gpa >> vm->page_shift;
+again:
+	base = (base + align - 1) & ~(align - 1);
+	for (pg = base; pg < base + num; ++pg) {
+		if (!sparsebit_is_set(region->unused_phy_pages, pg)) {
+			base = sparsebit_next_set(region->unused_phy_pages, pg);
+			if (!base) {
+				fprintf(stderr, "No guest physical page available, "
+					"min_gpa: 0x%lx page_size: 0x%x memslot: %u\n",
+					min_gpa, vm->page_size, memslot);
+				fputs("---- vm dump ----\n", stderr);
+				vm_dump(stderr, vm, 2);
+				abort();
 			}
+			goto again;
 		}
-	} while (pg && pg != base + num);
-
-	if (pg == 0) {
-		fprintf(stderr, "No guest physical page available, "
-			"min_gpa: 0x%lx page_size: 0x%x memslot: %u\n",
Quoted 9 lines

tools/testing/selftests/kvm/include/kvm_util.h gpa_t __vm_phy_pages_alloc(struct kvm_vm *vm, size_t num, · line 2058

Quoted 5 lines
tools/testing/selftests/kvm/include/kvm_util.h +0 -4
-			min_gpa, vm->page_size, memslot);
-		fputs("---- vm dump ----\n", stderr);
-		vm_dump(stderr, vm, 2);
-		abort();
 	}

This is unnecessary churn. I'm not saying the current code is pretty or anything, but unless I'm missing something, this can simply be:

Not really, we need the base to be aligned everytime, that's why the goto again loop aligns the base in the new code. Plus I feel the above refactoring also simplifies the special handling of pg == 0 case, which earlier was being handled separately after the loop ends.

Quoted 11 lines
tools/testing/selftests/kvm/lib/kvm_util.c +1 -1
@@ -2025,7 +2027,7 @@ gpa_t __vm_phy_pages_alloc(struct kvm_vm *vm, size_t nr_pages, gpa_t min_gpa,
        TEST_ASSERT(!protected || region->protected_phy_pages,
                    "Region doesn't support protected memory");
 
-       base = pg = min_gpa >> vm->page_shift;
+       base = pg = ALIGN(min_gpa >> vm->page_shift, alignment);
        do {
                for (; pg < base + nr_pages; ++pg) {
                        if (!sparsebit_is_set(region->unused_phy_pages, pg)) {
Quoted 2 lines
Quoted 4 lines
Quoted 4 lines

for (pg = base; pg < base + num; ++pg) {

Signature · 1 line
2.50.1 (Apple Git-155)

Thanks once again for your help with this!

-ritesh

#5 lore raw

Re: [PATCH v3 RESEND 02/10] KVM: selftests: Add aligned guest physical page allocator

Quoted 49 lines · Ritesh Harjani
Quoted 38 lines · Sean Christopherson
Quoted 37 lines · Ritesh Harjani (IBM)

From: Nicholas Piggin <[email protected]>

powerpc will require this to allocate MMU tables in guest memory that are larger than guest base page size.

[Rebased to latest mainline tree]
---
 .../testing/selftests/kvm/include/kvm_util.h  | 20 +++++++++--
 tools/testing/selftests/kvm/lib/kvm_util.c    | 33 +++++++++----------
 2 files changed, 33 insertions(+), 20 deletions(-)
tools/testing/selftests/kvm/include/kvm_util.h +3 -3
index 3666a8530f31..c515c918c2c9 100644
@@ -991,8 +991,8 @@ void kvm_gsi_routing_write(struct kvm_vm *vm, struct kvm_irq_routing *routing);
 const char *exit_reason_str(unsigned int exit_reason);
 
 gpa_t vm_phy_page_alloc(struct kvm_vm *vm, gpa_t min_gpa, u32 memslot);
-gpa_t __vm_phy_pages_alloc(struct kvm_vm *vm, size_t num, gpa_t min_gpa,
-			   u32 memslot, bool protected);
+gpa_t __vm_phy_pages_alloc(struct kvm_vm *vm, size_t num, size_t align,
+			   gpa_t min_gpa, u32 memslot, bool protected);
 gpa_t vm_alloc_page_table(struct kvm_vm *vm);
 
 static inline gpa_t vm_phy_pages_alloc(struct kvm_vm *vm, size_t num,
@@ -1003,10 +1003,24 @@ static inline gpa_t vm_phy_pages_alloc(struct kvm_vm *vm, size_t num,
 	 * protected memory, as the majority of memory for such VMs is
 	 * protected, i.e. using shared memory is effectively opt-in.
 	 */
-	return __vm_phy_pages_alloc(vm, num, min_gpa, memslot,
+	return __vm_phy_pages_alloc(vm, num, 1, min_gpa, memslot,
 				    vm_arch_has_protected_memory(vm));
 }
 
Quoted 8 lines

tools/testing/selftests/kvm/include/kvm_util.h static inline gpa_t vm_phy_pages_alloc(struct kvm_vm *vm, size_t num, · line 1012

Quoted 3 lines
tools/testing/selftests/kvm/include/kvm_util.h +3 -0
+static inline gpa_t vm_phy_pages_alloc_align(struct kvm_vm *vm, size_t num,
+					     size_t align, gpa_t min_gpa,
+					     u32 memslot)

Given that the PPC usage is all for naturally aligned allocations, I think it makes sense for that to be the API, i.e. have "bool naturally_aligned" instead of an arbitrary alignment.

Quoted 2 lines

I would still prefer passing an explicit align value to the allocator, because IMHO that's a useful allocator interface to have.

Why? What are the use cases? I can't think of anything that requires multi-page allocations to have specific alignment, all of the cases I can think of require natural alignment.

For sub-page allocations, supporting semi-arbitrary alignments makes sense, but I'm not convinced we should try and support that for page-granularity allocations.

Quoted 5 lines

However, if we do want to go down this road than I don't have any strong objection either, since as you mentioned powerpc mostly just needs natual alignment for it's page table region. So alignment can be extracted from the region type as you described below, so no need to pass it all the time.

..

Quoted 11 lines
Quoted 1 line

The bonus is that @min_gpa goes away too.

powerpc needs min_gpa for it's exception handling pages. see.

	excp_paddr = vm_phy_pages_alloc(vm, excp_pages, 0,
					vm->memslots[MEM_REGION_DATA]);

	TEST_ASSERT(excp_paddr == 0,
		    "Interrupt vectors not allocated at gPA address 0: (0x%lx)",
		    excp_paddr);
Quoted 2 lines

So, will arch still have an access to the API for passing min_gpa = 0 for cases like above?

Yep, ____vm_phy_pages_alloc() will be globally visible, and I think is quite appropriate in this case since it's more than just specifying a minimum GPA, it's really specifying an _exact_ GPA for the allocation.

gpa_t ____vm_phy_pages_alloc(struct kvm_vm *vm, size_t nr_pages, gpa_t min_gpa,
u32 memslot, bool protected, bool naturally_aligned)

Quoted 5 lines
Quoted 4 lines

It'll probably take me a few days/weeks, but I'll try get a series posted before the 7.2 merge window closes, so that you can build on top to get the PPC selftests support landed in 7.3.

Quoted 8 lines

Thanks Sean for your help! Yes, landing kvm selftests for powerpc will be definitely helpful to verify against any kvm regressions.

BTW, I was thinking whether landing powerpc first will be easier for you to consider all the API requirements from all users / usecases? But either way is fine please. I can work on top of your changes too and if something is missing for powerpc, we can add / modify on top, once your series is finished.

One idea would be for me to include the PPC support in the series; it's "just" a patch or two on top, albeit one pretty big patch.

Quoted 40 lines
Quoted 31 lines
Quoted 31 lines
tools/testing/selftests/kvm/include/kvm_util.h +14 -11
@@ -2039,23 +2039,22 @@ gpa_t __vm_phy_pages_alloc(struct kvm_vm *vm, size_t num,
 	TEST_ASSERT(!protected || region->protected_phy_pages,
 		    "Region doesn't support protected memory");
 
-	base = pg = min_gpa >> vm->page_shift;
-	do {
-		for (; pg < base + num; ++pg) {
-			if (!sparsebit_is_set(region->unused_phy_pages, pg)) {
-				base = pg = sparsebit_next_set(region->unused_phy_pages, pg);
-				break;
+	base = min_gpa >> vm->page_shift;
+again:
+	base = (base + align - 1) & ~(align - 1);
+	for (pg = base; pg < base + num; ++pg) {
+		if (!sparsebit_is_set(region->unused_phy_pages, pg)) {
+			base = sparsebit_next_set(region->unused_phy_pages, pg);
+			if (!base) {
+				fprintf(stderr, "No guest physical page available, "
+					"min_gpa: 0x%lx page_size: 0x%x memslot: %u\n",
+					min_gpa, vm->page_size, memslot);
+				fputs("---- vm dump ----\n", stderr);
+				vm_dump(stderr, vm, 2);
+				abort();
 			}
+			goto again;
 		}
-	} while (pg && pg != base + num);
-
-	if (pg == 0) {
-		fprintf(stderr, "No guest physical page available, "
-			"min_gpa: 0x%lx page_size: 0x%x memslot: %u\n",
Quoted 8 lines

tools/testing/selftests/kvm/include/kvm_util.h gpa_t __vm_phy_pages_alloc(struct kvm_vm *vm, size_t num, · line 2058

Quoted 5 lines
tools/testing/selftests/kvm/include/kvm_util.h +0 -4
-			min_gpa, vm->page_size, memslot);
-		fputs("---- vm dump ----\n", stderr);
-		vm_dump(stderr, vm, 2);
-		abort();
 	}

This is unnecessary churn. I'm not saying the current code is pretty or anything, but unless I'm missing something, this can simply be:

Quoted 2 lines

Not really, we need the base to be aligned everytime, that's why the goto again loop aligns the base in the new code.

Ooh, right, pg needs to be advanced by the aligned number of pages. Ugh, the whole do-while part is bizarre, and AFAICT only "works" by dumb luck.

Quoted 2 lines

Plus I feel the above refactoring also simplifies the special handling of pg == 0 case, which earlier was being handled separately after the loop ends.

Yeah, I fiddled with a few other options, but I think I like your approach the most.

#6 lore raw

Re: [PATCH v3 RESEND 02/10] KVM: selftests: Add aligned guest physical page allocator

Quoted 50 lines · Sean Christopherson
Quoted 49 lines · Ritesh Harjani
Quoted 46 lines · Sean Christopherson
Quoted 30 lines · Ritesh Harjani (IBM)

From: Nicholas Piggin <[email protected]>

powerpc will require this to allocate MMU tables in guest memory that are larger than guest base page size.

[Rebased to latest mainline tree]
---
 .../testing/selftests/kvm/include/kvm_util.h  | 20 +++++++++--
 tools/testing/selftests/kvm/lib/kvm_util.c    | 33 +++++++++----------
 2 files changed, 33 insertions(+), 20 deletions(-)
tools/testing/selftests/kvm/include/kvm_util.h +2 -2
index 3666a8530f31..c515c918c2c9 100644
@@ -991,8 +991,8 @@ void kvm_gsi_routing_write(struct kvm_vm *vm, struct kvm_irq_routing *routing);
 const char *exit_reason_str(unsigned int exit_reason);
 
 gpa_t vm_phy_page_alloc(struct kvm_vm *vm, gpa_t min_gpa, u32 memslot);
-gpa_t __vm_phy_pages_alloc(struct kvm_vm *vm, size_t num, gpa_t min_gpa,
-			   u32 memslot, bool protected);
+gpa_t __vm_phy_pages_alloc(struct kvm_vm *vm, size_t num, size_t align,
+			   gpa_t min_gpa, u32 memslot, bool protected);
 gpa_t vm_alloc_page_table(struct kvm_vm *vm);
 
 static inline gpa_t vm_phy_pages_alloc(struct kvm_vm *vm, size_t num,
@@ -1003,10 +1003,24 @@ static inline gpa_t vm_phy_pages_alloc(struct kvm_vm *vm, size_t num,
 	 * protected memory, as the majority of memory for such VMs is

tools/testing/selftests/kvm/include/kvm_util.h static inline gpa_t vm_phy_pages_alloc(struct kvm_vm *vm, size_t num, · line 1012

Quoted 10 lines
tools/testing/selftests/kvm/include/kvm_util.h +4 -1
 	 * protected, i.e. using shared memory is effectively opt-in.
 	 */
-	return __vm_phy_pages_alloc(vm, num, min_gpa, memslot,
+	return __vm_phy_pages_alloc(vm, num, 1, min_gpa, memslot,
 				    vm_arch_has_protected_memory(vm));
 }
 
+static inline gpa_t vm_phy_pages_alloc_align(struct kvm_vm *vm, size_t num,
+					     size_t align, gpa_t min_gpa,
+					     u32 memslot)

Given that the PPC usage is all for naturally aligned allocations, I think it makes sense for that to be the API, i.e. have "bool naturally_aligned" instead of an arbitrary alignment.

Quoted 7 lines
Quoted 2 lines

I would still prefer passing an explicit align value to the allocator, because IMHO that's a useful allocator interface to have.

Why? What are the use cases? I can't think of anything that requires multi-page allocations to have specific alignment, all of the cases I can think of require natural alignment.

I agree, that's what I mentioned too, so far all cases we care about, they require natual alignment. So it should be fine.

Quoted 25 lines

For sub-page allocations, supporting semi-arbitrary alignments makes sense, but I'm not convinced we should try and support that for page-granularity allocations.

Quoted 5 lines

However, if we do want to go down this road than I don't have any strong objection either, since as you mentioned powerpc mostly just needs natual alignment for it's page table region. So alignment can be extracted from the region type as you described below, so no need to pass it all the time.

..

Quoted 11 lines
Quoted 1 line

The bonus is that @min_gpa goes away too.

powerpc needs min_gpa for it's exception handling pages. see.

	excp_paddr = vm_phy_pages_alloc(vm, excp_pages, 0,
					vm->memslots[MEM_REGION_DATA]);

	TEST_ASSERT(excp_paddr == 0,
		    "Interrupt vectors not allocated at gPA address 0: (0x%lx)",
		    excp_paddr);
Quoted 2 lines

So, will arch still have an access to the API for passing min_gpa = 0 for cases like above?

Quoted 7 lines

Yep, ____vm_phy_pages_alloc() will be globally visible, and I think is quite appropriate in this case since it's more than just specifying a minimum GPA, it's really specifying an _exact_ GPA for the allocation.

gpa_t ____vm_phy_pages_alloc(struct kvm_vm *vm, size_t nr_pages, gpa_t min_gpa,
u32 memslot, bool protected, bool naturally_aligned)

Right, Thanks!

Quoted 8 lines
Quoted 8 lines
Quoted 4 lines

It'll probably take me a few days/weeks, but I'll try get a series posted before the 7.2 merge window closes, so that you can build on top to get the PPC selftests support landed in 7.3.

Thanks Sean for your help! Yes, landing kvm selftests for powerpc will be definitely helpful to verify against any kvm regressions.

Quoted 9 lines
Quoted 5 lines

BTW, I was thinking whether landing powerpc first will be easier for you to consider all the API requirements from all users / usecases? But either way is fine please. I can work on top of your changes too and if something is missing for powerpc, we can add / modify on top, once your series is finished.

One idea would be for me to include the PPC support in the series; it's "just" a patch or two on top, albeit one pretty big patch.

That should be ok Sean. I can rebase my changes on top of yours once your series is ready then. I will be on travel next week (OSS Mumbai) and I don't want to stop your patch series due to my late replies for any of the powerpc part.

So once your series is ready - I can rebase this series on top of it and it can go as we discussed it earlier - so that we can try and land these for 7.3, if possible.

Thanks again for your help :)

Quoted 43 lines
Quoted 40 lines
Quoted 31 lines
Quoted 31 lines
tools/testing/selftests/kvm/include/kvm_util.h +14 -11
@@ -2039,23 +2039,22 @@ gpa_t __vm_phy_pages_alloc(struct kvm_vm *vm, size_t num,
 	TEST_ASSERT(!protected || region->protected_phy_pages,
 		    "Region doesn't support protected memory");
 
-	base = pg = min_gpa >> vm->page_shift;
-	do {
-		for (; pg < base + num; ++pg) {
-			if (!sparsebit_is_set(region->unused_phy_pages, pg)) {
-				base = pg = sparsebit_next_set(region->unused_phy_pages, pg);
-				break;
+	base = min_gpa >> vm->page_shift;
+again:
+	base = (base + align - 1) & ~(align - 1);
+	for (pg = base; pg < base + num; ++pg) {
+		if (!sparsebit_is_set(region->unused_phy_pages, pg)) {
+			base = sparsebit_next_set(region->unused_phy_pages, pg);
+			if (!base) {
+				fprintf(stderr, "No guest physical page available, "
+					"min_gpa: 0x%lx page_size: 0x%x memslot: %u\n",
+					min_gpa, vm->page_size, memslot);
+				fputs("---- vm dump ----\n", stderr);
+				vm_dump(stderr, vm, 2);
+				abort();
 			}
+			goto again;
 		}
-	} while (pg && pg != base + num);
-
-	if (pg == 0) {
-		fprintf(stderr, "No guest physical page available, "
-			"min_gpa: 0x%lx page_size: 0x%x memslot: %u\n",
Quoted 8 lines

tools/testing/selftests/kvm/include/kvm_util.h gpa_t __vm_phy_pages_alloc(struct kvm_vm *vm, size_t num, · line 2058

Quoted 5 lines
tools/testing/selftests/kvm/include/kvm_util.h +0 -4
-			min_gpa, vm->page_size, memslot);
-		fputs("---- vm dump ----\n", stderr);
-		vm_dump(stderr, vm, 2);
-		abort();
 	}

This is unnecessary churn. I'm not saying the current code is pretty or anything, but unless I'm missing something, this can simply be:

Quoted 2 lines

Not really, we need the base to be aligned everytime, that's why the goto again loop aligns the base in the new code.

Quoted 8 lines

Ooh, right, pg needs to be advanced by the aligned number of pages. Ugh, the whole do-while part is bizarre, and AFAICT only "works" by dumb luck.

Quoted 2 lines

Plus I feel the above refactoring also simplifies the special handling of pg == 0 case, which earlier was being handled separately after the loop ends.

Yeah, I fiddled with a few other options, but I think I like your approach the most.

Sure then, Thanks!

-ritesh

#7 lore raw

Re: [PATCH v3 RESEND 02/10] KVM: selftests: Add aligned guest physical page allocator

In reply to Sean Christopherson
Quoted 6 lines · Sean Christopherson

Compile tested only at this point, but I now have a series of ~17 patches to yield:
<..>
It'll probably take me a few days/weeks, but I'll try get a series posted before the 7.2 merge window closes, so that you can build on top to get the PPC selftests support landed in 7.3.

Hello Sean,

I have addressed the comments which we discussed in v3. Kindly let me know if you want me to post v4 or otherwise I was thinking once you post your base patches (to take natural alignment into account, which we discussed here [1]), then I can rebase my changes on top of that series.

[1]: https://lore.kernel.org/linuxppc-dev/[email protected]/

Thanks for your help on this!

-ritesh

#8 lore raw

PATCH RESEND v3 3/10 KVM: PPC: selftests: add support for powerpc

In reply to Ritesh Harjani (IBM)

From: Nicholas Piggin <[email protected]>

Implement KVM selftests support for powerpc (Book3S-64).

ucalls are implemented with an unsupported PAPR hcall number which will always cause KVM to exit to userspace.

Virtual memory is implemented for the radix MMU, and only a base page size is supported (both 4K and 64K).

Guest interrupts are taken in real-mode, so require a page allocated at gRA 0x0. Interrupt entry is complicated because gVA:gRA is not 1:1 mapped (like the kernel is), so the MMU can not just be switched on and off.

[Rebased to latest mainline tree, "cc" to clobber list, fix the size calculation in kvm_arch_vm_post_create()]

---
 MAINTAINERS                                   |   2 +
 tools/testing/selftests/kvm/Makefile          |   2 +-
 tools/testing/selftests/kvm/Makefile.kvm      |  10 +
 .../testing/selftests/kvm/include/kvm_util.h  |   9 +
 .../selftests/kvm/include/powerpc/hcall.h     |  17 +
 .../kvm/include/powerpc/kvm_util_arch.h       |  22 +
 .../selftests/kvm/include/powerpc/ppc_asm.h   |  32 ++
 .../selftests/kvm/include/powerpc/processor.h |  38 ++
 .../selftests/kvm/include/powerpc/ucall.h     |  21 +
 tools/testing/selftests/kvm/lib/guest_modes.c |  20 +-
 tools/testing/selftests/kvm/lib/kvm_util.c    |   8 +
 .../selftests/kvm/lib/powerpc/handlers.S      |  93 ++++
 .../testing/selftests/kvm/lib/powerpc/hcall.c |  45 ++
 .../selftests/kvm/lib/powerpc/processor.c     | 483 ++++++++++++++++++
 .../testing/selftests/kvm/lib/powerpc/ucall.c |  22 +
 15 files changed, 821 insertions(+), 3 deletions(-)
 create mode 100644 tools/testing/selftests/kvm/include/powerpc/hcall.h
 create mode 100644 tools/testing/selftests/kvm/include/powerpc/kvm_util_arch.h
 create mode 100644 tools/testing/selftests/kvm/include/powerpc/ppc_asm.h
 create mode 100644 tools/testing/selftests/kvm/include/powerpc/processor.h
 create mode 100644 tools/testing/selftests/kvm/include/powerpc/ucall.h
 create mode 100644 tools/testing/selftests/kvm/lib/powerpc/handlers.S
 create mode 100644 tools/testing/selftests/kvm/lib/powerpc/hcall.c
 create mode 100644 tools/testing/selftests/kvm/lib/powerpc/processor.c
 create mode 100644 tools/testing/selftests/kvm/lib/powerpc/ucall.c
MAINTAINERS +2 -0
index 355e4ab2f9e5..9848e8d6ae04 100644
@@ -14119,6 +14119,8 @@ F:	arch/powerpc/include/asm/kvm*
 F:	arch/powerpc/include/uapi/asm/kvm*
 F:	arch/powerpc/kernel/kvm*
 F:	arch/powerpc/kvm/
+F:	tools/testing/selftests/kvm/*/powerpc/
+F:	tools/testing/selftests/kvm/powerpc/
 
 KERNEL VIRTUAL MACHINE FOR RISC-V (KVM/riscv)
 M:	Anup Patel <[email protected]>
tools/testing/selftests/kvm/Makefile +1 -1
index f2b223072b62..03d91f00092f 100644
@@ -3,7 +3,7 @@ top_srcdir = ../../../..
 include $(top_srcdir)/scripts/subarch.include
 ARCH            ?= $(SUBARCH)
 
-ifeq ($(ARCH),$(filter $(ARCH),arm64 s390 riscv x86 x86_64 loongarch))
+ifeq ($(ARCH),$(filter $(ARCH),arm64 s390 riscv x86 x86_64 loongarch powerpc))
 # Top-level selftests allows ARCH=x86_64 :-(
 ifeq ($(ARCH),x86_64)
 	override ARCH := x86
tools/testing/selftests/kvm/Makefile.kvm +10 -0
index 9118a5a51b89..825bea7f851d 100644
@@ -52,6 +52,11 @@ LIBKVM_loongarch += lib/loongarch/processor.c
 LIBKVM_loongarch += lib/loongarch/ucall.c
 LIBKVM_loongarch += lib/loongarch/exception.S
 
+LIBKVM_powerpc += lib/powerpc/handlers.S
+LIBKVM_powerpc += lib/powerpc/processor.c
+LIBKVM_powerpc += lib/powerpc/ucall.c
+LIBKVM_powerpc += lib/powerpc/hcall.c
+
 # Non-compiled test targets
 TEST_PROGS_x86 += x86/nx_huge_pages_test.sh
 
@@ -239,6 +244,11 @@ TEST_GEN_PROGS_loongarch += memslot_perf_test
 TEST_GEN_PROGS_loongarch += set_memory_region_test
 TEST_GEN_PROGS_loongarch += steal_time
 
+TEST_GEN_PROGS_powerpc = $(TEST_GEN_PROGS_COMMON)
+TEST_GEN_PROGS_powerpc += access_tracking_perf_test
+TEST_GEN_PROGS_powerpc += dirty_log_perf_test
+TEST_GEN_PROGS_powerpc += hardware_disable_test
+
 SPLIT_TESTS += arch_timer
 SPLIT_TESTS += get-reg-list
 
tools/testing/selftests/kvm/include/kvm_util.h +9 -0
index c515c918c2c9..10f03a182c8b 100644
@@ -209,6 +209,9 @@ enum vm_guest_mode {
 	VM_MODE_P41V48_4K,
 	VM_MODE_P41V39_4K,
 
+	VM_MODE_P52V52_4K,	/* For powerpc64 */
+	VM_MODE_P52V52_64K,
+
 	NUM_VM_MODES,
 };
 
@@ -268,6 +271,12 @@ extern enum vm_guest_mode vm_mode_default;
 #define MIN_PAGE_SHIFT			12U
 #define ptes_per_page(page_size)	((page_size) / 8)
 
+#elif defined(__powerpc64__)
+
+#define VM_MODE_DEFAULT			vm_mode_default
+#define MIN_PAGE_SHIFT			12U
+#define ptes_per_page(page_size)	((page_size) / 8)
+
 #endif
 
 #define VM_SHAPE_DEFAULT	VM_SHAPE(VM_MODE_DEFAULT)
tools/testing/selftests/kvm/include/powerpc/hcall.h new file +17 -0
new file mode 100644
index 000000000000..4028baa6c5d8
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * powerpc hcall defines
+ */
+#ifndef SELFTEST_KVM_HCALL_H
+#define SELFTEST_KVM_HCALL_H
+
+#include <linux/compiler.h>
+
+/* Ucalls use unimplemented PAPR hcall 0 which exits KVM */
+#define H_UCALL	0
+
+int64_t hcall0(uint64_t token);
+int64_t hcall1(uint64_t token, uint64_t arg1);
+int64_t hcall2(uint64_t token, uint64_t arg1, uint64_t arg2);
+
+#endif
tools/testing/selftests/kvm/include/powerpc/kvm_util_arch.h new file +22 -0
new file mode 100644
index 000000000000..5d45c25cd299
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef SELFTEST_KVM_UTIL_ARCH_H
+#define SELFTEST_KVM_UTIL_ARCH_H
+
+#include <stdint.h>
+
+#include "kvm_util_types.h"
+
+struct kvm_mmu_arch {};
+
+/* Page table fragment cache for guest page tables < page size */
+struct vm_pt_frag_cache {
+	gpa_t page;
+	size_t page_nr_used;
+};
+
+struct kvm_vm_arch {
+	gpa_t prtb; /* process table */
+	struct vm_pt_frag_cache pt_frag_cache[2]; /* 256B and 4KB PT caches */
+};
+
+#endif  /* SELFTEST_KVM_UTIL_ARCH_H */
tools/testing/selftests/kvm/include/powerpc/ppc_asm.h new file +32 -0
new file mode 100644
index 000000000000..b9df64659792
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * powerpc asm specific defines
+ */
+#ifndef SELFTEST_KVM_PPC_ASM_H
+#define SELFTEST_KVM_PPC_ASM_H
+
+#define STACK_FRAME_MIN_SIZE	112 /* Could be 32 on ELFv2 */
+#define STACK_REDZONE_SIZE	512
+
+#define INT_FRAME_SIZE		(STACK_FRAME_MIN_SIZE + STACK_REDZONE_SIZE)
+
+#define SPR_SRR0	0x01a
+#define SPR_SRR1	0x01b
+#define SPR_CFAR	0x01c
+
+#define MSR_SF		0x8000000000000000ULL
+#define MSR_HV		0x1000000000000000ULL
+#define MSR_VEC		0x0000000002000000ULL
+#define MSR_VSX		0x0000000000800000ULL
+#define MSR_EE		0x0000000000008000ULL
+#define MSR_PR		0x0000000000004000ULL
+#define MSR_FP		0x0000000000002000ULL
+#define MSR_ME		0x0000000000001000ULL
+#define MSR_IR		0x0000000000000020ULL
+#define MSR_DR		0x0000000000000010ULL
+#define MSR_RI		0x0000000000000002ULL
+#define MSR_LE		0x0000000000000001ULL
+
+#define LPCR_ILE	0x0000000002000000ULL
+
+#endif
tools/testing/selftests/kvm/include/powerpc/processor.h new file +38 -0
new file mode 100644
index 000000000000..cb75b77c33bb
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * powerpc processor specific defines
+ */
+#ifndef SELFTEST_KVM_PROCESSOR_H
+#define SELFTEST_KVM_PROCESSOR_H
+
+#include <linux/compiler.h>
+#include "ppc_asm.h"
+
+extern unsigned char __interrupts_start[];
+extern unsigned char __interrupts_end[];
+
+struct kvm_vm;
+struct kvm_vcpu;
+
+struct ex_regs {
+	uint64_t	gprs[32];
+	uint64_t	nia;
+	uint64_t	msr;
+	uint64_t	cfar;
+	uint64_t	lr;
+	uint64_t	ctr;
+	uint64_t	xer;
+	uint32_t	cr;
+	uint32_t	trap;
+	uint64_t	vaddr; /* vaddr of this struct */
+};
+
+void vm_install_exception_handler(struct kvm_vm *vm, int vector,
+			void (*handler)(struct ex_regs *));
+
+static inline void cpu_relax(void)
+{
+	asm volatile("" ::: "memory");
+}
+
+#endif
tools/testing/selftests/kvm/include/powerpc/ucall.h new file +21 -0
new file mode 100644
index 000000000000..e0dbe91e8848
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef SELFTEST_KVM_UCALL_H
+#define SELFTEST_KVM_UCALL_H
+
+#include "hcall.h"
+
+#define UCALL_EXIT_REASON	KVM_EXIT_PAPR_HCALL
+
+#define UCALL_R4_UCALL	0x5715 /* regular ucall, r5 contains ucall pointer */
+#define UCALL_R4_SIMPLE	0x0000 /* simple exit usable by asm with no ucall data */
+
+static inline void ucall_arch_init(struct kvm_vm *vm, gpa_t mmio_gpa)
+{
+}
+
+static inline void ucall_arch_do_ucall(gva_t uc)
+{
+	hcall2(H_UCALL, UCALL_R4_UCALL, (uintptr_t)(uc));
+}
+
+#endif
tools/testing/selftests/kvm/lib/guest_modes.c +18 -2
index 7a96c43b5704..439766fad693 100644
@@ -4,16 +4,20 @@
  */
 #include "guest_modes.h"
 
-#if defined(__aarch64__) || defined(__riscv)
+#if defined(__aarch64__) || defined(__riscv) || defined(__powerpc64__)
 #include "processor.h"
 enum vm_guest_mode vm_mode_default;
 #endif
 
+#if defined(__powerpc64__)
+#include <unistd.h>
+#endif
+
 struct guest_mode guest_modes[NUM_VM_MODES];
 
 void guest_modes_append_default(void)
 {
-#if !defined(__aarch64__) && !defined(__riscv)
+#if !defined(__aarch64__) && !defined(__riscv) && !defined(__powerpc64__)
 	guest_mode_append(VM_MODE_DEFAULT, true);
 #endif
 
@@ -108,6 +112,18 @@ void guest_modes_append_default(void)
 		TEST_ASSERT(vm_mode_default != NUM_VM_MODES, "No supported mode!");
 	}
 #endif
+#ifdef __powerpc64__
+	{
+		TEST_REQUIRE(kvm_has_cap(KVM_CAP_PPC_MMU_RADIX));
+		/* Radix guest EA and RA are 52-bit on POWER9 and POWER10 */
+		if (sysconf(_SC_PAGESIZE) == 4096)
+			vm_mode_default = VM_MODE_P52V52_4K;
+		else
+			vm_mode_default = VM_MODE_P52V52_64K;
+		guest_mode_append(VM_MODE_P52V52_4K, true);
+		guest_mode_append(VM_MODE_P52V52_64K, true);
+	}
+#endif
 }
 
 void for_each_guest_mode(void (*func)(enum vm_guest_mode, void *), void *arg)
tools/testing/selftests/kvm/lib/kvm_util.c +8 -0
index ac7215824203..e00a25f59416 100644
@@ -218,6 +218,8 @@ const char *vm_guest_mode_string(u32 i)
 		[VM_MODE_P41V57_4K]	= "PA-bits:41,  VA-bits:57,  4K pages",
 		[VM_MODE_P41V48_4K]	= "PA-bits:41,  VA-bits:48,  4K pages",
 		[VM_MODE_P41V39_4K]	= "PA-bits:41,  VA-bits:39,  4K pages",
+		[VM_MODE_P52V52_4K]	= "PA-bits:52,  VA-bits:52,  4K pages",
+		[VM_MODE_P52V52_64K]	= "PA-bits:52,  VA-bits:52, 64K pages",
 	};
 	_Static_assert(sizeof(strings)/sizeof(char *) == NUM_VM_MODES,
 		       "Missing new mode strings?");
@@ -254,6 +256,8 @@ const struct vm_guest_mode_params vm_guest_mode_params[] = {
 	[VM_MODE_P41V57_4K]	= { 41, 57,  0x1000, 12 },
 	[VM_MODE_P41V48_4K]	= { 41, 48,  0x1000, 12 },
 	[VM_MODE_P41V39_4K]	= { 41, 39,  0x1000, 12 },
+	[VM_MODE_P52V52_4K]	= { 52, 52,  0x1000, 12 },
+	[VM_MODE_P52V52_64K]	= { 52, 52, 0x10000, 16 },
 };
 _Static_assert(sizeof(vm_guest_mode_params)/sizeof(struct vm_guest_mode_params) == NUM_VM_MODES,
 	       "Missing new mode params?");
@@ -371,6 +375,10 @@ struct kvm_vm *____vm_create(struct vm_shape shape)
 	case VM_MODE_P41V39_4K:
 		vm->mmu.pgtable_levels = 3;
 		break;
+	case VM_MODE_P52V52_4K:
+	case VM_MODE_P52V52_64K:
+		vm->mmu.pgtable_levels = 4;
+		break;
 	default:
 		TEST_FAIL("Unknown guest mode: 0x%x", vm->mode);
 	}
tools/testing/selftests/kvm/lib/powerpc/handlers.S new file +93 -0

93 lines not on this page · raw message

tools/testing/selftests/kvm/lib/powerpc/hcall.c new file +45 -0

45 lines not on this page · raw message

tools/testing/selftests/kvm/lib/powerpc/processor.c new file +483 -0

483 lines not on this page · raw message

tools/testing/selftests/kvm/lib/powerpc/ucall.c new file +22 -0
new file mode 100644
index 000000000000..3481a7a0b850
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ucall support. A ucall is a "hypercall to host userspace".
+ */
+#include "kvm_util.h"
+#include "ucall_common.h"
+#include "hcall.h"
+
+void *ucall_arch_get_ucall(struct kvm_vcpu *vcpu)
+{
+	struct kvm_run *run = vcpu->run;
+
+	if (run->exit_reason == UCALL_EXIT_REASON &&
+	    run->papr_hcall.nr == H_UCALL) {
+		struct kvm_regs regs;
+
+		vcpu_regs_get(vcpu, &regs);
+		if (regs.gpr[4] == UCALL_R4_UCALL)
+			return (void *)regs.gpr[5];
+	}
+	return NULL;
+}
Signature · 1 line
2.50.1 (Apple Git-155)
#9 lore raw

PATCH RESEND v3 4/10 KVM: PPC: selftests: powerpc enable kvm_create_max_vcpus test

In reply to Ritesh Harjani (IBM)

From: Nicholas Piggin <[email protected]>

powerpc's maximum permitted vCPU ID depends on the VM's SMT mode, and the maximum reported by KVM_CAP_MAX_VCPU_ID exceeds a simple non-SMT VM's limit.

The powerpc KVM selftest port uses non-SMT VMs, so add a workaround to the kvm_create_max_vcpus test case to limit vCPU IDs to KVM_CAP_MAX_VCPUS on powerpc.

[Rebased to latest mainline tree]
---
 tools/testing/selftests/kvm/kvm_create_max_vcpus.c | 9 +++++++++
 1 file changed, 9 insertions(+)
tools/testing/selftests/kvm/kvm_create_max_vcpus.c +9 -0
index c5310736ed06..a82c13d6cdf5 100644
@@ -56,6 +56,15 @@ int main(int argc, char *argv[])
 		    "KVM_MAX_VCPU_IDS (%d) must be at least as large as KVM_MAX_VCPUS (%d).",
 		    kvm_max_vcpu_id, kvm_max_vcpus);
 
+#ifdef __powerpc64__
+	/*
+	 * powerpc has a particular format for the vcpu ID that depends on
+	 * the guest SMT mode, and the max ID cap is too large for non-SMT
+	 * modes, where the maximum ID is the same as the maximum vCPUs.
+	 */
+	kvm_max_vcpu_id = kvm_max_vcpus;
+#endif
+
 	test_vcpu_creation(0, kvm_max_vcpus);
 
 	if (kvm_max_vcpu_id > kvm_max_vcpus)
Signature · 1 line
2.50.1 (Apple Git-155)
#10 lore raw

Re: [PATCH v3 RESEND 04/10] KVM: PPC: selftests: powerpc enable kvm_create_max_vcpus test

Quoted 9 lines · Ritesh Harjani (IBM)

From: Nicholas Piggin <[email protected]>

powerpc's maximum permitted vCPU ID depends on the VM's SMT mode, and the maximum reported by KVM_CAP_MAX_VCPU_ID exceeds a simple non-SMT VM's limit.

The powerpc KVM selftest port uses non-SMT VMs, so add a workaround to the kvm_create_max_vcpus test case to limit vCPU IDs to KVM_CAP_MAX_VCPUS on powerpc.

How is this not a KVM bug? Literally the reason this test exists is to validate KVM's advertised KVM_CAP_MAX_VCPU_ID and KVM_CAP_MAX_VCPUS.

#11 lore raw

Re: [PATCH v3 RESEND 04/10] KVM: PPC: selftests: powerpc enable kvm_create_max_vcpus test

Quoted 7 lines · Sean Christopherson
Quoted 6 lines · Ritesh Harjani (IBM)

From: Nicholas Piggin <[email protected]>

powerpc's maximum permitted vCPU ID depends on the VM's SMT mode, and the maximum reported by KVM_CAP_MAX_VCPU_ID exceeds a simple non-SMT VM's limit.

Quoted 6 lines
Quoted 3 lines

The powerpc KVM selftest port uses non-SMT VMs, so add a workaround to the kvm_create_max_vcpus test case to limit vCPU IDs to KVM_CAP_MAX_VCPUS on powerpc.

How is this not a KVM bug? Literally the reason this test exists is to validate KVM's advertised KVM_CAP_MAX_VCPU_ID and KVM_CAP_MAX_VCPUS.

It's not a KVM bug, it's expected on PowerPC. On PowerPC, vCPU ID encodes SMT topology, e.g. on P9, vcpu id = core * stride + thread,
.. where the stride is same as kvm->arch.emul_smt_mode (VM's emulated SMT mode)

So the vcpu ID space can be sparse, however KVM_CAP_MAX_VCPU_ID is the absolute ceil value (MAX_SMT_THREADS * KVM_MAX_VCORES) i.e. the value with the maximum stride / SMT value.

Since default selftest VM uses stride 1, so it rejects IDS >= max_vcpus.

e.g.
static int kvmppc_core_vcpu_create_hv(struct kvm_vcpu *vcpu)
...

		if (id >= (KVM_MAX_VCPUS * kvm->arch.emul_smt_mode)) {
			pr_devel("KVM: VCPU ID too high\n");
			core = KVM_MAX_VCORES;              /* rejected case */
		} else {

So, it's expected on PowerPC. vcpus with higher IDs can be created but for that we need to set KVM_CAP_PPC_SMT and use strided (sparse) IDs. But since the test as of now is not doing that - that's the reason why the patch only allows to test max vcpu IDs upto max vcpus.

But I guess you must be hating the #ifdef __powerpc__ there. I agree I don't like it either.. maybe we can do it this way?

-#ifdef __powerpc64__

        /*
-        * powerpc has a particular format for the vcpu ID that depends on
-        * the guest SMT mode, and the max ID cap is too large for non-SMT
-        * modes, where the maximum ID is the same as the maximum vCPUs.
+        * Some architectures (e.g. powerpc) encode topology into the vCPU ID,
+        * so a default VM can't necessarily use the full advertised ID range.
+        * Let the arch limit the highest ID this test will create.
         */

- kvm_max_vcpu_id = kvm_max_vcpus;
-#endif
+ kvm_max_vcpu_id = kvm_arch_vcpu_id_limit(kvm_max_vcpus, kvm_max_vcpu_id);

And then in kvm_util.c -
+
+__weak int kvm_arch_vcpu_id_limit(int nr_vcpus, int vcpu_id_max) +{
+ return vcpu_id_max;
+}

and lib/powerpc/processor.c can define -

+
+int kvm_arch_vcpu_id_limit(int nr_vcpus, int vcpu_id_max) +{
+ /*

+        * The stride is the default SMT mode from KVM_CAP_PPC_SMT (1 on
+        * POWER9+, the host's threads-per-subcore on POWER8) and is always <=
+        * MAX_SMT_THREADS, so the result never exceeds KVM_CAP_MAX_VCPU_ID.
+        *
+        * TODO: exercising the higher (sparse) ID range would require setting
+        * KVM_CAP_PPC_SMT and creating strided vCPU IDs.
+        */

+
+ int stride = kvm_check_cap(KVM_CAP_PPC_SMT);
+
+ return nr_vcpus * (stride > 0 ? stride : 1);
+}

If this looks good, then I can re-spin a newer version with the following changes:

1. Use above logic in Patch-4 for kvm_create_max_vcpus_test instead of hardcoded #ifdef __powerpc__ logic.

2. Drop patch-5 (print vcpu_id) debug patch

3. Squash all the type specifier changes i.e. Patch 6-10 in the main Patch-3, the patch which adds kvm selftests support for powerpc.

-ritesh

#12 lore raw

Re: [PATCH v3 RESEND 04/10] KVM: PPC: selftests: powerpc enable kvm_create_max_vcpus test

Quoted 34 lines · Ritesh Harjani
Quoted 7 lines · Sean Christopherson
Quoted 6 lines · Ritesh Harjani (IBM)

From: Nicholas Piggin <[email protected]>

powerpc's maximum permitted vCPU ID depends on the VM's SMT mode, and the maximum reported by KVM_CAP_MAX_VCPU_ID exceeds a simple non-SMT VM's limit.

Quoted 6 lines
Quoted 3 lines

The powerpc KVM selftest port uses non-SMT VMs, so add a workaround to the kvm_create_max_vcpus test case to limit vCPU IDs to KVM_CAP_MAX_VCPUS on powerpc.

How is this not a KVM bug? Literally the reason this test exists is to validate KVM's advertised KVM_CAP_MAX_VCPU_ID and KVM_CAP_MAX_VCPUS.

It's not a KVM bug, it's expected on PowerPC. On PowerPC, vCPU ID encodes SMT topology, e.g. on P9, vcpu id = core * stride + thread,
.. where the stride is same as kvm->arch.emul_smt_mode (VM's emulated SMT mode)

So the vcpu ID space can be sparse, however KVM_CAP_MAX_VCPU_ID is the absolute ceil value (MAX_SMT_THREADS * KVM_MAX_VCORES) i.e. the value with the maximum stride / SMT value.

Since default selftest VM uses stride 1, so it rejects IDS >= max_vcpus.

e.g.
static int kvmppc_core_vcpu_create_hv(struct kvm_vcpu *vcpu)
...

		if (id >= (KVM_MAX_VCPUS * kvm->arch.emul_smt_mode)) {
			pr_devel("KVM: VCPU ID too high\n");
			core = KVM_MAX_VCORES;              /* rejected case */
		} else {
Quoted 7 lines

So, it's expected on PowerPC. vcpus with higher IDs can be created but for that we need to set KVM_CAP_PPC_SMT and use strided (sparse) IDs. But since the test as of now is not doing that - that's the reason why the patch only allows to test max vcpu IDs upto max vcpus.

But I guess you must be hating the #ifdef __powerpc__ there. I agree I don't like it either.. maybe we can do it this way?

I don't love the #ifdef, but it's more that I didn't want to effectively skip a test because KVM was reporting bad information. But after peeking at KVM_CAP_PPC_SMT, I 100% agree we don't want to deal with that here.

Quoted 15 lines
(quoted diff) +4 -6
-#ifdef __powerpc64__
        /*
-        * powerpc has a particular format for the vcpu ID that depends on
-        * the guest SMT mode, and the max ID cap is too large for non-SMT
-        * modes, where the maximum ID is the same as the maximum vCPUs.
+        * Some architectures (e.g. powerpc) encode topology into the vCPU ID,
+        * so a default VM can't necessarily use the full advertised ID range.
+        * Let the arch limit the highest ID this test will create.
         */
-       kvm_max_vcpu_id = kvm_max_vcpus;
-#endif
+       kvm_max_vcpu_id = kvm_arch_vcpu_id_limit(kvm_max_vcpus, kvm_max_vcpu_id);

And then in kvm_util.c -

Review

Quoted 5 lines
(quoted diff) +5 -0
+
+__weak int kvm_arch_vcpu_id_limit(int nr_vcpus, int vcpu_id_max)
+{
+       return vcpu_id_max;
+}

What if we do this? We're going to be bleeding PPC details into the test no matter what, adding an arch hooks just seems like extra cruft and an unnecessary layer of indirection.

	/*
	 * Skip the vCPU ID test when running on PowerPC with SMT support, in
	 * which case system topology is encoded into the vCPU ID, and so a VM
	 * can't use the full advertised vCPU ID range without crafting a valid
	 * platform specific topology.
	 */
	if (kvm_max_vcpu_id > kvm_max_vcpus && !kvm_check_cap(KVM_CAP_PPC_SMT))
		test_vcpu_creation(
			kvm_max_vcpu_id - kvm_max_vcpus, kvm_max_vcpus);
#13 lore raw

Re: [PATCH v3 RESEND 04/10] KVM: PPC: selftests: powerpc enable kvm_create_max_vcpus test

Quoted 72 lines · Sean Christopherson
Quoted 34 lines · Ritesh Harjani
Quoted 7 lines · Sean Christopherson
Quoted 6 lines · Ritesh Harjani (IBM)

From: Nicholas Piggin <[email protected]>

powerpc's maximum permitted vCPU ID depends on the VM's SMT mode, and the maximum reported by KVM_CAP_MAX_VCPU_ID exceeds a simple non-SMT VM's limit.

Quoted 6 lines
Quoted 3 lines

The powerpc KVM selftest port uses non-SMT VMs, so add a workaround to the kvm_create_max_vcpus test case to limit vCPU IDs to KVM_CAP_MAX_VCPUS on powerpc.

How is this not a KVM bug? Literally the reason this test exists is to validate KVM's advertised KVM_CAP_MAX_VCPU_ID and KVM_CAP_MAX_VCPUS.

It's not a KVM bug, it's expected on PowerPC. On PowerPC, vCPU ID encodes SMT topology, e.g. on P9, vcpu id = core * stride + thread,
.. where the stride is same as kvm->arch.emul_smt_mode (VM's emulated SMT mode)

So the vcpu ID space can be sparse, however KVM_CAP_MAX_VCPU_ID is the absolute ceil value (MAX_SMT_THREADS * KVM_MAX_VCORES) i.e. the value with the maximum stride / SMT value.

Since default selftest VM uses stride 1, so it rejects IDS >= max_vcpus.

e.g.
static int kvmppc_core_vcpu_create_hv(struct kvm_vcpu *vcpu)
...

		if (id >= (KVM_MAX_VCPUS * kvm->arch.emul_smt_mode)) {
			pr_devel("KVM: VCPU ID too high\n");
			core = KVM_MAX_VCORES;              /* rejected case */
		} else {
Quoted 7 lines

So, it's expected on PowerPC. vcpus with higher IDs can be created but for that we need to set KVM_CAP_PPC_SMT and use strided (sparse) IDs. But since the test as of now is not doing that - that's the reason why the patch only allows to test max vcpu IDs upto max vcpus.

But I guess you must be hating the #ifdef __powerpc__ there. I agree I don't like it either.. maybe we can do it this way?

I don't love the #ifdef, but it's more that I didn't want to effectively skip a test because KVM was reporting bad information. But after peeking at KVM_CAP_PPC_SMT, I 100% agree we don't want to deal with that here.

Quoted 15 lines
(quoted diff) +4 -6
-#ifdef __powerpc64__
        /*
-        * powerpc has a particular format for the vcpu ID that depends on
-        * the guest SMT mode, and the max ID cap is too large for non-SMT
-        * modes, where the maximum ID is the same as the maximum vCPUs.
+        * Some architectures (e.g. powerpc) encode topology into the vCPU ID,
+        * so a default VM can't necessarily use the full advertised ID range.
+        * Let the arch limit the highest ID this test will create.
         */
-       kvm_max_vcpu_id = kvm_max_vcpus;
-#endif
+       kvm_max_vcpu_id = kvm_arch_vcpu_id_limit(kvm_max_vcpus, kvm_max_vcpu_id);

And then in kvm_util.c -

Review

Quoted 5 lines
(quoted diff) +5 -0
+
+__weak int kvm_arch_vcpu_id_limit(int nr_vcpus, int vcpu_id_max)
+{
+       return vcpu_id_max;
+}

What if we do this? We're going to be bleeding PPC details into the test no matter what, adding an arch hooks just seems like extra cruft and an unnecessary layer of indirection.

Quoted 9 lines
	/*
	 * Skip the vCPU ID test when running on PowerPC with SMT support, in
	 * which case system topology is encoded into the vCPU ID, and so a VM
	 * can't use the full advertised vCPU ID range without crafting a valid
	 * platform specific topology.
	 */
	if (kvm_max_vcpu_id > kvm_max_vcpus && !kvm_check_cap(KVM_CAP_PPC_SMT))
		test_vcpu_creation(
			kvm_max_vcpu_id - kvm_max_vcpus, kvm_max_vcpus);

Thanks! That should do and I think that's the most cleaner version.

I will change patch-4 with your suggested changes then.

-ritesh

#14 lore raw

PATCH RESEND v3 5/10 KVM: selftests: Print the vcpu_id when KVM_CREATE_VCPU ioctl fails

In reply to Ritesh Harjani (IBM)

Print the vcpu_id and errno when the KVM_CREATE_VCPU ioctl fails, for debug purposes.
This helped in debugging an issue with KVM on PowerVM, where KVM_CREATE_VCPU only supports max 2048 vcpus, because the PAPR_HCALL H_GUEST_CREATE_VCPU ("Documentation/arch/powerpc/kvm-nested.rst") supports only up to 0-2047 vcpu_id. However KVM_CAP_MAX_VCPUS capability extension always reports max_vcpus as NR_CPUS of the host.

---
 tools/testing/selftests/kvm/lib/kvm_util.c | 7 +++++++
 1 file changed, 7 insertions(+)
tools/testing/selftests/kvm/lib/kvm_util.c +7 -0
index e00a25f59416..6319e2037882 100644
@@ -1354,6 +1354,13 @@ struct kvm_vcpu *__vm_vcpu_add(struct kvm_vm *vm, u32 vcpu_id)
 	vcpu->vm = vm;
 	vcpu->id = vcpu_id;
 	vcpu->fd = __vm_ioctl(vm, KVM_CREATE_VCPU, (void *)(unsigned long)vcpu_id);
+	if (vcpu->fd < 0) {
+		int saved_errno = errno;
+
+		pr_info("Failed KVM_CREATE_VCPU for vcpu_id %u with errno %d\n",
+			vcpu_id, saved_errno);
+		errno = saved_errno;
+	}
 	TEST_ASSERT_VM_VCPU_IOCTL(vcpu->fd >= 0, KVM_CREATE_VCPU, vcpu->fd, vm);
 
 	TEST_ASSERT(vcpu_mmap_sz() >= sizeof(*vcpu->run), "vcpu mmap size "
Signature · 1 line
2.50.1 (Apple Git-155)
#15 lore raw

Re: [PATCH v3 RESEND 05/10] KVM: selftests: Print the vcpu_id when KVM_CREATE_VCPU ioctl fails

Quoted 18 lines · Ritesh Harjani (IBM)

Print the vcpu_id and errno when the KVM_CREATE_VCPU ioctl fails, for debug purposes.
This helped in debugging an issue with KVM on PowerVM, where KVM_CREATE_VCPU only supports max 2048 vcpus, because the PAPR_HCALL H_GUEST_CREATE_VCPU ("Documentation/arch/powerpc/kvm-nested.rst") supports only up to 0-2047 vcpu_id. However KVM_CAP_MAX_VCPUS capability extension always reports max_vcpus as NR_CPUS of the host.

---
 tools/testing/selftests/kvm/lib/kvm_util.c | 7 +++++++
 1 file changed, 7 insertions(+)
tools/testing/selftests/kvm/lib/kvm_util.c +0 -0
index e00a25f59416..6319e2037882 100644

tools/testing/selftests/kvm/lib/kvm_util.c struct kvm_vcpu *__vm_vcpu_add(struct kvm_vm *vm, u32 vcpu_id) · line 1362

Quoted 9 lines
tools/testing/selftests/kvm/lib/kvm_util.c +6 -0
@@ -1354,6 +1354,13 @@ struct kvm_vcpu *__vm_vcpu_add(struct kvm_vm *vm, u32 vcpu_id)
 	vcpu->vm = vm;
 	vcpu->id = vcpu_id;
 	vcpu->fd = __vm_ioctl(vm, KVM_CREATE_VCPU, (void *)(unsigned long)vcpu_id);
+	if (vcpu->fd < 0) {
+		int saved_errno = errno;
+
+		pr_info("Failed KVM_CREATE_VCPU for vcpu_id %u with errno %d\n",
+			vcpu_id, saved_errno);
+		errno = saved_errno;

Sorry, but NAK. There are myriad failures where printing extra information can help debug a failure/assert, I don't want to create a slippery slope where the codebase is littered with extra print statements that someone found useful at some point.

#16 lore raw

PATCH RESEND v3 6/10 KVM: PPC: selftests: Use u64 instead of uint64_t

In reply to Ritesh Harjani (IBM)

commit 26f8453288d4c ("KVM: selftests: Use u64 instead of uint64_t") made this change from uint64_t -> u64 for all other kvm selftests.

Do the same for powerpc as well. No functional changes expected.

---
 .../selftests/kvm/include/powerpc/hcall.h     |  6 +--
 .../selftests/kvm/include/powerpc/processor.h | 16 +++----
 .../testing/selftests/kvm/lib/powerpc/hcall.c |  6 +--
 .../selftests/kvm/lib/powerpc/processor.c     | 44 +++++++++----------
 4 files changed, 36 insertions(+), 36 deletions(-)
tools/testing/selftests/kvm/include/powerpc/hcall.h +3 -3
index 4028baa6c5d8..f923b3f5e233 100644
@@ -10,8 +10,8 @@
 /* Ucalls use unimplemented PAPR hcall 0 which exits KVM */
 #define H_UCALL	0
 
-int64_t hcall0(uint64_t token);
-int64_t hcall1(uint64_t token, uint64_t arg1);
-int64_t hcall2(uint64_t token, uint64_t arg1, uint64_t arg2);
+int64_t hcall0(u64 token);
+int64_t hcall1(u64 token, u64 arg1);
+int64_t hcall2(u64 token, u64 arg1, u64 arg2);
 
 #endif
tools/testing/selftests/kvm/include/powerpc/processor.h +8 -8
index cb75b77c33bb..cbbe390ae244 100644
@@ -15,16 +15,16 @@ struct kvm_vm;
 struct kvm_vcpu;
 
 struct ex_regs {
-	uint64_t	gprs[32];
-	uint64_t	nia;
-	uint64_t	msr;
-	uint64_t	cfar;
-	uint64_t	lr;
-	uint64_t	ctr;
-	uint64_t	xer;
+	u64	gprs[32];
+	u64	nia;
+	u64	msr;
+	u64	cfar;
+	u64	lr;
+	u64	ctr;
+	u64	xer;
 	uint32_t	cr;
 	uint32_t	trap;
-	uint64_t	vaddr; /* vaddr of this struct */
+	u64	vaddr; /* vaddr of this struct */
 };
 
 void vm_install_exception_handler(struct kvm_vm *vm, int vector,
tools/testing/selftests/kvm/lib/powerpc/hcall.c +3 -3
index efb4318252be..cd10022572a5 100644
@@ -5,7 +5,7 @@
 #include "kvm_util.h"
 #include "hcall.h"
 
-int64_t hcall0(uint64_t token)
+int64_t hcall0(u64 token)
 {
 	register uintptr_t r3 asm ("r3") = token;
 
@@ -17,7 +17,7 @@ int64_t hcall0(uint64_t token)
 	return r3;
 }
 
-int64_t hcall1(uint64_t token, uint64_t arg1)
+int64_t hcall1(u64 token, u64 arg1)
 {
 	register uintptr_t r3 asm ("r3") = token;
 	register uintptr_t r4 asm ("r4") = arg1;
@@ -30,7 +30,7 @@ int64_t hcall1(uint64_t token, uint64_t arg1)
 	return r3;
 }
 
-int64_t hcall2(uint64_t token, uint64_t arg1, uint64_t arg2)
+int64_t hcall2(u64 token, u64 arg1, u64 arg2)
 {
 	register uintptr_t r3 asm ("r3") = token;
 	register uintptr_t r4 asm ("r4") = arg1;
tools/testing/selftests/kvm/lib/powerpc/processor.c +22 -22

116 lines not on this page · raw message

Signature · 1 line
2.50.1 (Apple Git-155)
#17 lore raw

PATCH RESEND v3 7/10 KVM: PPC: selftests: Use s64 instead of int64_t

In reply to Ritesh Harjani (IBM)

commit 286e8903aed14 ("KVM: selftests: Use s64 instead of int64_t") made this change from int64_t -> s64 for all other kvm selftests.

Do the same for powerpc as well. No functional changes expected. It uses the same method describes in above commit.

git ls-files tools/testing/selftests/kvm | xargs sed -i 's/int64_t/s64/g'

---
 tools/testing/selftests/kvm/include/powerpc/hcall.h | 6 +++---
 tools/testing/selftests/kvm/lib/powerpc/hcall.c     | 6 +++---
 2 files changed, 6 insertions(+), 6 deletions(-)
tools/testing/selftests/kvm/include/powerpc/hcall.h +3 -3
index f923b3f5e233..21b2bf9180f1 100644
@@ -10,8 +10,8 @@
 /* Ucalls use unimplemented PAPR hcall 0 which exits KVM */
 #define H_UCALL	0
 
-int64_t hcall0(u64 token);
-int64_t hcall1(u64 token, u64 arg1);
-int64_t hcall2(u64 token, u64 arg1, u64 arg2);
+s64 hcall0(u64 token);
+s64 hcall1(u64 token, u64 arg1);
+s64 hcall2(u64 token, u64 arg1, u64 arg2);
 
 #endif
tools/testing/selftests/kvm/lib/powerpc/hcall.c +3 -3
index cd10022572a5..d5f5282654ee 100644
@@ -5,7 +5,7 @@
 #include "kvm_util.h"
 #include "hcall.h"
 
-int64_t hcall0(u64 token)
+s64 hcall0(u64 token)
 {
 	register uintptr_t r3 asm ("r3") = token;
 
@@ -17,7 +17,7 @@ int64_t hcall0(u64 token)
 	return r3;
 }
 
-int64_t hcall1(u64 token, u64 arg1)
+s64 hcall1(u64 token, u64 arg1)
 {
 	register uintptr_t r3 asm ("r3") = token;
 	register uintptr_t r4 asm ("r4") = arg1;
@@ -30,7 +30,7 @@ int64_t hcall1(u64 token, u64 arg1)
 	return r3;
 }
 
-int64_t hcall2(u64 token, u64 arg1, u64 arg2)
+s64 hcall2(u64 token, u64 arg1, u64 arg2)
 {
 	register uintptr_t r3 asm ("r3") = token;
 	register uintptr_t r4 asm ("r4") = arg1;
Signature · 1 line
2.50.1 (Apple Git-155)
#18 lore raw

PATCH RESEND v3 8/10 KVM: PPC: selftests: Use u32 instead of uint32_t

In reply to Ritesh Harjani (IBM)

commit 0c3a8774692aa ("KVM: selftests: Use u32 instead of uint32_t") made this change from uint32_t -> u32 for all other kvm selftests.

Do the same for powerpc as well. No functional changes expected.

It uses the same method described in above commit.
git ls-files tools/testing/selftests/kvm | xargs sed -i 's/uint32_t/u32/g'

---
 tools/testing/selftests/kvm/include/powerpc/processor.h | 4 ++--
 tools/testing/selftests/kvm/lib/powerpc/processor.c     | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)
tools/testing/selftests/kvm/include/powerpc/processor.h +2 -2
index cbbe390ae244..95ec3debc83c 100644
@@ -22,8 +22,8 @@ struct ex_regs {
 	u64	lr;
 	u64	ctr;
 	u64	xer;
-	uint32_t	cr;
-	uint32_t	trap;
+	u32	cr;
+	u32	trap;
 	u64	vaddr; /* vaddr of this struct */
 };
 
tools/testing/selftests/kvm/lib/powerpc/processor.c +1 -1
index ac5c3421ec81..0a65fc3a8d9a 100644
@@ -312,7 +312,7 @@ void vcpu_arch_set_entry_point(struct kvm_vcpu *vcpu, void *guest_code)
 	vcpu_regs_set(vcpu, &regs);
 }
 
-struct kvm_vcpu *vm_arch_vcpu_add(struct kvm_vm *vm, uint32_t vcpu_id)
+struct kvm_vcpu *vm_arch_vcpu_add(struct kvm_vm *vm, u32 vcpu_id)
 {
 	const size_t stack_size = SZ_64K;
 	gva_t stack_vaddr, ex_regs_vaddr;
Signature · 1 line
2.50.1 (Apple Git-155)
#19 lore raw

PATCH RESEND v3 9/10 KVM: PPC: selftests: Use u8 instead of uint8_t

In reply to Ritesh Harjani (IBM)

commit 6ec982b5a2c7c ("KVM: selftests: Use u8 instead of uint8_t") made this change from uint32_t -> u32 for all other kvm selftests.

Do the same for powerpc as well. No functional changes expected.

It uses the same method described in above commit.
git ls-files tools/testing/selftests/kvm | xargs sed -i 's/uint8_t/u8/g'

---
 tools/testing/selftests/kvm/lib/powerpc/processor.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
tools/testing/selftests/kvm/lib/powerpc/processor.c +3 -3
index 0a65fc3a8d9a..2c1e95c8aa9c 100644
@@ -256,7 +256,7 @@ gpa_t addr_arch_gva2gpa(struct kvm_vm *vm, gva_t gva)
 }
 
 static void virt_dump_pt(FILE *stream, struct kvm_vm *vm, gpa_t pt,
-			 gva_t va, int level, uint8_t indent)
+			 gva_t va, int level, u8 indent)
 {
 	int size, idx;
 
@@ -283,7 +283,7 @@ static void virt_dump_pt(FILE *stream, struct kvm_vm *vm, gpa_t pt,
 
 }
 
-void virt_arch_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent)
+void virt_arch_dump(FILE *stream, struct kvm_vm *vm, u8 indent)
 {
 	gpa_t pt = vm->mmu.pgd;
 
@@ -380,7 +380,7 @@ void vcpu_args_set(struct kvm_vcpu *vcpu, unsigned int num, ...)
 	va_end(ap);
 }
 
-void vcpu_arch_dump(FILE *stream, struct kvm_vcpu *vcpu, uint8_t indent)
+void vcpu_arch_dump(FILE *stream, struct kvm_vcpu *vcpu, u8 indent)
 {
 	struct kvm_regs regs;
 
Signature · 1 line
2.50.1 (Apple Git-155)
#20 lore raw

Re: [PATCH v3 RESEND 09/10] KVM: PPC: selftests: Use u8 instead of uint8_t

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [Low] Commit message contains a copy-paste typo, incorrectly stating the conversion was from uint32_t to…

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] Commit message contains a copy-paste typo, incorrectly stating the conversion was from uint32_t to u32. --

commit be805dd1657bb3d5b73a2937cc30e09c502a04eb
Author: Ritesh Harjani (IBM) <[email protected]>

KVM: PPC: selftests: Use u8 instead of uint8_t

This commit updates the powerpc KVM selftests to use u8 instead of uint8_t, bringing it in line with the rest of the KVM selftests.

Quoted 2 lines

commit 6ec982b5a2c7c ("KVM: selftests: Use u8 instead of uint8_t") made this change from uint32_t -> u32 for all other kvm selftests.

[Severity: Low]
This isn't a bug, but there appears to be a copy-paste typo in the commit message. It mentions converting from uint32_t to u32, whereas the patch title, the sed command below it, and the actual code changes are converting uint8_t to u8.

Could this part of the commit message be updated to say uint8_t to u8 so that it accurately reflects the diff?

Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=9
#21 lore raw

PATCH RESEND v3 10/10 KVM: PPC: selftests: Replace u64 gpa, u64 gva|vaddr with gpa_t and gva_t

In reply to Ritesh Harjani (IBM)

commit df079910f9814 ("KVM: selftests: Replace "u64 gpa" with "gpa_t" throughout") commit 014dfb7b9bf3f ("KVM: selftests: Replace "vaddr" with "gva" throughout")

Similar to above 2 commits, this patch makes the relevant changes to powerpc kvm selftests code to make use of gpa_t and gva_t types instead of u64 throughout the code.

No functional change intended.

---
 .../selftests/kvm/include/powerpc/processor.h |  3 ++-
 .../selftests/kvm/lib/powerpc/processor.c     | 20 +++++++++----------
 2 files changed, 12 insertions(+), 11 deletions(-)
tools/testing/selftests/kvm/include/powerpc/processor.h +2 -1
index 95ec3debc83c..f0ee21a8e2d4 100644
@@ -7,6 +7,7 @@
 
 #include <linux/compiler.h>
 #include "ppc_asm.h"
+#include "kvm_util_types.h"
 
 extern unsigned char __interrupts_start[];
 extern unsigned char __interrupts_end[];
@@ -24,7 +25,7 @@ struct ex_regs {
 	u64	xer;
 	u32	cr;
 	u32	trap;
-	u64	vaddr; /* vaddr of this struct */
+	gva_t	gva; /* gva of this struct */
 };
 
 void vm_install_exception_handler(struct kvm_vm *vm, int vector,
tools/testing/selftests/kvm/lib/powerpc/processor.c +10 -10
index 2c1e95c8aa9c..009a0859ba05 100644
@@ -97,17 +97,17 @@ static u64 pt_entry_coverage(struct kvm_vm *vm, int level)
 	return size;
 }
 
-static int pt_idx(struct kvm_vm *vm, u64 vaddr, int level, u64 *nls)
+static int pt_idx(struct kvm_vm *vm, gva_t gva, int level, u64 *nls)
 {
 	switch (level) {
 	case 1:
 		if (nls)
 			*nls = 0x9;
-		return (vaddr >> 39) & 0x1fff;
+		return (gva >> 39) & 0x1fff;
 	case 2:
 		if (nls)
 			*nls = 0x9;
-		return (vaddr >> 30) & 0x1ff;
+		return (gva >> 30) & 0x1ff;
 	case 3:
 		if (vm->mode == VM_MODE_P52V52_4K) {
 			if (nls)
@@ -116,12 +116,12 @@ static int pt_idx(struct kvm_vm *vm, u64 vaddr, int level, u64 *nls)
 			if (nls)
 				*nls = 0x5;
 		}
-		return (vaddr >> 21) & 0x1ff;
+		return (gva >> 21) & 0x1ff;
 	case 4:
 		if (vm->mode == VM_MODE_P52V52_4K)
-			return (vaddr >> 12) & 0x1ff;
+			return (gva >> 12) & 0x1ff;
 		else /* vm->mode == VM_MODE_P52V52_64K */
-			return (vaddr >> 16) & 0x1f;
+			return (gva >> 16) & 0x1f;
 	default:
 		TEST_ASSERT(false, "Invalid page table level %d\n", level);
 		return 0;
@@ -129,9 +129,9 @@ static int pt_idx(struct kvm_vm *vm, u64 vaddr, int level, u64 *nls)
 }
 
 static u64 *virt_get_pte(struct kvm_vm *vm, gpa_t pt,
-			  u64 vaddr, int level, u64 *nls)
+			  gva_t gva, int level, u64 *nls)
 {
-	int idx = pt_idx(vm, vaddr, level, nls);
+	int idx = pt_idx(vm, gva, level, nls);
 	u64 *ptep = addr_gpa2hva(vm, pt + idx * 8);
 
 	return ptep;
@@ -189,7 +189,7 @@ static gpa_t __vm_alloc_pt(struct kvm_vm *vm, u64 pt_shift)
 	return pt;
 }
 
-void virt_arch_pg_map(struct kvm_vm *vm, u64 gva, u64 gpa)
+void virt_arch_pg_map(struct kvm_vm *vm, gva_t gva, gpa_t gpa)
 {
 	gpa_t pt = vm->mmu.pgd;
 	u64 *ptep, pte;
@@ -331,7 +331,7 @@ struct kvm_vcpu *vm_arch_vcpu_add(struct kvm_vm *vm, u32 vcpu_id)
 				       MEM_REGION_DATA);
 	ex_regs_paddr = addr_gva2gpa(vm, ex_regs_vaddr);
 	ex_regs = addr_gpa2hva(vm, ex_regs_paddr);
-	ex_regs->vaddr = ex_regs_vaddr;
+	ex_regs->gva = ex_regs_vaddr;
 
 	vcpu = __vm_vcpu_add(vm, vcpu_id);
 
Signature · 1 line
2.50.1 (Apple Git-155)
#22 lore raw
In reply to Ritesh Harjani (IBM)
Quoted 6 lines · Ritesh Harjani (IBM)

Nicholas Piggin (4):
KVM: selftests: Move pgd_created check into virt_pgd_alloc
KVM: selftests: Add aligned guest physical page allocator
KVM: PPC: selftests: add support for powerpc
KVM: PPC: selftests: powerpc enable kvm_create_max_vcpus test

Quoted 8 lines

Ritesh Harjani (IBM) (6):
KVM: selftests: Print the vcpu_id when KVM_CREATE_VCPU ioctl fails
KVM: PPC: selftests: Use u64 instead of uint64_t
KVM: PPC: selftests: Use s64 instead of int64_t
KVM: PPC: selftests: Use u32 instead of uint32_t
KVM: PPC: selftests: Use u8 instead of uint8_t
KVM: PPC: selftests: Replace u64 gpa, u64 gva|vaddr with gpa_t and
gva_t

Squash these typedef changes into the patch where the "bad" typedefs are used. Give yourself attribution for Co-developed-by if desired, but don't introduce code only to immediately fix it.

#23 lore raw
Quoted 16 lines · Sean Christopherson
Quoted 6 lines · Ritesh Harjani (IBM)

Nicholas Piggin (4):
KVM: selftests: Move pgd_created check into virt_pgd_alloc
KVM: selftests: Add aligned guest physical page allocator
KVM: PPC: selftests: add support for powerpc
KVM: PPC: selftests: powerpc enable kvm_create_max_vcpus test

Quoted 8 lines

Ritesh Harjani (IBM) (6):
KVM: selftests: Print the vcpu_id when KVM_CREATE_VCPU ioctl fails
KVM: PPC: selftests: Use u64 instead of uint64_t
KVM: PPC: selftests: Use s64 instead of int64_t
KVM: PPC: selftests: Use u32 instead of uint32_t
KVM: PPC: selftests: Use u8 instead of uint8_t
KVM: PPC: selftests: Replace u64 gpa, u64 gva|vaddr with gpa_t and
gva_t

Quoted 3 lines

Squash these typedef changes into the patch where the "bad" typedefs are used. Give yourself attribution for Co-developed-by if desired, but don't introduce code only to immediately fix it.

This was noticed only later in v2->v3, and I wanted to keep the original patch from Nick the same. But no issues, I can squash this in the main patch in the next revision.

However I was hoping if I can get some feedback on the overall patch series as well especially the non-powerpc patches (1,2). One other question - Should this go via powerpc tree or via kvm tree?

-ritesh

#24 lore raw
Quoted 1 line · Ritesh Harjani

One other question - Should this go via powerpc tree or via kvm tree?

Definitely the KVM tree.