[PATCH] Memmory mapped PCI configuration
Nico Huber <[email protected]> Tue, 18 Feb 2014 12:50:26 +0100
| Newsgroups | gmane.comp.emulators.bochs.devel |
|---|---|
| Message-ID | <[email protected]> |
Dear Bochs developers, please find attached a patch to implement memory mapped PCI configuration (MMConf) in Bochs. This PCIe style of configuration maps one 4K page for each PCI device' configuration space. My patch maps for this the 256MB from 0xd0000000 to 0xdfffffff. I haven't looked very deep if this conflicts with any other resources but first tests showed it working. If you wonder, we use MMConf to map individual PCI devices into VMX guests. Which is way easier than i/o port emulation. I'm not sure if I did everything the right way. Any comments on this patch are welcome. I can provide another patch that advertises this memory region through ACPI if anyone cares. Kind regards, Nico Huber -- M. Sc. Nico Huber Berater, SINA-Softwareentwicklung Public Sector secunet Security Networks AG Tel.: +49-201-5454-3635, Fax: +49-201-5454-1325 E-Mail: [email protected] Mergenthalerallee 77, 65760 Eschborn, Deutschland www.secunet.com ______________________________________________________________________ Sitz: Kronprinzenstraße 30, 45128 Essen, Deutschland Amtsgericht Essen HRB 13615 Vorstand: Dr. Rainer Baumgart (Vors.), Willem Bulthuis, Thomas Pleines Aufsichtsratsvorsitzender: Dr. Peter Zattler ______________________________________________________________________ Index: iodev/iodev.h =================================================================== --- iodev/iodev.h (Revision 11935) +++ iodev/iodev.h (Arbeitskopie) @@ -538,6 +538,11 @@ // are use each of the IRQ 0..15 lines are stored here char *irq_handler_name[BX_MAX_IRQS]; + static bx_bool mmcfg_read_handler(bx_phy_address a20addr, unsigned len, void *data, void *param); + bx_bool mmcfg_read(bx_phy_address a20addr, unsigned len, void *data); + static bx_bool mmcfg_write_handler(bx_phy_address a20addr, unsigned len, void *data, void *param); + bx_bool mmcfg_write(bx_phy_address a20addr, unsigned len, void *data); + static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); BX_DEV_SMF Bit32u read(Bit32u address, unsigned io_len); Index: iodev/devices.cc =================================================================== --- iodev/devices.cc (Revision 11935) +++ iodev/devices.cc (Arbeitskopie) @@ -262,6 +262,8 @@ DEV_register_ioread_handler(this, read_handler, i, "i440FX", 7); DEV_register_iowrite_handler(this, write_handler, i, "i440FX", 7); } + + DEV_register_memory_handlers(this, mmcfg_read_handler, mmcfg_write_handler, 0xd0000000, 0xdfffffff); } #endif @@ -357,6 +359,7 @@ void bx_devices_c::exit() { // delete i/o handlers before unloading plugins + DEV_unregister_memory_handlers(this, 0xd0000000, 0xdfffffff); struct io_handler_struct *io_read_handler = io_read_handlers.next; struct io_handler_struct *curr = NULL; while (io_read_handler != &io_read_handlers) { @@ -399,6 +402,77 @@ init_stubs(); } +bx_bool bx_devices_c::mmcfg_read_handler(bx_phy_address a20addr, unsigned len, void *data, void *param) +{ + bx_devices_c *class_ptr = (bx_devices_c *) param; + return class_ptr->mmcfg_read(a20addr, len, data); +} + +bx_bool bx_devices_c::mmcfg_read(bx_phy_address a20addr, unsigned len, void *data) +{ + if ((len != 1 ) && + (len != 2 || (a20addr & 0x1) != 0x0) && + (len != 4 || (a20addr & 0x3) != 0x0)) { + BX_PANIC(("Unsupported MMConf read at address 0x" FMT_PHY_ADDRX ", len %u !", a20addr, len)); + return 1; + } + + Bit8u bus, devfunc; + Bit16u regnum; + Bit32u handle, value; + + bus = (a20addr >> 20) & 0xff; + devfunc = (a20addr >> 12) & 0xff; + regnum = a20addr & 0xfff; + handle = pci.handler_id[devfunc]; + if (!bus && !(regnum & 0xf00) && (handle < BX_MAX_PCI_DEVICES)) + value = pci.pci_handler[handle].handler->pci_read_handler(regnum & 0xff, len); + else + value = 0xffffffff; + + switch (len) { + case 1: + *((Bit8u *)data) = value & 0xff; + break; + case 2: + *((Bit16u *)data) = value & 0xffff; + break; + case 4: + *((Bit32u *)data) = value; + break; + } + return 1; +} + +bx_bool bx_devices_c::mmcfg_write_handler(bx_phy_address a20addr, unsigned len, void *data, void *param) +{ + bx_devices_c *class_ptr = (bx_devices_c *) param; + return class_ptr->mmcfg_write(a20addr, len, data); +} + +bx_bool bx_devices_c::mmcfg_write(bx_phy_address a20addr, unsigned len, void *data) +{ + if ((len != 1 ) && + (len != 2 || (a20addr & 0x1) != 0x0) && + (len != 4 || (a20addr & 0x3) != 0x0)) { + BX_PANIC(("Unsupported MMConf write to address 0x" FMT_PHY_ADDRX ", len %u !", a20addr, len)); + return 1; + } + + Bit8u bus, devfunc; + Bit16u regnum; + Bit32u handle, value; + + bus = (a20addr >> 20) & 0xff; + devfunc = (a20addr >> 12) & 0xff; + regnum = a20addr & 0xfff; + handle = pci.handler_id[devfunc]; + if (!bus && !(regnum & 0xf00) && (handle < BX_MAX_PCI_DEVICES)) + pci.pci_handler[handle].handler->pci_write_handler(regnum & 0xff, *((Bit32u *)data), len); + + return 1; +} + Bit32u bx_devices_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) { #if !BX_USE_DEV_SMF ------------------------------------------------------------------------------ Managing the Performance of Cloud-Based Applications Take advantage of what the Cloud has to offer - Avoid Common Pitfalls. Read the Whitepaper. http://pubads.g.doubleclick.net/gampad/clk?id=121054471&iu=/4140/ostg.clktrk _______________________________________________ bochs-developers mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/bochs-developers