On Fri, Mar 20, 2020 at 06:48:53AM +0100, Gerd Hoffmann wrote:
+static void *pci_mmconfig_addr(u16 bdf, u32 addr) +{
- if (!mmconfig)
return NULL;
- return (void*)(mmconfig + ((u32)bdf << 12) + addr);
+}
void pci_config_writel(u16 bdf, u32 addr, u32 val) {
- outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD);
- outl(val, PORT_PCI_DATA);
- void *mmcfg = pci_mmconfig_addr(bdf, addr);
- if (mmcfg) {
writel(mmcfg, val);
- } else {
outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD);
outl(val, PORT_PCI_DATA);
- }
}
The pci_config_writeX() functions are called from 16-bit mode and 32-big segment mode, so this doesn't look correct to me.
Oh. Wasn't aware of that.
What device would call the pci_config_writeX() functions frequently enough that performance would matter?
I expect most vmexists come from PCI bar configuration in POST which runs in 32bit mode. I think we can restrict this to 32bit mode without loosing much.
What is the time improvement for using mmconfig?
--- a/src/hw/pci.c +++ b/src/hw/pci.c @@ -18,6 +18,8 @@ static u32 mmconfig;
static void *pci_mmconfig_addr(u16 bdf, u32 addr) {
- if (MODESEGMENT)
if (!mmconfig) return NULL; return (void*)(mmconfig + ((u32)bdf << 12) + addr);return NULL;
FWIW, given the low-level nature of these functions, it may be worth using wrappers like the following:
void pci_config_writel(u16 bdf, u32 addr, u32 val) { if (!MODESEGMENT && mmconfig) pci_mmconfig_writel(bdf, addr, val); else pci_ioconfig_writel(bdf, addr, val); }
-Kevin