lkml.org 
[lkml]   [2021]   [Dec]   [16]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v2 03/13] KVM: selftests: add hooks for managing encrypted guest memory
    Date
    VM implementations that make use of encrypted memory need a way to
    configure things like the encryption/shared bit position for page
    table handling, the default encryption policy for internal allocations
    made by the core library, and a way to fetch the list/bitmap of
    encrypted pages to do the actual memory encryption. Add an interface to
    configure these parameters. Also introduce a sparsebit map to track
    allocations/mappings that should be treated as encrypted, and provide
    a way for VM implementations to retrieve it to handle operations
    related memory encryption.

    Reviewed-by: Mingwei Zhang <mizhang@google.com>
    Signed-off-by: Michael Roth <michael.roth@amd.com>
    ---
    .../selftests/kvm/include/kvm_util_base.h | 7 +++
    tools/testing/selftests/kvm/lib/kvm_util.c | 52 +++++++++++++++++--
    .../selftests/kvm/lib/kvm_util_internal.h | 10 ++++
    3 files changed, 66 insertions(+), 3 deletions(-)

    diff --git a/tools/testing/selftests/kvm/include/kvm_util_base.h b/tools/testing/selftests/kvm/include/kvm_util_base.h
    index 4e2946ba3ff7..58856339210a 100644
    --- a/tools/testing/selftests/kvm/include/kvm_util_base.h
    +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h
    @@ -365,4 +365,11 @@ int vcpu_get_stats_fd(struct kvm_vm *vm, uint32_t vcpuid);

    uint32_t guest_get_vcpuid(void);

    +void vm_set_memory_encryption(struct kvm_vm *vm, bool enc_by_default, bool has_enc_bit,
    + uint8_t enc_bit);
    +
    +const struct sparsebit *vm_get_encrypted_phy_pages(struct kvm_vm *vm, int slot,
    + vm_paddr_t *gpa_start,
    + uint64_t *size);
    +
    #endif /* SELFTEST_KVM_UTIL_BASE_H */
    diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c
    index f0f0250847f3..dfedf82207e1 100644
    --- a/tools/testing/selftests/kvm/lib/kvm_util.c
    +++ b/tools/testing/selftests/kvm/lib/kvm_util.c
    @@ -626,6 +626,7 @@ static void __vm_mem_region_delete(struct kvm_vm *vm,
    "rc: %i errno: %i", ret, errno);

    sparsebit_free(&region->unused_phy_pages);
    + sparsebit_free(&region->encrypted_phy_pages);
    ret = munmap(region->mmap_start, region->mmap_size);
    TEST_ASSERT(ret == 0, "munmap failed, rc: %i errno: %i", ret, errno);

    @@ -932,6 +933,7 @@ void vm_userspace_mem_region_add(struct kvm_vm *vm,
    }

    region->unused_phy_pages = sparsebit_alloc();
    + region->encrypted_phy_pages = sparsebit_alloc();
    sparsebit_set_num(region->unused_phy_pages,
    guest_paddr >> vm->page_shift, npages);
    region->region.slot = slot;
    @@ -1161,6 +1163,7 @@ void vm_vcpu_add(struct kvm_vm *vm, uint32_t vcpuid)
    * num - number of pages
    * paddr_min - Physical address minimum
    * memslot - Memory region to allocate page from
    + * encrypt - Whether to treat the pages as encrypted
    *
    * Output Args: None
    *
    @@ -1172,8 +1175,9 @@ void vm_vcpu_add(struct kvm_vm *vm, uint32_t vcpuid)
    * 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)
    +static vm_paddr_t
    +_vm_phy_pages_alloc(struct kvm_vm *vm, size_t num, vm_paddr_t paddr_min,
    + uint32_t memslot, bool encrypt)
    {
    struct userspace_mem_region *region;
    sparsebit_idx_t pg, base;
    @@ -1206,12 +1210,22 @@ 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 (encrypt)
    + sparsebit_set(region->encrypted_phy_pages, pg);
    + }

    return base * vm->page_size;
    }

    +vm_paddr_t vm_phy_pages_alloc(struct kvm_vm *vm, size_t num,
    + vm_paddr_t paddr_min, uint32_t memslot)
    +{
    + return _vm_phy_pages_alloc(vm, num, paddr_min, memslot,
    + vm->memcrypt.enc_by_default);
    +}
    +
    vm_paddr_t vm_phy_page_alloc(struct kvm_vm *vm, vm_paddr_t paddr_min,
    uint32_t memslot)
    {
    @@ -2192,6 +2206,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 (vm->memcrypt.enabled) {
    + fprintf(stream, "%*sencrypted_phy_pages: ", indent + 2, "");
    + sparsebit_dump(stream, region->encrypted_phy_pages, 0);
    + }
    }
    fprintf(stream, "%*sMapped Virtual Pages:\n", indent, "");
    sparsebit_dump(stream, vm->vpages_mapped, indent + 2);
    @@ -2389,3 +2407,31 @@ int vcpu_get_stats_fd(struct kvm_vm *vm, uint32_t vcpuid)

    return ioctl(vcpu->fd, KVM_GET_STATS_FD, NULL);
    }
    +
    +void vm_set_memory_encryption(struct kvm_vm *vm, bool enc_by_default, bool has_enc_bit,
    + uint8_t enc_bit)
    +{
    + vm->memcrypt.enabled = true;
    + vm->memcrypt.enc_by_default = enc_by_default;
    + vm->memcrypt.has_enc_bit = has_enc_bit;
    + vm->memcrypt.enc_bit = enc_bit;
    +}
    +
    +const struct sparsebit *
    +vm_get_encrypted_phy_pages(struct kvm_vm *vm, int slot, vm_paddr_t *gpa_start,
    + uint64_t *size)
    +{
    + struct userspace_mem_region *region;
    +
    + if (!vm->memcrypt.enabled)
    + return NULL;
    +
    + region = memslot2region(vm, slot);
    + if (!region)
    + return NULL;
    +
    + *size = region->region.memory_size;
    + *gpa_start = region->region.guest_phys_addr;
    +
    + return region->encrypted_phy_pages;
    +}
    diff --git a/tools/testing/selftests/kvm/lib/kvm_util_internal.h b/tools/testing/selftests/kvm/lib/kvm_util_internal.h
    index a03febc24ba6..99ccab86115c 100644
    --- a/tools/testing/selftests/kvm/lib/kvm_util_internal.h
    +++ b/tools/testing/selftests/kvm/lib/kvm_util_internal.h
    @@ -16,6 +16,7 @@
    struct userspace_mem_region {
    struct kvm_userspace_memory_region region;
    struct sparsebit *unused_phy_pages;
    + struct sparsebit *encrypted_phy_pages;
    int fd;
    off_t offset;
    void *host_mem;
    @@ -44,6 +45,14 @@ struct userspace_mem_regions {
    DECLARE_HASHTABLE(slot_hash, 9);
    };

    +/* Memory encryption policy/configuration. */
    +struct vm_memcrypt {
    + bool enabled;
    + int8_t enc_by_default;
    + bool has_enc_bit;
    + int8_t enc_bit;
    +};
    +
    struct kvm_vm {
    int mode;
    unsigned long type;
    @@ -67,6 +76,7 @@ struct kvm_vm {
    vm_vaddr_t idt;
    vm_vaddr_t handlers;
    uint32_t dirty_ring_size;
    + struct vm_memcrypt memcrypt;
    };

    struct vcpu *vcpu_find(struct kvm_vm *vm, uint32_t vcpuid);
    --
    2.25.1
    \
     
     \ /
      Last update: 2021-12-16 18:18    [W:3.290 / U:0.256 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site