mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-08-10 20:43:48 +00:00
hv: add functions to initialize vmsix capability
- add 'vpci_add_capability()' to initialize one PCI capability in config space. - add 'add_vmsix_capability()' to add vmsix capability. Tracked-On: #5407 Signed-off-by: Yonghua Huang <yonghua.huang@intel.com> Reviewed-by: Li, Fei <fei1.li@intel.com> Reviewed-by: Wang, Yu1 <yu1.wang@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
parent
cdfc82f03b
commit
8137e49e17
@ -109,3 +109,43 @@ int32_t vmsix_handle_table_mmio_access(struct io_request *io_req, void *priv_dat
|
||||
(void)rw_vmsix_table((struct pci_vdev *)priv_data, io_req);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @pre vdev != NULL
|
||||
*/
|
||||
int32_t add_vmsix_capability(struct pci_vdev *vdev, uint32_t entry_num, uint8_t bar_num)
|
||||
{
|
||||
uint32_t table_size, i;
|
||||
struct msixcap msixcap;
|
||||
int32_t ret = -1;
|
||||
|
||||
if ((bar_num < PCI_BAR_COUNT) &&
|
||||
(entry_num <= min(CONFIG_MAX_MSIX_TABLE_NUM, VMSIX_MAX_TABLE_ENTRY_NUM))) {
|
||||
|
||||
table_size = VMSIX_MAX_ENTRY_TABLE_SIZE;
|
||||
|
||||
vdev->msix.caplen = MSIX_CAPLEN;
|
||||
vdev->msix.table_bar = bar_num;
|
||||
vdev->msix.table_offset = 0U;
|
||||
vdev->msix.table_count = entry_num;
|
||||
|
||||
/* set mask bit of vector control register */
|
||||
for (i = 0; i < entry_num; i++)
|
||||
vdev->msix.table_entries[i].vector_control |= PCIM_MSIX_VCTRL_MASK;
|
||||
|
||||
(void)memset(&msixcap, 0U, sizeof(struct msixcap));
|
||||
|
||||
msixcap.capid = PCIY_MSIX;
|
||||
msixcap.msgctrl = entry_num - 1U;
|
||||
|
||||
/* - MSI-X table start at offset 0 */
|
||||
msixcap.table_info = bar_num;
|
||||
msixcap.pba_info = table_size | bar_num;
|
||||
|
||||
vdev->msix.capoff = vpci_add_capability(vdev, (uint8_t *)(&msixcap), sizeof(struct msixcap));
|
||||
if (vdev->msix.capoff != 0U) {
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -791,3 +791,56 @@ void vpci_update_one_vbar(struct pci_vdev *vdev, uint32_t bar_idx, uint32_t val,
|
||||
vdev->vbars[update_idx].base_gpa = 0UL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief Add emulated legacy PCI capability support for virtual PCI device
|
||||
*
|
||||
* @param vdev Pointer to vdev data structure
|
||||
* @param capdata Pointer to buffer that holds the capability data to be added.
|
||||
* @param caplen Length of buffer that holds the capability data to be added.
|
||||
*
|
||||
* @pre vdev != NULL
|
||||
* @pre vdev->vpci != NULL
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
uint32_t vpci_add_capability(struct pci_vdev *vdev, uint8_t *capdata, uint8_t caplen)
|
||||
{
|
||||
#define CAP_START_OFFSET PCI_CFG_HEADER_LENGTH
|
||||
|
||||
uint8_t capoff, reallen;
|
||||
uint16_t sts;
|
||||
uint32_t ret = 0U;
|
||||
|
||||
reallen = roundup(caplen, 4U); /* dword aligned */
|
||||
|
||||
sts = pci_vdev_read_vcfg(vdev, PCIR_STATUS, 2U);
|
||||
if ((sts & PCIM_STATUS_CAPPRESENT) == 0U) {
|
||||
capoff = CAP_START_OFFSET;
|
||||
} else {
|
||||
capoff = vdev->free_capoff;
|
||||
}
|
||||
|
||||
/* Check if we have enough space */
|
||||
if (((uint16_t)capoff + reallen) <= PCI_CONFIG_SPACE_SIZE) {
|
||||
/* Set the previous capability pointer */
|
||||
if ((sts & PCIM_STATUS_CAPPRESENT) == 0U) {
|
||||
pci_vdev_write_vcfg(vdev, PCIR_CAP_PTR, 1U, capoff);
|
||||
pci_vdev_write_vcfg(vdev, PCIR_STATUS, 2U, sts|PCIM_STATUS_CAPPRESENT);
|
||||
} else {
|
||||
pci_vdev_write_vcfg(vdev, vdev->prev_capoff + 1U, 1U, capoff);
|
||||
}
|
||||
|
||||
/* Copy the capability */
|
||||
(void)memcpy_s((void *)&vdev->cfgdata.data_8[capoff], caplen, (void *)capdata, caplen);
|
||||
|
||||
/* Set the next capability pointer */
|
||||
pci_vdev_write_vcfg(vdev, capoff + 1U, 1U, 0U);
|
||||
|
||||
vdev->prev_capoff = capoff;
|
||||
vdev->free_capoff = capoff + reallen;
|
||||
ret = capoff;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -33,6 +33,15 @@
|
||||
#include <list.h>
|
||||
#include <pci.h>
|
||||
|
||||
/*
|
||||
* For hypervisor emulated PCI devices, vMSIX Table contains 128 entries
|
||||
* at most. vMSIX Table begins at an offset of 0, and maps the vMSIX PBA
|
||||
* beginning at an offset of 2 KB.
|
||||
*/
|
||||
#define VMSIX_MAX_TABLE_ENTRY_NUM 128U
|
||||
#define VMSIX_MAX_ENTRY_TABLE_SIZE 2048U
|
||||
#define VMSIX_ENTRY_TABLE_PBA_BAR_SIZE 4096U
|
||||
|
||||
static inline struct acrn_vm *vpci2vm(const struct acrn_vpci *vpci)
|
||||
{
|
||||
return container_of(vpci, struct acrn_vm, vpci);
|
||||
@ -144,6 +153,7 @@ void write_vmsi_cap_reg(struct pci_vdev *vdev, uint32_t offset, uint32_t bytes,
|
||||
void deinit_vmsi(const struct pci_vdev *vdev);
|
||||
|
||||
void init_vmsix_pt(struct pci_vdev *vdev);
|
||||
int32_t add_vmsix_capability(struct pci_vdev *vdev, uint32_t entry_num, uint8_t bar_num);
|
||||
bool write_vmsix_cap_reg(struct pci_vdev *vdev, uint32_t offset, uint32_t bytes, uint32_t val);
|
||||
void write_pt_vmsix_cap_reg(struct pci_vdev *vdev, uint32_t offset, uint32_t bytes, uint32_t val);
|
||||
uint32_t rw_vmsix_table(struct pci_vdev *vdev, struct io_request *io_req);
|
||||
@ -160,6 +170,7 @@ uint32_t sriov_bar_offset(const struct pci_vdev *vdev, uint32_t bar_idx);
|
||||
|
||||
uint32_t pci_vdev_read_vcfg(const struct pci_vdev *vdev, uint32_t offset, uint32_t bytes);
|
||||
void pci_vdev_write_vcfg(struct pci_vdev *vdev, uint32_t offset, uint32_t bytes, uint32_t val);
|
||||
uint32_t vpci_add_capability(struct pci_vdev *vdev, uint8_t *capdata, uint8_t caplen);
|
||||
|
||||
uint32_t pci_vdev_read_vbar(const struct pci_vdev *vdev, uint32_t idx);
|
||||
void pci_vdev_write_vbar(struct pci_vdev *vdev, uint32_t idx, uint32_t val);
|
||||
|
@ -60,6 +60,14 @@ struct pci_msi {
|
||||
};
|
||||
|
||||
/* MSI-X capability structure */
|
||||
struct msixcap {
|
||||
uint8_t capid;
|
||||
uint8_t nextptr;
|
||||
uint16_t msgctrl;
|
||||
uint32_t table_info; /* bar index and offset */
|
||||
uint32_t pba_info; /* bar index and offset */
|
||||
} __packed;
|
||||
|
||||
struct pci_msix {
|
||||
struct msix_table_entry table_entries[CONFIG_MAX_MSIX_TABLE_NUM];
|
||||
uint64_t mmio_gpa;
|
||||
@ -115,6 +123,9 @@ struct pci_vdev {
|
||||
uint32_t nr_bars; /* 6 for normal device, 2 for bridge, 1 for cardbus */
|
||||
struct pci_vbar vbars[PCI_BAR_COUNT];
|
||||
|
||||
uint8_t prev_capoff; /* Offset of previous vPCI capability */
|
||||
uint8_t free_capoff; /* Next free offset to add vPCI capability */
|
||||
|
||||
struct pci_msi msi;
|
||||
struct pci_msix msix;
|
||||
struct pci_cap_sriov sriov;
|
||||
|
@ -15,6 +15,9 @@
|
||||
/** Roundup (x/y) to ( x/y + (x%y) ? 1 : 0) **/
|
||||
#define INT_DIV_ROUNDUP(x, y) ((((x)+(y))-1)/(y))
|
||||
|
||||
/** Roundup (x) to (y) aligned **/
|
||||
#define roundup(x, y) (((x) + ((y) - 1UL)) & (~((y) - 1UL)))
|
||||
|
||||
#define min(x, y) ((x) < (y)) ? (x) : (y)
|
||||
|
||||
#define max(x, y) ((x) < (y)) ? (y) : (x)
|
||||
|
Loading…
Reference in New Issue
Block a user