hv: vpci: add vmsix capability registers rw permission control
Guest may write a MSI-X capability register with only RW bits setting on. This works well on native since the hardware will make sure RO register bits could not over-write. However, the software needs more efforts to achieve this. This patch does this by defining a RW permission mapping base on bits. When a guest tries to write a MSI-X Capability register, only modify the RW bits on vCFG space. Tracked-On: #4550 Signed-off-by: Li Fei1 <fei1.li@intel.com>
This commit is contained in:
parent
ea0ba47b02
commit
ce3451827a
|
@ -112,7 +112,7 @@ static void remap_one_vmsix_entry(const struct pci_vdev *vdev, uint32_t index)
|
||||||
/**
|
/**
|
||||||
* @pre vdev != NULL
|
* @pre vdev != NULL
|
||||||
*/
|
*/
|
||||||
void read_vmsix_cfg(const struct pci_vdev *vdev, uint32_t offset, uint32_t bytes, uint32_t *val)
|
void read_vmsix_cap_reg(const struct pci_vdev *vdev, uint32_t offset, uint32_t bytes, uint32_t *val)
|
||||||
{
|
{
|
||||||
/* For PIO access, we emulate Capability Structures only */
|
/* For PIO access, we emulate Capability Structures only */
|
||||||
*val = pci_vdev_read_vcfg(vdev, offset, bytes);
|
*val = pci_vdev_read_vcfg(vdev, offset, bytes);
|
||||||
|
@ -124,16 +124,20 @@ void read_vmsix_cfg(const struct pci_vdev *vdev, uint32_t offset, uint32_t bytes
|
||||||
* @pre vdev != NULL
|
* @pre vdev != NULL
|
||||||
* @pre vdev->pdev != NULL
|
* @pre vdev->pdev != NULL
|
||||||
*/
|
*/
|
||||||
void write_vmsix_cfg(struct pci_vdev *vdev, uint32_t offset, uint32_t bytes, uint32_t val)
|
void write_vmsix_cap_reg(struct pci_vdev *vdev, uint32_t offset, uint32_t bytes, uint32_t val)
|
||||||
{
|
{
|
||||||
uint32_t old_msgctrl, msgctrl;
|
static const uint8_t msix_ro_mask[12U] = {
|
||||||
|
0xffU, 0xffU, 0xffU, 0x3fU, /* Only Function Mask and MSI-X Enable writable */
|
||||||
|
0xffU, 0xffU, 0xffU, 0xffU,
|
||||||
|
0xffU, 0xffU, 0xffU, 0xffU };
|
||||||
|
uint32_t msgctrl, old, ro_mask = ~0U;
|
||||||
|
|
||||||
old_msgctrl = pci_vdev_read_vcfg(vdev, vdev->msix.capoff + PCIR_MSIX_CTRL, 2U);
|
(void)memcpy_s((void *)&ro_mask, bytes, (void *)&msix_ro_mask[offset - vdev->msix.capoff], bytes);
|
||||||
/* Write to vdev */
|
if (ro_mask != ~0U) {
|
||||||
pci_vdev_write_vcfg(vdev, offset, bytes, val);
|
old = pci_vdev_read_vcfg(vdev, vdev->msix.capoff, bytes);
|
||||||
msgctrl = pci_vdev_read_vcfg(vdev, vdev->msix.capoff + PCIR_MSIX_CTRL, 2U);
|
pci_vdev_write_vcfg(vdev, offset, bytes, (old & ro_mask) | (val & ~ro_mask));
|
||||||
|
|
||||||
if (((old_msgctrl ^ msgctrl) & (PCIM_MSIXCTRL_MSIX_ENABLE | PCIM_MSIXCTRL_FUNCTION_MASK)) != 0U) {
|
msgctrl = pci_vdev_read_vcfg(vdev, vdev->msix.capoff + PCIR_MSIX_CTRL, 2U);
|
||||||
/* If MSI Enable is being set, make sure INTxDIS bit is set */
|
/* If MSI Enable is being set, make sure INTxDIS bit is set */
|
||||||
if ((msgctrl & PCIM_MSIXCTRL_MSIX_ENABLE) != 0U) {
|
if ((msgctrl & PCIM_MSIXCTRL_MSIX_ENABLE) != 0U) {
|
||||||
enable_disable_pci_intx(vdev->pdev->bdf, false);
|
enable_disable_pci_intx(vdev->pdev->bdf, false);
|
||||||
|
|
|
@ -498,7 +498,7 @@ static int32_t write_pt_dev_cfg(struct pci_vdev *vdev, uint32_t offset,
|
||||||
} else if (msicap_access(vdev, offset)) {
|
} else if (msicap_access(vdev, offset)) {
|
||||||
write_vmsi_cap_reg(vdev, offset, bytes, val);
|
write_vmsi_cap_reg(vdev, offset, bytes, val);
|
||||||
} else if (msixcap_access(vdev, offset)) {
|
} else if (msixcap_access(vdev, offset)) {
|
||||||
write_vmsix_cfg(vdev, offset, bytes, val);
|
write_vmsix_cap_reg(vdev, offset, bytes, val);
|
||||||
} else if (sriovcap_access(vdev, offset)) {
|
} else if (sriovcap_access(vdev, offset)) {
|
||||||
write_sriov_cap_reg(vdev, offset, bytes, val);
|
write_sriov_cap_reg(vdev, offset, bytes, val);
|
||||||
} else {
|
} else {
|
||||||
|
@ -523,7 +523,7 @@ static int32_t read_pt_dev_cfg(const struct pci_vdev *vdev, uint32_t offset,
|
||||||
} else if (msicap_access(vdev, offset)) {
|
} else if (msicap_access(vdev, offset)) {
|
||||||
read_vmsi_cap_reg(vdev, offset, bytes, val);
|
read_vmsi_cap_reg(vdev, offset, bytes, val);
|
||||||
} else if (msixcap_access(vdev, offset)) {
|
} else if (msixcap_access(vdev, offset)) {
|
||||||
read_vmsix_cfg(vdev, offset, bytes, val);
|
read_vmsix_cap_reg(vdev, offset, bytes, val);
|
||||||
} else if (sriovcap_access(vdev, offset)) {
|
} else if (sriovcap_access(vdev, offset)) {
|
||||||
read_sriov_cap_reg(vdev, offset, bytes, val);
|
read_sriov_cap_reg(vdev, offset, bytes, val);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -124,8 +124,8 @@ void deinit_vmsi(struct pci_vdev *vdev);
|
||||||
|
|
||||||
void init_vmsix(struct pci_vdev *vdev);
|
void init_vmsix(struct pci_vdev *vdev);
|
||||||
int32_t vmsix_handle_table_mmio_access(struct io_request *io_req, void *handler_private_data);
|
int32_t vmsix_handle_table_mmio_access(struct io_request *io_req, void *handler_private_data);
|
||||||
void read_vmsix_cfg(const struct pci_vdev *vdev, uint32_t offset, uint32_t bytes, uint32_t *val);
|
void read_vmsix_cap_reg(const struct pci_vdev *vdev, uint32_t offset, uint32_t bytes, uint32_t *val);
|
||||||
void write_vmsix_cfg(struct pci_vdev *vdev, uint32_t offset, uint32_t bytes, uint32_t val);
|
void write_vmsix_cap_reg(struct pci_vdev *vdev, uint32_t offset, uint32_t bytes, uint32_t val);
|
||||||
void deinit_vmsix(struct pci_vdev *vdev);
|
void deinit_vmsix(struct pci_vdev *vdev);
|
||||||
|
|
||||||
void init_vsriov(struct pci_vdev *vdev);
|
void init_vsriov(struct pci_vdev *vdev);
|
||||||
|
|
Loading…
Reference in New Issue