qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH,RFC]: PCI Host Proxy v0.1
@ 2004-05-31 17:16 Gianni Tedesco
  2004-05-31 18:48 ` Kyle Hayes
  2004-06-01  0:04 ` Gianni Tedesco
  0 siblings, 2 replies; 5+ messages in thread
From: Gianni Tedesco @ 2004-05-31 17:16 UTC (permalink / raw)
  To: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 1647 bytes --]

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 :)

[-- Attachment #2: qemu-pciproxy-0.1.diff --]
[-- Type: text/x-patch, Size: 16645 bytes --]

diff -urN qemu.orig/Makefile.target qemu/Makefile.target
--- qemu.orig/Makefile.target	2004-05-31 16:53:24.000000000 +0100
+++ qemu/Makefile.target	2004-05-31 16:53:19.000000000 +0100
@@ -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
diff -urN qemu.orig/configure qemu/configure
--- qemu.orig/configure	2004-05-31 16:53:24.000000000 +0100
+++ qemu/configure	2004-05-31 16:53:19.000000000 +0100
@@ -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
diff -urN qemu.orig/hw/pc.c qemu/hw/pc.c
--- qemu.orig/hw/pc.c	2004-05-31 16:53:24.000000000 +0100
+++ qemu/hw/pc.c	2004-05-31 16:53:19.000000000 +0100
@@ -386,6 +386,8 @@
     if (pci_enabled) {
         i440fx_init();
         piix3_init();
+        if ( pciproxy_devpath )
+	    pciproxy_add_device(pciproxy_devpath);
     }
 
     /* init basic PC hardware */
diff -urN qemu.orig/hw/pciproxy.c qemu/hw/pciproxy.c
--- qemu.orig/hw/pciproxy.c	1970-01-01 01:00:00.000000000 +0100
+++ qemu/hw/pciproxy.c	2004-05-31 17:33:13.000000000 +0100
@@ -0,0 +1,577 @@
+/*
+ * QEMU PCI Host proxy
+ * Copyright (c) 2004 Gianni Tedesco
+ * This code is released under the terms of the GNU GPL v2.
+ *
+ * This code is dedicated towards my muse, my inspiration, Broadcom Corporation.
+ * Without your spite I would not have been compelled to write this code.
+ *
+ * TODO:
+ *  o Support memory mapped resources
+ *  o Support ROM resources
+ *  o Map IRQs
+*/
+
+#include "vl.h"
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#if HAVE_SYS_IO_H
+#include <sys/io.h>
+#endif
+
+#define PROC_DEVICES "/proc/bus/pci/devices"
+#define PCIPROXY_RESOURCES 7
+#define PCIPROXY_ROM_SLOT 6
+
+/* Ioctls for /proc/bus/pci/X/Y nodes. */
+#define PCIIOC_BASE             ('P' << 24 | 'C' << 16 | 'I' << 8)
+/* Get controller for PCI device. */
+#define PCIIOC_CONTROLLER       (PCIIOC_BASE | 0x00)
+/* Set mmap state to I/O space. */
+#define PCIIOC_MMAP_IS_IO       (PCIIOC_BASE | 0x01)
+/* Set mmap state to MEM space. */
+#define PCIIOC_MMAP_IS_MEM      (PCIIOC_BASE | 0x02)
+/* Enable/disable write-combining. */
+#define PCIIOC_WRITE_COMBINE    (PCIIOC_BASE | 0x03)
+/* Send user-defined signal for irqs */
+#define PCIIOC_SIGIRQ		(PCIIOC_BASE | 0x04)
+struct pci_sigirq {
+	int sig;
+	void *ptr;
+};
+
+struct pciproxy {
+	struct PCIDevice pcidev;
+	uint32_t len[PCIPROXY_RESOURCES];
+	uint32_t qemu_map[PCIPROXY_RESOURCES];
+	void *map[PCIPROXY_RESOURCES];
+	uint32_t io_allowed;
+	uint32_t bar[PCIPROXY_RESOURCES];
+	int dev, bus, fn;
+	int fd;
+};
+
+static inline const char *sys_err(void)
+{
+	return strerror(errno);
+}
+
+static int easy_explode(char *str, char split, char **toks, int max_toks)
+{
+	char *tmp;
+	int tok;
+	int state;
+
+	for(tmp=str,state=tok=0; *tmp && tok < max_toks; tmp++) {
+		if ( state == 0 ) {
+			if ( *tmp == split ) {
+				toks[tok++] = NULL;
+			}else if ( !isspace(*tmp) ) {
+				state = 1;
+				toks[tok++] = tmp;
+			}
+		}else if ( state == 1 ) {
+			if ( *tmp == split || isspace(*tmp) ) {
+				*tmp = '\0';
+				state = 0;
+			}
+		}
+	}
+
+	return tok;
+}
+
+#if 0
+static int read_config_dword(struct pciproxy *pci, uint32_t idx, uint32_t *word)
+{
+	ssize_t ret = pread(pci->fd, word, sizeof(*word), idx);
+	*word = le32_to_cpu(*word);
+	return (ret == (ssize_t)sizeof(*word));
+}
+
+static int read_config_word(struct pciproxy *pci, uint32_t idx, uint16_t *word)
+{
+	ssize_t ret = pread(pci->fd, word, sizeof(*word), idx);
+	*word = le16_to_cpu(*word);
+	return (ret == (ssize_t)sizeof(*word));
+}
+
+static int read_config_byte(struct pciproxy *pci, uint32_t idx, uint8_t *word)
+{
+	ssize_t ret = pread(pci->fd, word, sizeof(*word), idx);
+	return (ret == (ssize_t)sizeof(*word));
+}
+
+static int write_config_dword(struct pciproxy *pci, uint32_t idx, uint32_t word)
+{
+	ssize_t ret;
+	word = cpu_to_le32(word);
+	ret = pwrite(pci->fd, &word, sizeof(word), idx);
+	return (ret == (ssize_t)sizeof(word));
+}
+
+static int write_config_word(struct pciproxy *pci, uint32_t idx, uint16_t word)
+{
+	ssize_t ret;
+	word = cpu_to_le16(word);
+	ret = pwrite(pci->fd, &word, sizeof(word), idx);
+	return (ret == (ssize_t)sizeof(word));
+}
+
+static int write_config_byte(struct pciproxy *pci, uint32_t idx, uint8_t word)
+{
+	ssize_t ret;
+	ret = pwrite(pci->fd, &word, sizeof(word), idx);
+	return (ret == (ssize_t)sizeof(word));
+}
+#endif
+
+/* Uses /proc/bus/devices to grab the length of the resources on our PCI
+ * device in a platform independant way.
+ */
+static int peek_resources(struct pciproxy *pci)
+{
+	FILE *f;
+	char buf[512];
+	char *tok[18];
+	uint32_t num;
+	int n, i;
+	
+	f = fopen(PROC_DEVICES, "r");
+	if ( f == NULL ) {
+		fprintf(stderr, "%s: open(): %s\n", PROC_DEVICES, sys_err());
+		return 0;
+	}
+
+	while ( fgets(buf, sizeof(buf), f) ) {
+		char *ptr;
+		
+		ptr = strchr(buf, '\r');
+		if ( ptr == NULL )
+			ptr = strchr(buf, '\n');
+		if ( ptr == NULL )
+			break;
+		*ptr = '\0';
+
+		n = easy_explode(buf, '\0', tok, 18);
+		if ( n < 17 )
+			continue;
+
+		num = strtoul(tok[0], NULL, 16);
+		if ( pci->bus != ((num & 0xff00) >> 8) )
+			continue;
+		if ( pci->dev != ((num & 0x00ff) >> 3) )
+			continue;
+		if ( pci->fn != (num & 0x7) )
+			continue;
+
+		for(i=0; i < PCIPROXY_RESOURCES; i++) {
+			num = strtoul(tok[10 + i], NULL, 16);
+			pci->len[i] = num;
+		}
+
+		fclose(f);
+		return 1;
+	}
+
+	fclose(f);
+	return 0;
+}
+
+/* Final fallback path if mmap and ioperm fails, we just use iopl to raise
+ * our I/O priv level so that we can do any I/O we like.
+ */
+static int map_with_iopl(struct pciproxy *pci, int i)
+{
+#if HAVE_IOPERM
+	int ret;
+
+	ret = iopl(3);
+	if ( ret == 0 ) {
+		pci->io_allowed |= (1<<i);
+		return 1;
+	}
+
+	fprintf(stderr, "%.2x:%.2x.%x iopl() slot %i: %s\n",
+		pci->bus, pci->dev, pci->fn, i, sys_err());
+#else
+	fprintf(stderr, "%.2x:%.2x.%x ioperm() slot %i: %s\n",
+		pci->bus, pci->dev, pci->fn, i, sys_err());
+#endif
+	return 0;
+}
+
+/* First fallback path if mmap failes, try to use ioperm for granular
+ * permission granting to the I/O ports.
+ */
+static int map_with_ioperm(struct pciproxy *pci, int i, uint32_t bar)
+{
+#if HAVE_IOPERM
+	u_int32_t from, to;
+	int ret;
+
+	from = bar & ~0x3;
+	to = from + pci->len[i];
+
+	ret = ioperm(from, to, 1);
+	if ( ret < 0 )
+		return map_with_iopl(pci, i);
+	pci->io_allowed |= (1<<i);
+	return 1;
+#else
+	fprintf(stderr, "%.2x:%.2x.%x mmap() slot %i: %s\n",
+		pci->bus, pci->dev, pci->fn, i, sys_err());
+	return 0;
+#endif
+}
+
+/* Try to mmap a given PCI resource from the /proc/bus/pci/XX/YY.Z file */
+static int map_resource(struct pciproxy *pci, int i, void *start_addr)
+{
+	uint32_t base, flags, len, ofs, pgmask, bar;
+	int prot, ioc, mmflags;
+	void *map;
+
+	len = pci->len[i];
+	bar = pci->bar[i];
+
+	if ( start_addr ) {
+		mmflags = MAP_SHARED | MAP_FIXED;
+	}else{
+		mmflags = MAP_SHARED;
+	}
+
+	if ( i == PCIPROXY_ROM_SLOT ) {
+		prot = PROT_READ;
+	}else{
+		prot = PROT_READ|PROT_WRITE;
+	}
+
+	if ( bar & PCI_ADDRESS_SPACE_IO ) {
+		flags = (bar & 0x3);
+		base = (bar & ~0x3);
+		ioc = PCIIOC_MMAP_IS_IO;
+	}else{
+		flags = (bar & 0xf);
+		base = (bar & ~0xf);
+		ioc = PCIIOC_MMAP_IS_MEM;
+	}
+
+	/* Round base address down to the nearest page boundary and length
+	 * up to the the nearest page boundary in order that we may mmap
+	 * the resource range.
+	 *
+	 * XXX: Assumes page size is a power of two. (big deal)
+	 */
+	pgmask  = sysconf(_SC_PAGESIZE) - 1;
+
+	ofs = base & pgmask;
+	base &= ~pgmask;
+	len += pgmask;
+	len &= ~pgmask;
+
+	if ( ioctl(pci->fd, ioc) ) {
+		fprintf(stderr, "%.2x:%.2x.%x ioctl() slot %i: %s\n",
+			pci->bus, pci->dev, pci->fn, i, sys_err());
+		return 0;
+	}
+
+	map = mmap(start_addr, len, prot, mmflags, pci->fd, base);
+	if ( (map == MAP_FAILED) ) {
+		if ( (flags & PCI_ADDRESS_SPACE_IO ) )
+			return map_with_ioperm(pci, i, bar);
+		fprintf(stderr, "%.2x:%.2x.%x mmap() slot %i: %s\n",
+			pci->bus, pci->dev, pci->fn, i, sys_err());
+		return 0;
+	}
+
+	pci->map[i] = map + ofs;
+	return 1;
+}
+
+/* Construct the filename of the /proc/bus/pci/XX/YY.Z file to open for our
+ * device and open it.
+ */
+static int open_proc_bus_pci(struct pciproxy *pci)
+{
+	char path[1024];
+	ssize_t ret;
+
+	snprintf(path, sizeof(path), "/proc/bus/pci/%.2x/%.2x.%x",
+		pci->bus, pci->dev, pci->fn);
+
+	pci->fd = open(path, O_RDWR);
+	if ( pci->fd < 0 ) {
+		fprintf(stderr, "%s: open(): %s\n", path, sys_err());
+		return 0;
+	}
+
+	ret = pread(pci->fd, pci->pcidev.config, sizeof(pci->pcidev.config), 0);
+	if ( ret != (ssize_t)sizeof(pci->pcidev.config) ) {
+intr:
+		if ( close(pci->fd) && errno == EINTR )
+			goto intr;
+		return 0;
+	}
+
+	/* Directly read the bar because on some architectures like PPC, the
+	 * kernels mapped base doesn't correspond to the address we need
+	 * to mmap on this FD. Also we need this info later on...
+	 */
+	pci->bar[0] = le32_to_cpu(*(uint32_t *)(pci->pcidev.config + 0x10));
+	pci->bar[1] = le32_to_cpu(*(uint32_t *)(pci->pcidev.config + 0x14));
+	pci->bar[2] = le32_to_cpu(*(uint32_t *)(pci->pcidev.config + 0x18));
+	pci->bar[3] = le32_to_cpu(*(uint32_t *)(pci->pcidev.config + 0x1c));
+	pci->bar[4] = le32_to_cpu(*(uint32_t *)(pci->pcidev.config + 0x20));
+	pci->bar[5] = le32_to_cpu(*(uint32_t *)(pci->pcidev.config + 0x24));
+	pci->bar[6] = le32_to_cpu(*(uint32_t *)(pci->pcidev.config + 0x30));
+
+	return 1;
+}
+
+static void iowrite(void *ptr, uint32_t addr, uint32_t data, uint32_t len)
+{
+	struct pciproxy *pci = (struct pciproxy *)ptr;
+	uint32_t ofs;
+	int i;
+
+	for(i=0; i < PCIPROXY_RESOURCES; i++) {
+		if ( pci->bar[i] && 
+			addr >= pci->qemu_map[i] &&
+			addr <= pci->qemu_map[i] + pci->len[i] ) {
+			break;
+		}
+	}
+
+	if ( i >= PCIPROXY_RESOURCES ) {
+		fprintf(stderr, "Write to unknown I/O resource (0x%.8x/%u)\n",
+				addr, len);
+		return;
+	}
+
+	ofs = addr - pci->qemu_map[i];
+	addr = pci->bar[i] & ~0x03;
+
+	if ( pci->map[i] ) {
+		/* TODO */
+		return;
+	}else{
+#if HAVE_SYS_IO_H
+		if ( !(pci->io_allowed & (1<<i)) ) 
+			return;
+
+		switch ( len ) {
+		case 1:
+			outb(data, addr + ofs);
+			break;
+		case 2:
+			outw(data, addr + ofs);
+			break;
+		case 3:
+			outl(data, addr + ofs);
+			break;
+		default:
+			return;
+		}
+#endif
+	}
+
+	printf("%u byte write 0x%.x/0x%.x(%u) wrote 0x%.8x\n",
+		len, addr + ofs, pci->qemu_map[i] + ofs, ofs, data);
+}
+
+static uint32_t ioread(void *ptr, uint32_t addr, uint32_t len)
+{
+	struct pciproxy *pci = (struct pciproxy *)ptr;
+	uint32_t ret, ofs;
+	int i;
+
+	for(i=0; i < PCIPROXY_RESOURCES; i++) {
+		if ( pci->bar[i] && 
+			addr >= pci->qemu_map[i] &&
+			addr <= pci->qemu_map[i] + pci->len[i] ) {
+			break;
+		}
+	}
+
+	if ( i >= PCIPROXY_RESOURCES ) {
+		fprintf(stderr, "Read from unknown I/O resource (0x%.8x/%u)\n",
+				addr, len);
+		return 0xffffffff;
+	}
+
+	ofs = addr - pci->qemu_map[i];
+	addr = pci->bar[i] & ~0x03;
+
+	if ( pci->map[i] ) {
+		/* TODO */
+		printf("Memory mapped I/O registers\n");
+		return 0xffffffff;
+	}else{
+#if HAVE_SYS_IO_H
+		if ( !(pci->io_allowed & (1<<i)) ) {
+			printf("IO not allowed\n");
+			return 0xffffffff;
+		}
+
+		switch ( len ) {
+		case 1:
+			ret = inb(addr + ofs);
+			break;
+		case 2:
+			ret = inw(addr + ofs);
+			break;
+		case 3:
+			ret = inl(addr + ofs);
+			break;
+		default:
+			ret = 0xffffffff;
+		}
+#endif
+	}
+
+	printf("%u byte read 0x%.x/0x%.x(%u) returned 0x%.8x\n",
+		len, addr + ofs, pci->qemu_map[i] + ofs, ofs, ret);
+	return ret;
+}
+
+static void iowritel(void *ptr, uint32_t addr, uint32_t data)
+{
+	iowrite(ptr, addr, data, 4);
+}
+static void iowritew(void *ptr, uint32_t addr, uint32_t data)
+{
+	iowrite(ptr, addr, data, 2);
+}
+static void iowriteb(void *ptr, uint32_t addr, uint32_t data)
+{
+	iowrite(ptr, addr, data, 1);
+}
+static uint32_t ioreadl(void *ptr, uint32_t addr)
+{
+	return ioread(ptr, addr, 4);
+}
+static uint32_t ioreadw(void *ptr, uint32_t addr)
+{
+	return ioread(ptr, addr, 2);
+}
+static uint32_t ioreadb(void *ptr, uint32_t addr)
+{
+	return ioread(ptr, addr, 1);
+}
+
+static void mapfunc(PCIDevice *pci_dev, int i,
+			uint32_t addr, uint32_t size, int type)
+{
+	struct pciproxy *pci = (struct pciproxy *)pci_dev;
+
+	pci->qemu_map[i] = addr;
+
+#if 0
+	if ( pci->map[i] ) {
+		uint32_t map;
+		uint32_t len;
+		uint32_t pgmask  = sysconf(_SC_PAGESIZE) - 1;
+		void *ret;
+
+		map = (uint32_t)pci->map[i];
+		len = pci->len[i];
+
+		map &= ~pgmask;
+		len += pgmask;
+		len &= ~pgmask;
+		printf("Unmapping slot #%i 0x%.8x %u\n", i, map, len);
+		munmap((void *)map, (size_t)len);
+		ret = mmap((void *)map, (size_t)len,
+			PROT_READ|PROT_WRITE|PROT_EXEC,
+			MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
+		if ( ret != (void *)map )
+			printf("FAILED\n");
+	}
+#endif
+
+	if ( type == PCI_ADDRESS_SPACE_IO ) {
+		uint32_t len = pci->len[i];
+
+		if ( !map_resource(pci, i, NULL) )
+			return;
+
+		register_ioport_read(addr, len, 4, ioreadl, pci);
+		register_ioport_read(addr, len, 2, ioreadw, pci);
+		register_ioport_read(addr, len, 1, ioreadb, pci);
+		register_ioport_write(addr, len, 4, iowritel, pci);
+		register_ioport_write(addr, len, 2, iowritew, pci);
+		register_ioport_write(addr, len, 1, iowriteb, pci);
+
+		printf("Mapped io slot #%i [0x%.8x] 0x%.8x (len=%u)\n",
+			i, pci->bar[i], addr, len);
+	}else{
+#if 0
+		if ( !map_resource(pci, i, phys_ram_base + addr) )
+			return;
+
+		printf("Mapped mem slot #%i [0x%.8x] 0x%.8x / %p - %p\n",
+			i, pci->bar[i], addr, phys_ram_base,
+			phys_ram_base + addr);
+#endif
+	}
+}
+
+void pciproxy_add_device(char *devpath)
+{
+	char *tok[3] = {NULL};
+	struct pciproxy *pci;
+	int i;
+
+	easy_explode(devpath, '.', &tok[1], 2);
+	if ( easy_explode(devpath, ':', &tok[0], 2) == 1 ) {
+		tok[1] = tok[0];
+		tok[0] = NULL;
+	}
+	for(i=0; i < 3; i++)
+		if ( tok[i] == NULL )
+			tok[i] = "0";
+
+	pci = (struct pciproxy *)pci_register_device("pciproxy",
+				sizeof(*pci), 0, -1,
+				NULL, NULL);
+
+	if ( pci == NULL ) {
+		fprintf(stderr, "pciproxy: Adding device failed\n");
+		return;
+	}
+
+	pci->bus = strtol(tok[0], NULL, 16);
+	pci->dev = strtol(tok[1], NULL, 16);
+	pci->fn = strtol(tok[2], NULL, 16);
+
+	printf("Adding PCI Host Proxy device: %.2x:%.2x:%x\n",
+		pci->bus, pci->dev, pci->fn);
+
+	peek_resources(pci);
+
+	if ( !open_proc_bus_pci(pci) ) {
+		printf("OI\n");
+		return;
+	}
+
+	for(i=0; i < PCIPROXY_RESOURCES; i++) {
+		uint32_t type;
+
+		/* XXX: Not yet implemented */
+		if ( i == PCIPROXY_ROM_SLOT )
+			continue;
+
+		type = (pci->bar[i] & PCI_ADDRESS_SPACE_IO) ?
+			PCI_ADDRESS_SPACE_IO :
+			PCI_ADDRESS_SPACE_MEM ;
+
+		if ( pci->bar[i] ) {
+			printf("Registering region %i\n", i);
+			pci_register_io_region((struct PCIDevice *)pci,
+					i, pci->len[i], type, mapfunc);
+		}
+	}
+
+	/* TODO: Setup sigirg if present, if not, warn */
+}
diff -urN qemu.orig/vl.c qemu/vl.c
--- qemu.orig/vl.c	2004-05-31 16:53:24.000000000 +0100
+++ qemu/vl.c	2004-05-31 17:35:45.000000000 +0100
@@ -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;
             }
         }
     }
