From 3db4491e1c930982a5368a996c7904c31c8675c6 Mon Sep 17 00:00:00 2001 From: Rong Liu Date: Wed, 5 May 2021 23:38:22 +0000 Subject: [PATCH] hv: PTM: Create virtual root port Create virtual root port through add_vdev hypercall. add_vdev identifies the virtual device to add by its vendor id and device id, then call the corresponding function to create virtual device. -create_vrp(): Find the right virtual root port to create by its secondary bus number, then initialize the virtual root port. And finally initialize PTM related configurations. -destroy_vrp(): nothing to destroy Tracked-On: #5915 Signed-off-by: Rong Liu Acked-by: Eddie Dong Acked-by: Jason Chen Acked-by: Yu Wang --- hypervisor/common/hypercall.c | 2 + hypervisor/dm/vpci/vroot_port.c | 86 ++++++++++++++++++--- hypervisor/include/arch/x86/asm/vm_config.h | 2 +- hypervisor/include/dm/vroot_port.h | 13 ++-- hypervisor/include/hw/pci.h | 9 +++ 5 files changed, 95 insertions(+), 17 deletions(-) diff --git a/hypervisor/common/hypercall.c b/hypervisor/common/hypercall.c index 6bf323509..2cb7f8f9e 100644 --- a/hypervisor/common/hypercall.c +++ b/hypervisor/common/hypercall.c @@ -25,6 +25,7 @@ #include #include #include +#include "vroot_port.h" #define DBG_LEVEL_HYCALL 6U @@ -48,6 +49,7 @@ static struct emul_dev_ops emul_dev_ops_tbl[] = { {(IVSHMEM_VENDOR_ID | (IVSHMEM_DEVICE_ID << 16U)), NULL, NULL}, #endif {(MCS9900_VENDOR | (MCS9900_DEV << 16U)), create_vmcs9900_vdev, destroy_vmcs9900_vdev}, + {(VRP_VENDOR | (VRP_DEVICE << 16U)), create_vrp, destroy_vrp}, }; bool is_hypercall_from_ring0(void) diff --git a/hypervisor/dm/vpci/vroot_port.c b/hypervisor/dm/vpci/vroot_port.c index 5af7d7a69..f9acac45f 100644 --- a/hypervisor/dm/vpci/vroot_port.c +++ b/hypervisor/dm/vpci/vroot_port.c @@ -5,8 +5,10 @@ * */ +#include #include #include +#include #include "vroot_port.h" #include "vpci_priv.h" @@ -14,11 +16,11 @@ #define PCIE_CAP_VPOS 0x40 /* pcie capability reg position */ #define PTM_CAP_VPOS PCI_ECAP_BASE_PTR /* ptm capability reg postion */ -static void init_vroot_port(struct pci_vdev *vdev) +static void init_vrp(struct pci_vdev *vdev) { /* vendor and device */ - pci_vdev_write_vcfg(vdev, PCIR_VENDOR, 2U, VROOT_PORT_VENDOR); - pci_vdev_write_vcfg(vdev, PCIR_DEVICE, 2U, VROOT_PORT_DEVICE); + pci_vdev_write_vcfg(vdev, PCIR_VENDOR, 2U, VRP_VENDOR); + pci_vdev_write_vcfg(vdev, PCIR_DEVICE, 2U, VRP_DEVICE); /* status register */ pci_vdev_write_vcfg(vdev, PCIR_STATUS, 2U, PCIM_STATUS_CAPPRESENT); @@ -46,13 +48,13 @@ static void init_vroot_port(struct pci_vdev *vdev) vdev->user = vdev; } -static void deinit_vroot_port(__unused struct pci_vdev *vdev) +static void deinit_vrp(__unused struct pci_vdev *vdev) { vdev->parent_user = NULL; vdev->user = NULL; } -static int32_t read_vroot_port_cfg(const struct pci_vdev *vdev, uint32_t offset, +static int32_t read_vrp_cfg(const struct pci_vdev *vdev, uint32_t offset, uint32_t bytes, uint32_t *val) { *val = pci_vdev_read_vcfg(vdev, offset, bytes); @@ -60,7 +62,7 @@ static int32_t read_vroot_port_cfg(const struct pci_vdev *vdev, uint32_t offset, return 0; } -static int32_t write_vroot_port_cfg(__unused struct pci_vdev *vdev, __unused uint32_t offset, +static int32_t write_vrp_cfg(__unused struct pci_vdev *vdev, __unused uint32_t offset, __unused uint32_t bytes, __unused uint32_t val) { pci_vdev_write_vcfg(vdev, offset, bytes, val); @@ -68,9 +70,71 @@ static int32_t write_vroot_port_cfg(__unused struct pci_vdev *vdev, __unused uin return 0; } -const struct pci_vdev_ops vroot_port_ops = { - .init_vdev = init_vroot_port, - .deinit_vdev = deinit_vroot_port, - .write_vdev_cfg = write_vroot_port_cfg, - .read_vdev_cfg = read_vroot_port_cfg, +/* + * @pre vdev != NULL + * @pre vrp_config != NULL + */ +static void init_ptm(struct pci_vdev *vdev, struct vrp_config *vrp_config) +{ + /* ptm capability register */ + if (vrp_config->ptm_capable) + { + pci_vdev_write_vcfg(vdev, PTM_CAP_VPOS, PCI_PTM_CAP_LEN, 0x0001001f); + + pci_vdev_write_vcfg(vdev, PTM_CAP_VPOS + PCIR_PTM_CAP, PCI_PTM_CAP_LEN, 0x406); + + pci_vdev_write_vcfg(vdev, PTM_CAP_VPOS + PCIR_PTM_CTRL, PCI_PTM_CAP_LEN, 0x3); + } + + /* emulate bus numbers */ + pci_vdev_write_vcfg(vdev, PCIR_PRIBUS_1, 1U, 0x00); /* virtual root port always connects to host bridge */ + pci_vdev_write_vcfg(vdev, PCIR_SECBUS_1, 1U, vrp_config->secondary_bus); + pci_vdev_write_vcfg(vdev, PCIR_SUBBUS_1, 1U, vrp_config->subordinate_bus); +} + +int32_t create_vrp(struct acrn_vm *vm, struct acrn_emul_dev *dev) +{ + struct acrn_vm_config *vm_config = get_vm_config(vm->vm_id); + struct acrn_vm_pci_dev_config *dev_config = NULL; + struct pci_vdev *vdev; + struct vrp_config *vrp_config; + + int i; + + vrp_config = (struct vrp_config*)dev->args; + + pr_acrnlog("%s: virtual root port phy_bdf=0x%x, vbdf=0x%x, vendor_id=0x%x, dev_id=0x%x,\ + primary_bus=0x%x, secondary_bus=0x%x, sub_bus=0x%x.\n", + __func__, vrp_config->phy_bdf, dev->slot, + dev->dev_id.fields.vendor_id, dev->dev_id.fields.device_id, + vrp_config->primary_bus, vrp_config->secondary_bus, vrp_config->subordinate_bus); + + for (i = 0U; i < vm_config->pci_dev_num; i++) { + dev_config = &vm_config->pci_devs[i]; + if (dev_config->vrp_sec_bus == vrp_config->secondary_bus) { + dev_config->vbdf.value = dev->slot; + dev_config->pbdf.value = vrp_config->phy_bdf; + dev_config->vdev_ops = &vrp_ops; + + vdev = vpci_init_vdev(&vm->vpci, dev_config, NULL); + + init_ptm(vdev, vrp_config); + + break; + } + } + + return 0; +} + +int32_t destroy_vrp(__unused struct pci_vdev *vdev) +{ + return 0; +} + +const struct pci_vdev_ops vrp_ops = { + .init_vdev = init_vrp, + .deinit_vdev = deinit_vrp, + .write_vdev_cfg = write_vrp_cfg, + .read_vdev_cfg = read_vrp_cfg, }; diff --git a/hypervisor/include/arch/x86/asm/vm_config.h b/hypervisor/include/arch/x86/asm/vm_config.h index 295452dcd..faea5ba9c 100644 --- a/hypervisor/include/arch/x86/asm/vm_config.h +++ b/hypervisor/include/arch/x86/asm/vm_config.h @@ -153,7 +153,7 @@ struct acrn_vm_pci_dev_config { /* TODO: All device specific attributions need move to other place */ struct target_vuart t_vuart; uint16_t vuart_idx; - uint16_t vroot_port_idx; + uint16_t vrp_sec_bus; /* use virtual root port's secondary bus as unique identification */ uint64_t vbar_base[PCI_BAR_COUNT]; /* vbar base address of PCI device, which is power-on default value */ struct pci_pdev *pdev; /* the physical PCI device if it's a PT device */ const struct pci_vdev_ops *vdev_ops; /* operations for PCI CFG read/write */ diff --git a/hypervisor/include/dm/vroot_port.h b/hypervisor/include/dm/vroot_port.h index f1155b3dc..034af20db 100644 --- a/hypervisor/include/dm/vroot_port.h +++ b/hypervisor/include/dm/vroot_port.h @@ -5,14 +5,17 @@ * */ -#ifndef __VROOT_PORT_H -#define __VROOT_PORT_H +#ifndef __VRP_H +#define __VRP_H #include "vpci.h" -#define VROOT_PORT_VENDOR 0x8086U -#define VROOT_PORT_DEVICE 0x9d14U +#define VRP_VENDOR 0x8086U +#define VRP_DEVICE 0x9d14U -extern const struct pci_vdev_ops vroot_port_ops; +extern const struct pci_vdev_ops vrp_ops; + +int32_t create_vrp(struct acrn_vm *vm, struct acrn_emul_dev *dev); +int32_t destroy_vrp(struct pci_vdev *vdev); #endif diff --git a/hypervisor/include/hw/pci.h b/hypervisor/include/hw/pci.h index 5410aab28..3acc75b76 100644 --- a/hypervisor/include/hw/pci.h +++ b/hypervisor/include/hw/pci.h @@ -120,6 +120,7 @@ #define PCI_ECAP_ID(hdr) ((uint32_t)((hdr) & 0xFFFFU)) #define PCI_ECAP_NEXT(hdr) ((uint32_t)(((hdr) >> 20U) & 0xFFCU)) #define PCIZ_SRIOV 0x10U +#define PCIZ_PTM 0x1fU /* SRIOV Definitions */ #define PCI_SRIOV_CAP_LEN 0x40U @@ -132,6 +133,14 @@ #define PCIR_SRIOV_VF_BAR_OFF 0x24U #define PCIM_SRIOV_VF_ENABLE 0x1U +/* PTM Definitions */ +#define PCI_PTM_CAP_LEN 0x04U +#define PCIR_PTM_CAP 0x04U +#define PCIR_PTM_CTRL 0x08U +#define PCIM_PTM_CAP_ROOT_CAPABLE 0x4U +#define PCIM_PTM_CTRL_ENABLED 0x1U +#define PCIM_PTM_CTRL_ROOT_SELECTED 0x2U + /* PCI Message Signalled Interrupts (MSI) */ #define PCIR_MSI_CTRL 0x02U #define PCIM_MSICTRL_64BIT 0x80U