]> Git Repo - J-linux.git/blobdiff - tools/testing/selftests/kvm/lib/kvm_util.c
Merge tag 'kvm-x86-pmu-6.9' of https://github.com/kvm-x86/linux into HEAD
[J-linux.git] / tools / testing / selftests / kvm / lib / kvm_util.c
index 9bafe44cb9786a8afb4dad7c11b30814cf29e15b..b2262b5fad9e79a509f9c686e675baf2b95b00a0 100644 (file)
@@ -27,7 +27,8 @@ int open_path_or_exit(const char *path, int flags)
        int fd;
 
        fd = open(path, flags);
-       __TEST_REQUIRE(fd >= 0, "%s not available (errno: %d)", path, errno);
+       __TEST_REQUIRE(fd >= 0 || errno != ENOENT, "Cannot open %s: %s", path, strerror(errno));
+       TEST_ASSERT(fd >= 0, "Failed to open '%s'", path);
 
        return fd;
 }
@@ -275,6 +276,7 @@ struct kvm_vm *____vm_create(struct vm_shape shape)
 
        vm->mode = shape.mode;
        vm->type = shape.type;
+       vm->subtype = shape.subtype;
 
        vm->pa_bits = vm_guest_mode_params[vm->mode].pa_bits;
        vm->va_bits = vm_guest_mode_params[vm->mode].va_bits;
@@ -315,6 +317,7 @@ struct kvm_vm *____vm_create(struct vm_shape shape)
        case VM_MODE_PXXV48_4K:
 #ifdef __x86_64__
                kvm_get_cpu_address_width(&vm->pa_bits, &vm->va_bits);
+               kvm_init_vm_address_properties(vm);
                /*
                 * Ignore KVM support for 5-level paging (vm->va_bits == 57),
                 * it doesn't take effect unless a CR4.LA57 is set, which it
@@ -370,7 +373,7 @@ static uint64_t vm_nr_pages_required(enum vm_guest_mode mode,
        uint64_t nr_pages;
 
        TEST_ASSERT(nr_runnable_vcpus,
-                   "Use vm_create_barebones() for VMs that _never_ have vCPUs\n");
+                   "Use vm_create_barebones() for VMs that _never_ have vCPUs");
 
        TEST_ASSERT(nr_runnable_vcpus <= kvm_check_cap(KVM_CAP_MAX_VCPUS),
                    "nr_vcpus = %d too large for host, max-vcpus = %d",
@@ -541,7 +544,7 @@ void kvm_pin_this_task_to_pcpu(uint32_t pcpu)
        CPU_ZERO(&mask);
        CPU_SET(pcpu, &mask);
        r = sched_setaffinity(0, sizeof(mask), &mask);
-       TEST_ASSERT(!r, "sched_setaffinity() failed for pCPU '%u'.\n", pcpu);
+       TEST_ASSERT(!r, "sched_setaffinity() failed for pCPU '%u'.", pcpu);
 }
 
 static uint32_t parse_pcpu(const char *cpu_str, const cpu_set_t *allowed_mask)
@@ -549,7 +552,7 @@ static uint32_t parse_pcpu(const char *cpu_str, const cpu_set_t *allowed_mask)
        uint32_t pcpu = atoi_non_negative("CPU number", cpu_str);
 
        TEST_ASSERT(CPU_ISSET(pcpu, allowed_mask),
-                   "Not allowed to run on pCPU '%d', check cgroups?\n", pcpu);
+                   "Not allowed to run on pCPU '%d', check cgroups?", pcpu);
        return pcpu;
 }
 
@@ -579,7 +582,7 @@ void kvm_parse_vcpu_pinning(const char *pcpus_string, uint32_t vcpu_to_pcpu[],
        int i, r;
 
        cpu_list = strdup(pcpus_string);
-       TEST_ASSERT(cpu_list, "strdup() allocation failed.\n");
+       TEST_ASSERT(cpu_list, "strdup() allocation failed.");
 
        r = sched_getaffinity(0, sizeof(allowed_mask), &allowed_mask);
        TEST_ASSERT(!r, "sched_getaffinity() failed");
@@ -588,7 +591,7 @@ void kvm_parse_vcpu_pinning(const char *pcpus_string, uint32_t vcpu_to_pcpu[],
 
        /* 1. Get all pcpus for vcpus. */
        for (i = 0; i < nr_vcpus; i++) {
-               TEST_ASSERT(cpu, "pCPU not provided for vCPU '%d'\n", i);
+               TEST_ASSERT(cpu, "pCPU not provided for vCPU '%d'", i);
                vcpu_to_pcpu[i] = parse_pcpu(cpu, &allowed_mask);
                cpu = strtok(NULL, delim);
        }
