Skip to contentSkip to conversation

: PCI Host Proxy v0.1

RFC PATCH In review Gianni Tedesco 2 participants 5 messages May 31, 2004 – Jun 1, 2004 Kbuild

lore
Share & tools
lore
#0 lore raw

RFC PATCH 1/1 : PCI Host Proxy v0.1

Hi,

Attached is the first draft of a patch to add PCI Host <-> Guest proxy mechanism. This allows PCI devices on the host machine to be presented to the guest operating system for usage. This is similar to the bochs 'pcidev' functionality. This code is not ready for inclusion yet, rather it is just to show where I'm at and perhaps provoke some discussion.

The code works only with a Linux host operating system (though should compile everywhere). We use the /proc/bus/pci interface to gain access to the PCI resources in an architecture-portable way.

This code is mainly intended for people who wish to reverse engineer device drivers on proprietary operating systems. This is due to some fairly serious technical shortfalls, most notably our lack of ability to trap and emulate PCI DMA transfers.

How to use:
1. Apply patch to qemu, rebuild and reinstall.
2. Find the bus:dev.fn numbers of the device you wish to map in to qemu using lspci. Run qemu with the "-pci -pciproxy bus:dev.fn" command line switches eg: "-pci -pciproxy 00:0a.0".

Here is a screenshot to prove it works ;)
http://www.scaramanga.co.uk/stuff/qemu-pciproxy-0.1.png (47KB)

Current limitations:
o Memory resources are not mapped in yet.
o ROM resources are not mapped in yet.
o IRQs are not passed along yet.
o Will probably never support PCI DMA without guest OS patching.

Future Ideas:
o Fast logging of information between guest OS -> hardware
o Log reading / conversion tool, so reverse engineers can share info
o Support PCI-DMA by patching guest OS's
o USB proxy along the same lines
o AGP support (map GART with Linux agpgart)

Have fun :)

Makefile.target +1 -1
diff -urN qemu.orig/Makefile.target qemu/Makefile.target
@@ -232,7 +232,7 @@
 endif
 
 # must use static linking to avoid leaving stuff in virtual address space
-VL_OBJS=vl.o osdep.o block.o monitor.o pci.o
+VL_OBJS=vl.o osdep.o block.o monitor.o pci.o pciproxy.o
 
 ifeq ($(TARGET_ARCH), i386)
 # Hardware support
configure +5 -0
diff -urN qemu.orig/configure qemu/configure
@@ -390,6 +390,11 @@
 elif test -f "/usr/include/byteswap.h" ; then
   echo "#define HAVE_BYTESWAP_H 1" >> $config_h
 fi
+if test -f "/usr/include/sys/io.h"; then
+  echo "#define HAVE_SYS_IO_H 1" >> $config_h
+  echo "#define HAVE_IOPL 1" >> $config_h
+  echo "#define HAVE_IOPERM 1" >> $config_h
+fi
 if test "$gdbstub" = "yes" ; then
   echo "CONFIG_GDBSTUB=yes" >> $config_mak
   echo "#define CONFIG_GDBSTUB 1" >> $config_h
hw/pc.c +2 -0
diff -urN qemu.orig/hw/pc.c qemu/hw/pc.c
@@ -386,6 +386,8 @@
     if (pci_enabled) {
         i440fx_init();
         piix3_init();
+        if ( pciproxy_devpath )
+	    pciproxy_add_device(pciproxy_devpath);
     }
 
     /* init basic PC hardware */
hw/pciproxy.c +577 -0

577 lines not on this page · raw message

vl.c +6 -0
diff -urN qemu.orig/vl.c qemu/vl.c
@@ -129,6 +129,7 @@
 int audio_enabled = 0;
 int pci_enabled = 0;
 int prep_enabled = 0;
+char *pciproxy_devpath = NULL;
 
 /***********************************************************/
 /* x86 ISA bus support */
@@ -2015,6 +2016,7 @@
     QEMU_OPTION_no_code_copy,
     QEMU_OPTION_pci,
     QEMU_OPTION_prep,
