PT_LOG("Error: couldn't locate device in libpci structures\n");
return NULL;
}
+ pci_fill_info(pci_dev, PCI_FILL_IRQ | PCI_FILL_BASES | PCI_FILL_ROM_BASE | PCI_FILL_SIZES);
if ( e_devfn == PT_VIRT_DEVFN_AUTO ) {
/*indicate a static assignment(not hotplug), so find a free PCI hot plug slot */
}
}
}
+
+ if (pci_enabled) {
+ PCI_EMULATION_INFO *p;
+ for (p = PciEmulationInfoHead; p != NULL; p = p->next) {
+ pci_emulation_init(pci_bus, p);
+ }
+ }
}
static void pc_init_pci(ram_addr_t ram_size, int vga_ram_size,
int power_on_php_slot(int);
int power_off_php_slot(int);
+/* pci_emulation.c */
+#include "hw/pci_emulation.h"
+
void do_pci_add(char *devname);
void do_pci_del(char *devname);
--- /dev/null
+/*
+ * Changes to PCI emulation made by Marathon Technologies, June 2008
+ */
+
+#include "vl.h"
+
+typedef struct {
+ PCIDevice dev;
+} PCI_EMULATION_State;
+
+void parse_pci_emulation_info(char *config_text, PCI_EMULATION_INFO *pci_emulation_info)
+{
+ char *p;
+ int i;
+ int ret;
+ for (p = config_text, i = 0; *p != '\0'; p++) {
+ if (*p == ':') {
+ break;
+ }
+ if (i < sizeof(pci_emulation_info->name) - 1) {
+ pci_emulation_info->name[i] = *p;
+ i++;
+ }
+ }
+ pci_emulation_info->name[i] = '\0';
+ if (*p == '\0') return;
+ p++;
+ ret = sscanf(p, "%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x",
+ &(pci_emulation_info->vendorid),
+ &(pci_emulation_info->deviceid),
+ &(pci_emulation_info->command),
+ &(pci_emulation_info->status),
+ &(pci_emulation_info->revision),
+ &(pci_emulation_info->classcode),
+ &(pci_emulation_info->headertype),
+ &(pci_emulation_info->subvendorid),
+ &(pci_emulation_info->subsystemid),
+ &(pci_emulation_info->interruputline),
+ &(pci_emulation_info->interruputpin));
+#ifdef DEBUG
+ fprintf(logfile, "qemu: pciemulation %s:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x\n",
+ pci_emulation_info->name,
+ pci_emulation_info->vendorid,
+ pci_emulation_info->deviceid,
+ pci_emulation_info->command,
+ pci_emulation_info->status,
+ pci_emulation_info->revision,
+ pci_emulation_info->classcode,
+ pci_emulation_info->headertype,
+ pci_emulation_info->subvendorid,
+ pci_emulation_info->subsystemid,
+ pci_emulation_info->interruputline,
+ pci_emulation_info->interruputpin);
+#endif
+ return;
+}
+
+static void pci_emulation_save(QEMUFile *f, void *opaque)
+{
+ PCIDevice *d = opaque;
+
+ pci_device_save(d, f);
+}
+
+static int pci_emulation_load(QEMUFile *f, void *opaque, int version_id)
+{
+ PCIDevice *d = opaque;
+
+ if (version_id != 1)
+ return -EINVAL;
+
+ return pci_device_load(d, f);
+}
+
+
+void pci_emulation_init(PCIBus *bus, PCI_EMULATION_INFO *pci_emulation_info)
+{
+ int instance_id;
+ PCI_EMULATION_State *d;
+ uint8_t *pci_conf;
+
+#ifdef DEBUG
+ fprintf(logfile, "qemu: pciinit\n");
+#endif
+
+ d = (PCI_EMULATION_State *)pci_register_device(bus,
+ pci_emulation_info->name,
+ sizeof(PCI_EMULATION_State),
+ -1,
+ NULL, NULL);
+ pci_conf = d->dev.config;
+ pci_conf[0x00] = pci_emulation_info->vendorid & 0xff;
+ pci_conf[0x01] = (pci_emulation_info->vendorid & 0xff00) >> 8;
+ pci_conf[0x02] = pci_emulation_info->deviceid & 0xff;
+ pci_conf[0x03] = (pci_emulation_info->deviceid & 0xff00) >> 8;
+ pci_conf[0x04] = pci_emulation_info->command & 0xff;
+ pci_conf[0x05] = (pci_emulation_info->command & 0xff00) >> 8;
+ pci_conf[0x06] = pci_emulation_info->status & 0xff;
+ pci_conf[0x07] = (pci_emulation_info->status & 0xff00) >> 8;
+ pci_conf[0x08] = pci_emulation_info->revision & 0xff;
+ pci_conf[0x09] = pci_emulation_info->classcode & 0xff;
+ pci_conf[0x0a] = (pci_emulation_info->classcode & 0xff00) >> 8;
+ pci_conf[0x0b] = (pci_emulation_info->classcode & 0xff0000) >> 16;
+ pci_conf[0x0e] = pci_emulation_info->headertype & 0xff;
+ pci_conf[0x2c] = pci_emulation_info->subvendorid & 0xff;
+ pci_conf[0x2d] = (pci_emulation_info->subvendorid & 0xff00) >> 8;
+ pci_conf[0x2e] = pci_emulation_info->subsystemid & 0xff;
+ pci_conf[0x2f] = (pci_emulation_info->subsystemid & 0xff00) >> 8;
+ pci_conf[0x3c] = pci_emulation_info->interruputline & 0xff;
+ pci_conf[0x3d] = pci_emulation_info->interruputpin & 0xff;
+
+ instance_id = pci_bus_num(bus) << 8 | d->dev.devfn;
+ register_savevm(pci_emulation_info->name, instance_id,
+ 1, pci_emulation_save, pci_emulation_load, d);
+
+
+ return;
+}
--- /dev/null
+/*
+ * Changes to PCI emulation made by Marathon Technologies, June 2008
+ */
+
+typedef struct PCI_EMULATION_INFO_t {
+ struct PCI_EMULATION_INFO_t *next;
+ char name[32];
+ unsigned int vendorid;
+ unsigned int deviceid;
+ unsigned int command;
+ unsigned int status;
+ unsigned int revision;
+ unsigned int classcode;
+ unsigned int headertype;
+ unsigned int subvendorid;
+ unsigned int subsystemid;
+ unsigned int interruputline;
+ unsigned int interruputpin;
+} PCI_EMULATION_INFO;
+
+void parse_pci_emulation_info(char *config_text, PCI_EMULATION_INFO *pci_emulation_info);
+void pci_emulation_init(PCIBus *bus, PCI_EMULATION_INFO *pci_emulation_info);
+
+extern PCI_EMULATION_INFO *PciEmulationInfoHead;
PT_LOG("error map msi\n");
return -1;
}
+
+ if ( pirq < 0 )
+ {
+ PT_LOG("invalid pirq number\n");
+ return -1;
+ }
+
dev->msi->pirq = pirq;
PT_LOG("msi mapped with pirq %x\n", pirq);
#define _PT_MSI_H
#include "vl.h"
-#include "pci/header.h"
#include "pci/pci.h"
#include "pass-through.h"
+#define PCI_CAP_ID_MSI 0x05 /* Message Signalled Interrupts */
+#define PCI_CAP_ID_MSIX 0x11 /* MSI-X */
+
+/* Message Signalled Interrupts registers */
+#define PCI_MSI_FLAGS 2 /* Various flags */
+#define PCI_MSI_FLAGS_64BIT 0x80 /* 64-bit addresses allowed */
+#define PCI_MSI_FLAGS_QSIZE 0x70 /* Message queue size configured */
+#define PCI_MSI_FLAGS_QMASK 0x0e /* Maximum queue size available */
+#define PCI_MSI_FLAGS_ENABLE 0x01 /* MSI feature enabled */
+#define PCI_MSI_RFU 3 /* Rest of capability flags */
+#define PCI_MSI_ADDRESS_LO 4 /* Lower 32 bits */
+#define PCI_MSI_ADDRESS_HI 8 /* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */
+#define PCI_MSI_DATA_32 8 /* 16 bits of data for 32-bit devices */
+#define PCI_MSI_DATA_64 12 /* 16 bits of data for 64-bit devices */
+
+/* MSI-X */
+#define PCI_MSIX_ENABLE 0x8000
+#define PCI_MSIX_MASK 0x4000
+#define PCI_MSIX_TABSIZE 0x03ff
+#define PCI_MSIX_TABLE 4
+#define PCI_MSIX_PBA 8
+#define PCI_MSIX_BIR 0x7
+
#define MSI_FLAG_UNINIT 0x1000
#define PT_MSI_MAPPED 0x2000
+ */
#define MSI_ADDR_HEADER 0xfee00000
-#define MSI_TARGET_CPU_SHIFT 12
+#define MSI_TARGET_CPU_SHIFT 12
#define MSI_ADDR_DESTID_MASK 0xfff0000f
#define MSI_ADDR_DESTID_CPU(cpu) ((cpu) << MSI_TARGET_CPU_SHIFT)
qemu_free(s);
}
-USBDevice *usb_msd_init(const char *filename)
+USBDevice *usb_msd_init(const char *filename, BlockDriver *drv)
{
MSDState *s;
BlockDriverState *bdrv;
return NULL;
bdrv = bdrv_new("usb");
- if (bdrv_open(bdrv, filename, 0) < 0)
+ if (bdrv_open2(bdrv, filename, 0, drv) < 0)
goto fail;
if (qemu_key_check(bdrv, filename))
goto fail;
USBDevice *usb_keyboard_init(void);
/* usb-msd.c */
-USBDevice *usb_msd_init(const char *filename);
+USBDevice *usb_msd_init(const char *filename, BlockDriver *drv);
/* usb-wacom.c */
USBDevice *usb_wacom_init(void);
static int domain_create_ring(struct domain *dom)
{
- int err, remote_port, ring_ref, rc;
+ int err, remote_port, ring_ref, limit, rc;
err = xs_gather(dom->xsh, dom->serialpath,
"ring-ref", "%u", &ring_ref,
"port", "%i", &remote_port,
+ "limit", "%i", &limit,
NULL);
if (err) {
err = xs_gather(dom->xsh, dom->conspath,
"ring-ref", "%u", &ring_ref,
"port", "%i", &remote_port,
+ "limit", "%i", &limit,
NULL);
if (err) {
fprintf(stderr, "Console: failed to find ring-ref/port yet\n");
dom->use_consolepath = 1;
} else
dom->use_consolepath = 0;
- fprintf(stderr, "Console: got ring-ref %d port %d\n", ring_ref, remote_port);
+ dom->buffer.max_capacity = limit;
+ fprintf(stderr, "Console: got ring-ref %d port %d limit %d\n",
+ ring_ref, remote_port, limit);
if ((ring_ref == dom->ring_ref) && (remote_port == dom->remote_port))
goto out;
#include "qemu-common.h"
#include "config.h"
-#ifdef CONFIG_STUBDOM
-#include <semaphore.h>
-#include <sched.h>
-#include <fbfront.h>
-#endif
-
#ifndef BTN_LEFT
#define BTN_LEFT 0x110 /* from <linux/input.h> */
#endif
* Scancodes are hardware-specific. These maps assumes a
* standard AT or PS/2 keyboard which is what QEMU feeds us.
*/
-static const unsigned char atkbd_set2_keycode[512] = {
+const unsigned char atkbd_set2_keycode[512] = {
0, 67, 65, 63, 61, 59, 60, 88, 0, 68, 66, 64, 62, 15, 41,117,
0, 56, 42, 93, 29, 16, 2, 0, 0, 0, 44, 31, 30, 17, 3, 0,
};
-static const unsigned char atkbd_unxlate_table[128] = {
+const unsigned char atkbd_unxlate_table[128] = {
0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13,
21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27,
return 0;
}
-#ifdef CONFIG_STUBDOM
-typedef struct XenFBState {
- struct semaphore kbd_sem;
- struct kbdfront_dev *kbd_dev;
- struct fbfront_dev *fb_dev;
- void *vga_vram, *nonshared_vram;
- DisplayState *ds;
-} XenFBState;
-
-XenFBState *xs;
-
-static char *kbd_path, *fb_path;
-
-static unsigned char linux2scancode[KEY_MAX + 1];
-
-static void xenfb_pv_colourdepth(DisplayState *ds, int depth);
-
-int xenfb_connect_vkbd(const char *path)
-{
- kbd_path = strdup(path);
- return 0;
-}
-
-int xenfb_connect_vfb(const char *path)
-{
- fb_path = strdup(path);
- return 0;
-}
-
-static void xenfb_pv_update(DisplayState *ds, int x, int y, int w, int h)
-{
- XenFBState *xs = ds->opaque;
- struct fbfront_dev *fb_dev = xs->fb_dev;
- if (!fb_dev)
- return;
- fbfront_update(fb_dev, x, y, w, h);
-}
-
-static void xenfb_pv_resize_shared(DisplayState *ds, int w, int h, int depth, int linesize, void *pixels)
-{
- XenFBState *xs = ds->opaque;
- struct fbfront_dev *fb_dev = xs->fb_dev;
- int offset;
- fprintf(stderr,"resize to %dx%d, %d required\n", w, h, linesize);
- xenfb_pv_colourdepth(ds, depth);
- ds->width = w;
- ds->height = h;
- if (!linesize)
- ds->shared_buf = 0;
- if (!ds->shared_buf)
- linesize = w * 4;
- ds->linesize = linesize;
- if (!fb_dev)
- return;
- if (ds->shared_buf) {
- offset = pixels - xs->vga_vram;
- ds->data = pixels;
- fbfront_resize(fb_dev, ds->width, ds->height, ds->linesize, ds->depth, offset);
- } else {
- ds->data = xs->nonshared_vram;
- fbfront_resize(fb_dev, w, h, linesize, ds->depth, VGA_RAM_SIZE);
- }
-}
-
-static void xenfb_pv_resize(DisplayState *ds, int w, int h)
-{
- xenfb_pv_resize_shared(ds, w, h, 0, 0, NULL);
-}
-
-static void xenfb_pv_colourdepth(DisplayState *ds, int depth)
-{
- XenFBState *xs = ds->opaque;
- struct fbfront_dev *fb_dev = xs->fb_dev;
- static int lastdepth = -1;
- if (!depth) {
- ds->shared_buf = 0;
- ds->depth = 32;
- } else {
- ds->shared_buf = 1;
- ds->depth = depth;
- }
- if (depth != lastdepth) {
- fprintf(stderr,"redepth to %d required\n", depth);
- lastdepth = depth;
- } else return;
- if (!fb_dev)
- return;
- if (ds->shared_buf) {
- ds->data = NULL;
- } else {
- ds->data = xs->nonshared_vram;
- }
-}
-
-static void xenfb_pv_setdata(DisplayState *ds, void *pixels)
-{
- XenFBState *xs = ds->opaque;
- struct fbfront_dev *fb_dev = xs->fb_dev;
- int offset = pixels - xs->vga_vram;
- ds->data = pixels;
- if (!fb_dev)
- return;
- fbfront_resize(fb_dev, ds->width, ds->height, ds->linesize, ds->depth, offset);
-}
-
-static void xenfb_pv_refresh(DisplayState *ds)
-{
- vga_hw_update();
-}
-
-static void xenfb_fb_handler(void *opaque)
-{
-#define FB_NUM_BATCH 4
- union xenfb_in_event buf[FB_NUM_BATCH];
- int n, i;
- XenFBState *xs = opaque;
- DisplayState *ds = xs->ds;
-
- n = fbfront_receive(xs->fb_dev, buf, FB_NUM_BATCH);
- for (i = 0; i < n; i++) {
- switch (buf[i].type) {
- case XENFB_TYPE_REFRESH_PERIOD:
- if (buf[i].refresh_period.period == XENFB_NO_REFRESH) {
- /* Sleeping interval */
- ds->idle = 1;
- ds->gui_timer_interval = 500;
- } else {
- /* Set interval */
- ds->idle = 0;
- ds->gui_timer_interval = buf[i].refresh_period.period;
- }
- default:
- /* ignore unknown events */
- break;
- }
- }
-}
-
-static void xenfb_kbd_handler(void *opaque)
-{
-#define KBD_NUM_BATCH 64
- union xenkbd_in_event buf[KBD_NUM_BATCH];
- int n, i;
- XenFBState *xs = opaque;
- DisplayState *s = xs->ds;
- static int buttons;
- static int x, y;
-
- n = kbdfront_receive(xs->kbd_dev, buf, KBD_NUM_BATCH);
- for (i = 0; i < n; i++) {
- switch (buf[i].type) {
-
- case XENKBD_TYPE_MOTION:
- fprintf(stderr, "FB backend sent us relative mouse motion event!\n");
- break;
-
- case XENKBD_TYPE_POS:
- {
- int new_x = buf[i].pos.abs_x;
- int new_y = buf[i].pos.abs_y;
- if (new_x >= s->width)
- new_x = s->width - 1;
- if (new_y >= s->height)
- new_y = s->height - 1;
- if (kbd_mouse_is_absolute()) {
- kbd_mouse_event(
- new_x * 0x7FFF / (s->width - 1),
- new_y * 0x7FFF / (s->height - 1),
- buf[i].pos.rel_z,
- buttons);
- } else {
- kbd_mouse_event(
- new_x - x,
- new_y - y,
- buf[i].pos.rel_z,
- buttons);
- }
- x = new_x;
- y = new_y;
- break;
- }
-
- case XENKBD_TYPE_KEY:
- {
- int keycode = buf[i].key.keycode;
- int button = 0;
-
- if (keycode == BTN_LEFT)
- button = MOUSE_EVENT_LBUTTON;
- else if (keycode == BTN_RIGHT)
- button = MOUSE_EVENT_RBUTTON;
- else if (keycode == BTN_MIDDLE)
- button = MOUSE_EVENT_MBUTTON;
-
- if (button) {
- if (buf[i].key.pressed)
- buttons |= button;
- else
- buttons &= ~button;
- if (kbd_mouse_is_absolute())
- kbd_mouse_event(
- x * 0x7FFF / (s->width - 1),
- y * 0x7FFF / (s->height - 1),
- 0,
- buttons);
- else
- kbd_mouse_event(0, 0, 0, buttons);
- } else {
- int scancode = linux2scancode[keycode];
- if (!scancode) {
- fprintf(stderr, "Can't convert keycode %x to scancode\n", keycode);
- break;
- }
- if (scancode & 0x80) {
- kbd_put_keycode(0xe0);
- scancode &= 0x7f;
- }
- if (!buf[i].key.pressed)
- scancode |= 0x80;
- kbd_put_keycode(scancode);
- }
- break;
- }
- }
- }
-}
-
-static void kbdfront_thread(void *p)
-{
- int scancode, keycode;
- XenFBState *xs = p;
- xs->kbd_dev = init_kbdfront(kbd_path, 1);
- if (!xs->kbd_dev) {
- fprintf(stderr,"can't open keyboard\n");
- exit(1);
- }
- up(&xs->kbd_sem);
- for (scancode = 0; scancode < 128; scancode++) {
- keycode = atkbd_set2_keycode[atkbd_unxlate_table[scancode]];
- linux2scancode[keycode] = scancode;
- keycode = atkbd_set2_keycode[atkbd_unxlate_table[scancode] | 0x80];
- linux2scancode[keycode] = scancode | 0x80;
- }
-}
-
-int xenfb_pv_display_init(DisplayState *ds)
-{
- if (!fb_path || !kbd_path)
- return -1;
-
- xs = qemu_mallocz(sizeof(XenFBState));
- if (!xs)
- return -1;
-
- init_SEMAPHORE(&xs->kbd_sem, 0);
- xs->ds = ds;
-
- create_thread("kbdfront", kbdfront_thread, (void*) xs);
-
- ds->data = xs->nonshared_vram = qemu_memalign(PAGE_SIZE, VGA_RAM_SIZE);
- memset(ds->data, 0, VGA_RAM_SIZE);
- ds->opaque = xs;
- ds->depth = 32;
- ds->bgr = 0;
- ds->width = 640;
- ds->height = 400;
- ds->linesize = 640 * 4;
- ds->dpy_update = xenfb_pv_update;
- ds->dpy_resize = xenfb_pv_resize;
- ds->dpy_resize_shared = xenfb_pv_resize_shared;
- ds->dpy_setdata = xenfb_pv_setdata;
- ds->dpy_refresh = xenfb_pv_refresh;
- return 0;
-}
-
-int xenfb_pv_display_start(void *data)
-{
- DisplayState *ds;
- struct fbfront_dev *fb_dev;
- int kbd_fd, fb_fd;
- int offset = 0;
- unsigned long *mfns;
- int n = VGA_RAM_SIZE / PAGE_SIZE;
- int i;
-
- if (!fb_path || !kbd_path)
- return 0;
-
- ds = xs->ds;
- xs->vga_vram = data;
- mfns = malloc(2 * n * sizeof(*mfns));
- for (i = 0; i < n; i++)
- mfns[i] = virtual_to_mfn(xs->vga_vram + i * PAGE_SIZE);
- for (i = 0; i < n; i++)
- mfns[n + i] = virtual_to_mfn(xs->nonshared_vram + i * PAGE_SIZE);
-
- fb_dev = init_fbfront(fb_path, mfns, ds->width, ds->height, ds->depth, ds->linesize, 2 * n);
- free(mfns);
- if (!fb_dev) {
- fprintf(stderr,"can't open frame buffer\n");
- exit(1);
- }
- free(fb_path);
-
- if (ds->shared_buf) {
- offset = (void*) ds->data - xs->vga_vram;
- } else {
- offset = VGA_RAM_SIZE;
- ds->data = xs->nonshared_vram;
- }
- if (offset)
- fbfront_resize(fb_dev, ds->width, ds->height, ds->linesize, ds->depth, offset);
-
- down(&xs->kbd_sem);
- free(kbd_path);
-
- kbd_fd = kbdfront_open(xs->kbd_dev);
- qemu_set_fd_handler(kbd_fd, xenfb_kbd_handler, NULL, xs);
-
- fb_fd = fbfront_open(fb_dev);
- qemu_set_fd_handler(fb_fd, xenfb_fb_handler, NULL, xs);
-
- xs->fb_dev = fb_dev;
- return 0;
-}
-#endif
-
/*
* Local variables:
* c-indent-level: 8
struct xenfb *xenfb_new(int domid, DisplayState *ds);
void xenfb_shutdown(struct xenfb *xenfb);
+extern const unsigned char atkbd_set2_keycode[512];
+extern const unsigned char atkbd_unxlate_table[128];
#endif
}
#endif
-void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
- int len, int is_write)
+void cpu_physical_memory_rw(target_phys_addr_t _addr, uint8_t *buf,
+ int _len, int is_write)
{
+ target_phys_addr_t addr = _addr;
+ int len = _len;
int l, io_index;
uint8_t *ptr;
uint32_t val;
} else if ((ptr = phys_ram_addr(addr)) != NULL) {
/* Writing to RAM */
memcpy_words(ptr, buf, l);
+#ifndef CONFIG_STUBDOM
if (logdirty_bitmap != NULL) {
/* Record that we have dirtied this frame */
unsigned long pfn = addr >> TARGET_PAGE_BITS;
|= 1UL << pfn % HOST_LONG_BITS;
}
}
+#endif
#ifdef __ia64__
sync_icache(ptr, l);
#endif
addr += l;
}
+#ifdef CONFIG_STUBDOM
+ if (logdirty_bitmap != NULL)
+ xc_hvm_modified_memory(xc_handle, domid, _addr >> TARGET_PAGE_BITS,
+ (_addr + _len + TARGET_PAGE_SIZE - 1) >> TARGET_PAGE_BITS
+ - _addr >> TARGET_PAGE_BITS);
+#endif
+
mapcache_unlock();
}
#endif
}
if (eject_device(bs, 0) < 0)
return;
- bdrv_open(bs, filename, 0);
+ bdrv_open2(bs, filename, 0, &bdrv_raw);
qemu_key_check(bs, filename);
}
/* XXX: use a two level table to limit memory usage */
#define MAX_IOPORTS 65536
+/* Max number of PCI emulation */
+#define MAX_PCI_EMULATION 32
+
const char *bios_dir = CONFIG_QEMU_SHAREDIR;
const char *bios_name = NULL;
void *ioport_opaque[MAX_IOPORTS];
int opengl_enabled = 0;
#endif
static const char *direct_pci;
+static int nb_pci_emulation = 0;
+static char pci_emulation_config_text[MAX_PCI_EMULATION][256];
+PCI_EMULATION_INFO *PciEmulationInfoHead = NULL;
CharDriverState *serial_hds[MAX_SERIAL_PORTS];
CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
#ifdef TARGET_I386
if (parse_host_port(&saddr, host_str) < 0)
return -1;
+static int pci_emulation_add(char *config_text)
+{
+ PCI_EMULATION_INFO *new;
+ if ((new = qemu_mallocz(sizeof(PCI_EMULATION_INFO))) == NULL) {
+ return -1;
+ }
+ parse_pci_emulation_info(config_text, new);
+ new->next = PciEmulationInfoHead;
+ PciEmulationInfoHead = new;
+ return 0;
+}
fd = net_socket_mcast_create(&saddr);
if (fd < 0)
} else if (!strcmp(devname, "keyboard")) {
dev = usb_keyboard_init();
} else if (strstart(devname, "disk:", &p)) {
- dev = usb_msd_init(p);
+ dev = usb_msd_init(p, &bdrv_raw);
+ } else if (strstart(devname, "disk-qcow:", &p)) {
+ dev = usb_msd_init(p, 0);
} else if (!strcmp(devname, "wacom-tablet")) {
dev = usb_wacom_init();
} else if (strstart(devname, "serial:", &p)) {
"-disable-opengl disable OpenGL rendering, using SDL"
#endif
"-direct-pci s specify pci passthrough, with configuration string s\n"
+ "-pciemulation name:vendorid:deviceid:command:status:revision:classcode:headertype:subvendorid:subsystemid:interruputline:interruputpin\n"
"-vcpus set CPU number of guest platform\n"
#ifdef TARGET_I386
"-no-fd-bootchk disable boot signature checking for floppy disks\n"
QEMU_OPTION_domid,
QEMU_OPTION_disable_opengl,
QEMU_OPTION_direct_pci,
+ QEMU_OPTION_pci_emulation,
QEMU_OPTION_vcpus,
QEMU_OPTION_acpi,
QEMU_OPTION_pidfile,
{ "vcpus", 1, QEMU_OPTION_vcpus },
{ "acpi", 0, QEMU_OPTION_acpi }, /* deprecated, for xend compatibility */
{ "direct_pci", HAS_ARG, QEMU_OPTION_direct_pci },
+ { "pciemulation", HAS_ARG, QEMU_OPTION_pci_emulation },
{ "pidfile", HAS_ARG, QEMU_OPTION_pidfile },
{ "win2k-hack", 0, QEMU_OPTION_win2k_hack },
{ "usbdevice", HAS_ARG, QEMU_OPTION_usbdevice },
}
ram_size = value;
break;
+ case QEMU_OPTION_pci_emulation:
+ if (nb_pci_emulation >= MAX_PCI_EMULATION) {
+ fprintf(stderr, "Too many PCI emulations\n");
+ exit(1);
+ }
+ pstrcpy(pci_emulation_config_text[nb_pci_emulation],
+ sizeof(pci_emulation_config_text[0]),
+ optarg);
+ nb_pci_emulation++;
+ break;
}
case QEMU_OPTION_domid:
domid = atoi(optarg);
}
}
+ for (i = 0; i < nb_pci_emulation; i++) {
+ if(pci_emulation_add(pci_emulation_config_text[i]) < 0) {
+ fprintf(stderr, "Warning: could not add PCI device %s\n",
+ pci_emulation_config_text[i]);
+ }
+ }
+
machine->init(ram_size, vga_ram_size, boot_devices, ds,
kernel_filename, kernel_cmdline, initrd_filename, cpu_model,
direct_pci);
OBJS += xen_machine_fv.o
OBJS += xen_blktap.o
OBJS += exec-dm.o
+OBJS += pci_emulation.o
+
+ifdef CONFIG_STUBDOM
+CONFIG_PASSTHROUGH=1
+OBJS += xenfbfront.o
+endif
ifdef CONFIG_PASSTHROUGH
OBJS+= pass-through.o
--- /dev/null
+#include <stdint.h>
+#include <xen/io/fbif.h>
+#include <xen/io/kbdif.h>
+#include <semaphore.h>
+#include <sched.h>
+#include <fbfront.h>
+
+#include <hw/xenfb.h>
+
+#include "vl.h"
+
+typedef struct XenFBState {
+ struct semaphore kbd_sem;
+ struct kbdfront_dev *kbd_dev;
+ struct fbfront_dev *fb_dev;
+ void *vga_vram, *nonshared_vram;
+ DisplayState *ds;
+} XenFBState;
+
+XenFBState *xs;
+
+static char *kbd_path, *fb_path;
+
+static unsigned char linux2scancode[KEY_MAX + 1];
+
+int xenfb_connect_vkbd(const char *path)
+{
+ kbd_path = strdup(path);
+ return 0;
+}
+
+int xenfb_connect_vfb(const char *path)
+{
+ fb_path = strdup(path);
+ return 0;
+}
+
+static void xenfb_pv_update(DisplayState *ds, int x, int y, int w, int h)
+{
+ XenFBState *xs = ds->opaque;
+ struct fbfront_dev *fb_dev = xs->fb_dev;
+ if (!fb_dev)
+ return;
+ fbfront_update(fb_dev, x, y, w, h);
+}
+
+static void xenfb_pv_resize_shared(DisplayState *ds, int w, int h, int depth, int linesize, void *pixels)
+{
+ XenFBState *xs = ds->opaque;
+ struct fbfront_dev *fb_dev = xs->fb_dev;
+ int offset;
+
+ fprintf(stderr,"resize to %dx%d@%d, %d required\n", w, h, depth, linesize);
+ ds->width = w;
+ ds->height = h;
+ if (!depth) {
+ ds->shared_buf = 0;
+ ds->depth = 32;
+ } else {
+ ds->shared_buf = 1;
+ ds->depth = depth;
+ }
+ if (!linesize)
+ ds->shared_buf = 0;
+ if (!ds->shared_buf)
+ linesize = w * 4;
+ ds->linesize = linesize;
+ if (!fb_dev)
+ return;
+ if (ds->shared_buf) {
+ offset = pixels - xs->vga_vram;
+ ds->data = pixels;
+ } else {
+ ds->data = xs->nonshared_vram;
+ fbfront_resize(fb_dev, w, h, linesize, ds->depth, VGA_RAM_SIZE);
+ }
+}
+
+static void xenfb_pv_resize(DisplayState *ds, int w, int h)
+{
+ xenfb_pv_resize_shared(ds, w, h, 0, 0, NULL);
+}
+
+static void xenfb_pv_setdata(DisplayState *ds, void *pixels)
+{
+ XenFBState *xs = ds->opaque;
+ struct fbfront_dev *fb_dev = xs->fb_dev;
+ int offset = pixels - xs->vga_vram;
+ ds->data = pixels;
+ if (!fb_dev)
+ return;
+ fbfront_resize(fb_dev, ds->width, ds->height, ds->linesize, ds->depth, offset);
+}
+
+static void xenfb_pv_refresh(DisplayState *ds)
+{
+ vga_hw_update();
+}
+
+static void xenfb_fb_handler(void *opaque)
+{
+#define FB_NUM_BATCH 4
+ union xenfb_in_event buf[FB_NUM_BATCH];
+ int n, i;
+ XenFBState *xs = opaque;
+ DisplayState *ds = xs->ds;
+
+ n = fbfront_receive(xs->fb_dev, buf, FB_NUM_BATCH);
+ for (i = 0; i < n; i++) {
+ switch (buf[i].type) {
+ case XENFB_TYPE_REFRESH_PERIOD:
+ if (buf[i].refresh_period.period == XENFB_NO_REFRESH) {
+ /* Sleeping interval */
+ ds->idle = 1;
+ ds->gui_timer_interval = 500;
+ } else {
+ /* Set interval */
+ ds->idle = 0;
+ ds->gui_timer_interval = buf[i].refresh_period.period;
+ }
+ default:
+ /* ignore unknown events */
+ break;
+ }
+ }
+}
+
+static void xenfb_kbd_handler(void *opaque)
+{
+#define KBD_NUM_BATCH 64
+ union xenkbd_in_event buf[KBD_NUM_BATCH];
+ int n, i;
+ XenFBState *xs = opaque;
+ DisplayState *s = xs->ds;
+ static int buttons;
+ static int x, y;
+
+ n = kbdfront_receive(xs->kbd_dev, buf, KBD_NUM_BATCH);
+ for (i = 0; i < n; i++) {
+ switch (buf[i].type) {
+
+ case XENKBD_TYPE_MOTION:
+ fprintf(stderr, "FB backend sent us relative mouse motion event!\n");
+ break;
+
+ case XENKBD_TYPE_POS:
+ {
+ int new_x = buf[i].pos.abs_x;
+ int new_y = buf[i].pos.abs_y;
+ if (new_x >= s->width)
+ new_x = s->width - 1;
+ if (new_y >= s->height)
+ new_y = s->height - 1;
+ if (kbd_mouse_is_absolute()) {
+ kbd_mouse_event(
+ new_x * 0x7FFF / (s->width - 1),
+ new_y * 0x7FFF / (s->height - 1),
+ buf[i].pos.rel_z,
+ buttons);
+ } else {
+ kbd_mouse_event(
+ new_x - x,
+ new_y - y,
+ buf[i].pos.rel_z,
+ buttons);
+ }
+ x = new_x;
+ y = new_y;
+ break;
+ }
+
+ case XENKBD_TYPE_KEY:
+ {
+ int keycode = buf[i].key.keycode;
+ int button = 0;
+
+ if (keycode == BTN_LEFT)
+ button = MOUSE_EVENT_LBUTTON;
+ else if (keycode == BTN_RIGHT)
+ button = MOUSE_EVENT_RBUTTON;
+ else if (keycode == BTN_MIDDLE)
+ button = MOUSE_EVENT_MBUTTON;
+
+ if (button) {
+ if (buf[i].key.pressed)
+ buttons |= button;
+ else
+ buttons &= ~button;
+ if (kbd_mouse_is_absolute())
+ kbd_mouse_event(
+ x * 0x7FFF / (s->width - 1),
+ y * 0x7FFF / (s->height - 1),
+ 0,
+ buttons);
+ else
+ kbd_mouse_event(0, 0, 0, buttons);
+ } else {
+ int scancode = linux2scancode[keycode];
+ if (!scancode) {
+ fprintf(stderr, "Can't convert keycode %x to scancode\n", keycode);
+ break;
+ }
+ if (scancode & 0x80) {
+ kbd_put_keycode(0xe0);
+ scancode &= 0x7f;
+ }
+ if (!buf[i].key.pressed)
+ scancode |= 0x80;
+ kbd_put_keycode(scancode);
+ }
+ break;
+ }
+ }
+ }
+}
+
+static void kbdfront_thread(void *p)
+{
+ int scancode, keycode;
+ XenFBState *xs = p;
+ xs->kbd_dev = init_kbdfront(kbd_path, 1);
+ if (!xs->kbd_dev) {
+ fprintf(stderr,"can't open keyboard\n");
+ exit(1);
+ }
+ up(&xs->kbd_sem);
+ for (scancode = 0; scancode < 128; scancode++) {
+ keycode = atkbd_set2_keycode[atkbd_unxlate_table[scancode]];
+ linux2scancode[keycode] = scancode;
+ keycode = atkbd_set2_keycode[atkbd_unxlate_table[scancode] | 0x80];
+ linux2scancode[keycode] = scancode | 0x80;
+ }
+}
+
+int xenfb_pv_display_init(DisplayState *ds)
+{
+ if (!fb_path || !kbd_path)
+ return -1;
+
+ xs = qemu_mallocz(sizeof(XenFBState));
+ if (!xs)
+ return -1;
+
+ init_SEMAPHORE(&xs->kbd_sem, 0);
+ xs->ds = ds;
+
+ create_thread("kbdfront", kbdfront_thread, (void*) xs);
+
+ ds->data = xs->nonshared_vram = qemu_memalign(PAGE_SIZE, VGA_RAM_SIZE);
+ memset(ds->data, 0, VGA_RAM_SIZE);
+ ds->opaque = xs;
+ ds->depth = 32;
+ ds->bgr = 0;
+ ds->width = 640;
+ ds->height = 400;
+ ds->linesize = 640 * 4;
+ ds->dpy_update = xenfb_pv_update;
+ ds->dpy_resize = xenfb_pv_resize;
+ ds->dpy_resize_shared = xenfb_pv_resize_shared;
+ ds->dpy_setdata = xenfb_pv_setdata;
+ ds->dpy_refresh = xenfb_pv_refresh;
+ return 0;
+}
+
+int xenfb_pv_display_start(void *data)
+{
+ DisplayState *ds;
+ struct fbfront_dev *fb_dev;
+ int kbd_fd, fb_fd;
+ int offset = 0;
+ unsigned long *mfns;
+ int n = VGA_RAM_SIZE / PAGE_SIZE;
+ int i;
+
+ if (!fb_path || !kbd_path)
+ return 0;
+
+ ds = xs->ds;
+ xs->vga_vram = data;
+ mfns = malloc(2 * n * sizeof(*mfns));
+ for (i = 0; i < n; i++)
+ mfns[i] = virtual_to_mfn(xs->vga_vram + i * PAGE_SIZE);
+ for (i = 0; i < n; i++)
+ mfns[n + i] = virtual_to_mfn(xs->nonshared_vram + i * PAGE_SIZE);
+
+ fb_dev = init_fbfront(fb_path, mfns, ds->width, ds->height, ds->depth, ds->linesize, 2 * n);
+ free(mfns);
+ if (!fb_dev) {
+ fprintf(stderr,"can't open frame buffer\n");
+ exit(1);
+ }
+ free(fb_path);
+
+ if (ds->shared_buf) {
+ offset = (void*) ds->data - xs->vga_vram;
+ } else {
+ offset = VGA_RAM_SIZE;
+ ds->data = xs->nonshared_vram;
+ }
+ if (offset)
+ fbfront_resize(fb_dev, ds->width, ds->height, ds->linesize, ds->depth, offset);
+
+ down(&xs->kbd_sem);
+ free(kbd_path);
+
+ kbd_fd = kbdfront_open(xs->kbd_dev);
+ qemu_set_fd_handler(kbd_fd, xenfb_kbd_handler, NULL, xs);
+
+ fb_fd = fbfront_open(fb_dev);
+ qemu_set_fd_handler(fb_fd, xenfb_fb_handler, NULL, xs);
+
+ xs->fb_dev = fb_dev;
+ return 0;
+}
/* get the pci pass-through parameter */
if (pasprintf(&buf, "/local/domain/0/backend/pci/%u/%u/num_devs",
- domid, pci_devid) == -1)
+ hvm_domid, pci_devid) == -1)
goto out;
free(params);
for ( i = 0; i < num; i++ ) {
if (pasprintf(&buf, "/local/domain/0/backend/pci/%u/%u/dev-%d",
- domid, pci_devid, i) != -1) {
+ hvm_domid, pci_devid, i) != -1) {
free(dev);
dev = xs_read(xsh, XBT_NULL, buf, &len);