diff -urN qemu.orig/vl.h qemu/vl.h
--- qemu.orig/vl.h	2004-05-31 16:53:24.000000000 +0100
+++ qemu/vl.h	2004-05-31 16:53:19.000000000 +0100
@@ -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)

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Qemu-devel] [PATCH,RFC]: PCI Host Proxy v0.1
  2004-05-31 17:16 [Qemu-devel] [PATCH,RFC]: PCI Host Proxy v0.1 Gianni Tedesco
@ 2004-05-31 18:48 ` Kyle Hayes
  2004-06-01  0:04 ` Gianni Tedesco
  1 sibling, 0 replies; 5+ messages in thread
From: Kyle Hayes @ 2004-05-31 18:48 UTC (permalink / raw)
  To: qemu-devel

On Monday 31 May 2004 10:16, Gianni Tedesco wrote:
> [snip]

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

Best,
Kyle

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Qemu-devel] [PATCH,RFC]: PCI Host Proxy v0.1
  2004-05-31 17:16 [Qemu-devel] [PATCH,RFC]: PCI Host Proxy v0.1 Gianni Tedesco
  2004-05-31 18:48 ` Kyle Hayes
@ 2004-06-01  0:04 ` Gianni Tedesco
  2004-06-01  0:12   ` Gianni Tedesco
  1 sibling, 1 reply; 5+ messages in thread
From: Gianni Tedesco @ 2004-06-01  0:04 UTC (permalink / raw)
  To: qemu-devel

On Mon, 2004-05-31 at 18:16 +0100, Gianni Tedesco wrote:
> 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?

-- 
// 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

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Qemu-devel] [PATCH,RFC]: PCI Host Proxy v0.1
  2004-06-01  0:04 ` Gianni Tedesco