+    QEMU_OPTION_pciproxy,
 };
 
 typedef struct QEMUOption {
@@ -2065,6 +2067,7 @@
 #ifdef TARGET_PPC
     { "prep", 0, QEMU_OPTION_prep },
 #endif
+    { "pciproxy", HAS_ARG, QEMU_OPTION_pciproxy },
     { NULL },
 };
 
@@ -2341,6 +2344,9 @@
             case QEMU_OPTION_prep:
                 prep_enabled = 1;
                 break;
+            case QEMU_OPTION_pciproxy:
+		pciproxy_devpath = (char *)optarg;
+                break;
             }
         }
     }
vl.h +4 -0
diff -urN qemu.orig/vl.h qemu/vl.h
@@ -434,6 +434,10 @@
 void pci_pmac_init(void);
 void pci_ppc_bios_init(void);
 
+/* pciproxy.c */
+void pciproxy_add_device(char *devpath);
+extern char *pciproxy_devpath;
+
 /* vga.c */
 
 #define VGA_RAM_SIZE (4096 * 1024)
#1 lore raw
Quoted 1 line · Gianni Tedesco

[snip]

Wow... This is very nice. I can see that it will help with driver support (via reverse engineering) a lot.

Best,
Kyle

#2 lore raw
In reply to Gianni Tedesco
Quoted 2 lines · Gianni Tedesco

Current limitations:
o Memory resources are not mapped in yet.

Fabrice,

Will the following work for PCI memory spaces? (I don't have any setups which do MMIO atm to test on).

for (i=addr; i < addr + len; i+=4)

    cpu_register_io_memory(i, pciproxy_readl, pciproxy_writel);

If so, can I allow it to pass down an opaque pointer?

Signature · 3 lines
// Gianni Tedesco (gianni at scaramanga dot co dot uk)
lynx --source www.scaramanga.co.uk/scaramanga.asc | gpg --import
8646BE7D: 6D9F 2287 870E A2C9 8F60 3A3C 91B5 7669 8646 BE7D
#3 lore raw
Quoted 11 lines · Gianni Tedesco
Quoted 2 lines · Gianni Tedesco

Current limitations:
o Memory resources are not mapped in yet.

Fabrice,

Will the following work for PCI memory spaces? (I don't have any setups which do MMIO atm to test on).

for (i=addr; i < addr + len; i+=4)

    cpu_register_io_memory(i, pciproxy_readl, pciproxy_writel);

erm, i mean, actually i do:

#define IOMEM_PCIPROXY (5 << IO_MEM_SHIFT)

cpu_register_io_memory(IOMEM_PCIPROXY >> IO_MEM_SHIFT,

                       pciproxy_readl,
                       pciproxy_writel);

cpu_register_phys_mem(addr, len, IOMEM_PCIPROXY);

And can i still make the change to cpu_register_io_memory to pass down an opaque pointer? Actually this would be nicer on the cpu_register_phys_mem, but that'd be an impact on hot-paths i guess so I'll just have to work around it in pciproxy.

Signature · 3 lines
// Gianni Tedesco (gianni at scaramanga dot co dot uk)
lynx --source www.scaramanga.co.uk/scaramanga.asc | gpg --import
8646BE7D: 6D9F 2287 870E A2C9 8F60 3A3C 91B5 7669 8646 BE7D
#4 lore raw
Quoted 4 lines · Gianni Tedesco

And can i still make the change to cpu_register_io_memory to pass down an opaque pointer? Actually this would be nicer on the cpu_register_phys_mem, but that'd be an impact on hot-paths i guess so I'll just have to work around it in pciproxy.

Actually it would be better served all round if I added an IO_MEM_CALLBACK and added a simple infrastructure to do:

cpu_register_callback_mem(addr, len, read_cbfn, write_cbfn);

That way there'd only be a lookup cost with something that used it. I'll hack up a patch to do that. And post it when ready.

Signature · 3 lines
// Gianni Tedesco (gianni at scaramanga dot co dot uk)
lynx --source www.scaramanga.co.uk/scaramanga.asc | gpg --import
8646BE7D: 6D9F 2287 870E A2C9 8F60 3A3C 91B5 7669 8646 BE7D