mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-16 02:38:33 +00:00
HV: deny HV owned PCI bar access from SOS
This patch denies Service VM the access permission to device resources owned by hypervisor. HV may own these devices: (1) debug uart pci device for debug version (2) type 1 pci device if have pre-launched VMs. Current implementation exposes the mmio/pio resource of HV owned devices to SOS, should remove them from SOS. Tracked-On: #5615 Signed-off-by: Tao Yuhong <yuhong.tao@intel.com>
This commit is contained in:
parent
6e7ce4a73f
commit
50d8525618
@ -64,7 +64,21 @@ struct acrn_vm_pci_dev_config *init_one_dev_config(struct pci_pdev *pdev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dev_config = &vm_config->pci_devs[vm_config->pci_dev_num];
|
dev_config = &vm_config->pci_devs[vm_config->pci_dev_num];
|
||||||
dev_config->emu_type = PCI_DEV_TYPE_PTDEV;
|
if (is_hv_owned_pdev(pdev->bdf)) {
|
||||||
|
/* SOS need to emulate the type1 pdevs owned by HV */
|
||||||
|
dev_config->emu_type = PCI_DEV_TYPE_SOSEMUL;
|
||||||
|
if (is_bridge(pdev)) {
|
||||||
|
dev_config->vdev_ops = &vpci_bridge_ops;
|
||||||
|
} else if (is_host_bridge(pdev)) {
|
||||||
|
dev_config->vdev_ops = &vhostbridge_ops;
|
||||||
|
} else {
|
||||||
|
/* May have type0 device, E.g. debug pci uart */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dev_config->emu_type = PCI_DEV_TYPE_PTDEV;
|
||||||
|
}
|
||||||
|
|
||||||
dev_config->vbdf.value = pdev->bdf.value;
|
dev_config->vbdf.value = pdev->bdf.value;
|
||||||
dev_config->pbdf.value = pdev->bdf.value;
|
dev_config->pbdf.value = pdev->bdf.value;
|
||||||
dev_config->pdev = pdev;
|
dev_config->pdev = pdev;
|
||||||
|
@ -332,6 +332,17 @@ static void deny_pdevs(struct acrn_vm *sos, struct acrn_vm_pci_dev_config *pci_d
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void deny_hv_owned_devices(struct acrn_vm *sos)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
const struct pci_pdev **hv_owned = get_hv_owned_pdevs();
|
||||||
|
|
||||||
|
for (i = 0U; i < get_hv_owned_pdev_num(); i++) {
|
||||||
|
deny_pci_bar_access(sos, hv_owned[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param[inout] vm pointer to a vm descriptor
|
* @param[inout] vm pointer to a vm descriptor
|
||||||
*
|
*
|
||||||
@ -410,6 +421,8 @@ static void prepare_sos_vm_memmap(struct acrn_vm *vm)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deny_hv_owned_devices(vm);
|
||||||
|
|
||||||
/* unmap AP trampoline code for security
|
/* unmap AP trampoline code for security
|
||||||
* This buffer is guaranteed to be page aligned.
|
* This buffer is guaranteed to be page aligned.
|
||||||
*/
|
*/
|
||||||
|
@ -625,18 +625,7 @@ struct pci_vdev *vpci_init_vdev(struct acrn_vpci *vpci, struct acrn_vm_pci_dev_c
|
|||||||
if (dev_config->vdev_ops != NULL) {
|
if (dev_config->vdev_ops != NULL) {
|
||||||
vdev->vdev_ops = dev_config->vdev_ops;
|
vdev->vdev_ops = dev_config->vdev_ops;
|
||||||
} else {
|
} else {
|
||||||
if (get_highest_severity_vm(false) == vpci2vm(vpci)) {
|
vdev->vdev_ops = &pci_pt_dev_ops;
|
||||||
vdev->vdev_ops = &pci_pt_dev_ops;
|
|
||||||
} else {
|
|
||||||
if (is_bridge(vdev->pdev)) {
|
|
||||||
vdev->vdev_ops = &vpci_bridge_ops;
|
|
||||||
} else if (is_host_bridge(vdev->pdev)) {
|
|
||||||
vdev->vdev_ops = &vhostbridge_ops;
|
|
||||||
} else {
|
|
||||||
vdev->vdev_ops = &pci_pt_dev_ops;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(dev_config->emu_type == PCI_DEV_TYPE_PTDEV,
|
ASSERT(dev_config->emu_type == PCI_DEV_TYPE_PTDEV,
|
||||||
"Only PCI_DEV_TYPE_PTDEV could not configure vdev_ops");
|
"Only PCI_DEV_TYPE_PTDEV could not configure vdev_ops");
|
||||||
ASSERT(dev_config->pdev != NULL, "PCI PTDev is not present on platform!");
|
ASSERT(dev_config->pdev != NULL, "PCI PTDev is not present on platform!");
|
||||||
|
@ -90,7 +90,7 @@ static void create_vf(struct pci_vdev *pf_vdev, union pci_bdf vf_bdf, uint16_t v
|
|||||||
* Per VT-d 8.3.3, the VFs are under the scope of the same
|
* Per VT-d 8.3.3, the VFs are under the scope of the same
|
||||||
* remapping unit as the associated PF when SRIOV is enabled.
|
* remapping unit as the associated PF when SRIOV is enabled.
|
||||||
*/
|
*/
|
||||||
vf_pdev = init_pdev(vf_bdf.value, pf_vdev->pdev->drhd_index);
|
vf_pdev = pci_init_pdev(vf_bdf, pf_vdev->pdev->drhd_index);
|
||||||
if (vf_pdev != NULL) {
|
if (vf_pdev != NULL) {
|
||||||
struct acrn_vm_pci_dev_config *dev_cfg;
|
struct acrn_vm_pci_dev_config *dev_cfg;
|
||||||
|
|
||||||
|
@ -54,6 +54,20 @@ static uint32_t num_pci_pdev;
|
|||||||
static struct pci_pdev pci_pdevs[CONFIG_MAX_PCI_DEV_NUM];
|
static struct pci_pdev pci_pdevs[CONFIG_MAX_PCI_DEV_NUM];
|
||||||
static struct hlist_head pdevs_hlist_heads[PDEV_HLIST_HASHSIZE];
|
static struct hlist_head pdevs_hlist_heads[PDEV_HLIST_HASHSIZE];
|
||||||
|
|
||||||
|
/* For HV owned pdev */
|
||||||
|
static uint32_t num_hv_owned_pci_pdev;
|
||||||
|
static struct pci_pdev *hv_owned_pci_pdevs[CONFIG_MAX_PCI_DEV_NUM];
|
||||||
|
|
||||||
|
uint32_t get_hv_owned_pdev_num(void)
|
||||||
|
{
|
||||||
|
return num_hv_owned_pci_pdev;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct pci_pdev **get_hv_owned_pdevs(void)
|
||||||
|
{
|
||||||
|
return (const struct pci_pdev **)hv_owned_pci_pdevs;
|
||||||
|
}
|
||||||
|
|
||||||
static struct pci_mmcfg_region phys_pci_mmcfg = {
|
static struct pci_mmcfg_region phys_pci_mmcfg = {
|
||||||
.address = DEFAULT_PCI_MMCFG_BASE,
|
.address = DEFAULT_PCI_MMCFG_BASE,
|
||||||
.start_bus = DEFAULT_PCI_MMCFG_START_BUS,
|
.start_bus = DEFAULT_PCI_MMCFG_START_BUS,
|
||||||
@ -352,25 +366,19 @@ bool is_plat_hidden_pdev(union pci_bdf bdf)
|
|||||||
return hidden;
|
return hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool is_hv_owned_pdev(union pci_bdf pbdf)
|
bool is_hv_owned_pdev(union pci_bdf pbdf)
|
||||||
{
|
{
|
||||||
bool hidden = false;
|
bool ret = false;
|
||||||
/* if it is debug uart, hide it*/
|
uint32_t i;
|
||||||
if (is_pci_dbg_uart(pbdf)) {
|
|
||||||
pr_info("hide pci uart dev: (%x:%x:%x)", pbdf.bits.b, pbdf.bits.d, pbdf.bits.f);
|
|
||||||
hidden = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return hidden;
|
for (i = 0U; i < num_hv_owned_pci_pdev; i++) {
|
||||||
}
|
if (bdf_is_equal(pbdf, hv_owned_pci_pdevs[i]->bdf)) {
|
||||||
|
pr_info("hv owned dev: (%x:%x:%x)", pbdf.bits.b, pbdf.bits.d, pbdf.bits.f);
|
||||||
static struct pci_pdev *pci_init_pdev(union pci_bdf pbdf, uint32_t drhd_index)
|
ret = true;
|
||||||
{
|
break;
|
||||||
struct pci_pdev *pdev = NULL;
|
}
|
||||||
if (!is_hv_owned_pdev(pbdf)) {
|
|
||||||
pdev = init_pdev(pbdf.value, drhd_index);
|
|
||||||
}
|
}
|
||||||
return pdev;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -779,20 +787,19 @@ static void pci_enumerate_cap(struct pci_pdev *pdev)
|
|||||||
*
|
*
|
||||||
* @return If there's a successfully initialized pdev return it, otherwise return NULL;
|
* @return If there's a successfully initialized pdev return it, otherwise return NULL;
|
||||||
*/
|
*/
|
||||||
struct pci_pdev *init_pdev(uint16_t pbdf, uint32_t drhd_index)
|
struct pci_pdev *pci_init_pdev(union pci_bdf bdf, uint32_t drhd_index)
|
||||||
{
|
{
|
||||||
uint8_t hdr_type, hdr_layout;
|
uint8_t hdr_type, hdr_layout;
|
||||||
union pci_bdf bdf;
|
|
||||||
struct pci_pdev *pdev = NULL;
|
struct pci_pdev *pdev = NULL;
|
||||||
|
bool is_hv_owned = false;
|
||||||
|
|
||||||
if (num_pci_pdev < CONFIG_MAX_PCI_DEV_NUM) {
|
if (num_pci_pdev < CONFIG_MAX_PCI_DEV_NUM) {
|
||||||
bdf.value = pbdf;
|
|
||||||
hdr_type = (uint8_t)pci_pdev_read_cfg(bdf, PCIR_HDRTYPE, 1U);
|
hdr_type = (uint8_t)pci_pdev_read_cfg(bdf, PCIR_HDRTYPE, 1U);
|
||||||
hdr_layout = (hdr_type & PCIM_HDRTYPE);
|
hdr_layout = (hdr_type & PCIM_HDRTYPE);
|
||||||
|
|
||||||
if ((hdr_layout == PCIM_HDRTYPE_NORMAL) || (hdr_layout == PCIM_HDRTYPE_BRIDGE)) {
|
if ((hdr_layout == PCIM_HDRTYPE_NORMAL) || (hdr_layout == PCIM_HDRTYPE_BRIDGE)) {
|
||||||
pdev = &pci_pdevs[num_pci_pdev];
|
pdev = &pci_pdevs[num_pci_pdev];
|
||||||
pdev->bdf.value = pbdf;
|
pdev->bdf = bdf;
|
||||||
pdev->hdr_type = hdr_type;
|
pdev->hdr_type = hdr_type;
|
||||||
pdev->base_class = (uint8_t)pci_pdev_read_cfg(bdf, PCIR_CLASS, 1U);
|
pdev->base_class = (uint8_t)pci_pdev_read_cfg(bdf, PCIR_CLASS, 1U);
|
||||||
pdev->sub_class = (uint8_t)pci_pdev_read_cfg(bdf, PCIR_SUBCLASS, 1U);
|
pdev->sub_class = (uint8_t)pci_pdev_read_cfg(bdf, PCIR_SUBCLASS, 1U);
|
||||||
@ -803,7 +810,18 @@ struct pci_pdev *init_pdev(uint16_t pbdf, uint32_t drhd_index)
|
|||||||
pci_enumerate_cap(pdev);
|
pci_enumerate_cap(pdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
hlist_add_head(&pdev->link, &pdevs_hlist_heads[hash64(pbdf, PDEV_HLIST_HASHBITS)]);
|
#if (PRE_VM_NUM != 0U)
|
||||||
|
/* HV owned pdev: 1.typ1 pdev if pre-launched VM exist; 2.pci debug uart */
|
||||||
|
is_hv_owned = (hdr_layout == PCIM_HDRTYPE_BRIDGE) || is_pci_dbg_uart(bdf);
|
||||||
|
#else
|
||||||
|
/* HV owned pdev: 1.pci debug uart */
|
||||||
|
is_hv_owned = is_pci_dbg_uart(bdf);
|
||||||
|
#endif
|
||||||
|
if (is_hv_owned) {
|
||||||
|
hv_owned_pci_pdevs[num_hv_owned_pci_pdev] = pdev;
|
||||||
|
num_hv_owned_pci_pdev++;
|
||||||
|
}
|
||||||
|
hlist_add_head(&pdev->link, &pdevs_hlist_heads[hash64(bdf.value, PDEV_HLIST_HASHBITS)]);
|
||||||
pdev->drhd_index = drhd_index;
|
pdev->drhd_index = drhd_index;
|
||||||
num_pci_pdev++;
|
num_pci_pdev++;
|
||||||
reserve_vmsix_on_msi_irtes(pdev);
|
reserve_vmsix_on_msi_irtes(pdev);
|
||||||
|
@ -338,11 +338,14 @@ void set_mmcfg_region(struct pci_mmcfg_region *region);
|
|||||||
#endif
|
#endif
|
||||||
struct pci_mmcfg_region *get_mmcfg_region(void);
|
struct pci_mmcfg_region *get_mmcfg_region(void);
|
||||||
|
|
||||||
struct pci_pdev *init_pdev(uint16_t pbdf, uint32_t drhd_index);
|
struct pci_pdev *pci_init_pdev(union pci_bdf pbdf, uint32_t drhd_index);
|
||||||
uint32_t pci_pdev_read_cfg(union pci_bdf bdf, uint32_t offset, uint32_t bytes);
|
uint32_t pci_pdev_read_cfg(union pci_bdf bdf, uint32_t offset, uint32_t bytes);
|
||||||
void pci_pdev_write_cfg(union pci_bdf bdf, uint32_t offset, uint32_t bytes, uint32_t val);
|
void pci_pdev_write_cfg(union pci_bdf bdf, uint32_t offset, uint32_t bytes, uint32_t val);
|
||||||
void enable_disable_pci_intx(union pci_bdf bdf, bool enable);
|
void enable_disable_pci_intx(union pci_bdf bdf, bool enable);
|
||||||
|
|
||||||
|
bool is_hv_owned_pdev(union pci_bdf pbdf);
|
||||||
|
uint32_t get_hv_owned_pdev_num(void);
|
||||||
|
const struct pci_pdev **get_hv_owned_pdevs(void);
|
||||||
/*
|
/*
|
||||||
* @brief Walks the PCI heirarchy and initializes array of pci_pdev structs
|
* @brief Walks the PCI heirarchy and initializes array of pci_pdev structs
|
||||||
* Uses DRHD info from ACPI DMAR tables to cover the endpoints and
|
* Uses DRHD info from ACPI DMAR tables to cover the endpoints and
|
||||||
|
Loading…
Reference in New Issue
Block a user