mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-05-11 18:04:25 +00:00
hv: vpci: fix pass-thru pcie device may access MSI-X BAR
Now ACRN would traps MSI-X Table Structure access and does MSI-X interrupt remapping for pass-thru PCIe devices. ACRN does this trap by unmmapping the address ranges where the MSI-X Table Structure locates in granularity of 4K pages. So there may have other registers (non-MSI-X structures) in these trapped pages However, the guest may access these registers (non-MSI-X structures) in these trapped pages, which needs to be forwarded to the physical device. This patch forwards the access to real hardware for pass-thru PCIe devices. Tracked-On: #8255 Signed-off-by: Fei Li <fei1.li@intel.com>
This commit is contained in:
parent
8d734dd915
commit
7c940207d2
@ -27,6 +27,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <asm/guest/vm.h>
|
#include <asm/guest/vm.h>
|
||||||
|
#include <asm/io.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <vpci.h>
|
#include <vpci.h>
|
||||||
#include <asm/guest/ept.h>
|
#include <asm/guest/ept.h>
|
||||||
@ -98,32 +99,46 @@ uint32_t rw_vmsix_table(struct pci_vdev *vdev, struct io_request *io_req)
|
|||||||
struct msix_table_entry *entry;
|
struct msix_table_entry *entry;
|
||||||
uint32_t entry_offset, table_offset, index = CONFIG_MAX_MSIX_TABLE_NUM;
|
uint32_t entry_offset, table_offset, index = CONFIG_MAX_MSIX_TABLE_NUM;
|
||||||
uint64_t offset;
|
uint64_t offset;
|
||||||
|
void *hva;
|
||||||
|
|
||||||
/* Must be full DWORD or full QWORD aligned. */
|
if ((mmio->size <= 8U) && mem_aligned_check(mmio->address, mmio->size)) {
|
||||||
if ((mmio->size == 4U) || (mmio->size == 8U)) {
|
|
||||||
offset = mmio->address - vdev->msix.mmio_gpa;
|
offset = mmio->address - vdev->msix.mmio_gpa;
|
||||||
if (msixtable_access(vdev, (uint32_t)offset)) {
|
if (msixtable_access(vdev, (uint32_t)offset)) {
|
||||||
|
/* Must be full DWORD or full QWORD aligned. */
|
||||||
|
if ((mmio->size == 4U) || (mmio->size == 8U)) {
|
||||||
|
|
||||||
table_offset = (uint32_t)(offset - vdev->msix.table_offset);
|
table_offset = (uint32_t)(offset - vdev->msix.table_offset);
|
||||||
index = table_offset / MSIX_TABLE_ENTRY_SIZE;
|
index = table_offset / MSIX_TABLE_ENTRY_SIZE;
|
||||||
|
|
||||||
entry = &vdev->msix.table_entries[index];
|
entry = &vdev->msix.table_entries[index];
|
||||||
entry_offset = table_offset % MSIX_TABLE_ENTRY_SIZE;
|
entry_offset = table_offset % MSIX_TABLE_ENTRY_SIZE;
|
||||||
|
|
||||||
if (mmio->direction == ACRN_IOREQ_DIR_READ) {
|
if (mmio->direction == ACRN_IOREQ_DIR_READ) {
|
||||||
(void)memcpy_s(&mmio->value, (size_t)mmio->size,
|
(void)memcpy_s(&mmio->value, (size_t)mmio->size,
|
||||||
(void *)entry + entry_offset, (size_t)mmio->size);
|
(void *)entry + entry_offset, (size_t)mmio->size);
|
||||||
|
} else {
|
||||||
|
(void)memcpy_s((void *)entry + entry_offset, (size_t)mmio->size,
|
||||||
|
&mmio->value, (size_t)mmio->size);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
(void)memcpy_s((void *)entry + entry_offset, (size_t)mmio->size,
|
pr_err("%s, Only DWORD and QWORD are permitted", __func__);
|
||||||
&mmio->value, (size_t)mmio->size);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (mmio->direction == ACRN_IOREQ_DIR_READ) {
|
if (vdev->pdev != NULL) {
|
||||||
mmio->value = 0UL;
|
hva = hpa2hva(vdev->msix.mmio_hpa + (mmio->address - vdev->msix.mmio_gpa));
|
||||||
|
stac();
|
||||||
|
if (mmio->direction == ACRN_IOREQ_DIR_READ) {
|
||||||
|
mmio->value = mmio_read(hva, mmio->size);
|
||||||
|
} else {
|
||||||
|
mmio_write(hva, mmio->size, mmio->value);
|
||||||
|
}
|
||||||
|
clac();
|
||||||
|
} else {
|
||||||
|
if (mmio->direction == ACRN_IOREQ_DIR_READ) {
|
||||||
|
mmio->value = 0UL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
pr_err("%s, Only DWORD and QWORD are permitted", __func__);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return index;
|
return index;
|
||||||
|
Loading…
Reference in New Issue
Block a user