clear-pkgs-linux-iot-lts2018/0765-Kernel-VHM-Use-the-tra...

153 lines
5.4 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Zhao Yakui <yakui.zhao@intel.com>
Date: Thu, 29 Nov 2018 13:58:11 +0800
Subject: [PATCH] Kernel/VHM: Use the traped pci_access addr based on VM
instead of static global variable
The emulation of PCI access is divided into two steps:
1. write the access addr into 0xCF8((bus << 16) | (dev << 11) | (func << 8) | (reg))
2. read/write the 0xCFC port
Now the static variable is defined to obtain the cached_bus/dev/func/reg.
But if the pci emulated access is triggered on two VM, it will cause that
the incorrect bus/dev/func/reg is cached.
So it is emulated based on per-vm instead of static global variable.
At the same time the pci_ext space is also supported. It is defined in
((reg & 0xF00) << 16).
Tracked-On: PKT-1592
Tracked-On: https://github.com/projectacrn/acrn-hypervisor/issues/1957
Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
Reviewed-by: Eddie Dong <eddie.dong@intel.com>
Tested-by: Yin, FengWei <fengwei.yin@intel.com>
---
drivers/vhm/vhm_ioreq.c | 50 +++++++++++++++------------------
include/linux/vhm/vhm_vm_mngt.h | 2 ++
2 files changed, 25 insertions(+), 27 deletions(-)
diff --git a/drivers/vhm/vhm_ioreq.c b/drivers/vhm/vhm_ioreq.c
index ac934fcd656f..b0ca41a402ea 100644
--- a/drivers/vhm/vhm_ioreq.c
+++ b/drivers/vhm/vhm_ioreq.c
@@ -729,12 +729,8 @@ static bool is_cfg_data(struct vhm_request *req)
req->reqs.pio_request.address < 0xcfc+4));
}
-static int cached_bus;
-static int cached_dev;
-static int cached_func;
-static int cached_reg;
-static int cached_enable;
-#define PCI_REGMAX 255 /* highest supported config register addr.*/
+#define PCI_LOWREG_MASK 255 /* the low 8-bit of supported pci_reg addr.*/
+#define PCI_HIGHREG_MASK 0xF00 /* the high 4-bit of supported pci_reg addr */
#define PCI_FUNCMAX 7 /* highest supported function number */
#define PCI_SLOTMAX 31 /* highest supported slot number */
#define PCI_BUSMAX 255 /* highest supported bus number */
@@ -748,42 +744,37 @@ static int handle_cf8cfc(struct vhm_vm *vm, struct vhm_request *req, int vcpu)
if (is_cfg_addr(req)) {
if (req->reqs.pio_request.direction == REQUEST_WRITE) {
if (req->reqs.pio_request.size == 4) {
- int value = req->reqs.pio_request.value;
-
- cached_bus = (value >> 16) & PCI_BUSMAX;
- cached_dev = (value >> 11) & PCI_SLOTMAX;
- cached_func = (value >> 8) & PCI_FUNCMAX;
- cached_reg = value & PCI_REGMAX;
- cached_enable =
- (value & CONF1_ENABLE) == CONF1_ENABLE;
+
+ vm->pci_conf_addr = (uint32_t ) req->reqs.pio_request.value;
req_handled = 1;
}
} else {
if (req->reqs.pio_request.size == 4) {
req->reqs.pio_request.value =
- (cached_bus << 16) |
- (cached_dev << 11) | (cached_func << 8)
- | cached_reg;
- if (cached_enable)
- req->reqs.pio_request.value |=
- CONF1_ENABLE;
+ vm->pci_conf_addr;
req_handled = 1;
}
}
} else if (is_cfg_data(req)) {
- if (!cached_enable) {
+ if (!(vm->pci_conf_addr & CONF1_ENABLE)) {
if (req->reqs.pio_request.direction == REQUEST_READ)
req->reqs.pio_request.value = 0xffffffff;
req_handled = 1;
} else {
/* pci request is same as io request at top */
int offset = req->reqs.pio_request.address - 0xcfc;
+ int pci_reg;
req->type = REQ_PCICFG;
- req->reqs.pci_request.bus = cached_bus;
- req->reqs.pci_request.dev = cached_dev;
- req->reqs.pci_request.func = cached_func;
- req->reqs.pci_request.reg = cached_reg + offset;
+ req->reqs.pci_request.bus = (vm->pci_conf_addr >> 16) &
+ PCI_BUSMAX;
+ req->reqs.pci_request.dev = (vm->pci_conf_addr >> 11) &
+ PCI_SLOTMAX;
+ req->reqs.pci_request.func = (vm->pci_conf_addr >> 8) &
+ PCI_FUNCMAX;
+ pci_reg = (vm->pci_conf_addr & PCI_LOWREG_MASK) +
+ ((vm->pci_conf_addr >> 16) & PCI_HIGHREG_MASK);
+ req->reqs.pci_request.reg = pci_reg + offset;
}
}
@@ -793,8 +784,13 @@ static int handle_cf8cfc(struct vhm_vm *vm, struct vhm_request *req, int vcpu)
return err ? err: req_handled;
}
-static bool bdf_match(struct ioreq_client *client)
+static bool bdf_match(struct vhm_vm *vm, struct ioreq_client *client)
{
+ int cached_bus, cached_dev, cached_func;
+
+ cached_bus = (vm->pci_conf_addr >> 16) & PCI_BUSMAX;
+ cached_dev = (vm->pci_conf_addr >> 11) & PCI_SLOTMAX;
+ cached_func = (vm->pci_conf_addr >> 8) & PCI_FUNCMAX;
return (client->trap_bdf &&
client->pci_bus == cached_bus &&
client->pci_dev == cached_dev &&
@@ -820,7 +816,7 @@ static struct ioreq_client *acrn_ioreq_find_client_by_request(struct vhm_vm *vm,
}
if (req->type == REQ_PCICFG) {
- if (bdf_match(client)) { /* bdf match client */
+ if (bdf_match(vm, client)) { /* bdf match client */
target_client = client;
break;
} else /* other or fallback client */
diff --git a/include/linux/vhm/vhm_vm_mngt.h b/include/linux/vhm/vhm_vm_mngt.h
index 65f647451fb8..c307536417f8 100644
--- a/include/linux/vhm/vhm_vm_mngt.h
+++ b/include/linux/vhm/vhm_vm_mngt.h
@@ -85,6 +85,7 @@ extern struct mutex vhm_vm_list_lock;
* @ioreq_client_list: list of ioreq clients
* @req_buf: request buffer shared between HV, SOS and UOS
* @pg: pointer to linux page which holds req_buf
+ * @pci_conf_addr: the access-trapped pci_conf_addr
*/
struct vhm_vm {
struct device *dev;
@@ -100,6 +101,7 @@ struct vhm_vm {
struct list_head ioreq_client_list;
struct vhm_request_buffer *req_buf;
struct page *pg;
+ uint32_t pci_conf_addr;
};
/**
--
https://clearlinux.org