@@ -715,6 +718,7 @@ static void __vm_mem_region_delete(struct kvm_vm *vm,
        vm_ioctl(vm, KVM_SET_USER_MEMORY_REGION2, &region->region);
 
        sparsebit_free(&region->unused_phy_pages);
+       sparsebit_free(&region->protected_phy_pages);
        ret = munmap(region->mmap_start, region->mmap_size);
        TEST_ASSERT(!ret, __KVM_SYSCALL_ERROR("munmap()", ret));
        if (region->fd >= 0) {
@@ -1096,6 +1100,8 @@ void vm_mem_add(struct kvm_vm *vm, enum vm_mem_backing_src_type src_type,
        }
 
        region->unused_phy_pages = sparsebit_alloc();
+       if (vm_arch_has_protected_memory(vm))
+               region->protected_phy_pages = sparsebit_alloc();
        sparsebit_set_num(region->unused_phy_pages,
                guest_paddr >> vm->page_shift, npages);
        region->region.slot = slot;
@@ -1107,7 +1113,7 @@ void vm_mem_add(struct kvm_vm *vm, enum vm_mem_backing_src_type src_type,
        TEST_ASSERT(ret == 0, "KVM_SET_USER_MEMORY_REGION2 IOCTL failed,\n"
                "  rc: %i errno: %i\n"
                "  slot: %u flags: 0x%x\n"
-               "  guest_phys_addr: 0x%lx size: 0x%lx guest_memfd: %d\n",
+               "  guest_phys_addr: 0x%lx size: 0x%lx guest_memfd: %d",
                ret, errno, slot, flags,
                guest_paddr, (uint64_t) region->region.memory_size,
                region->region.guest_memfd);
@@ -1272,7 +1278,7 @@ void vm_guest_mem_fallocate(struct kvm_vm *vm, uint64_t base, uint64_t size,
                len = min_t(uint64_t, end - gpa, region->region.memory_size - offset);
 
                ret = fallocate(region->region.guest_memfd, mode, fd_offset, len);
-               TEST_ASSERT(!ret, "fallocate() failed to %s at %lx (len = %lu), fd = %d, mode = %x, offset = %lx\n",
+               TEST_ASSERT(!ret, "fallocate() failed to %s at %lx (len = %lu), fd = %d, mode = %x, offset = %lx",
                            punch_hole ? "punch hole" : "allocate", gpa, len,
                            region->region.guest_memfd, mode, fd_offset);
        }
@@ -1315,7 +1321,7 @@ struct kvm_vcpu *__vm_vcpu_add(struct kvm_vm *vm, uint32_t vcpu_id)
        struct kvm_vcpu *vcpu;
 
        /* Confirm a vcpu with the specified id doesn't already exist. */
-       TEST_ASSERT(!vcpu_exists(vm, vcpu_id), "vCPU%d already exists\n", vcpu_id);
+       TEST_ASSERT(!vcpu_exists(vm, vcpu_id), "vCPU%d already exists", vcpu_id);
 
        /* Allocate and initialize new vcpu structure. */
        vcpu = calloc(1, sizeof(*vcpu));
@@ -1426,15 +1432,17 @@ va_found:
        return pgidx_start * vm->page_size;
 }
 
-vm_vaddr_t __vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min,
-                           enum kvm_mem_region_type type)
+static vm_vaddr_t ____vm_vaddr_alloc(struct kvm_vm *vm, size_t sz,
+                                    vm_vaddr_t vaddr_min,
+                                    enum kvm_mem_region_type type,
+                                    bool protected)
 {
        uint64_t pages = (sz >> vm->page_shift) + ((sz % vm->page_size) != 0);
 
        virt_pgd_alloc(vm);
-       vm_paddr_t paddr = vm_phy_pages_alloc(vm, pages,
-                                             KVM_UTIL_MIN_PFN * vm->page_size,
-                                             vm->memslots[type]);
+       vm_paddr_t paddr = __vm_phy_pages_alloc(vm, pages,
+                                               KVM_UTIL_MIN_PFN * vm->page_size,
+                                               vm->memslots[type], protected);
 
        /*
         * Find an unused range of virtual page addresses of at least
@@ -1454,6 +1462,20 @@ vm_vaddr_t __vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min,
        return vaddr_start;
 }
 
+vm_vaddr_t __vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min,
+                           enum kvm_mem_region_type type)
+{
+       return ____vm_vaddr_alloc(vm, sz, vaddr_min, type,
+                                 vm_arch_has_protected_memory(vm));
+}
+
+vm_vaddr_t vm_vaddr_alloc_shared(struct kvm_vm *vm, size_t sz,
+                                vm_vaddr_t vaddr_min,
+                                enum kvm_mem_region_type type)
+{
+       return ____vm_vaddr_alloc(vm, sz, vaddr_min, type, false);
+}
+
 /*
  * VM Virtual Address Allocate
  *
@@ -1576,6 +1598,8 @@ void *addr_gpa2hva(struct kvm_vm *vm, vm_paddr_t gpa)
 {
        struct userspace_mem_region *region;
 
+       gpa = vm_untag_gpa(vm, gpa);
+
        region = userspace_mem_region_find(vm, gpa, gpa);
        if (!region) {
                TEST_FAIL("No vm physical memory at 0x%lx", gpa);
@@ -1922,6 +1946,10 @@ void vm_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent)
                        region->host_mem);
                fprintf(stream, "%*sunused_phy_pages: ", indent + 2, "");
                sparsebit_dump(stream, region->unused_phy_pages, 0);
+               if (region->protected_phy_pages) {
+                       fprintf(stream, "%*sprotected_phy_pages: ", indent + 2, "");
+                       sparsebit_dump(stream, region->protected_phy_pages, 0);
+               }
        }
        fprintf(stream, "%*sMapped Virtual Pages:\n", indent, "");
        sparsebit_dump(stream, vm->vpages_mapped, indent + 2);
@@ -2023,6 +2051,7 @@ const char *exit_reason_str(unsigned int exit_reason)
  *   num - number of pages
  *   paddr_min - Physical address minimum
  *   memslot - Memory region to allocate page from
+ *   protected - True if the pages will be used as protected/private memory
  *
  * Output Args: None
  *
@@ -2034,8 +2063,9 @@ 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 paddr_min.
  */
-vm_paddr_t vm_phy_pages_alloc(struct kvm_vm *vm, size_t num,
-                             vm_paddr_t paddr_min, uint32_t memslot)
+vm_paddr_t __vm_phy_pages_alloc(struct kvm_vm *vm, size_t num,
+                               vm_paddr_t paddr_min, uint32_t memslot,
+                               bool protected)
 {
        struct userspace_mem_region *region;
        sparsebit_idx_t pg, base;
@@ -2048,8 +2078,10 @@ vm_paddr_t vm_phy_pages_alloc(struct kvm_vm *vm, size_t num,
                paddr_min, vm->page_size);
 
        region = memslot2region(vm, memslot);
-       base = pg = paddr_min >> vm->page_shift;
+       TEST_ASSERT(!protected || region->protected_phy_pages,
+                   "Region doesn't support protected memory");
 
+       base = pg = paddr_min >> vm->page_shift;
        do {
                for (; pg < base + num; ++pg) {
                        if (!sparsebit_is_set(region->unused_phy_pages, pg)) {
@@ -2068,8 +2100,11 @@ vm_paddr_t vm_phy_pages_alloc(struct kvm_vm *vm, size_t num,
                abort();
        }
 
-       for (pg = base; pg < base + num; ++pg)
+       for (pg = base; pg < base + num; ++pg) {
                sparsebit_clear(region->unused_phy_pages, pg);
+               if (protected)
+                       sparsebit_set(region->protected_phy_pages, pg);
+       }
 
        return base * vm->page_size;
 }
@@ -2273,3 +2308,18 @@ void __attribute((constructor)) kvm_selftest_init(void)
 
        kvm_selftest_arch_init();
 }
+
+bool vm_is_gpa_protected(struct kvm_vm *vm, vm_paddr_t paddr)
+{
+       sparsebit_idx_t pg = 0;
+       struct userspace_mem_region *region;
+
+       if (!vm_arch_has_protected_memory(vm))
+               return false;
+
+       region = userspace_mem_region_find(vm, paddr, paddr);
+       TEST_ASSERT(region, "No vm physical memory at 0x%lx", paddr);
+
+       pg = paddr >> vm->page_shift;
+       return sparsebit_is_set(region->protected_phy_pages, pg);
+}
This page took 0.035509 seconds and 4 git commands to generate.