@ 2004-06-01  0:12   ` Gianni Tedesco
  2004-06-01  0:22     ` Gianni Tedesco
  0 siblings, 1 reply; 5+ messages in thread
From: Gianni Tedesco @ 2004-06-01  0:12 UTC (permalink / raw)
  To: qemu-devel

On Tue, 2004-06-01 at 01:04 +0100, Gianni Tedesco wrote:
> On Mon, 2004-05-31 at 18:16 +0100, Gianni Tedesco wrote:
> > 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.

-- 
// 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

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Qemu-devel] [PATCH,RFC]: PCI Host Proxy v0.1
  2004-06-01  0:12   ` Gianni Tedesco
@ 2004-06-01  0:22     ` Gianni Tedesco
  0 siblings, 0 replies; 5+ messages in thread
From: Gianni Tedesco @ 2004-06-01  0:22 UTC (permalink / raw)
  To: qemu-devel

On Tue, 2004-06-01 at 01:12 +0100, Gianni Tedesco wrote:
> 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.

-- 
// 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

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2004-06-01  0:23 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-05-31 17:16 [Qemu-devel] [PATCH,RFC]: PCI Host Proxy v0.1 Gianni Tedesco
2004-05-31 18:48 ` Kyle Hayes
2004-06-01  0:04 ` Gianni Tedesco
2004-06-01  0:12   ` Gianni Tedesco
2004-06-01  0:22     ` Gianni Tedesco

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).