From f81b39225ca87059875ac43e39f9656b86bb5c61 Mon Sep 17 00:00:00 2001 From: Fei Li Date: Fri, 6 Aug 2021 10:11:34 +0800 Subject: [PATCH] HV: refine acrn_mmiodev data structure 1. add a name field to indicate what the MMIO Device is. 2. add two more MMIO resource to the acrn_mmiodev data structure. Tracked-On: #6366 Signed-off-by: Tao Yuhong Signed-off-by: Fei Li --- devicemodel/hw/mmio/core.c | 24 +++++---- hypervisor/arch/x86/guest/vm.c | 5 ++ hypervisor/common/hypercall.c | 16 +++--- hypervisor/dm/mmio_dev.c | 50 +++++++++++++------ hypervisor/dm/vgpio.c | 2 +- hypervisor/include/public/acrn_common.h | 22 +++++--- .../scenario_config/vm_configurations_c.py | 4 +- 7 files changed, 76 insertions(+), 47 deletions(-) diff --git a/devicemodel/hw/mmio/core.c b/devicemodel/hw/mmio/core.c index 7789f39ec..0fa4b50f1 100644 --- a/devicemodel/hw/mmio/core.c +++ b/devicemodel/hw/mmio/core.c @@ -73,13 +73,15 @@ int parse_pt_acpidev(char *opt) /* TODO: support acpi dev framework, remove these TPM hard code */ if (strncmp(opt, "MSFT0101", 8) == 0) { strncpy(mmio_devs[mmio_dev_idx].name, "MSFT0101", 8); + + strncpy(mmio_devs[mmio_dev_idx].dev.name, "tpm2", 4); /* TODO: We would parse the /proc/iomem to get the corresponding resources */ - mmio_devs[mmio_dev_idx].dev.service_vm_pa = 0xFED40000UL; + mmio_devs[mmio_dev_idx].dev.res[0].host_pa = 0xFED40000UL; /* FIXME: The 0xFED40000 doesn't conflict with other mmio or system memory so far. * This need to be fixed by redesign the mmio_dev_alloc_gpa_resource32(). */ - mmio_devs[mmio_dev_idx].dev.user_vm_pa = 0xFED40000UL; - mmio_devs[mmio_dev_idx].dev.size = 0x00005000UL; + mmio_devs[mmio_dev_idx].dev.res[0].user_vm_pa = 0xFED40000UL; + mmio_devs[mmio_dev_idx].dev.res[0].size = 0x00005000UL; mmio_dev_idx++; pt_tpm2 = true; } @@ -103,8 +105,8 @@ int parse_pt_mmiodev(char *opt) (!dm_strtoul(cp + 1, &cp, 16, &size))) { pr_dbg("%s pt mmiodev base: 0x%lx, size: 0x%lx\n", __func__, base_hpa, size); strncpy(mmio_devs[mmio_dev_idx].name, pt_mmiodev.name, 8); - mmio_devs[mmio_dev_idx].dev.service_vm_pa = base_hpa; - mmio_devs[mmio_dev_idx].dev.size = size; + mmio_devs[mmio_dev_idx].dev.res[0].host_pa = base_hpa; + mmio_devs[mmio_dev_idx].dev.res[0].size = size; mmio_dev_idx++; } else { pr_err("%s, %s invalid, please check!\n", __func__, opt); @@ -131,14 +133,14 @@ int init_mmio_dev(struct vmctx *ctx, struct mmio_dev_ops *ops, struct acrn_mmiod int ret; uint32_t base; - if (mmiodev->user_vm_pa == 0UL) { + if (mmiodev->res[0].user_vm_pa == 0UL) { /* FIXME: The mmio_dev_alloc_gpa_resource32 needs to add one new parameter to indicate * if the caller needs one specific GPA instead of dynamic allocation. */ - ret = mmio_dev_alloc_gpa_resource32(&base, mmiodev->size); + ret = mmio_dev_alloc_gpa_resource32(&base, mmiodev->res[0].size); if (ret < 0) return ret; - mmiodev->user_vm_pa = base; + mmiodev->res[0].user_vm_pa = base; } return ops->init(ctx, mmiodev); @@ -159,8 +161,8 @@ int init_mmio_devs(struct vmctx *ctx) if (ops != NULL) { err = init_mmio_dev(ctx, ops, &mmio_devs[i].dev); pr_notice("mmiodev[%d] hpa:0x%x gpa:0x%x size:0x%x err:%d\n", i, - mmio_devs[i].dev.service_vm_pa, mmio_devs[i].dev.user_vm_pa, - mmio_devs[i].dev.size, err); + mmio_devs[i].dev.res[0].host_pa, mmio_devs[i].dev.res[0].user_vm_pa, + mmio_devs[i].dev.res[0].size, err); } if (err != 0) @@ -220,7 +222,7 @@ uint64_t get_mmio_dev_tpm2_base_gpa(void) for (i = 0; i < mmio_dev_idx; i++) { if (!strcmp(mmio_devs[i].name, "MSFT0101")) { - base_gpa = mmio_devs[i].dev.user_vm_pa; + base_gpa = mmio_devs[i].dev.res[0].user_vm_pa; break; } } diff --git a/hypervisor/arch/x86/guest/vm.c b/hypervisor/arch/x86/guest/vm.c index 74d2a775c..6d8068cd7 100644 --- a/hypervisor/arch/x86/guest/vm.c +++ b/hypervisor/arch/x86/guest/vm.c @@ -291,6 +291,11 @@ static void prepare_prelaunched_vm_memmap(struct acrn_vm *vm, const struct acrn_ } for (i = 0U; i < MAX_MMIO_DEV_NUM; i++) { + /* Now we include the TPM2 event log region in ACPI NVS, so we need to + * delete this potential mapping first. + */ + (void)deassign_mmio_dev(vm, &vm_config->mmiodevs[i]); + (void)assign_mmio_dev(vm, &vm_config->mmiodevs[i]); #ifdef P2SB_VGPIO_DM_ENABLED diff --git a/hypervisor/common/hypercall.c b/hypervisor/common/hypercall.c index f3b28b702..d01aef17e 100644 --- a/hypervisor/common/hypercall.c +++ b/hypervisor/common/hypercall.c @@ -925,11 +925,9 @@ int32_t hcall_assign_mmiodev(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm, /* We should only assign a device to a post-launched VM at creating time for safety, not runtime or other cases*/ if (is_created_vm(target_vm)) { if (copy_from_gpa(vm, &mmiodev, param2, sizeof(mmiodev)) == 0) { - if (ept_is_valid_mr(vm, mmiodev.service_vm_pa, mmiodev.size)) { - ret = deassign_mmio_dev(vm, &mmiodev); - if (ret == 0) { - ret = assign_mmio_dev(target_vm, &mmiodev); - } + ret = deassign_mmio_dev(vm, &mmiodev); + if (ret == 0) { + ret = assign_mmio_dev(target_vm, &mmiodev); } } } else { @@ -960,11 +958,9 @@ int32_t hcall_deassign_mmiodev(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm /* We should only de-assign a device from a post-launched VM at creating/shutdown/reset time */ if ((is_paused_vm(target_vm) || is_created_vm(target_vm))) { if (copy_from_gpa(vm, &mmiodev, param2, sizeof(mmiodev)) == 0) { - if (ept_is_valid_mr(target_vm, mmiodev.user_vm_pa, mmiodev.size)) { - ret = deassign_mmio_dev(target_vm, &mmiodev); - if (ret == 0) { - ret = assign_mmio_dev(vm, &mmiodev); - } + ret = deassign_mmio_dev(target_vm, &mmiodev); + if (ret == 0) { + ret = assign_mmio_dev(vm, &mmiodev); } } } else { diff --git a/hypervisor/dm/mmio_dev.c b/hypervisor/dm/mmio_dev.c index 41bb4bf75..75ec9bcb7 100644 --- a/hypervisor/dm/mmio_dev.c +++ b/hypervisor/dm/mmio_dev.c @@ -10,18 +10,28 @@ #include #include #include +#include + int32_t assign_mmio_dev(struct acrn_vm *vm, const struct acrn_mmiodev *mmiodev) { - int32_t ret = -EINVAL; + int32_t i, ret = 0; + const struct acrn_mmiores *res; - if (mem_aligned_check(mmiodev->user_vm_pa, PAGE_SIZE) && - mem_aligned_check(mmiodev->service_vm_pa, PAGE_SIZE) && - mem_aligned_check(mmiodev->size, PAGE_SIZE)) { - ept_add_mr(vm, (uint64_t *)vm->arch_vm.nworld_eptp, mmiodev->service_vm_pa, - is_sos_vm(vm) ? mmiodev->service_vm_pa: mmiodev->user_vm_pa, - mmiodev->size, EPT_RWX | EPT_UNCACHED); - ret = 0; + for (i = 0; i < MMIODEV_RES_NUM; i++) { + res = &mmiodev->res[i]; + if (mem_aligned_check(res->user_vm_pa, PAGE_SIZE) && + mem_aligned_check(res->host_pa, PAGE_SIZE) && + mem_aligned_check(res->size, PAGE_SIZE)) { + ept_add_mr(vm, (uint64_t *)vm->arch_vm.nworld_eptp, res->host_pa, + is_sos_vm(vm) ? res->host_pa : res->user_vm_pa, + res->size, EPT_RWX | (res->mem_type & EPT_MT_MASK)); + } else { + pr_err("%s invalid mmio res[%d] gpa:0x%lx hpa:0x%lx size:0x%lx", + __FUNCTION__, i, res->user_vm_pa, res->host_pa, res->size); + ret = -EINVAL; + break; + } } return ret; @@ -29,14 +39,24 @@ int32_t assign_mmio_dev(struct acrn_vm *vm, const struct acrn_mmiodev *mmiodev) int32_t deassign_mmio_dev(struct acrn_vm *vm, const struct acrn_mmiodev *mmiodev) { - int32_t ret = -EINVAL; + int32_t i, ret = 0; + uint64_t gpa; + const struct acrn_mmiores *res; - if (mem_aligned_check(mmiodev->user_vm_pa, PAGE_SIZE) && - mem_aligned_check(mmiodev->service_vm_pa, PAGE_SIZE) && - mem_aligned_check(mmiodev->size, PAGE_SIZE)) { - ept_del_mr(vm, (uint64_t *)vm->arch_vm.nworld_eptp, - is_sos_vm(vm) ? mmiodev->service_vm_pa: mmiodev->user_vm_pa, mmiodev->size); - ret = 0; + for (i = 0; i < MMIODEV_RES_NUM; i++) { + res = &mmiodev->res[i]; + gpa = is_sos_vm(vm) ? res->host_pa : res->user_vm_pa; + if (ept_is_valid_mr(vm, gpa, res->size)) { + if (mem_aligned_check(gpa, PAGE_SIZE) && + mem_aligned_check(res->size, PAGE_SIZE)) { + ept_del_mr(vm, (uint64_t *)vm->arch_vm.nworld_eptp, gpa, res->size); + } else { + pr_err("%s invalid mmio res[%d] gpa:0x%lx hpa:0x%lx size:0x%lx", + __FUNCTION__, i, res->user_vm_pa, res->host_pa, res->size); + ret = -EINVAL; + break; + } + } } return ret; diff --git a/hypervisor/dm/vgpio.c b/hypervisor/dm/vgpio.c index e2e3b23f9..c58027e7a 100644 --- a/hypervisor/dm/vgpio.c +++ b/hypervisor/dm/vgpio.c @@ -139,7 +139,7 @@ void register_vgpio_handler(struct acrn_vm *vm, const struct acrn_mmiodev *mmiod gpa_start = mmiodev->user_vm_pa + (P2SB_BASE_GPIO_PORT_ID << P2SB_PORTID_SHIFT); gpio_pcr_sz = P2SB_PCR_SPACE_SIZE_PER_AGENT * P2SB_MAX_GPIO_COMMUNITIES; gpa_end = gpa_start + gpio_pcr_sz; - base_hpa = mmiodev->service_vm_pa + (P2SB_BASE_GPIO_PORT_ID << P2SB_PORTID_SHIFT); + base_hpa = mmiodev->host_pa + (P2SB_BASE_GPIO_PORT_ID << P2SB_PORTID_SHIFT); /* emulate MMIO access to the GPIO private configuration space registers */ set_paging_supervisor((uint64_t)hpa2hva(base_hpa), gpio_pcr_sz); diff --git a/hypervisor/include/public/acrn_common.h b/hypervisor/include/public/acrn_common.h index 9f224bfe8..f1c60f31b 100644 --- a/hypervisor/include/public/acrn_common.h +++ b/hypervisor/include/public/acrn_common.h @@ -654,19 +654,25 @@ struct acrn_pcidev { uint32_t bar[ACRN_PCI_NUM_BARS]; }; +#define MMIODEV_RES_NUM 3 /** * @brief Info to assign or deassign a MMIO device for a VM */ struct acrn_mmiodev { - /** the gpa of the MMIO region for the MMIO device */ - uint64_t user_vm_pa; - - /** the hpa of the MMIO region for the MMIO device */ - uint64_t service_vm_pa; - - /** the size of the MMIO region for the MMIO device */ - uint64_t size; + char name[8]; + struct acrn_mmiores { + /** the gpa of the MMIO region for the MMIO device */ + uint64_t user_vm_pa; + /** the hpa of the MMIO region for the MMIO device: for post-launched VM + * it's pa in service vm; for pre-launched VM it's pa in HV. + */ + uint64_t host_pa; + /** the size of the MMIO region for the MMIO resource */ + uint64_t size; + /** the memory type of the MMIO region for the MMIO resource */ + uint64_t mem_type; + } res[MMIODEV_RES_NUM]; }; /** diff --git a/misc/config_tools/scenario_config/vm_configurations_c.py b/misc/config_tools/scenario_config/vm_configurations_c.py index b9d2361d3..22b140bb0 100644 --- a/misc/config_tools/scenario_config/vm_configurations_c.py +++ b/misc/config_tools/scenario_config/vm_configurations_c.py @@ -341,7 +341,7 @@ def gen_pre_launch_vm(vm_type, vm_i, scenario_items, config): print("\t\t.pt_tpm2 = true,", file=config) print("\t\t.mmiodevs[0] = {", file=config) print("\t\t\t.user_vm_pa = VM0_TPM_BUFFER_BASE_ADDR_GPA,", file=config) - print("\t\t\t.service_vm_pa = VM0_TPM_BUFFER_BASE_ADDR,", file=config) + print("\t\t\t.host_pa = VM0_TPM_BUFFER_BASE_ADDR,", file=config) print("\t\t\t.size = VM0_TPM_BUFFER_SIZE,", file=config) print("\t\t},", file=config) print("#endif", file=config) @@ -351,7 +351,7 @@ def gen_pre_launch_vm(vm_type, vm_i, scenario_items, config): print("\t\t.pt_p2sb_bar = true,", file=config) print("\t\t.mmiodevs[0] = {", file=config) print("\t\t\t.user_vm_pa = P2SB_BAR_ADDR_GPA,", file=config) - print("\t\t\t.service_vm_pa = P2SB_BAR_ADDR,", file=config) + print("\t\t\t.host_pa = P2SB_BAR_ADDR,", file=config) print("\t\t\t.size = P2SB_BAR_SIZE,", file=config) print("\t\t},", file=config) print("#endif", file=config)