From 55b7fae67afc622b5b3f863f98d58c60b252ff08 Mon Sep 17 00:00:00 2001 From: Tao Yuhong Date: Mon, 21 Sep 2020 06:06:21 -0400 Subject: [PATCH] HV: pci-vuart: pci based vuart emulation Add emulation for pci based vuart device mcs9900 at hv land. add struct pci_vdev_ops vuart_pci_ops, the vdev callbalks for vuart. How to use In misc/vm_configs/scenarios///pci_dev.c, add pci vuart config to vm_pci_devs[] array. For example: struct acrn_vm_pci_dev_config vm0_pci_devs[] = { /* console vuart setting*/ { .emu_type = PCI_DEV_TYPE_HVEMUL, .vbdf.bits = {.b = 0x00U, .d = 0x04U, .f = 0x00U}, .vdev_ops = &vmcs_ops, .vbar_base[0] = 0x80001000, /* mmio bar */ .vbar_base[1] = 0x80002000, /* msix bar */ .vuart_idx = 0, }, /* communication vuart setting */ { .emu_type = PCI_DEV_TYPE_HVEMUL, .vbdf.bits = {.b = 0x00U, .d = 0x05U, .f = 0x00U}, .vdev_ops = &vmcs_ops, .vbar_base[0] = 0x80003000, .vbar_base[1] = 0x80004000, .vuart_idx = 1, .t_vuart.vm_id = 1U, .t_vuart.vuart_id = 1U, }, } Tracked-On: #5394 Signed-off-by: Tao Yuhong Reviewed-by: Wang, Yu1 Acked-by: Eddie Dong --- hypervisor/Makefile | 1 + hypervisor/dm/vpci/vmcs9900.c | 152 +++++++++++++++++++++++++++++++ hypervisor/include/dm/vmcs9900.h | 15 +++ hypervisor/include/hw/pci.h | 3 + misc/hv_prebuild/vm_cfg_checks.c | 2 + 5 files changed, 173 insertions(+) create mode 100644 hypervisor/dm/vpci/vmcs9900.c create mode 100644 hypervisor/include/dm/vmcs9900.h diff --git a/hypervisor/Makefile b/hypervisor/Makefile index 890245b8f..1f288e70c 100644 --- a/hypervisor/Makefile +++ b/hypervisor/Makefile @@ -309,6 +309,7 @@ VP_DM_C_SRCS += dm/vpci/vmsi.c VP_DM_C_SRCS += dm/vpci/vmsix.c VP_DM_C_SRCS += dm/vpci/vmsix_on_msi.c VP_DM_C_SRCS += dm/vpci/vsriov.c +VP_DM_C_SRCS += dm/vpci/vmcs9900.c VP_DM_C_SRCS += dm/mmio_dev.c VP_DM_C_SRCS += dm/vgpio.c VP_DM_C_SRCS += arch/x86/guest/vlapic.c diff --git a/hypervisor/dm/vpci/vmcs9900.c b/hypervisor/dm/vpci/vmcs9900.c new file mode 100644 index 000000000..b27afe314 --- /dev/null +++ b/hypervisor/dm/vpci/vmcs9900.c @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2020 Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include "vpci_priv.h" + +#define MCS9900_MMIO_BAR 0U +#define MCS9900_MSIX_BAR 1U + +static int32_t read_vmcs9900_cfg(const struct pci_vdev *vdev, + uint32_t offset, uint32_t bytes, + uint32_t * val) +{ + if (vbar_access(vdev, offset)) { + *val = pci_vdev_read_vbar(vdev, pci_bar_index(offset)); + } else { + *val = pci_vdev_read_vcfg(vdev, offset, bytes); + } + + return 0; +} + +static int32_t vmcs9900_mmio_handler(struct io_request *io_req, void *data) +{ + struct mmio_request *mmio = &io_req->reqs.mmio; + struct pci_vdev *vdev = (struct pci_vdev *)data; + struct acrn_vuart *vu = vdev->priv_data; + struct pci_vbar *vbar = &vdev->vbars[MCS9900_MMIO_BAR]; + uint16_t offset; + + offset = mmio->address - vbar->base_gpa; + + if (mmio->direction == REQUEST_READ) { + mmio->value = vuart_read_reg(vu, offset); + } else { + vuart_write_reg(vu, offset, (uint8_t) mmio->value); + } + return 0; +} + +static void map_vmcs9900_vbar(struct pci_vdev *vdev, uint32_t idx) +{ + struct acrn_vuart *vu = vdev->priv_data; + struct acrn_vm *vm = vpci2vm(vdev->vpci); + struct pci_vbar *vbar = &vdev->vbars[idx]; + + if ((idx == MCS9900_MMIO_BAR) && (vbar->base_gpa != 0UL)) { + register_mmio_emulation_handler(vm, vmcs9900_mmio_handler, + vbar->base_gpa, vbar->base_gpa + vbar->size, vdev, false); + ept_del_mr(vm, (uint64_t *)vm->arch_vm.nworld_eptp, vbar->base_gpa, vbar->size); + vu->active = true; + } else if ((idx == MCS9900_MSIX_BAR) && (vbar->base_gpa != 0UL)) { + register_mmio_emulation_handler(vm, vmsix_handle_table_mmio_access, vbar->base_gpa, + (vbar->base_gpa + vbar->size), vdev, false); + ept_del_mr(vm, (uint64_t *)vm->arch_vm.nworld_eptp, vbar->base_gpa, vbar->size); + vdev->msix.mmio_gpa = vbar->base_gpa; + } + +} + +static void unmap_vmcs9900_vbar(struct pci_vdev *vdev, uint32_t idx) +{ + struct acrn_vuart *vu = vdev->priv_data; + struct acrn_vm *vm = vpci2vm(vdev->vpci); + struct pci_vbar *vbar = &vdev->vbars[idx]; + + if ((idx == MCS9900_MMIO_BAR) && (vbar->base_gpa != 0UL)) { + vu->active = false; + } + unregister_mmio_emulation_handler(vm, vbar->base_gpa, vbar->base_gpa + vbar->size); +} + +static int32_t write_vmcs9900_cfg(struct pci_vdev *vdev, uint32_t offset, + uint32_t bytes, uint32_t val) +{ + if (vbar_access(vdev, offset)) { + vpci_update_one_vbar(vdev, pci_bar_index(offset), val, + map_vmcs9900_vbar, unmap_vmcs9900_vbar); + } else if (msixcap_access(vdev, offset)) { + write_vmsix_cap_reg(vdev, offset, bytes, val); + } else { + pci_vdev_write_vcfg(vdev, offset, bytes, val); + } + + return 0; +} + +static void init_vmcs9900(struct pci_vdev *vdev) +{ + struct acrn_vm_pci_dev_config *pci_cfg = vdev->pci_dev_config; + struct acrn_vm *vm = vpci2vm(vdev->vpci); + struct pci_vbar *mmio_vbar = &vdev->vbars[MCS9900_MMIO_BAR]; + struct pci_vbar *msix_vbar = &vdev->vbars[MCS9900_MSIX_BAR]; + struct acrn_vuart *vu = &vm->vuart[pci_cfg->vuart_idx]; + + /* 8250-pci compartiable device */ + pci_vdev_write_vcfg(vdev, PCIR_VENDOR, 2U, MCS9900_VENDOR); + pci_vdev_write_vcfg(vdev, PCIR_DEVICE, 2U, MCS9900_DEV); + pci_vdev_write_vcfg(vdev, PCIR_CLASS, 1U, PCIC_SIMPLECOMM); + pci_vdev_write_vcfg(vdev, PCIV_SUB_SYSTEM_ID, 2U, 0x1000U); + pci_vdev_write_vcfg(vdev, PCIV_SUB_VENDOR_ID, 2U, 0xa000U); + pci_vdev_write_vcfg(vdev, PCIR_SUBCLASS, 1U, 0x0U); + pci_vdev_write_vcfg(vdev, PCIR_CLASS_CODE, 1U, 0x2U); + + add_vmsix_capability(vdev, 1, MCS9900_MSIX_BAR); + + /* initialize vuart-pci mem bar */ + mmio_vbar->type = PCIBAR_MEM32; + mmio_vbar->size = 0x1000U; + mmio_vbar->base_gpa = pci_cfg->vbar_base[MCS9900_MMIO_BAR]; + mmio_vbar->mask = (uint32_t) (~(mmio_vbar->size - 1UL)); + mmio_vbar->fixed = (uint32_t) (mmio_vbar->base_gpa & PCI_BASE_ADDRESS_MEM_MASK); + + /* initialize vuart-pci msix bar */ + msix_vbar->type = PCIBAR_MEM32; + msix_vbar->size = 0x1000U; + msix_vbar->base_gpa = pci_cfg->vbar_base[MCS9900_MSIX_BAR]; + msix_vbar->mask = (uint32_t) (~(msix_vbar->size - 1UL)); + msix_vbar->fixed = (uint32_t) (msix_vbar->base_gpa & PCI_BASE_ADDRESS_MEM_MASK); + + vdev->nr_bars = 2; + + pci_vdev_write_vbar(vdev, MCS9900_MMIO_BAR, mmio_vbar->base_gpa); + pci_vdev_write_vbar(vdev, MCS9900_MSIX_BAR, msix_vbar->base_gpa); + + /* init acrn_vuart */ + pr_info("init acrn_vuart[%d]", pci_cfg->vuart_idx); + vdev->priv_data = vu; + init_pci_vuart(vdev); + + vdev->user = vdev; +} + +static void deinit_vmcs9900(struct pci_vdev *vdev) +{ + deinit_pci_vuart(vdev); + vdev->user = NULL; +} + +const struct pci_vdev_ops vmcs9900_ops = { + .init_vdev = init_vmcs9900, + .deinit_vdev = deinit_vmcs9900, + .write_vdev_cfg = write_vmcs9900_cfg, + .read_vdev_cfg = read_vmcs9900_cfg, +}; diff --git a/hypervisor/include/dm/vmcs9900.h b/hypervisor/include/dm/vmcs9900.h new file mode 100644 index 000000000..16e658c2a --- /dev/null +++ b/hypervisor/include/dm/vmcs9900.h @@ -0,0 +1,15 @@ +/* + * Copyright (C) 2020 Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef VMCS9900_H +#define VMCS9900_H + +#define MCS9900_VENDOR 0x9710U +#define MCS9900_DEV 0x9900U + +extern const struct pci_vdev_ops vmcs9900_ops; + +#endif diff --git a/hypervisor/include/hw/pci.h b/hypervisor/include/hw/pci.h index d6cc5dae5..761b7d6d0 100644 --- a/hypervisor/include/hw/pci.h +++ b/hypervisor/include/hw/pci.h @@ -74,6 +74,7 @@ #define PCIR_STATUS 0x06U #define PCIM_STATUS_CAPPRESENT 0x0010U #define PCIR_REVID 0x08U +#define PCIR_CLASS_CODE 0x09U #define PCIR_SUBCLASS 0x0AU #define PCIR_CLASS 0x0BU #define PCIR_HDRTYPE 0x0EU @@ -91,6 +92,7 @@ #define PCIM_BAR_MEM_64 0x04U #define PCIM_BAR_MEM_BASE 0xFFFFFFF0U #define PCIV_SUB_VENDOR_ID 0x2CU +#define PCIV_SUB_SYSTEM_ID 0x2EU #define PCIR_CAP_PTR 0x34U #define PCIR_CAP_PTR_CARDBUS 0x14U #define PCI_BASE_ADDRESS_MEM_MASK (~0x0fUL) @@ -98,6 +100,7 @@ #define PCIR_INTERRUPT_LINE 0x3cU #define PCIR_INTERRUPT_PIN 0x3dU +#define PCIC_SIMPLECOMM 0x07U /* config registers for header type 1 (PCI-to-PCI bridge) devices */ #define PCIR_PRIBUS_1 0x18U #define PCIR_SECBUS_1 0x19U diff --git a/misc/hv_prebuild/vm_cfg_checks.c b/misc/hv_prebuild/vm_cfg_checks.c index 31ae9a6e4..4c73fccaf 100644 --- a/misc/hv_prebuild/vm_cfg_checks.c +++ b/misc/hv_prebuild/vm_cfg_checks.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -23,6 +24,7 @@ static uint8_t safety_vm_uuid1[16] = SAFETY_VM_UUID1; struct acrn_vm_pci_dev_config sos_pci_devs[CONFIG_MAX_PCI_DEV_NUM]; const struct pci_vdev_ops vhostbridge_ops; const struct pci_vdev_ops vpci_ivshmem_ops; +const struct pci_vdev_ops vmcs9900_ops; #define PLATFORM_CPUS_MASK ((1UL << MAX_PCPU_NUM) - 1UL)