From: Nicholas Piggin <[email protected]>

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

Signed-off-by: Nicholas Piggin <[email protected]>
[Rebased to latest mainline tree]
Signed-off-by: Ritesh Harjani (IBM) <[email protected]>
---
 .../testing/selftests/kvm/include/kvm_util.h  | 20 +++++++++--
 tools/testing/selftests/kvm/lib/kvm_util.c    | 33 +++++++++----------
 2 files changed, 33 insertions(+), 20 deletions(-)

diff --git a/tools/testing/selftests/kvm/include/kvm_util.h 
b/tools/testing/selftests/kvm/include/kvm_util.h
index 3666a8530f31..c515c918c2c9 100644
--- a/tools/testing/selftests/kvm/include/kvm_util.h
+++ b/tools/testing/selftests/kvm/include/kvm_util.h
@@ -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).
diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c 
b/tools/testing/selftests/kvm/lib/kvm_util.c
index 2a76eca7029d..cdb004c9ba56 100644
--- a/tools/testing/selftests/kvm/lib/kvm_util.c
+++ b/tools/testing/selftests/kvm/lib/kvm_util.c
@@ -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) {
-- 
2.39.5


Reply via email to