* Re: [PATCH] Pass-through a graphic card
2008-05-09 11:11 [PATCH] Pass-through a graphic card Jean Guyader
@ 2008-05-09 11:18 ` Jean Guyader
2008-05-09 11:32 ` Samuel Thibault
2008-05-09 11:27 ` Samuel Thibault
` (2 subsequent siblings)
3 siblings, 1 reply; 13+ messages in thread
From: Jean Guyader @ 2008-05-09 11:18 UTC (permalink / raw)
To: xen-devel; +Cc: Ian Pratt, Keir Fraser, Kamala Narasimhan
[-- Attachment #1: Type: text/plain, Size: 63 bytes --]
Sorry, I forgot a file in my previous patch.
--
Jean Guyader
[-- Attachment #2: vga_pt.patch --]
[-- Type: text/x-diff, Size: 29636 bytes --]
diff -r 810d8c3ac992 tools/firmware/hvmloader/config.h
--- a/tools/firmware/hvmloader/config.h Thu May 08 16:58:33 2008 +0100
+++ b/tools/firmware/hvmloader/config.h Fri May 09 12:16:40 2008 +0100
@@ -23,7 +23,7 @@
/* Memory map. */
#define HYPERCALL_PHYSICAL_ADDRESS 0x00080000
#define VGABIOS_PHYSICAL_ADDRESS 0x000C0000
-#define ETHERBOOT_PHYSICAL_ADDRESS 0x000C8000
+#define ETHERBOOT_PHYSICAL_ADDRESS 0x000D0000
#define EXTBOOT_PHYSICAL_ADDRESS 0x000DF800
#define SMBIOS_PHYSICAL_ADDRESS 0x000E9000
#define SMBIOS_MAXIMUM_SIZE 0x00001000
diff -r 810d8c3ac992 tools/firmware/hvmloader/hvmloader.c
--- a/tools/firmware/hvmloader/hvmloader.c Thu May 08 16:58:33 2008 +0100
+++ b/tools/firmware/hvmloader/hvmloader.c Fri May 09 12:16:40 2008 +0100
@@ -464,7 +464,16 @@ int main(void)
if ( (get_vcpu_nr() > 1) || get_apic_mode() )
create_mp_tables();
- if ( cirrus_check() )
+ if ( get_vga_pt_enabled() )
+ {
+ printf("Loading dom0 VGABIOS ...\n");
+ printf(" - 0x%x (0x%x)\n", get_vga_pt_bios_paddr(), get_vga_pt_bios_size());
+ memcpy((void*)VGABIOS_PHYSICAL_ADDRESS,
+ (void*)get_vga_pt_bios_paddr(),
+ get_vga_pt_bios_size());
+ vgabios_sz = get_vga_pt_bios_size();
+ }
+ else if ( cirrus_check() )
{
printf("Loading Cirrus VGABIOS ...\n");
memcpy((void *)VGABIOS_PHYSICAL_ADDRESS,
diff -r 810d8c3ac992 tools/firmware/hvmloader/util.c
--- a/tools/firmware/hvmloader/util.c Thu May 08 16:58:33 2008 +0100
+++ b/tools/firmware/hvmloader/util.c Fri May 09 12:16:40 2008 +0100
@@ -594,6 +594,24 @@ int get_vcpu_nr(void)
return (t ? t->nr_vcpus : 1);
}
+int get_vga_pt_enabled(void)
+{
+ struct hvm_info_table *t = get_hvm_info_table();
+ return (t && t->vga_bios_paddr > 0);
+}
+
+int get_vga_pt_bios_paddr(void)
+{
+ struct hvm_info_table *t = get_hvm_info_table();
+ return (t ? t->vga_bios_paddr : 0);
+}
+
+int get_vga_pt_bios_size(void)
+{
+ struct hvm_info_table *t = get_hvm_info_table();
+ return (t ? t->vga_bios_size : -1);
+}
+
int get_acpi_enabled(void)
{
struct hvm_info_table *t = get_hvm_info_table();
diff -r 810d8c3ac992 tools/firmware/hvmloader/util.h
--- a/tools/firmware/hvmloader/util.h Thu May 08 16:58:33 2008 +0100
+++ b/tools/firmware/hvmloader/util.h Fri May 09 12:16:40 2008 +0100
@@ -106,6 +106,9 @@ int get_vcpu_nr(void);
int get_vcpu_nr(void);
int get_acpi_enabled(void);
int get_apic_mode(void);
+int get_vga_pt_enabled(void);
+int get_vga_pt_bios_paddr(void);
+int get_vga_pt_bios_size(void);
/* String and memory functions */
int strcmp(const char *cs, const char *ct);
diff -r 810d8c3ac992 tools/ioemu/Makefile.target
--- a/tools/ioemu/Makefile.target Thu May 08 16:58:33 2008 +0100
+++ b/tools/ioemu/Makefile.target Fri May 09 12:16:40 2008 +0100
@@ -499,6 +499,9 @@ COCOA_LIBS+=-framework CoreAudio
COCOA_LIBS+=-framework CoreAudio
endif
endif
+
+VL_OBJS+=dom0_driver.o
+
ifdef CONFIG_SLIRP
CPPFLAGS+=-I$(SRC_PATH)/slirp
SLIRP_OBJS=cksum.o if.o ip_icmp.o ip_input.o ip_output.o \
diff -r 810d8c3ac992 tools/ioemu/dom0_driver.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/dom0_driver.c Fri May 09 12:16:40 2008 +0100
@@ -0,0 +1,151 @@
+/*
+ * QEMU dom0 /dev/input driver
+ *
+ * Copyright (c) 2008 Citrix Systems
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "vl.h"
+
+#include <sys/types.h>
+#include <linux/input.h>
+#include <linux/kd.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#define EVENT_MAX 10
+#define EVENT_PATH "/dev/input/event"
+
+struct dom0_driver
+{
+ int event_fds[EVENT_MAX];
+ int mouse_button_state;
+};
+
+static struct dom0_driver driver;
+
+static void dom0_update(DisplayState *ds, int x, int y, int w, int h)
+{
+}
+
+static void dom0_resize(DisplayState *ds, int w, int h, int linesize)
+{
+}
+
+static void dom0_refresh(DisplayState *ds)
+{
+}
+
+static void dom0_read(void *opaque)
+{
+ struct input_event event[5];
+ int i = 0;
+ int read_sz = 0;
+ int fd = *(int *)opaque;
+
+ read_sz = read(fd, event, sizeof (struct input_event) * 5);
+ for (i = 0; i < read_sz / (sizeof (struct input_event)); i++)
+ {
+ if (event[i].type == EV_KEY)
+ {
+ if (event[i].code >= BTN_MOUSE)
+ {
+ /* Mouse Key */
+ int type = 0;
+
+ switch(event[i].code)
+ {
+ case BTN_LEFT: type = MOUSE_EVENT_LBUTTON; break;
+ case BTN_RIGHT: type = MOUSE_EVENT_RBUTTON; break;
+ }
+
+ if (event[i].value)
+ driver.mouse_button_state |= type;
+ else
+ driver.mouse_button_state &= ~type;
+ kbd_mouse_event(0, 0, 0, driver.mouse_button_state);
+ }
+ else
+ {
+ /* Keyboard key */
+ if (event[i].value == 1)
+ kbd_put_keycode(event[i].code | 0x80);
+ else
+ kbd_put_keycode(event[i].code & 0x7f);
+ }
+ }
+
+ if (event[i].type == EV_REL)
+ {
+ /* Mouse motion */
+ int x = 0, y = 0, z = 0;
+
+ switch (event[i].code)
+ {
+ case REL_X : x = event[i].value; break;
+ case REL_Y : y = event[i].value; break;
+ case REL_WHEEL : z = event[i].value; break;
+ }
+
+ kbd_mouse_event(x, y, z, driver.mouse_button_state);
+ }
+ }
+}
+
+static void dom0_driver_event_init()
+{
+ char dev_name[strlen(EVENT_PATH) + 3];
+ int fd = -1;
+ int i = 0;
+ int e = 0;
+
+ do
+ {
+ if (e == EVENT_MAX)
+ return;
+ snprintf(dev_name, sizeof (dev_name), "%s%d", EVENT_PATH, i++);
+ if ((fd = open(dev_name, O_RDONLY)) == -1)
+ return;
+ printf("Using %s\n", dev_name);
+ ioctl(fd, EVIOCGRAB, 1);
+ qemu_set_fd_handler(fd, dom0_read, NULL, &driver.event_fds[e]);
+ driver.event_fds[e++] = fd;
+ }
+ while (1);
+}
+
+void dom0_driver_init(DisplayState *ds)
+{
+ dom0_driver_event_init();
+
+ ds->data = NULL;
+ ds->linesize = 0;
+ ds->depth = 0;
+ ds->dpy_update = dom0_update;
+ ds->dpy_resize = dom0_resize;
+ ds->dpy_colourdepth = NULL;
+ ds->dpy_refresh = dom0_refresh;
+}
diff -r 810d8c3ac992 tools/ioemu/hw/pc.c
--- a/tools/ioemu/hw/pc.c Thu May 08 16:58:33 2008 +0100
+++ b/tools/ioemu/hw/pc.c Fri May 09 12:16:40 2008 +0100
@@ -814,6 +814,13 @@ static void pc_init1(uint64_t ram_size,
CPUState *env;
NICInfo *nd;
int rc;
+#ifdef CONFIG_DM
+ unsigned long vga_pt_enabled = 0;
+#endif /* CONFIG_DM */
+
+#ifdef CONFIG_DM
+ xc_get_hvm_param(xc_handle, domid, HVM_PARAM_VGA_PT_ENABLED, &vga_pt_enabled);
+#endif /* CONFIG_DM */
linux_boot = (kernel_filename != NULL);
@@ -862,12 +869,18 @@ static void pc_init1(uint64_t ram_size,
}
/* VGA BIOS load */
- if (cirrus_vga_enabled) {
- snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_CIRRUS_FILENAME);
- } else {
- snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_FILENAME);
+#ifdef CONFIG_DM
+ if (!vga_pt_enabled)
+#endif /* CONFIG_DM */
+ {
+ fprintf(stderr, "Load qemu pci vga\n");
+ if (cirrus_vga_enabled) {
+ snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_CIRRUS_FILENAME);
+ } else {
+ snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_FILENAME);
+ }
+ ret = load_image(buf, phys_ram_base + vga_bios_offset);
}
- ret = load_image(buf, phys_ram_base + vga_bios_offset);
#endif /* !NOBIOS */
/* setup basic memory access */
@@ -925,22 +938,27 @@ static void pc_init1(uint64_t ram_size,
register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL);
- if (cirrus_vga_enabled) {
- if (pci_enabled) {
- pci_cirrus_vga_init(pci_bus,
- ds, NULL, ram_size,
- vga_ram_size);
+#ifdef CONFIG_DM
+ if (!vga_pt_enabled)
+#endif /* CONFIG_DM */
+ {
+ if (cirrus_vga_enabled) {
+ if (pci_enabled) {
+ pci_cirrus_vga_init(pci_bus,
+ ds, NULL, ram_size,
+ vga_ram_size);
+ } else {
+ isa_cirrus_vga_init(ds, NULL, ram_size,
+ vga_ram_size);
+ }
} else {
- isa_cirrus_vga_init(ds, NULL, ram_size,
- vga_ram_size);
- }
- } else {
- if (pci_enabled) {
- pci_vga_init(pci_bus, ds, NULL, ram_size,
- vga_ram_size, 0, 0);
- } else {
- isa_vga_init(ds, NULL, ram_size,
- vga_ram_size);
+ if (pci_enabled) {
+ pci_vga_init(pci_bus, ds, NULL, ram_size,
+ vga_ram_size, 0, 0);
+ } else {
+ isa_vga_init(ds, NULL, ram_size,
+ vga_ram_size);
+ }
}
}
diff -r 810d8c3ac992 tools/ioemu/vl.c
--- a/tools/ioemu/vl.c Thu May 08 16:58:33 2008 +0100
+++ b/tools/ioemu/vl.c Fri May 09 12:16:40 2008 +0100
@@ -179,6 +179,9 @@ int opengl_enabled = 1;
#else
int opengl_enabled = 0;
#endif
+#ifdef CONFIG_DM
+int dom0_control = 0;
+#endif /* CONFIG_DM */
int no_quit = 0;
CharDriverState *serial_hds[MAX_SERIAL_PORTS];
CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
@@ -4455,6 +4458,7 @@ static void dumb_resize(DisplayState *ds
static void dumb_refresh(DisplayState *ds)
{
+ printf("dumb_refresh\n");
vga_hw_update();
}
@@ -6486,8 +6490,9 @@ void help(void)
"-no-quit disable SDL window close capability\n"
#endif
#ifdef CONFIG_OPENGL
- "-disable-opengl disable OpenGL rendering, using SDL"
-#endif
+ "-disable-opengl disable OpenGL rendering, using SDL\n"
+#endif
+ "-enable-dom0 enable dom0 controling qemu\n"
#ifdef TARGET_I386
"-no-fd-bootchk disable boot signature checking for floppy disks\n"
#endif
@@ -6667,6 +6672,9 @@ enum {
QEMU_OPTION_full_screen,
QEMU_OPTION_no_quit,
QEMU_OPTION_disable_opengl,
+#ifdef CONFIG_DM
+ QEMU_OPTION_dom0_control,
+#endif /* CONFIG_DM */
QEMU_OPTION_pidfile,
QEMU_OPTION_no_kqemu,
QEMU_OPTION_kernel_kqemu,
@@ -6765,6 +6773,7 @@ const QEMUOption qemu_options[] = {
{ "no-quit", 0, QEMU_OPTION_no_quit },
#endif
{ "disable-opengl", 0, QEMU_OPTION_disable_opengl },
+ { "enable-dom0", 0, QEMU_OPTION_dom0_control },
{ "pidfile", HAS_ARG, QEMU_OPTION_pidfile },
{ "win2k-hack", 0, QEMU_OPTION_win2k_hack },
{ "usbdevice", HAS_ARG, QEMU_OPTION_usbdevice },
@@ -7516,6 +7525,11 @@ int main(int argc, char **argv)
case QEMU_OPTION_disable_opengl:
opengl_enabled = 0;
break;
+#ifdef CONFIG_DM
+ case QEMU_OPTION_dom0_control:
+ dom0_control = 1;
+ break;
+#endif /* CONFIG_DM */
case QEMU_OPTION_pidfile:
create_pidfile(optarg);
break;
@@ -7823,12 +7837,18 @@ int main(int argc, char **argv)
init_ioports();
/* terminal init */
+
#ifdef CONFIG_STUBDOM
if (xenfb_pv_display_init(ds) == 0) {
} else
#endif
if (nographic) {
+#ifdef CONFIG_DM
+ if (dom0_control == 1)
+ dom0_driver_init(ds);
+#else
dumb_display_init(ds);
+#endif /* CONFIG_DM */
} else if (vnc_display != NULL || vncunused != 0) {
int vnc_display_port;
char password[20];
@@ -7842,7 +7862,9 @@ int main(int argc, char **argv)
vnc_start_viewer(vnc_display_port);
#endif
xenstore_write_vncport(vnc_display_port);
- } else {
+ }
+ else
+ {
#if defined(CONFIG_SDL)
sdl_display_init(ds, full_screen, opengl_enabled);
#elif defined(CONFIG_COCOA)
diff -r 810d8c3ac992 tools/ioemu/vl.h
--- a/tools/ioemu/vl.h Thu May 08 16:58:33 2008 +0100
+++ b/tools/ioemu/vl.h Fri May 09 12:16:40 2008 +0100
@@ -997,6 +997,9 @@ void do_info_vnc(void);
void do_info_vnc(void);
int vnc_start_viewer(int port);
+/* dom0_driver.c */
+void dom0_driver_init(DisplayState *ds);
+
/* x_keymap.c */
extern uint8_t _translate_keycode(const int key);
diff -r 810d8c3ac992 tools/libxc/xc_hvm_build.c
--- a/tools/libxc/xc_hvm_build.c Thu May 08 16:58:33 2008 +0100
+++ b/tools/libxc/xc_hvm_build.c Fri May 09 12:16:40 2008 +0100
@@ -152,9 +152,121 @@ static int loadelfimage(
return rc;
}
+static int linux_get_vgabios(int xc_handle,
+ unsigned char *buf,
+ int len)
+{
+ char buff[1024];
+ FILE *fd, *mem;
+ char *end_ptr;
+ uint32_t start, end, size;
+
+ if (!(fd = fopen("/proc/iomem", "r")))
+ return 0;
+
+ while (fgets(buff, 1024, fd))
+ if (strstr(buff, "Video ROM"))
+ break;
+
+ if (feof(fd))
+ {
+ fclose(fd);
+ return 0;
+ }
+
+ fclose(fd);
+ start = strtol(buff, &end_ptr, 16);
+ end = strtol(end_ptr + 1, NULL, 16);
+ size = end - start + 1;
+
+ if (!(mem = fopen("/dev/mem", "r")))
+ return 0;
+
+ fseek(mem, start, SEEK_SET);
+ fread(buf, 1, size, mem);
+ fclose(mem);
+
+ return size;
+}
+
+static int linux_map_vga_ioport(int xc_handler,
+ uint32_t dom)
+{
+ FILE *fd = NULL;
+ char buff[256];
+ uint32_t start, end;
+ char *buff_end = NULL;
+
+ if (!(fd = fopen("/proc/ioports", "r")))
+ return -1;
+
+ while (fgets(buff, 256, fd))
+ if (strstr(buff, "vga"))
+ break;
+
+ if (feof(fd))
+ {
+ fclose(fd);
+ return -1;
+ }
+
+ fclose(fd);
+
+ start = strtol(buff, &buff_end, 16);
+ end = strtol(buff_end + 1, NULL, 16);
+
+ return xc_domain_ioport_mapping(xc_handler, dom,
+ start, start, end - start + 1, 1);
+}
+
+static int setup_vga_pt(int xc_handle,
+ uint32_t dom,
+ uint32_t paddr,
+ struct hvm_info_table *hvm_info)
+{
+ int rc = 0;
+ unsigned char *bios = NULL;
+ int bios_size = 0;
+ char *va_bios = NULL;
+ uint32_t pfn = 0;
+
+ /* Allocated 128K for the vga bios */
+ if (!(bios = malloc(128 * 1024)))
+ return -1;
+
+ /* Align paddr on the first next page */
+ pfn = (paddr >> XC_PAGE_SHIFT) + 1;
+
+ bios_size = linux_get_vgabios(xc_handle, bios, 128 * 1024);
+
+ if (bios_size <= 0)
+ {
+ free(bios);
+ return -1;
+ }
+
+ va_bios = xc_map_foreign_range(xc_handle, dom, 16 * XC_PAGE_SIZE,
+ PROT_READ | PROT_WRITE, pfn);
+
+ memcpy(va_bios, bios, bios_size);
+ hvm_info->vga_bios_paddr = pfn << XC_PAGE_SHIFT;
+ hvm_info->vga_bios_size = bios_size;
+ munmap(va_bios, 16 * XC_PAGE_SIZE);
+ free(bios);
+
+ rc |= xc_domain_memory_mapping(xc_handle, dom,
+ 0xa0000 >> XC_PAGE_SHIFT,
+ 0xa0000 >> XC_PAGE_SHIFT,
+ 2 * 16, 1);
+ rc |= linux_map_vga_ioport(xc_handle, dom);
+
+ return rc;
+}
+
static int setup_guest(int xc_handle,
uint32_t dom, int memsize,
- char *image, unsigned long image_size)
+ char *image, unsigned long image_size,
+ struct hvm_info_table *hvm_info)
{
xen_pfn_t *page_array = NULL;
unsigned long i, nr_pages = (unsigned long)memsize << (20 - PAGE_SHIFT);
@@ -167,6 +279,7 @@ static int setup_guest(int xc_handle,
uint64_t v_start, v_end;
int rc;
xen_capabilities_info_t caps;
+ unsigned long vga_pt_enabled = 0;
/* An HVM guest must be initialised with at least 2MB memory. */
if ( memsize < 2 )
@@ -190,7 +303,7 @@ static int setup_guest(int xc_handle,
goto error_out;
}
- IPRINTF("VIRTUAL MEMORY ARRANGEMENT:\n"
+ fprintf(stderr, "VIRTUAL MEMORY ARRANGEMENT:\n"
" Loader: %016"PRIx64"->%016"PRIx64"\n"
" TOTAL: %016"PRIx64"->%016"PRIx64"\n"
" ENTRY ADDRESS: %016"PRIx64"\n",
@@ -314,6 +427,14 @@ static int setup_guest(int xc_handle,
}
free(page_array);
+
+ /* Setup VGA pass through */
+ if ( xc_get_hvm_param(xc_handle, dom,
+ HVM_PARAM_VGA_PT_ENABLED, &vga_pt_enabled) )
+ return -1;
+ if ( vga_pt_enabled )
+ return setup_vga_pt(xc_handle, dom, elf.pend, hvm_info);
+
return 0;
error_out:
@@ -325,7 +446,8 @@ static int xc_hvm_build_internal(int xc_
uint32_t domid,
int memsize,
char *image,
- unsigned long image_size)
+ unsigned long image_size,
+ struct hvm_info_table *hvm_info)
{
if ( (image == NULL) || (image_size == 0) )
{
@@ -333,7 +455,7 @@ static int xc_hvm_build_internal(int xc_
return -1;
}
- return setup_guest(xc_handle, domid, memsize, image, image_size);
+ return setup_guest(xc_handle, domid, memsize, image, image_size, hvm_info);
}
static inline int is_loadable_phdr(Elf32_Phdr *phdr)
@@ -348,9 +470,10 @@ int xc_hvm_build(int xc_handle,
int xc_hvm_build(int xc_handle,
uint32_t domid,
int memsize,
- const char *image_name)
+ const char *image_name,
+ struct hvm_info_table *hvm_info)
{
- char *image;
+ char *image;
int sts;
unsigned long image_size;
@@ -358,7 +481,8 @@ int xc_hvm_build(int xc_handle,
((image = xc_read_image(image_name, &image_size)) == NULL) )
return -1;
- sts = xc_hvm_build_internal(xc_handle, domid, memsize, image, image_size);
+ sts = xc_hvm_build_internal(xc_handle, domid, memsize,
+ image, image_size, hvm_info);
free(image);
@@ -372,7 +496,8 @@ int xc_hvm_build_mem(int xc_handle,
uint32_t domid,
int memsize,
const char *image_buffer,
- unsigned long image_size)
+ unsigned long image_size,
+ struct hvm_info_table *hvm_info)
{
int sts;
unsigned long img_len;
@@ -394,7 +519,7 @@ int xc_hvm_build_mem(int xc_handle,
}
sts = xc_hvm_build_internal(xc_handle, domid, memsize,
- img, img_len);
+ img, img_len, hvm_info);
/* xc_inflate_buffer may return the original buffer pointer (for
for already inflated buffers), so exercise some care in freeing */
diff -r 810d8c3ac992 tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h Thu May 08 16:58:33 2008 +0100
+++ b/tools/libxc/xenctrl.h Fri May 09 12:16:40 2008 +0100
@@ -30,6 +30,7 @@
#include <xen/xsm/acm.h>
#include <xen/xsm/acm_ops.h>
#include <xen/xsm/flask_op.h>
+#include <xen/hvm/params.h>
#ifdef __ia64__
#define XC_PAGE_SHIFT 14
diff -r 810d8c3ac992 tools/libxc/xenguest.h
--- a/tools/libxc/xenguest.h Thu May 08 16:58:33 2008 +0100
+++ b/tools/libxc/xenguest.h Fri May 09 12:16:40 2008 +0100
@@ -6,6 +6,8 @@
* Copyright (c) 2003-2004, K A Fraser.
*/
+#include <xen/hvm/hvm_info_table.h>
+
#ifndef XENGUEST_H
#define XENGUEST_H
@@ -13,7 +15,6 @@
#define XCFLAGS_DEBUG 2
#define XCFLAGS_HVM 4
#define XCFLAGS_STDVGA 8
-
/**
* This function will save a running domain.
@@ -128,12 +129,14 @@ int xc_hvm_build(int xc_handle,
int xc_hvm_build(int xc_handle,
uint32_t domid,
int memsize,
- const char *image_name);
+ const char *image_name,
+ struct hvm_info_table *hvm_info);
int xc_hvm_build_mem(int xc_handle,
uint32_t domid,
int memsize,
const char *image_buffer,
- unsigned long image_size);
+ unsigned long image_size,
+ struct hvm_info_table *hvm_info);
#endif /* XENGUEST_H */
diff -r 810d8c3ac992 tools/libxc/xg_private.c
--- a/tools/libxc/xg_private.c Thu May 08 16:58:33 2008 +0100
+++ b/tools/libxc/xg_private.c Fri May 09 12:16:40 2008 +0100
@@ -193,7 +193,8 @@ __attribute__((weak))
int xc_hvm_build(int xc_handle,
uint32_t domid,
int memsize,
- const char *image_name)
+ const char *image_name,
+ struct hvm_info_table *hvm_info)
{
errno = ENOSYS;
return -1;
diff -r 810d8c3ac992 tools/python/xen/lowlevel/xc/xc.c
--- a/tools/python/xen/lowlevel/xc/xc.c Thu May 08 16:58:33 2008 +0100
+++ b/tools/python/xen/lowlevel/xc/xc.c Fri May 09 12:16:40 2008 +0100
@@ -721,22 +721,28 @@ static PyObject *pyxc_hvm_build(XcObject
{
uint32_t dom;
#if !defined(__ia64__)
+ struct hvm_info_table hvm_info;
struct hvm_info_table *va_hvm;
uint8_t *va_map, sum;
int i;
#endif
char *image;
- int memsize, vcpus = 1, acpi = 0, apic = 1;
+ int memsize, vcpus = 1, acpi = 0, apic = 1, vga_pt = 0;
static char *kwd_list[] = { "domid",
"memsize", "image", "vcpus", "acpi",
- "apic", NULL };
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|iii", kwd_list,
+ "apic", "vga_pt", NULL };
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|iiii", kwd_list,
&dom, &memsize,
- &image, &vcpus, &acpi, &apic) )
+ &image, &vcpus, &acpi, &apic, &vga_pt) )
return NULL;
- if ( xc_hvm_build(self->xc_handle, dom, memsize, image) != 0 )
+ if ( xc_set_hvm_param(self->xc_handle, dom,
+ HVM_PARAM_VGA_PT_ENABLED, vga_pt) )
+ return pyxc_error_to_exception();
+
+ memset(&hvm_info, 0, sizeof(hvm_info));
+ if ( xc_hvm_build(self->xc_handle, dom, memsize, image, &hvm_info) != 0 )
return pyxc_error_to_exception();
#if !defined(__ia64__)
@@ -747,7 +753,7 @@ static PyObject *pyxc_hvm_build(XcObject
if ( va_map == NULL )
return PyErr_SetFromErrno(xc_error_obj);
va_hvm = (struct hvm_info_table *)(va_map + HVM_INFO_OFFSET);
- memset(va_hvm, 0, sizeof(*va_hvm));
+ memcpy(va_hvm, &hvm_info, sizeof (*va_hvm));
strncpy(va_hvm->signature, "HVM INFO", 8);
va_hvm->length = sizeof(struct hvm_info_table);
va_hvm->acpi_enabled = acpi;
diff -r 810d8c3ac992 tools/python/xen/xend/XendConfig.py
--- a/tools/python/xen/xend/XendConfig.py Thu May 08 16:58:33 2008 +0100
+++ b/tools/python/xen/xend/XendConfig.py Fri May 09 12:16:40 2008 +0100
@@ -160,6 +160,7 @@ XENAPI_PLATFORM_CFG_TYPES = {
'vhpt': int,
'guest_os_type': str,
'hap': int,
+ 'vga_passthrough' : int,
}
# Xen API console 'other_config' keys.
diff -r 810d8c3ac992 tools/python/xen/xend/image.py
--- a/tools/python/xen/xend/image.py Thu May 08 16:58:33 2008 +0100
+++ b/tools/python/xen/xend/image.py Fri May 09 12:16:40 2008 +0100
@@ -310,6 +310,10 @@ class ImageHandler:
if int(vmConfig['platform'].get('monitor', 0)) != 0:
ret = ret + ['-monitor', 'vc']
+
+ if (int(vmConfig['platform'].get('vga_passthrough', 0))) == 1:
+ ret.append('-enable-dom0');
+
return ret
def getDeviceModelArgs(self, restore = False):
@@ -536,6 +540,7 @@ class HVMImageHandler(ImageHandler):
self.apic = int(vmConfig['platform'].get('apic', 0))
self.acpi = int(vmConfig['platform'].get('acpi', 0))
self.guest_os_type = vmConfig['platform'].get('guest_os_type')
+ self.vga_pt = int(vmConfig['platform'].get('vga_passthrough', 0))
self.vmConfig = vmConfig
@@ -661,6 +666,7 @@ class HVMImageHandler(ImageHandler):
mem_mb = self.getRequiredInitialReservation() / 1024
+ log.debug(self.vmConfig)
log.debug("domid = %d", self.vm.getDomid())
log.debug("image = %s", self.loader)
log.debug("store_evtchn = %d", store_evtchn)
@@ -668,13 +674,15 @@ class HVMImageHandler(ImageHandler):
log.debug("vcpus = %d", self.vm.getVCpuCount())
log.debug("acpi = %d", self.acpi)
log.debug("apic = %d", self.apic)
+ log.debug("vga_pt = %d", self.vga_pt)
rc = xc.hvm_build(domid = self.vm.getDomid(),
image = self.loader,
memsize = mem_mb,
vcpus = self.vm.getVCpuCount(),
acpi = self.acpi,
- apic = self.apic)
+ apic = self.apic,
+ vga_pt = self.vga_pt)
rc['notes'] = { 'SUSPEND_CANCEL': 1 }
rc['store_mfn'] = xc.hvm_get_param(self.vm.getDomid(),
diff -r 810d8c3ac992 tools/python/xen/xm/create.py
--- a/tools/python/xen/xm/create.py Thu May 08 16:58:33 2008 +0100
+++ b/tools/python/xen/xm/create.py Fri May 09 12:16:40 2008 +0100
@@ -557,6 +557,10 @@ gopts.var('cpuid_check', val="IN[,SIN]:e
fn=append_value, default=[],
use="""Cpuid check description.""")
+gopts.var('vga_passthrough', val='VGA_PT',
+ fn=set_int, default=None,
+ use="Enable the passthrough for the graphic card.")
+
def err(msg):
"""Print an error to stderr and exit.
"""
@@ -763,7 +767,8 @@ def configure_hvm(config_image, vals):
'vnc', 'vncdisplay', 'vncunused', 'vncconsole', 'vnclisten',
'sdl', 'display', 'xauthority', 'rtc_timeoffset', 'monitor',
'acpi', 'apic', 'usb', 'usbdevice', 'keymap', 'pci', 'hpet',
- 'guest_os_type', 'hap', 'opengl', 'cpuid', 'cpuid_check']
+ 'guest_os_type', 'hap', 'opengl', 'cpuid', 'cpuid_check',
+ 'vga_passthrough' ]
for a in args:
if a in vals.__dict__ and vals.__dict__[a] is not None:
diff -r 810d8c3ac992 xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c Thu May 08 16:58:33 2008 +0100
+++ b/xen/arch/x86/hvm/hvm.c Fri May 09 12:16:40 2008 +0100
@@ -310,7 +310,8 @@ int hvm_domain_initialise(struct domain
if ( rc != 0 )
goto fail1;
- stdvga_init(d);
+ if ( !d->arch.hvm_domain.params[HVM_PARAM_VGA_PT_ENABLED] )
+ stdvga_init(d);
hvm_init_ioreq_page(d, &d->arch.hvm_domain.ioreq);
hvm_init_ioreq_page(d, &d->arch.hvm_domain.buf_ioreq);
diff -r 810d8c3ac992 xen/include/public/hvm/hvm_info_table.h
--- a/xen/include/public/hvm/hvm_info_table.h Thu May 08 16:58:33 2008 +0100
+++ b/xen/include/public/hvm/hvm_info_table.h Fri May 09 12:16:40 2008 +0100
@@ -36,6 +36,9 @@ struct hvm_info_table {
uint8_t acpi_enabled;
uint8_t apic_mode;
uint32_t nr_vcpus;
+ uint32_t vga_bios_paddr;
+ uint32_t vga_bios_size;
+
};
#endif /* __XEN_PUBLIC_HVM_HVM_INFO_TABLE_H__ */
diff -r 810d8c3ac992 xen/include/public/hvm/params.h
--- a/xen/include/public/hvm/params.h Thu May 08 16:58:33 2008 +0100
+++ b/xen/include/public/hvm/params.h Fri May 09 12:16:40 2008 +0100
@@ -90,6 +90,9 @@
/* Device Model domain, defaults to 0. */
#define HVM_PARAM_DM_DOMAIN 13
-#define HVM_NR_PARAMS 14
+/* Boolean : VGA passthrough */
+#define HVM_PARAM_VGA_PT_ENABLED 14
+
+#define HVM_NR_PARAMS 15
#endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */
[-- Attachment #3: Type: text/plain, Size: 138 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: Re: [PATCH] Pass-through a graphic card
2008-05-09 11:18 ` Jean Guyader
@ 2008-05-09 11:32 ` Samuel Thibault
0 siblings, 0 replies; 13+ messages in thread
From: Samuel Thibault @ 2008-05-09 11:32 UTC (permalink / raw)
To: Jean Guyader; +Cc: Ian Pratt, xen-devel, Keir Fraser, Kamala Narasimhan
Jean Guyader, le Fri 09 May 2008 12:18:15 +0100, a écrit :
> +#define EVENT_MAX 10
> +#define EVENT_PATH "/dev/input/event"
> +
> +struct dom0_driver
> +{
> + int event_fds[EVENT_MAX];
> + int mouse_button_state;
> +};
Dynamically allocate event_fds instead of having a fixed limit? (I have
already 8 input devices on my laptop ;) )
Samuel
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] Pass-through a graphic card
2008-05-09 11:11 [PATCH] Pass-through a graphic card Jean Guyader
2008-05-09 11:18 ` Jean Guyader
@ 2008-05-09 11:27 ` Samuel Thibault
2008-05-09 13:56 ` Jean Guyader
2008-05-15 10:11 ` Jean Guyader
3 siblings, 0 replies; 13+ messages in thread
From: Samuel Thibault @ 2008-05-09 11:27 UTC (permalink / raw)
To: Jean Guyader; +Cc: Ian Pratt, xen-devel, Keir Fraser, Kamala Narasimhan
Jean Guyader, le Fri 09 May 2008 12:11:44 +0100, a écrit :
> - Then we start qemu with the new option -enable-dom0 to have the
> dom0's keyboard and the mouse redirected into the guest.
I would suggest to a more expressive name, like -dom0-input
> Be careful, vnc must be at 0.
Can't you have the dom0 option override the vnc option?
> + if (!(mem = fopen("/dev/mem", "r")))
> + return 0;
> +
> + fseek(mem, start, SEEK_SET);
> + fread(buf, 1, size, mem);
> + fclose(mem);
Mmm, no need for f functionnalities, you can just replace it with
open/lseek/read/close.
> + bios_size = linux_get_vgabios(xc_handle, bios, 128 * 1024);
> +
> + if (bios_size <= 0)
> + {
> + free(bios);
> + return -1;
> + }
> +
> + va_bios = xc_map_foreign_range(xc_handle, dom, 16 * XC_PAGE_SIZE,
use bios_size here instead?
> + PROT_READ | PROT_WRITE, pfn);
> +
> + memcpy(va_bios, bios, bios_size);
> + hvm_info->vga_bios_paddr = pfn << XC_PAGE_SHIFT;
> + hvm_info->vga_bios_size = bios_size;
> + munmap(va_bios, 16 * XC_PAGE_SIZE);
> + free(bios);
> +
> + rc |= xc_domain_memory_mapping(xc_handle, dom,
> + 0xa0000 >> XC_PAGE_SHIFT,
> + 0xa0000 >> XC_PAGE_SHIFT,
> + 2 * 16, 1);
use (0xc0000 - 0xa0000) >> XC_PAGE_SHIFT instead?
> @@ -190,7 +303,7 @@ static int setup_guest(int xc_handle,
> goto error_out;
> }
>
> - IPRINTF("VIRTUAL MEMORY ARRANGEMENT:\n"
> + fprintf(stderr, "VIRTUAL MEMORY ARRANGEMENT:\n"
> " Loader: %016"PRIx64"->%016"PRIx64"\n"
> " TOTAL: %016"PRIx64"->%016"PRIx64"\n"
Mmm, I guess you should not change that :)
Samuel
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH] Pass-through a graphic card
2008-05-09 11:11 [PATCH] Pass-through a graphic card Jean Guyader
2008-05-09 11:18 ` Jean Guyader
2008-05-09 11:27 ` Samuel Thibault
@ 2008-05-09 13:56 ` Jean Guyader
2008-05-09 14:02 ` Daniel P. Berrange
2008-05-09 14:25 ` Daniel P. Berrange
2008-05-15 10:11 ` Jean Guyader
3 siblings, 2 replies; 13+ messages in thread
From: Jean Guyader @ 2008-05-09 13:56 UTC (permalink / raw)
To: xen-devel; +Cc: Ian Pratt, Keir Fraser, Kamala Narasimhan
[-- Attachment #1: Type: text/plain, Size: 83 bytes --]
Here, a new patch with the modifications that Samuel suggested.
--
Jean Guyader
[-- Attachment #2: vga_pt2.patch --]
[-- Type: text/x-diff, Size: 30322 bytes --]
diff -r 810d8c3ac992 tools/firmware/hvmloader/config.h
--- a/tools/firmware/hvmloader/config.h Thu May 08 16:58:33 2008 +0100
+++ b/tools/firmware/hvmloader/config.h Fri May 09 14:53:11 2008 +0100
@@ -23,7 +23,7 @@
/* Memory map. */
#define HYPERCALL_PHYSICAL_ADDRESS 0x00080000
#define VGABIOS_PHYSICAL_ADDRESS 0x000C0000
-#define ETHERBOOT_PHYSICAL_ADDRESS 0x000C8000
+#define ETHERBOOT_PHYSICAL_ADDRESS 0x000D0000
#define EXTBOOT_PHYSICAL_ADDRESS 0x000DF800
#define SMBIOS_PHYSICAL_ADDRESS 0x000E9000
#define SMBIOS_MAXIMUM_SIZE 0x00001000
diff -r 810d8c3ac992 tools/firmware/hvmloader/hvmloader.c
--- a/tools/firmware/hvmloader/hvmloader.c Thu May 08 16:58:33 2008 +0100
+++ b/tools/firmware/hvmloader/hvmloader.c Fri May 09 14:53:11 2008 +0100
@@ -464,7 +464,16 @@ int main(void)
if ( (get_vcpu_nr() > 1) || get_apic_mode() )
create_mp_tables();
- if ( cirrus_check() )
+ if ( get_vga_pt_enabled() )
+ {
+ printf("Loading dom0 VGABIOS ...\n");
+ printf(" - 0x%x (0x%x)\n", get_vga_pt_bios_paddr(), get_vga_pt_bios_size());
+ memcpy((void*)VGABIOS_PHYSICAL_ADDRESS,
+ (void*)get_vga_pt_bios_paddr(),
+ get_vga_pt_bios_size());
+ vgabios_sz = get_vga_pt_bios_size();
+ }
+ else if ( cirrus_check() )
{
printf("Loading Cirrus VGABIOS ...\n");
memcpy((void *)VGABIOS_PHYSICAL_ADDRESS,
diff -r 810d8c3ac992 tools/firmware/hvmloader/util.c
--- a/tools/firmware/hvmloader/util.c Thu May 08 16:58:33 2008 +0100
+++ b/tools/firmware/hvmloader/util.c Fri May 09 14:53:11 2008 +0100
@@ -594,6 +594,24 @@ int get_vcpu_nr(void)
return (t ? t->nr_vcpus : 1);
}
+int get_vga_pt_enabled(void)
+{
+ struct hvm_info_table *t = get_hvm_info_table();
+ return (t && t->vga_bios_paddr > 0);
+}
+
+int get_vga_pt_bios_paddr(void)
+{
+ struct hvm_info_table *t = get_hvm_info_table();
+ return (t ? t->vga_bios_paddr : 0);
+}
+
+int get_vga_pt_bios_size(void)
+{
+ struct hvm_info_table *t = get_hvm_info_table();
+ return (t ? t->vga_bios_size : -1);
+}
+
int get_acpi_enabled(void)
{
struct hvm_info_table *t = get_hvm_info_table();
diff -r 810d8c3ac992 tools/firmware/hvmloader/util.h
--- a/tools/firmware/hvmloader/util.h Thu May 08 16:58:33 2008 +0100
+++ b/tools/firmware/hvmloader/util.h Fri May 09 14:53:11 2008 +0100
@@ -106,6 +106,9 @@ int get_vcpu_nr(void);
int get_vcpu_nr(void);
int get_acpi_enabled(void);
int get_apic_mode(void);
+int get_vga_pt_enabled(void);
+int get_vga_pt_bios_paddr(void);
+int get_vga_pt_bios_size(void);
/* String and memory functions */
int strcmp(const char *cs, const char *ct);
diff -r 810d8c3ac992 tools/ioemu/Makefile.target
--- a/tools/ioemu/Makefile.target Thu May 08 16:58:33 2008 +0100
+++ b/tools/ioemu/Makefile.target Fri May 09 14:53:11 2008 +0100
@@ -499,6 +499,9 @@ COCOA_LIBS+=-framework CoreAudio
COCOA_LIBS+=-framework CoreAudio
endif
endif
+
+VL_OBJS+=dom0_driver.o
+
ifdef CONFIG_SLIRP
CPPFLAGS+=-I$(SRC_PATH)/slirp
SLIRP_OBJS=cksum.o if.o ip_icmp.o ip_input.o ip_output.o \
diff -r 810d8c3ac992 tools/ioemu/dom0_driver.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/dom0_driver.c Fri May 09 14:53:11 2008 +0100
@@ -0,0 +1,163 @@
+/*
+ * QEMU dom0 /dev/input driver
+ *
+ * Copyright (c) 2008 Citrix Systems
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "vl.h"
+
+#include <sys/types.h>
+#include <linux/input.h>
+#include <linux/kd.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#define EVENT_PATH "/dev/input/event"
+
+struct dom0_driver
+{
+ int *event_fds;
+ int event_nb;
+ int mouse_button_state;
+};
+
+static struct dom0_driver driver;
+
+static void dom0_update(DisplayState *ds, int x, int y, int w, int h)
+{
+}
+
+static void dom0_resize(DisplayState *ds, int w, int h, int linesize)
+{
+}
+
+static void dom0_refresh(DisplayState *ds)
+{
+}
+
+static void dom0_read(void *opaque)
+{
+ struct input_event event[5];
+ int i = 0;
+ int read_sz = 0;
+ int fd = *(int *)opaque;
+
+ read_sz = read(fd, event, sizeof (struct input_event) * 5);
+ for (i = 0; i < read_sz / (sizeof (struct input_event)); i++)
+ {
+ if (event[i].type == EV_KEY)
+ {
+ if (event[i].code >= BTN_MOUSE)
+ {
+ /* Mouse Key */
+ int type = 0;
+
+ switch(event[i].code)
+ {
+ case BTN_LEFT: type = MOUSE_EVENT_LBUTTON; break;
+ case BTN_RIGHT: type = MOUSE_EVENT_RBUTTON; break;
+ }
+
+ if (event[i].value)
+ driver.mouse_button_state |= type;
+ else
+ driver.mouse_button_state &= ~type;
+ kbd_mouse_event(0, 0, 0, driver.mouse_button_state);
+ }
+ else
+ {
+ /* Keyboard key */
+ if (event[i].value == 1)
+ kbd_put_keycode(event[i].code | 0x80);
+ else
+ kbd_put_keycode(event[i].code & 0x7f);
+ }
+ }
+
+ if (event[i].type == EV_REL)
+ {
+ /* Mouse motion */
+ int x = 0, y = 0, z = 0;
+
+ switch (event[i].code)
+ {
+ case REL_X : x = event[i].value; break;
+ case REL_Y : y = event[i].value; break;
+ case REL_WHEEL : z = event[i].value; break;
+ }
+
+ kbd_mouse_event(x, y, z, driver.mouse_button_state);
+ }
+ }
+}
+
+static void dom0_driver_event_init()
+{
+ char dev_name[strlen(EVENT_PATH) + 3];
+ int fd = -1;
+ int i = 0;
+
+ do
+ {
+ snprintf(dev_name, sizeof (dev_name), "%s%d", EVENT_PATH, i++);
+ if ((fd = open(dev_name, O_RDONLY)) == -1)
+ return;
+ printf("Using %s\n", dev_name);
+
+ driver.event_fds = realloc(driver.event_fds,
+ driver.event_nb + 1);
+ ioctl(fd, EVIOCGRAB, 1);
+
+ driver.event_fds[driver.event_nb] = fd;
+ qemu_set_fd_handler(fd, dom0_read, NULL,
+ &driver.event_fds[driver.event_nb]);
+ driver.event_nb++;
+ }
+ while (1);
+}
+
+static void dom0_driver_cleanup(void)
+{
+ free(driver.event_fds);
+}
+
+void dom0_driver_init(DisplayState *ds)
+{
+ memset(&driver, 0, sizeof (driver));
+
+ dom0_driver_event_init();
+
+ ds->data = NULL;
+ ds->linesize = 0;
+ ds->depth = 0;
+ ds->dpy_update = dom0_update;
+ ds->dpy_resize = dom0_resize;
+ ds->dpy_colourdepth = NULL;
+ ds->dpy_refresh = dom0_refresh;
+
+ atexit(dom0_driver_cleanup);
+}
diff -r 810d8c3ac992 tools/ioemu/hw/pc.c
--- a/tools/ioemu/hw/pc.c Thu May 08 16:58:33 2008 +0100
+++ b/tools/ioemu/hw/pc.c Fri May 09 14:53:11 2008 +0100
@@ -814,6 +814,13 @@ static void pc_init1(uint64_t ram_size,
CPUState *env;
NICInfo *nd;
int rc;
+#ifdef CONFIG_DM
+ unsigned long vga_pt_enabled = 0;
+#endif /* CONFIG_DM */
+
+#ifdef CONFIG_DM
+ xc_get_hvm_param(xc_handle, domid, HVM_PARAM_VGA_PT_ENABLED, &vga_pt_enabled);
+#endif /* CONFIG_DM */
linux_boot = (kernel_filename != NULL);
@@ -862,12 +869,18 @@ static void pc_init1(uint64_t ram_size,
}
/* VGA BIOS load */
- if (cirrus_vga_enabled) {
- snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_CIRRUS_FILENAME);
- } else {
- snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_FILENAME);
+#ifdef CONFIG_DM
+ if (!vga_pt_enabled)
+#endif /* CONFIG_DM */
+ {
+ fprintf(stderr, "Load qemu pci vga\n");
+ if (cirrus_vga_enabled) {
+ snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_CIRRUS_FILENAME);
+ } else {
+ snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_FILENAME);
+ }
+ ret = load_image(buf, phys_ram_base + vga_bios_offset);
}
- ret = load_image(buf, phys_ram_base + vga_bios_offset);
#endif /* !NOBIOS */
/* setup basic memory access */
@@ -925,22 +938,27 @@ static void pc_init1(uint64_t ram_size,
register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL);
- if (cirrus_vga_enabled) {
- if (pci_enabled) {
- pci_cirrus_vga_init(pci_bus,
- ds, NULL, ram_size,
- vga_ram_size);
+#ifdef CONFIG_DM
+ if (!vga_pt_enabled)
+#endif /* CONFIG_DM */
+ {
+ if (cirrus_vga_enabled) {
+ if (pci_enabled) {
+ pci_cirrus_vga_init(pci_bus,
+ ds, NULL, ram_size,
+ vga_ram_size);
+ } else {
+ isa_cirrus_vga_init(ds, NULL, ram_size,
+ vga_ram_size);
+ }
} else {
- isa_cirrus_vga_init(ds, NULL, ram_size,
- vga_ram_size);
- }
- } else {
- if (pci_enabled) {
- pci_vga_init(pci_bus, ds, NULL, ram_size,
- vga_ram_size, 0, 0);
- } else {
- isa_vga_init(ds, NULL, ram_size,
- vga_ram_size);
+ if (pci_enabled) {
+ pci_vga_init(pci_bus, ds, NULL, ram_size,
+ vga_ram_size, 0, 0);
+ } else {
+ isa_vga_init(ds, NULL, ram_size,
+ vga_ram_size);
+ }
}
}
diff -r 810d8c3ac992 tools/ioemu/vl.c
--- a/tools/ioemu/vl.c Thu May 08 16:58:33 2008 +0100
+++ b/tools/ioemu/vl.c Fri May 09 14:53:11 2008 +0100
@@ -179,6 +179,9 @@ int opengl_enabled = 1;
#else
int opengl_enabled = 0;
#endif
+#ifdef CONFIG_DM
+int dom0_input = 0;
+#endif /* CONFIG_DM */
int no_quit = 0;
CharDriverState *serial_hds[MAX_SERIAL_PORTS];
CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
@@ -6486,8 +6489,9 @@ void help(void)
"-no-quit disable SDL window close capability\n"
#endif
#ifdef CONFIG_OPENGL
- "-disable-opengl disable OpenGL rendering, using SDL"
-#endif
+ "-disable-opengl disable OpenGL rendering, using SDL\n"
+#endif
+ "-dom0-input enable dom0 controling qemu\n"
#ifdef TARGET_I386
"-no-fd-bootchk disable boot signature checking for floppy disks\n"
#endif
@@ -6667,6 +6671,9 @@ enum {
QEMU_OPTION_full_screen,
QEMU_OPTION_no_quit,
QEMU_OPTION_disable_opengl,
+#ifdef CONFIG_DM
+ QEMU_OPTION_dom0_input,
+#endif /* CONFIG_DM */
QEMU_OPTION_pidfile,
QEMU_OPTION_no_kqemu,
QEMU_OPTION_kernel_kqemu,
@@ -6765,6 +6772,7 @@ const QEMUOption qemu_options[] = {
{ "no-quit", 0, QEMU_OPTION_no_quit },
#endif
{ "disable-opengl", 0, QEMU_OPTION_disable_opengl },
+ { "dom0-input", 0, QEMU_OPTION_dom0_input },
{ "pidfile", HAS_ARG, QEMU_OPTION_pidfile },
{ "win2k-hack", 0, QEMU_OPTION_win2k_hack },
{ "usbdevice", HAS_ARG, QEMU_OPTION_usbdevice },
@@ -7516,6 +7524,11 @@ int main(int argc, char **argv)
case QEMU_OPTION_disable_opengl:
opengl_enabled = 0;
break;
+#ifdef CONFIG_DM
+ case QEMU_OPTION_dom0_input:
+ dom0_input = 1;
+ break;
+#endif /* CONFIG_DM */
case QEMU_OPTION_pidfile:
create_pidfile(optarg);
break;
@@ -7823,12 +7836,18 @@ int main(int argc, char **argv)
init_ioports();
/* terminal init */
+
#ifdef CONFIG_STUBDOM
if (xenfb_pv_display_init(ds) == 0) {
} else
#endif
if (nographic) {
+#ifdef CONFIG_DM
+ if (dom0_input == 1)
+ dom0_driver_init(ds);
+#else
dumb_display_init(ds);
+#endif /* CONFIG_DM */
} else if (vnc_display != NULL || vncunused != 0) {
int vnc_display_port;
char password[20];
@@ -7842,7 +7861,9 @@ int main(int argc, char **argv)
vnc_start_viewer(vnc_display_port);
#endif
xenstore_write_vncport(vnc_display_port);
- } else {
+ }
+ else
+ {
#if defined(CONFIG_SDL)
sdl_display_init(ds, full_screen, opengl_enabled);
#elif defined(CONFIG_COCOA)
diff -r 810d8c3ac992 tools/ioemu/vl.h
--- a/tools/ioemu/vl.h Thu May 08 16:58:33 2008 +0100
+++ b/tools/ioemu/vl.h Fri May 09 14:53:11 2008 +0100
@@ -997,6 +997,9 @@ void do_info_vnc(void);
void do_info_vnc(void);
int vnc_start_viewer(int port);
+/* dom0_driver.c */
+void dom0_driver_init(DisplayState *ds);
+
/* x_keymap.c */
extern uint8_t _translate_keycode(const int key);
diff -r 810d8c3ac992 tools/libxc/xc_hvm_build.c
--- a/tools/libxc/xc_hvm_build.c Thu May 08 16:58:33 2008 +0100
+++ b/tools/libxc/xc_hvm_build.c Fri May 09 14:53:11 2008 +0100
@@ -152,9 +152,122 @@ static int loadelfimage(
return rc;
}
+static int linux_get_vgabios(int xc_handle,
+ unsigned char *buf,
+ int len)
+{
+ char buff[1024];
+ FILE *fd;
+ int mem;
+ char *end_ptr;
+ uint32_t start, end, size;
+
+ if (!(fd = fopen("/proc/iomem", "r")))
+ return 0;
+
+ while (fgets(buff, 1024, fd))
+ if (strstr(buff, "Video ROM"))
+ break;
+
+ if (feof(fd))
+ {
+ fclose(fd);
+ return 0;
+ }
+
+ fclose(fd);
+ start = strtol(buff, &end_ptr, 16);
+ end = strtol(end_ptr + 1, NULL, 16);
+ size = end - start + 1;
+
+ if ((mem = open("/dev/mem", O_RDONLY)) < 0)
+ return 0;
+
+ lseek(mem, start, SEEK_SET);
+ read(mem, buf, size);
+ close(mem);
+
+ return size;
+}
+
+static int linux_map_vga_ioport(int xc_handler,
+ uint32_t dom)
+{
+ FILE *fd = NULL;
+ char buff[256];
+ uint32_t start, end;
+ char *buff_end = NULL;
+
+ if (!(fd = fopen("/proc/ioports", "r")))
+ return -1;
+
+ while (fgets(buff, 256, fd))
+ if (strstr(buff, "vga"))
+ break;
+
+ if (feof(fd))
+ {
+ fclose(fd);
+ return -1;
+ }
+
+ fclose(fd);
+
+ start = strtol(buff, &buff_end, 16);
+ end = strtol(buff_end + 1, NULL, 16);
+
+ return xc_domain_ioport_mapping(xc_handler, dom,
+ start, start, end - start + 1, 1);
+}
+
+static int setup_vga_pt(int xc_handle,
+ uint32_t dom,
+ uint32_t paddr,
+ struct hvm_info_table *hvm_info)
+{
+ int rc = 0;
+ unsigned char *bios = NULL;
+ int bios_size = 0;
+ char *va_bios = NULL;
+ uint32_t pfn = 0;
+
+ /* Allocated 128K for the vga bios */
+ if (!(bios = malloc(128 * 1024)))
+ return -1;
+
+ /* Align paddr on the first next page */
+ pfn = (paddr >> XC_PAGE_SHIFT) + 1;
+
+ bios_size = linux_get_vgabios(xc_handle, bios, 128 * 1024);
+
+ if (bios_size <= 0)
+ {
+ free(bios);
+ return -1;
+ }
+
+ va_bios = xc_map_foreign_range(xc_handle, dom,
+ bios_size + bios_size % XC_PAGE_SIZE,
+ PROT_READ | PROT_WRITE, pfn);
+ memcpy(va_bios, bios, bios_size);
+ hvm_info->vga_bios_paddr = pfn << XC_PAGE_SHIFT;
+ hvm_info->vga_bios_size = bios_size;
+ munmap(va_bios, bios_size + bios_size % XC_PAGE_SIZE);
+ free(bios);
+
+ rc |= xc_domain_memory_mapping(xc_handle, dom,
+ 0xa0000 >> XC_PAGE_SHIFT,
+ 0xa0000 >> XC_PAGE_SHIFT,
+ (0xc0000 - 0xa0000) >> XC_PAGE_SHIFT,
+ 1);
+ rc |= linux_map_vga_ioport(xc_handle, dom);
+ return rc;
+}
+
static int setup_guest(int xc_handle,
uint32_t dom, int memsize,
- char *image, unsigned long image_size)
+ char *image, unsigned long image_size,
+ struct hvm_info_table *hvm_info)
{
xen_pfn_t *page_array = NULL;
unsigned long i, nr_pages = (unsigned long)memsize << (20 - PAGE_SHIFT);
@@ -167,6 +280,7 @@ static int setup_guest(int xc_handle,
uint64_t v_start, v_end;
int rc;
xen_capabilities_info_t caps;
+ unsigned long vga_pt_enabled = 0;
/* An HVM guest must be initialised with at least 2MB memory. */
if ( memsize < 2 )
@@ -314,6 +428,14 @@ static int setup_guest(int xc_handle,
}
free(page_array);
+
+ /* Setup VGA pass through */
+ if ( xc_get_hvm_param(xc_handle, dom,
+ HVM_PARAM_VGA_PT_ENABLED, &vga_pt_enabled) )
+ return -1;
+ if ( vga_pt_enabled )
+ return setup_vga_pt(xc_handle, dom, elf.pend, hvm_info);
+
return 0;
error_out:
@@ -325,7 +447,8 @@ static int xc_hvm_build_internal(int xc_
uint32_t domid,
int memsize,
char *image,
- unsigned long image_size)
+ unsigned long image_size,
+ struct hvm_info_table *hvm_info)
{
if ( (image == NULL) || (image_size == 0) )
{
@@ -333,7 +456,7 @@ static int xc_hvm_build_internal(int xc_
return -1;
}
- return setup_guest(xc_handle, domid, memsize, image, image_size);
+ return setup_guest(xc_handle, domid, memsize, image, image_size, hvm_info);
}
static inline int is_loadable_phdr(Elf32_Phdr *phdr)
@@ -348,9 +471,10 @@ int xc_hvm_build(int xc_handle,
int xc_hvm_build(int xc_handle,
uint32_t domid,
int memsize,
- const char *image_name)
+ const char *image_name,
+ struct hvm_info_table *hvm_info)
{
- char *image;
+ char *image;
int sts;
unsigned long image_size;
@@ -358,7 +482,8 @@ int xc_hvm_build(int xc_handle,
((image = xc_read_image(image_name, &image_size)) == NULL) )
return -1;
- sts = xc_hvm_build_internal(xc_handle, domid, memsize, image, image_size);
+ sts = xc_hvm_build_internal(xc_handle, domid, memsize,
+ image, image_size, hvm_info);
free(image);
@@ -372,7 +497,8 @@ int xc_hvm_build_mem(int xc_handle,
uint32_t domid,
int memsize,
const char *image_buffer,
- unsigned long image_size)
+ unsigned long image_size,
+ struct hvm_info_table *hvm_info)
{
int sts;
unsigned long img_len;
@@ -394,7 +520,7 @@ int xc_hvm_build_mem(int xc_handle,
}
sts = xc_hvm_build_internal(xc_handle, domid, memsize,
- img, img_len);
+ img, img_len, hvm_info);
/* xc_inflate_buffer may return the original buffer pointer (for
for already inflated buffers), so exercise some care in freeing */
diff -r 810d8c3ac992 tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h Thu May 08 16:58:33 2008 +0100
+++ b/tools/libxc/xenctrl.h Fri May 09 14:53:11 2008 +0100
@@ -30,6 +30,7 @@
#include <xen/xsm/acm.h>
#include <xen/xsm/acm_ops.h>
#include <xen/xsm/flask_op.h>
+#include <xen/hvm/params.h>
#ifdef __ia64__
#define XC_PAGE_SHIFT 14
diff -r 810d8c3ac992 tools/libxc/xenguest.h
--- a/tools/libxc/xenguest.h Thu May 08 16:58:33 2008 +0100
+++ b/tools/libxc/xenguest.h Fri May 09 14:53:11 2008 +0100
@@ -6,6 +6,8 @@
* Copyright (c) 2003-2004, K A Fraser.
*/
+#include <xen/hvm/hvm_info_table.h>
+
#ifndef XENGUEST_H
#define XENGUEST_H
@@ -13,7 +15,6 @@
#define XCFLAGS_DEBUG 2
#define XCFLAGS_HVM 4
#define XCFLAGS_STDVGA 8
-
/**
* This function will save a running domain.
@@ -128,12 +129,14 @@ int xc_hvm_build(int xc_handle,
int xc_hvm_build(int xc_handle,
uint32_t domid,
int memsize,
- const char *image_name);
+ const char *image_name,
+ struct hvm_info_table *hvm_info);
int xc_hvm_build_mem(int xc_handle,
uint32_t domid,
int memsize,
const char *image_buffer,
- unsigned long image_size);
+ unsigned long image_size,
+ struct hvm_info_table *hvm_info);
#endif /* XENGUEST_H */
diff -r 810d8c3ac992 tools/libxc/xg_private.c
--- a/tools/libxc/xg_private.c Thu May 08 16:58:33 2008 +0100
+++ b/tools/libxc/xg_private.c Fri May 09 14:53:11 2008 +0100
@@ -193,7 +193,8 @@ __attribute__((weak))
int xc_hvm_build(int xc_handle,
uint32_t domid,
int memsize,
- const char *image_name)
+ const char *image_name,
+ struct hvm_info_table *hvm_info)
{
errno = ENOSYS;
return -1;
diff -r 810d8c3ac992 tools/python/xen/lowlevel/xc/xc.c
--- a/tools/python/xen/lowlevel/xc/xc.c Thu May 08 16:58:33 2008 +0100
+++ b/tools/python/xen/lowlevel/xc/xc.c Fri May 09 14:53:12 2008 +0100
@@ -721,22 +721,28 @@ static PyObject *pyxc_hvm_build(XcObject
{
uint32_t dom;
#if !defined(__ia64__)
+ struct hvm_info_table hvm_info;
struct hvm_info_table *va_hvm;
uint8_t *va_map, sum;
int i;
#endif
char *image;
- int memsize, vcpus = 1, acpi = 0, apic = 1;
+ int memsize, vcpus = 1, acpi = 0, apic = 1, vga_pt = 0;
static char *kwd_list[] = { "domid",
"memsize", "image", "vcpus", "acpi",
- "apic", NULL };
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|iii", kwd_list,
+ "apic", "vga_pt", NULL };
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|iiii", kwd_list,
&dom, &memsize,
- &image, &vcpus, &acpi, &apic) )
+ &image, &vcpus, &acpi, &apic, &vga_pt) )
return NULL;
- if ( xc_hvm_build(self->xc_handle, dom, memsize, image) != 0 )
+ if ( xc_set_hvm_param(self->xc_handle, dom,
+ HVM_PARAM_VGA_PT_ENABLED, vga_pt) )
+ return pyxc_error_to_exception();
+
+ memset(&hvm_info, 0, sizeof(hvm_info));
+ if ( xc_hvm_build(self->xc_handle, dom, memsize, image, &hvm_info) != 0 )
return pyxc_error_to_exception();
#if !defined(__ia64__)
@@ -747,7 +753,7 @@ static PyObject *pyxc_hvm_build(XcObject
if ( va_map == NULL )
return PyErr_SetFromErrno(xc_error_obj);
va_hvm = (struct hvm_info_table *)(va_map + HVM_INFO_OFFSET);
- memset(va_hvm, 0, sizeof(*va_hvm));
+ memcpy(va_hvm, &hvm_info, sizeof (*va_hvm));
strncpy(va_hvm->signature, "HVM INFO", 8);
va_hvm->length = sizeof(struct hvm_info_table);
va_hvm->acpi_enabled = acpi;
diff -r 810d8c3ac992 tools/python/xen/xend/XendConfig.py
--- a/tools/python/xen/xend/XendConfig.py Thu May 08 16:58:33 2008 +0100
+++ b/tools/python/xen/xend/XendConfig.py Fri May 09 14:53:12 2008 +0100
@@ -160,6 +160,7 @@ XENAPI_PLATFORM_CFG_TYPES = {
'vhpt': int,
'guest_os_type': str,
'hap': int,
+ 'vga_passthrough' : int,
}
# Xen API console 'other_config' keys.
diff -r 810d8c3ac992 tools/python/xen/xend/image.py
--- a/tools/python/xen/xend/image.py Thu May 08 16:58:33 2008 +0100
+++ b/tools/python/xen/xend/image.py Fri May 09 14:53:12 2008 +0100
@@ -240,6 +240,8 @@ class ImageHandler:
vnc_config = {}
has_vnc = int(vmConfig['platform'].get('vnc', 0)) != 0
has_sdl = int(vmConfig['platform'].get('sdl', 0)) != 0
+ has_vga_passthrough = int(vmConfig['platform'].get('monitor', 0)) != 0;
+
opengl = 1
for dev_uuid in vmConfig['console_refs']:
dev_type, dev_info = vmConfig['devices'][dev_uuid]
@@ -260,7 +262,7 @@ class ImageHandler:
ret.append("-k")
ret.append(keymap)
- if has_vnc:
+ if has_vnc and not has_vga_passthrough:
if not vnc_config:
for key in ('vncunused', 'vnclisten', 'vncdisplay',
'vncpasswd'):
@@ -308,8 +310,12 @@ class ImageHandler:
else:
ret.append('-nographic')
- if int(vmConfig['platform'].get('monitor', 0)) != 0:
+ if has_vga_passthrough:
ret = ret + ['-monitor', 'vc']
+
+ if (int(vmConfig['platform'].get('vga_passthrough', 0))) == 1:
+ ret.append('-dom0-input');
+
return ret
def getDeviceModelArgs(self, restore = False):
@@ -536,6 +542,7 @@ class HVMImageHandler(ImageHandler):
self.apic = int(vmConfig['platform'].get('apic', 0))
self.acpi = int(vmConfig['platform'].get('acpi', 0))
self.guest_os_type = vmConfig['platform'].get('guest_os_type')
+ self.vga_pt = int(vmConfig['platform'].get('vga_passthrough', 0))
self.vmConfig = vmConfig
@@ -661,6 +668,7 @@ class HVMImageHandler(ImageHandler):
mem_mb = self.getRequiredInitialReservation() / 1024
+ log.debug(self.vmConfig)
log.debug("domid = %d", self.vm.getDomid())
log.debug("image = %s", self.loader)
log.debug("store_evtchn = %d", store_evtchn)
@@ -668,13 +676,15 @@ class HVMImageHandler(ImageHandler):
log.debug("vcpus = %d", self.vm.getVCpuCount())
log.debug("acpi = %d", self.acpi)
log.debug("apic = %d", self.apic)
+ log.debug("vga_pt = %d", self.vga_pt)
rc = xc.hvm_build(domid = self.vm.getDomid(),
image = self.loader,
memsize = mem_mb,
vcpus = self.vm.getVCpuCount(),
acpi = self.acpi,
- apic = self.apic)
+ apic = self.apic,
+ vga_pt = self.vga_pt)
rc['notes'] = { 'SUSPEND_CANCEL': 1 }
rc['store_mfn'] = xc.hvm_get_param(self.vm.getDomid(),
diff -r 810d8c3ac992 tools/python/xen/xm/create.py
--- a/tools/python/xen/xm/create.py Thu May 08 16:58:33 2008 +0100
+++ b/tools/python/xen/xm/create.py Fri May 09 14:53:12 2008 +0100
@@ -557,6 +557,10 @@ gopts.var('cpuid_check', val="IN[,SIN]:e
fn=append_value, default=[],
use="""Cpuid check description.""")
+gopts.var('vga_passthrough', val='VGA_PT',
+ fn=set_int, default=None,
+ use="Enable the passthrough for the graphic card.")
+
def err(msg):
"""Print an error to stderr and exit.
"""
@@ -763,7 +767,8 @@ def configure_hvm(config_image, vals):
'vnc', 'vncdisplay', 'vncunused', 'vncconsole', 'vnclisten',
'sdl', 'display', 'xauthority', 'rtc_timeoffset', 'monitor',
'acpi', 'apic', 'usb', 'usbdevice', 'keymap', 'pci', 'hpet',
- 'guest_os_type', 'hap', 'opengl', 'cpuid', 'cpuid_check']
+ 'guest_os_type', 'hap', 'opengl', 'cpuid', 'cpuid_check',
+ 'vga_passthrough' ]
for a in args:
if a in vals.__dict__ and vals.__dict__[a] is not None:
diff -r 810d8c3ac992 xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c Thu May 08 16:58:33 2008 +0100
+++ b/xen/arch/x86/hvm/hvm.c Fri May 09 14:53:12 2008 +0100
@@ -310,7 +310,8 @@ int hvm_domain_initialise(struct domain
if ( rc != 0 )
goto fail1;
- stdvga_init(d);
+ if ( !d->arch.hvm_domain.params[HVM_PARAM_VGA_PT_ENABLED] )
+ stdvga_init(d);
hvm_init_ioreq_page(d, &d->arch.hvm_domain.ioreq);
hvm_init_ioreq_page(d, &d->arch.hvm_domain.buf_ioreq);
diff -r 810d8c3ac992 xen/include/public/hvm/hvm_info_table.h
--- a/xen/include/public/hvm/hvm_info_table.h Thu May 08 16:58:33 2008 +0100
+++ b/xen/include/public/hvm/hvm_info_table.h Fri May 09 14:53:12 2008 +0100
@@ -36,6 +36,9 @@ struct hvm_info_table {
uint8_t acpi_enabled;
uint8_t apic_mode;
uint32_t nr_vcpus;
+ uint32_t vga_bios_paddr;
+ uint32_t vga_bios_size;
+
};
#endif /* __XEN_PUBLIC_HVM_HVM_INFO_TABLE_H__ */
diff -r 810d8c3ac992 xen/include/public/hvm/params.h
--- a/xen/include/public/hvm/params.h Thu May 08 16:58:33 2008 +0100
+++ b/xen/include/public/hvm/params.h Fri May 09 14:53:12 2008 +0100
@@ -90,6 +90,9 @@
/* Device Model domain, defaults to 0. */
#define HVM_PARAM_DM_DOMAIN 13
-#define HVM_NR_PARAMS 14
+/* Boolean : VGA passthrough */
+#define HVM_PARAM_VGA_PT_ENABLED 14
+
+#define HVM_NR_PARAMS 15
#endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */
[-- Attachment #3: Type: text/plain, Size: 138 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH] Pass-through a graphic card
2008-05-09 13:56 ` Jean Guyader
@ 2008-05-09 14:02 ` Daniel P. Berrange
2008-05-09 14:25 ` Daniel P. Berrange
1 sibling, 0 replies; 13+ messages in thread
From: Daniel P. Berrange @ 2008-05-09 14:02 UTC (permalink / raw)
To: Jean Guyader; +Cc: xen-devel
On Fri, May 09, 2008 at 02:56:47PM +0100, Jean Guyader wrote:
>
> Here, a new patch with the modifications that Samuel suggested.
Could you adjust your mail client so it attaches patches as text/plain
or include them inline to the body. Using text/xdiff means that many
mail clients won't quote the patch when replying making sending patch
feedback really much more difficult / convoluted
Regards,
Daniel.
--
|: Red Hat, Engineering, Boston -o- http://people.redhat.com/berrange/ :|
|: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] Pass-through a graphic card
2008-05-09 13:56 ` Jean Guyader
2008-05-09 14:02 ` Daniel P. Berrange
@ 2008-05-09 14:25 ` Daniel P. Berrange
2008-05-09 15:47 ` Jean Guyader
1 sibling, 1 reply; 13+ messages in thread
From: Daniel P. Berrange @ 2008-05-09 14:25 UTC (permalink / raw)
To: Jean Guyader; +Cc: Ian Pratt, xen-devel, Keir Fraser, Kamala Narasimhan
On Fri, May 09, 2008 at 02:56:47PM +0100, Jean Guyader wrote:
>
> Here, a new patch with the modifications that Samuel suggested.
> +static void dom0_read(void *opaque)
> +{
> + struct input_event event[5];
> + int i = 0;
> + int read_sz = 0;
> + int fd = *(int *)opaque;
> +
> + read_sz = read(fd, event, sizeof (struct input_event) * 5);
Could simply do 'sizeof(event)' here I believe.
> +static void dom0_driver_event_init()
> +{
> + char dev_name[strlen(EVENT_PATH) + 3];
> + int fd = -1;
> + int i = 0;
> +
> + do
> + {
> + snprintf(dev_name, sizeof (dev_name), "%s%d", EVENT_PATH, i++);
> + if ((fd = open(dev_name, O_RDONLY)) == -1)
> + return;
> + printf("Using %s\n", dev_name);
> +
> + driver.event_fds = realloc(driver.event_fds,
> + driver.event_nb + 1);
Error checking on reallocs...
> + ioctl(fd, EVIOCGRAB, 1);
ioctls can fail.
> + driver.event_fds[driver.event_nb] = fd;
> + qemu_set_fd_handler(fd, dom0_read, NULL,
> + &driver.event_fds[driver.event_nb]);
> + driver.event_nb++;
> + }
> + while (1);
> +}
> diff -r 810d8c3ac992 tools/ioemu/hw/pc.c
> --- a/tools/ioemu/hw/pc.c Thu May 08 16:58:33 2008 +0100
> +++ b/tools/ioemu/hw/pc.c Fri May 09 14:53:11 2008 +0100
> @@ -814,6 +814,13 @@ static void pc_init1(uint64_t ram_size,
> CPUState *env;
> NICInfo *nd;
> int rc;
> +#ifdef CONFIG_DM
> + unsigned long vga_pt_enabled = 0;
> +#endif /* CONFIG_DM */
> +
> +#ifdef CONFIG_DM
> + xc_get_hvm_param(xc_handle, domid, HVM_PARAM_VGA_PT_ENABLED, &vga_pt_enabled);
> +#endif /* CONFIG_DM */
This API can return a failure code.
> @@ -152,9 +152,122 @@ static int loadelfimage(
> return rc;
> }
>
> +static int linux_get_vgabios(int xc_handle,
> + unsigned char *buf,
> + int len)
> +{
> + char buff[1024];
> + FILE *fd;
> + int mem;
> + char *end_ptr;
> + uint32_t start, end, size;
> +
> + if (!(fd = fopen("/proc/iomem", "r")))
> + return 0;
> +
> + while (fgets(buff, 1024, fd))
> + if (strstr(buff, "Video ROM"))
> + break;
> +
> + if (feof(fd))
Should be also checking ferror(fd)
> + {
> + fclose(fd);
> + return 0;
> + }
> +
> + fclose(fd);
> + start = strtol(buff, &end_ptr, 16);
> + end = strtol(end_ptr + 1, NULL, 16);
> + size = end - start + 1;
> +
> + if ((mem = open("/dev/mem", O_RDONLY)) < 0)
> + return 0;
> +
> + lseek(mem, start, SEEK_SET);
> + read(mem, buf, size);
Check for failure / partial reads.
> +static int linux_map_vga_ioport(int xc_handler,
> + uint32_t dom)
> +{
> + FILE *fd = NULL;
> + char buff[256];
> + uint32_t start, end;
> + char *buff_end = NULL;
> +
> + if (!(fd = fopen("/proc/ioports", "r")))
> + return -1;
> +
> + while (fgets(buff, 256, fd))
> + if (strstr(buff, "vga"))
> + break;
> +
> + if (feof(fd))
Also check ferror(fd)
> + {
> + fclose(fd);
> + return -1;
> + }
> +
> + fclose(fd);
> +
> + start = strtol(buff, &buff_end, 16);
> + end = strtol(buff_end + 1, NULL, 16);
> +
> + return xc_domain_ioport_mapping(xc_handler, dom,
> + start, start, end - start + 1, 1);
> +}
> +
> +static int setup_vga_pt(int xc_handle,
> + uint32_t dom,
> + uint32_t paddr,
> + struct hvm_info_table *hvm_info)
> +{
> + int rc = 0;
> + unsigned char *bios = NULL;
> + int bios_size = 0;
> + char *va_bios = NULL;
> + uint32_t pfn = 0;
> +
> + /* Allocated 128K for the vga bios */
> + if (!(bios = malloc(128 * 1024)))
> + return -1;
> +
> + /* Align paddr on the first next page */
> + pfn = (paddr >> XC_PAGE_SHIFT) + 1;
> +
> + bios_size = linux_get_vgabios(xc_handle, bios, 128 * 1024);
> +
> + if (bios_size <= 0)
> + {
> + free(bios);
> + return -1;
> + }
> +
> + va_bios = xc_map_foreign_range(xc_handle, dom,
> + bios_size + bios_size % XC_PAGE_SIZE,
> + PROT_READ | PROT_WRITE, pfn);
This call can fail.
> @@ -348,9 +471,10 @@ int xc_hvm_build(int xc_handle,
> int xc_hvm_build(int xc_handle,
> uint32_t domid,
> int memsize,
> - const char *image_name)
> + const char *image_name,
> + struct hvm_info_table *hvm_info)
> {
> - char *image;
> + char *image;
Needless whitespace error.
Regards,
Daniel
--
|: Red Hat, Engineering, Boston -o- http://people.redhat.com/berrange/ :|
|: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH] Pass-through a graphic card
2008-05-09 14:25 ` Daniel P. Berrange
@ 2008-05-09 15:47 ` Jean Guyader
0 siblings, 0 replies; 13+ messages in thread
From: Jean Guyader @ 2008-05-09 15:47 UTC (permalink / raw)
To: Daniel P. Berrange; +Cc: Ian Pratt, xen-devel, Keir Fraser, Kamala Narasimhan
[-- Attachment #1: Type: text/plain, Size: 105 bytes --]
Thanks for the feedbacks.
Here a new version of this patch with more error handling.
--
Jean Guyader
[-- Attachment #2: vga_pt3.patch --]
[-- Type: text/plain, Size: 30420 bytes --]
diff -r 810d8c3ac992 tools/firmware/hvmloader/config.h
--- a/tools/firmware/hvmloader/config.h Thu May 08 16:58:33 2008 +0100
+++ b/tools/firmware/hvmloader/config.h Fri May 09 16:47:04 2008 +0100
@@ -23,7 +23,7 @@
/* Memory map. */
#define HYPERCALL_PHYSICAL_ADDRESS 0x00080000
#define VGABIOS_PHYSICAL_ADDRESS 0x000C0000
-#define ETHERBOOT_PHYSICAL_ADDRESS 0x000C8000
+#define ETHERBOOT_PHYSICAL_ADDRESS 0x000D0000
#define EXTBOOT_PHYSICAL_ADDRESS 0x000DF800
#define SMBIOS_PHYSICAL_ADDRESS 0x000E9000
#define SMBIOS_MAXIMUM_SIZE 0x00001000
diff -r 810d8c3ac992 tools/firmware/hvmloader/hvmloader.c
--- a/tools/firmware/hvmloader/hvmloader.c Thu May 08 16:58:33 2008 +0100
+++ b/tools/firmware/hvmloader/hvmloader.c Fri May 09 16:47:04 2008 +0100
@@ -464,7 +464,16 @@ int main(void)
if ( (get_vcpu_nr() > 1) || get_apic_mode() )
create_mp_tables();
- if ( cirrus_check() )
+ if ( get_vga_pt_enabled() )
+ {
+ printf("Loading dom0 VGABIOS ...\n");
+ printf(" - 0x%x (0x%x)\n", get_vga_pt_bios_paddr(), get_vga_pt_bios_size());
+ memcpy((void*)VGABIOS_PHYSICAL_ADDRESS,
+ (void*)get_vga_pt_bios_paddr(),
+ get_vga_pt_bios_size());
+ vgabios_sz = get_vga_pt_bios_size();
+ }
+ else if ( cirrus_check() )
{
printf("Loading Cirrus VGABIOS ...\n");
memcpy((void *)VGABIOS_PHYSICAL_ADDRESS,
diff -r 810d8c3ac992 tools/firmware/hvmloader/util.c
--- a/tools/firmware/hvmloader/util.c Thu May 08 16:58:33 2008 +0100
+++ b/tools/firmware/hvmloader/util.c Fri May 09 16:47:04 2008 +0100
@@ -594,6 +594,24 @@ int get_vcpu_nr(void)
return (t ? t->nr_vcpus : 1);
}
+int get_vga_pt_enabled(void)
+{
+ struct hvm_info_table *t = get_hvm_info_table();
+ return (t && t->vga_bios_paddr > 0);
+}
+
+int get_vga_pt_bios_paddr(void)
+{
+ struct hvm_info_table *t = get_hvm_info_table();
+ return (t ? t->vga_bios_paddr : 0);
+}
+
+int get_vga_pt_bios_size(void)
+{
+ struct hvm_info_table *t = get_hvm_info_table();
+ return (t ? t->vga_bios_size : -1);
+}
+
int get_acpi_enabled(void)
{
struct hvm_info_table *t = get_hvm_info_table();
diff -r 810d8c3ac992 tools/firmware/hvmloader/util.h
--- a/tools/firmware/hvmloader/util.h Thu May 08 16:58:33 2008 +0100
+++ b/tools/firmware/hvmloader/util.h Fri May 09 16:47:04 2008 +0100
@@ -106,6 +106,9 @@ int get_vcpu_nr(void);
int get_vcpu_nr(void);
int get_acpi_enabled(void);
int get_apic_mode(void);
+int get_vga_pt_enabled(void);
+int get_vga_pt_bios_paddr(void);
+int get_vga_pt_bios_size(void);
/* String and memory functions */
int strcmp(const char *cs, const char *ct);
diff -r 810d8c3ac992 tools/ioemu/Makefile.target
--- a/tools/ioemu/Makefile.target Thu May 08 16:58:33 2008 +0100
+++ b/tools/ioemu/Makefile.target Fri May 09 16:47:04 2008 +0100
@@ -499,6 +499,9 @@ COCOA_LIBS+=-framework CoreAudio
COCOA_LIBS+=-framework CoreAudio
endif
endif
+
+VL_OBJS+=dom0_driver.o
+
ifdef CONFIG_SLIRP
CPPFLAGS+=-I$(SRC_PATH)/slirp
SLIRP_OBJS=cksum.o if.o ip_icmp.o ip_input.o ip_output.o \
diff -r 810d8c3ac992 tools/ioemu/dom0_driver.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/dom0_driver.c Fri May 09 16:47:04 2008 +0100
@@ -0,0 +1,172 @@
+/*
+ * QEMU dom0 /dev/input driver
+ *
+ * Copyright (c) 2008 Citrix Systems
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "vl.h"
+
+#include <sys/types.h>
+#include <linux/input.h>
+#include <linux/kd.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#define EVENT_PATH "/dev/input/event"
+
+struct dom0_driver
+{
+ int *event_fds;
+ int event_nb;
+ int mouse_button_state;
+};
+
+static struct dom0_driver driver;
+
+static void dom0_update(DisplayState *ds, int x, int y, int w, int h)
+{
+}
+
+static void dom0_resize(DisplayState *ds, int w, int h, int linesize)
+{
+}
+
+static void dom0_refresh(DisplayState *ds)
+{
+}
+
+static void dom0_read(void *opaque)
+{
+ struct input_event event[5];
+ int i = 0;
+ int read_sz = 0;
+ int fd = *(int *)opaque;
+
+ read_sz = read(fd, event, sizeof (event));
+ for (i = 0; i < read_sz / (sizeof (struct input_event)); i++)
+ {
+ if (event[i].type == EV_KEY)
+ {
+ if (event[i].code >= BTN_MOUSE)
+ {
+ /* Mouse Key */
+ int type = 0;
+
+ switch(event[i].code)
+ {
+ case BTN_LEFT: type = MOUSE_EVENT_LBUTTON; break;
+ case BTN_RIGHT: type = MOUSE_EVENT_RBUTTON; break;
+ }
+
+ if (event[i].value)
+ driver.mouse_button_state |= type;
+ else
+ driver.mouse_button_state &= ~type;
+ kbd_mouse_event(0, 0, 0, driver.mouse_button_state);
+ }
+ else
+ {
+ /* Keyboard key */
+ if (event[i].value == 1)
+ kbd_put_keycode(event[i].code | 0x80);
+ else
+ kbd_put_keycode(event[i].code & 0x7f);
+ }
+ }
+
+ if (event[i].type == EV_REL)
+ {
+ /* Mouse motion */
+ int x = 0, y = 0, z = 0;
+
+ switch (event[i].code)
+ {
+ case REL_X : x = event[i].value; break;
+ case REL_Y : y = event[i].value; break;
+ case REL_WHEEL : z = event[i].value; break;
+ }
+
+ kbd_mouse_event(x, y, z, driver.mouse_button_state);
+ }
+ }
+}
+
+static void dom0_driver_event_init()
+{
+ char dev_name[strlen(EVENT_PATH) + 3];
+ int fd = -1;
+ int i = 0;
+
+ do
+ {
+ snprintf(dev_name, sizeof (dev_name), "%s%d", EVENT_PATH, i++);
+ if ((fd = open(dev_name, O_RDONLY)) == -1)
+ return;
+ printf("Using %s\n", dev_name);
+
+ if (ioctl(fd, EVIOCGRAB, 1) == -1)
+ {
+ close(fd);
+ continue;
+ }
+
+ if (!(driver.event_fds = realloc(driver.event_fds,
+ (driver.event_nb + 1) * sizeof (int))))
+ {
+ fprintf(stderr, "dom0_driver: memory allocation failed\n");
+ exit(1);
+ }
+
+ driver.event_fds[driver.event_nb] = fd;
+ qemu_set_fd_handler(fd, dom0_read, NULL,
+ &driver.event_fds[driver.event_nb]);
+ driver.event_nb++;
+ }
+ while (1);
+}
+
+static void dom0_driver_cleanup(void)
+{
+ free(driver.event_fds);
+}
+
+void dom0_driver_init(DisplayState *ds)
+{
+ memset(&driver, 0, sizeof (driver));
+
+ dom0_driver_event_init();
+
+ ds->data = NULL;
+ ds->linesize = 0;
+ ds->depth = 0;
+ ds->dpy_update = dom0_update;
+ ds->dpy_resize = dom0_resize;
+ ds->dpy_colourdepth = NULL;
+ ds->dpy_refresh = dom0_refresh;
+
+ atexit(dom0_driver_cleanup);
+}
diff -r 810d8c3ac992 tools/ioemu/hw/pc.c
--- a/tools/ioemu/hw/pc.c Thu May 08 16:58:33 2008 +0100
+++ b/tools/ioemu/hw/pc.c Fri May 09 16:47:04 2008 +0100
@@ -814,6 +814,19 @@ static void pc_init1(uint64_t ram_size,
CPUState *env;
NICInfo *nd;
int rc;
+#ifdef CONFIG_DM
+ unsigned long vga_pt_enabled = 0;
+#endif /* CONFIG_DM */
+
+#ifdef CONFIG_DM
+ if (xc_get_hvm_param(xc_handle, domid,
+ HVM_PARAM_VGA_PT_ENABLED, &vga_pt_enabled))
+ {
+ fprintf(stderr, "vga passthrough : xc_get_hvm_param failed\n");
+ exit(1);
+ }
+
+#endif /* CONFIG_DM */
linux_boot = (kernel_filename != NULL);
@@ -862,12 +875,18 @@ static void pc_init1(uint64_t ram_size,
}
/* VGA BIOS load */
- if (cirrus_vga_enabled) {
- snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_CIRRUS_FILENAME);
- } else {
- snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_FILENAME);
+#ifdef CONFIG_DM
+ if (!vga_pt_enabled)
+#endif /* CONFIG_DM */
+ {
+ fprintf(stderr, "Load qemu pci vga\n");
+ if (cirrus_vga_enabled) {
+ snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_CIRRUS_FILENAME);
+ } else {
+ snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_FILENAME);
+ }
+ ret = load_image(buf, phys_ram_base + vga_bios_offset);
}
- ret = load_image(buf, phys_ram_base + vga_bios_offset);
#endif /* !NOBIOS */
/* setup basic memory access */
@@ -925,22 +944,27 @@ static void pc_init1(uint64_t ram_size,
register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL);
- if (cirrus_vga_enabled) {
- if (pci_enabled) {
- pci_cirrus_vga_init(pci_bus,
- ds, NULL, ram_size,
- vga_ram_size);
+#ifdef CONFIG_DM
+ if (!vga_pt_enabled)
+#endif /* CONFIG_DM */
+ {
+ if (cirrus_vga_enabled) {
+ if (pci_enabled) {
+ pci_cirrus_vga_init(pci_bus,
+ ds, NULL, ram_size,
+ vga_ram_size);
+ } else {
+ isa_cirrus_vga_init(ds, NULL, ram_size,
+ vga_ram_size);
+ }
} else {
- isa_cirrus_vga_init(ds, NULL, ram_size,
- vga_ram_size);
- }
- } else {
- if (pci_enabled) {
- pci_vga_init(pci_bus, ds, NULL, ram_size,
- vga_ram_size, 0, 0);
- } else {
- isa_vga_init(ds, NULL, ram_size,
- vga_ram_size);
+ if (pci_enabled) {
+ pci_vga_init(pci_bus, ds, NULL, ram_size,
+ vga_ram_size, 0, 0);
+ } else {
+ isa_vga_init(ds, NULL, ram_size,
+ vga_ram_size);
+ }
}
}
diff -r 810d8c3ac992 tools/ioemu/vl.c
--- a/tools/ioemu/vl.c Thu May 08 16:58:33 2008 +0100
+++ b/tools/ioemu/vl.c Fri May 09 16:47:04 2008 +0100
@@ -179,6 +179,9 @@ int opengl_enabled = 1;
#else
int opengl_enabled = 0;
#endif
+#ifdef CONFIG_DM
+int dom0_input = 0;
+#endif /* CONFIG_DM */
int no_quit = 0;
CharDriverState *serial_hds[MAX_SERIAL_PORTS];
CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
@@ -6486,8 +6489,9 @@ void help(void)
"-no-quit disable SDL window close capability\n"
#endif
#ifdef CONFIG_OPENGL
- "-disable-opengl disable OpenGL rendering, using SDL"
-#endif
+ "-disable-opengl disable OpenGL rendering, using SDL\n"
+#endif
+ "-dom0-input enable dom0 controling qemu\n"
#ifdef TARGET_I386
"-no-fd-bootchk disable boot signature checking for floppy disks\n"
#endif
@@ -6667,6 +6671,9 @@ enum {
QEMU_OPTION_full_screen,
QEMU_OPTION_no_quit,
QEMU_OPTION_disable_opengl,
+#ifdef CONFIG_DM
+ QEMU_OPTION_dom0_input,
+#endif /* CONFIG_DM */
QEMU_OPTION_pidfile,
QEMU_OPTION_no_kqemu,
QEMU_OPTION_kernel_kqemu,
@@ -6765,6 +6772,7 @@ const QEMUOption qemu_options[] = {
{ "no-quit", 0, QEMU_OPTION_no_quit },
#endif
{ "disable-opengl", 0, QEMU_OPTION_disable_opengl },
+ { "dom0-input", 0, QEMU_OPTION_dom0_input },
{ "pidfile", HAS_ARG, QEMU_OPTION_pidfile },
{ "win2k-hack", 0, QEMU_OPTION_win2k_hack },
{ "usbdevice", HAS_ARG, QEMU_OPTION_usbdevice },
@@ -7516,6 +7524,11 @@ int main(int argc, char **argv)
case QEMU_OPTION_disable_opengl:
opengl_enabled = 0;
break;
+#ifdef CONFIG_DM
+ case QEMU_OPTION_dom0_input:
+ dom0_input = 1;
+ break;
+#endif /* CONFIG_DM */
case QEMU_OPTION_pidfile:
create_pidfile(optarg);
break;
@@ -7823,12 +7836,18 @@ int main(int argc, char **argv)
init_ioports();
/* terminal init */
+
#ifdef CONFIG_STUBDOM
if (xenfb_pv_display_init(ds) == 0) {
} else
#endif
if (nographic) {
+#ifdef CONFIG_DM
+ if (dom0_input == 1)
+ dom0_driver_init(ds);
+#else
dumb_display_init(ds);
+#endif /* CONFIG_DM */
} else if (vnc_display != NULL || vncunused != 0) {
int vnc_display_port;
char password[20];
diff -r 810d8c3ac992 tools/ioemu/vl.h
--- a/tools/ioemu/vl.h Thu May 08 16:58:33 2008 +0100
+++ b/tools/ioemu/vl.h Fri May 09 16:47:04 2008 +0100
@@ -997,6 +997,9 @@ void do_info_vnc(void);
void do_info_vnc(void);
int vnc_start_viewer(int port);
+/* dom0_driver.c */
+void dom0_driver_init(DisplayState *ds);
+
/* x_keymap.c */
extern uint8_t _translate_keycode(const int key);
diff -r 810d8c3ac992 tools/libxc/xc_hvm_build.c
--- a/tools/libxc/xc_hvm_build.c Thu May 08 16:58:33 2008 +0100
+++ b/tools/libxc/xc_hvm_build.c Fri May 09 16:47:04 2008 +0100
@@ -152,9 +152,134 @@ static int loadelfimage(
return rc;
}
+static int linux_get_vgabios(int xc_handle,
+ unsigned char *buf,
+ int len)
+{
+ char buff[1024];
+ FILE *fd;
+ int mem;
+ char *end_ptr;
+ uint32_t start, end, size;
+
+ if (!(fd = fopen("/proc/iomem", "r")))
+ return 0;
+
+ while (fgets(buff, 1024, fd))
+ if (strstr(buff, "Video ROM"))
+ break;
+
+ if (feof(fd) || ferror(fd))
+ {
+ fclose(fd);
+ return 0;
+ }
+
+ fclose(fd);
+ start = strtol(buff, &end_ptr, 16);
+ end = strtol(end_ptr + 1, NULL, 16);
+ size = end - start + 1;
+
+ if ((mem = open("/dev/mem", O_RDONLY)) < 0)
+ return 0;
+
+ if (start != lseek(mem, start, SEEK_SET))
+ {
+ close(mem);
+ return 0;
+ }
+
+ if (size != read(mem, buf, size))
+ size = 0;
+ close(mem);
+ return size;
+}
+
+static int linux_map_vga_ioport(int xc_handler,
+ uint32_t dom)
+{
+ FILE *fd = NULL;
+ char buff[256];
+ uint32_t start, end;
+ char *buff_end = NULL;
+
+ if (!(fd = fopen("/proc/ioports", "r")))
+ return -1;
+
+ while (fgets(buff, 256, fd))
+ if (strstr(buff, "vga"))
+ break;
+
+ if (feof(fd) || ferror(fd))
+ {
+ fclose(fd);
+ return -1;
+ }
+
+ fclose(fd);
+
+ start = strtol(buff, &buff_end, 16);
+ end = strtol(buff_end + 1, NULL, 16);
+
+ return xc_domain_ioport_mapping(xc_handler, dom,
+ start, start, end - start + 1, 1);
+}
+
+static int setup_vga_pt(int xc_handle,
+ uint32_t dom,
+ uint32_t paddr,
+ struct hvm_info_table *hvm_info)
+{
+ int rc = 0;
+ unsigned char *bios = NULL;
+ int bios_size = 0;
+ char *va_bios = NULL;
+ uint32_t pfn = 0;
+
+ /* Allocated 128K for the vga bios */
+ if (!(bios = malloc(128 * 1024)))
+ return -1;
+
+ /* Align paddr on the first next page */
+ pfn = (paddr >> XC_PAGE_SHIFT) + 1;
+
+ bios_size = linux_get_vgabios(xc_handle, bios, 128 * 1024);
+ if (bios_size == 0)
+ {
+ rc = -1;
+ goto error;
+ }
+
+ va_bios = xc_map_foreign_range(xc_handle, dom,
+ bios_size + bios_size % XC_PAGE_SIZE,
+ PROT_READ | PROT_WRITE, pfn);
+ if (!va_bios)
+ {
+ rc = -1;
+ goto error;
+ }
+
+ memcpy(va_bios, bios, bios_size);
+ hvm_info->vga_bios_paddr = pfn << XC_PAGE_SHIFT;
+ hvm_info->vga_bios_size = bios_size;
+ munmap(va_bios, bios_size + bios_size % XC_PAGE_SIZE);
+
+ rc |= xc_domain_memory_mapping(xc_handle, dom,
+ 0xa0000 >> XC_PAGE_SHIFT,
+ 0xa0000 >> XC_PAGE_SHIFT,
+ (0xc0000 - 0xa0000) >> XC_PAGE_SHIFT,
+ 1);
+ rc |= linux_map_vga_ioport(xc_handle, dom);
+
+error:
+ free(bios);
+ return rc;
+}
+
static int setup_guest(int xc_handle,
uint32_t dom, int memsize,
- char *image, unsigned long image_size)
+ char *image, unsigned long image_size,
+ struct hvm_info_table *hvm_info)
{
xen_pfn_t *page_array = NULL;
unsigned long i, nr_pages = (unsigned long)memsize << (20 - PAGE_SHIFT);
@@ -167,6 +292,7 @@ static int setup_guest(int xc_handle,
uint64_t v_start, v_end;
int rc;
xen_capabilities_info_t caps;
+ unsigned long vga_pt_enabled = 0;
/* An HVM guest must be initialised with at least 2MB memory. */
if ( memsize < 2 )
@@ -314,6 +440,14 @@ static int setup_guest(int xc_handle,
}
free(page_array);
+
+ /* Setup VGA pass through */
+ if ( xc_get_hvm_param(xc_handle, dom,
+ HVM_PARAM_VGA_PT_ENABLED, &vga_pt_enabled) )
+ return -1;
+ if ( vga_pt_enabled )
+ return setup_vga_pt(xc_handle, dom, elf.pend, hvm_info);
+
return 0;
error_out:
@@ -325,7 +459,8 @@ static int xc_hvm_build_internal(int xc_
uint32_t domid,
int memsize,
char *image,
- unsigned long image_size)
+ unsigned long image_size,
+ struct hvm_info_table *hvm_info)
{
if ( (image == NULL) || (image_size == 0) )
{
@@ -333,7 +468,7 @@ static int xc_hvm_build_internal(int xc_
return -1;
}
- return setup_guest(xc_handle, domid, memsize, image, image_size);
+ return setup_guest(xc_handle, domid, memsize, image, image_size, hvm_info);
}
static inline int is_loadable_phdr(Elf32_Phdr *phdr)
@@ -348,7 +483,8 @@ int xc_hvm_build(int xc_handle,
int xc_hvm_build(int xc_handle,
uint32_t domid,
int memsize,
- const char *image_name)
+ const char *image_name,
+ struct hvm_info_table *hvm_info)
{
char *image;
int sts;
@@ -358,7 +494,8 @@ int xc_hvm_build(int xc_handle,
((image = xc_read_image(image_name, &image_size)) == NULL) )
return -1;
- sts = xc_hvm_build_internal(xc_handle, domid, memsize, image, image_size);
+ sts = xc_hvm_build_internal(xc_handle, domid, memsize,
+ image, image_size, hvm_info);
free(image);
@@ -372,7 +509,8 @@ int xc_hvm_build_mem(int xc_handle,
uint32_t domid,
int memsize,
const char *image_buffer,
- unsigned long image_size)
+ unsigned long image_size,
+ struct hvm_info_table *hvm_info)
{
int sts;
unsigned long img_len;
@@ -394,7 +532,7 @@ int xc_hvm_build_mem(int xc_handle,
}
sts = xc_hvm_build_internal(xc_handle, domid, memsize,
- img, img_len);
+ img, img_len, hvm_info);
/* xc_inflate_buffer may return the original buffer pointer (for
for already inflated buffers), so exercise some care in freeing */
diff -r 810d8c3ac992 tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h Thu May 08 16:58:33 2008 +0100
+++ b/tools/libxc/xenctrl.h Fri May 09 16:47:04 2008 +0100
@@ -30,6 +30,7 @@
#include <xen/xsm/acm.h>
#include <xen/xsm/acm_ops.h>
#include <xen/xsm/flask_op.h>
+#include <xen/hvm/params.h>
#ifdef __ia64__
#define XC_PAGE_SHIFT 14
diff -r 810d8c3ac992 tools/libxc/xenguest.h
--- a/tools/libxc/xenguest.h Thu May 08 16:58:33 2008 +0100
+++ b/tools/libxc/xenguest.h Fri May 09 16:47:04 2008 +0100
@@ -6,6 +6,8 @@
* Copyright (c) 2003-2004, K A Fraser.
*/
+#include <xen/hvm/hvm_info_table.h>
+
#ifndef XENGUEST_H
#define XENGUEST_H
@@ -13,7 +15,6 @@
#define XCFLAGS_DEBUG 2
#define XCFLAGS_HVM 4
#define XCFLAGS_STDVGA 8
-
/**
* This function will save a running domain.
@@ -128,12 +129,14 @@ int xc_hvm_build(int xc_handle,
int xc_hvm_build(int xc_handle,
uint32_t domid,
int memsize,
- const char *image_name);
+ const char *image_name,
+ struct hvm_info_table *hvm_info);
int xc_hvm_build_mem(int xc_handle,
uint32_t domid,
int memsize,
const char *image_buffer,
- unsigned long image_size);
+ unsigned long image_size,
+ struct hvm_info_table *hvm_info);
#endif /* XENGUEST_H */
diff -r 810d8c3ac992 tools/libxc/xg_private.c
--- a/tools/libxc/xg_private.c Thu May 08 16:58:33 2008 +0100
+++ b/tools/libxc/xg_private.c Fri May 09 16:47:04 2008 +0100
@@ -193,7 +193,8 @@ __attribute__((weak))
int xc_hvm_build(int xc_handle,
uint32_t domid,
int memsize,
- const char *image_name)
+ const char *image_name,
+ struct hvm_info_table *hvm_info)
{
errno = ENOSYS;
return -1;
diff -r 810d8c3ac992 tools/python/xen/lowlevel/xc/xc.c
--- a/tools/python/xen/lowlevel/xc/xc.c Thu May 08 16:58:33 2008 +0100
+++ b/tools/python/xen/lowlevel/xc/xc.c Fri May 09 16:47:04 2008 +0100
@@ -721,22 +721,28 @@ static PyObject *pyxc_hvm_build(XcObject
{
uint32_t dom;
#if !defined(__ia64__)
+ struct hvm_info_table hvm_info;
struct hvm_info_table *va_hvm;
uint8_t *va_map, sum;
int i;
#endif
char *image;
- int memsize, vcpus = 1, acpi = 0, apic = 1;
+ int memsize, vcpus = 1, acpi = 0, apic = 1, vga_pt = 0;
static char *kwd_list[] = { "domid",
"memsize", "image", "vcpus", "acpi",
- "apic", NULL };
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|iii", kwd_list,
+ "apic", "vga_pt", NULL };
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|iiii", kwd_list,
&dom, &memsize,
- &image, &vcpus, &acpi, &apic) )
+ &image, &vcpus, &acpi, &apic, &vga_pt) )
return NULL;
- if ( xc_hvm_build(self->xc_handle, dom, memsize, image) != 0 )
+ if ( xc_set_hvm_param(self->xc_handle, dom,
+ HVM_PARAM_VGA_PT_ENABLED, vga_pt) )
+ return pyxc_error_to_exception();
+
+ memset(&hvm_info, 0, sizeof(hvm_info));
+ if ( xc_hvm_build(self->xc_handle, dom, memsize, image, &hvm_info) != 0 )
return pyxc_error_to_exception();
#if !defined(__ia64__)
@@ -747,7 +753,7 @@ static PyObject *pyxc_hvm_build(XcObject
if ( va_map == NULL )
return PyErr_SetFromErrno(xc_error_obj);
va_hvm = (struct hvm_info_table *)(va_map + HVM_INFO_OFFSET);
- memset(va_hvm, 0, sizeof(*va_hvm));
+ memcpy(va_hvm, &hvm_info, sizeof (*va_hvm));
strncpy(va_hvm->signature, "HVM INFO", 8);
va_hvm->length = sizeof(struct hvm_info_table);
va_hvm->acpi_enabled = acpi;
diff -r 810d8c3ac992 tools/python/xen/xend/XendConfig.py
--- a/tools/python/xen/xend/XendConfig.py Thu May 08 16:58:33 2008 +0100
+++ b/tools/python/xen/xend/XendConfig.py Fri May 09 16:47:04 2008 +0100
@@ -160,6 +160,7 @@ XENAPI_PLATFORM_CFG_TYPES = {
'vhpt': int,
'guest_os_type': str,
'hap': int,
+ 'vga_passthrough' : int,
}
# Xen API console 'other_config' keys.
diff -r 810d8c3ac992 tools/python/xen/xend/image.py
--- a/tools/python/xen/xend/image.py Thu May 08 16:58:33 2008 +0100
+++ b/tools/python/xen/xend/image.py Fri May 09 16:47:04 2008 +0100
@@ -240,6 +240,8 @@ class ImageHandler:
vnc_config = {}
has_vnc = int(vmConfig['platform'].get('vnc', 0)) != 0
has_sdl = int(vmConfig['platform'].get('sdl', 0)) != 0
+ has_vga_passthrough = int(vmConfig['platform'].get('vga_passthrough', 0)) != 0;
+
opengl = 1
for dev_uuid in vmConfig['console_refs']:
dev_type, dev_info = vmConfig['devices'][dev_uuid]
@@ -260,7 +262,7 @@ class ImageHandler:
ret.append("-k")
ret.append(keymap)
- if has_vnc:
+ if has_vnc and not has_vga_passthrough:
if not vnc_config:
for key in ('vncunused', 'vnclisten', 'vncdisplay',
'vncpasswd'):
@@ -310,6 +312,10 @@ class ImageHandler:
if int(vmConfig['platform'].get('monitor', 0)) != 0:
ret = ret + ['-monitor', 'vc']
+
+ if has_vga_passthrough:
+ ret.append('-dom0-input');
+
return ret
def getDeviceModelArgs(self, restore = False):
@@ -536,6 +542,7 @@ class HVMImageHandler(ImageHandler):
self.apic = int(vmConfig['platform'].get('apic', 0))
self.acpi = int(vmConfig['platform'].get('acpi', 0))
self.guest_os_type = vmConfig['platform'].get('guest_os_type')
+ self.vga_pt = int(vmConfig['platform'].get('vga_passthrough', 0))
self.vmConfig = vmConfig
@@ -661,6 +668,7 @@ class HVMImageHandler(ImageHandler):
mem_mb = self.getRequiredInitialReservation() / 1024
+ log.debug(self.vmConfig)
log.debug("domid = %d", self.vm.getDomid())
log.debug("image = %s", self.loader)
log.debug("store_evtchn = %d", store_evtchn)
@@ -668,13 +676,15 @@ class HVMImageHandler(ImageHandler):
log.debug("vcpus = %d", self.vm.getVCpuCount())
log.debug("acpi = %d", self.acpi)
log.debug("apic = %d", self.apic)
+ log.debug("vga_pt = %d", self.vga_pt)
rc = xc.hvm_build(domid = self.vm.getDomid(),
image = self.loader,
memsize = mem_mb,
vcpus = self.vm.getVCpuCount(),
acpi = self.acpi,
- apic = self.apic)
+ apic = self.apic,
+ vga_pt = self.vga_pt)
rc['notes'] = { 'SUSPEND_CANCEL': 1 }
rc['store_mfn'] = xc.hvm_get_param(self.vm.getDomid(),
diff -r 810d8c3ac992 tools/python/xen/xm/create.py
--- a/tools/python/xen/xm/create.py Thu May 08 16:58:33 2008 +0100
+++ b/tools/python/xen/xm/create.py Fri May 09 16:47:04 2008 +0100
@@ -557,6 +557,10 @@ gopts.var('cpuid_check', val="IN[,SIN]:e
fn=append_value, default=[],
use="""Cpuid check description.""")
+gopts.var('vga_passthrough', val='VGA_PT',
+ fn=set_int, default=None,
+ use="Enable the passthrough for the graphic card.")
+
def err(msg):
"""Print an error to stderr and exit.
"""
@@ -763,7 +767,8 @@ def configure_hvm(config_image, vals):
'vnc', 'vncdisplay', 'vncunused', 'vncconsole', 'vnclisten',
'sdl', 'display', 'xauthority', 'rtc_timeoffset', 'monitor',
'acpi', 'apic', 'usb', 'usbdevice', 'keymap', 'pci', 'hpet',
- 'guest_os_type', 'hap', 'opengl', 'cpuid', 'cpuid_check']
+ 'guest_os_type', 'hap', 'opengl', 'cpuid', 'cpuid_check',
+ 'vga_passthrough' ]
for a in args:
if a in vals.__dict__ and vals.__dict__[a] is not None:
diff -r 810d8c3ac992 xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c Thu May 08 16:58:33 2008 +0100
+++ b/xen/arch/x86/hvm/hvm.c Fri May 09 16:47:04 2008 +0100
@@ -310,7 +310,8 @@ int hvm_domain_initialise(struct domain
if ( rc != 0 )
goto fail1;
- stdvga_init(d);
+ if ( !d->arch.hvm_domain.params[HVM_PARAM_VGA_PT_ENABLED] )
+ stdvga_init(d);
hvm_init_ioreq_page(d, &d->arch.hvm_domain.ioreq);
hvm_init_ioreq_page(d, &d->arch.hvm_domain.buf_ioreq);
diff -r 810d8c3ac992 xen/include/public/hvm/hvm_info_table.h
--- a/xen/include/public/hvm/hvm_info_table.h Thu May 08 16:58:33 2008 +0100
+++ b/xen/include/public/hvm/hvm_info_table.h Fri May 09 16:47:04 2008 +0100
@@ -36,6 +36,9 @@ struct hvm_info_table {
uint8_t acpi_enabled;
uint8_t apic_mode;
uint32_t nr_vcpus;
+ uint32_t vga_bios_paddr;
+ uint32_t vga_bios_size;
+
};
#endif /* __XEN_PUBLIC_HVM_HVM_INFO_TABLE_H__ */
diff -r 810d8c3ac992 xen/include/public/hvm/params.h
--- a/xen/include/public/hvm/params.h Thu May 08 16:58:33 2008 +0100
+++ b/xen/include/public/hvm/params.h Fri May 09 16:47:04 2008 +0100
@@ -90,6 +90,9 @@
/* Device Model domain, defaults to 0. */
#define HVM_PARAM_DM_DOMAIN 13
-#define HVM_NR_PARAMS 14
+/* Boolean : VGA passthrough */
+#define HVM_PARAM_VGA_PT_ENABLED 14
+
+#define HVM_NR_PARAMS 15
#endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */
[-- Attachment #3: Type: text/plain, Size: 138 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] Pass-through a graphic card
2008-05-09 11:11 [PATCH] Pass-through a graphic card Jean Guyader
` (2 preceding siblings ...)
2008-05-09 13:56 ` Jean Guyader
@ 2008-05-15 10:11 ` Jean Guyader
2008-05-15 11:13 ` Samuel Thibault
3 siblings, 1 reply; 13+ messages in thread
From: Jean Guyader @ 2008-05-15 10:11 UTC (permalink / raw)
To: xen-devel; +Cc: Ian Pratt, Keir Fraser, Kamala Narasimhan
[-- Attachment #1: Type: text/plain, Size: 960 bytes --]
Hi,
Here a new version of the vga pass through patch.
The HVM_PARAM was removed, in that way this patch doesn't change
anything in the hypervisor.
This patch has to be applied instead the previous one.
Thanks to all people who have tried this experimental patch by them
self. Please continue to send my your feedback.
---
This patch is for pass-through the principal graphic card to a hvm guest.
This is what is done inside :
- We map the VGA frame buffer into the guest's memory (0xa0000 ->
0xbffff)
- We get the vga bios address from /dev/iomem and we put it at the
end of hvmloader. Etherboot has been moved to 0xD0000 to let enough
space to load the dom0 vgabios (it could be pretty big).
- Map the vga ioport using /dev/ioports.
- Then we start qemu with the new option -enable-dom0 to have the
dom0's keyboard and the mouse redirected into the guest.
Signed-off-by: Jean Guyader <jean.guyader@eu.citrix.com>
--
Jean Guyader
[-- Attachment #2: vga_pt4.patch --]
[-- Type: text/plain, Size: 23804 bytes --]
diff -r 29dc52031954 tools/firmware/hvmloader/config.h
--- a/tools/firmware/hvmloader/config.h Thu May 15 09:38:00 2008 +0100
+++ b/tools/firmware/hvmloader/config.h Thu May 15 10:57:46 2008 +0100
@@ -23,7 +23,7 @@
/* Memory map. */
#define HYPERCALL_PHYSICAL_ADDRESS 0x00080000
#define VGABIOS_PHYSICAL_ADDRESS 0x000C0000
-#define ETHERBOOT_PHYSICAL_ADDRESS 0x000C8000
+#define ETHERBOOT_PHYSICAL_ADDRESS 0x000D0000
#define EXTBOOT_PHYSICAL_ADDRESS 0x000DF800
#define SMBIOS_PHYSICAL_ADDRESS 0x000E9000
#define SMBIOS_MAXIMUM_SIZE 0x00001000
diff -r 29dc52031954 tools/firmware/hvmloader/hvmloader.c
--- a/tools/firmware/hvmloader/hvmloader.c Thu May 15 09:38:00 2008 +0100
+++ b/tools/firmware/hvmloader/hvmloader.c Thu May 15 10:57:46 2008 +0100
@@ -464,7 +464,16 @@ int main(void)
if ( (get_vcpu_nr() > 1) || get_apic_mode() )
create_mp_tables();
- if ( cirrus_check() )
+ if ( get_vga_pt_enabled() )
+ {
+ printf("Loading dom0 VGABIOS ...\n");
+ printf(" - 0x%x (0x%x)\n", get_vga_pt_bios_paddr(), get_vga_pt_bios_size());
+ memcpy((void*)VGABIOS_PHYSICAL_ADDRESS,
+ (void*)get_vga_pt_bios_paddr(),
+ get_vga_pt_bios_size());
+ vgabios_sz = get_vga_pt_bios_size();
+ }
+ else if ( cirrus_check() )
{
printf("Loading Cirrus VGABIOS ...\n");
memcpy((void *)VGABIOS_PHYSICAL_ADDRESS,
diff -r 29dc52031954 tools/firmware/hvmloader/util.c
--- a/tools/firmware/hvmloader/util.c Thu May 15 09:38:00 2008 +0100
+++ b/tools/firmware/hvmloader/util.c Thu May 15 10:57:46 2008 +0100
@@ -594,6 +594,24 @@ int get_vcpu_nr(void)
return (t ? t->nr_vcpus : 1);
}
+int get_vga_pt_enabled(void)
+{
+ struct hvm_info_table *t = get_hvm_info_table();
+ return (t && t->vga_bios_paddr > 0);
+}
+
+int get_vga_pt_bios_paddr(void)
+{
+ struct hvm_info_table *t = get_hvm_info_table();
+ return (t ? t->vga_bios_paddr : 0);
+}
+
+int get_vga_pt_bios_size(void)
+{
+ struct hvm_info_table *t = get_hvm_info_table();
+ return (t ? t->vga_bios_size : -1);
+}
+
int get_acpi_enabled(void)
{
struct hvm_info_table *t = get_hvm_info_table();
diff -r 29dc52031954 tools/firmware/hvmloader/util.h
--- a/tools/firmware/hvmloader/util.h Thu May 15 09:38:00 2008 +0100
+++ b/tools/firmware/hvmloader/util.h Thu May 15 10:57:46 2008 +0100
@@ -106,6 +106,9 @@ int get_vcpu_nr(void);
int get_vcpu_nr(void);
int get_acpi_enabled(void);
int get_apic_mode(void);
+int get_vga_pt_enabled(void);
+int get_vga_pt_bios_paddr(void);
+int get_vga_pt_bios_size(void);
/* String and memory functions */
int strcmp(const char *cs, const char *ct);
diff -r 29dc52031954 tools/ioemu/Makefile.target
--- a/tools/ioemu/Makefile.target Thu May 15 09:38:00 2008 +0100
+++ b/tools/ioemu/Makefile.target Thu May 15 10:57:46 2008 +0100
@@ -499,6 +499,9 @@ COCOA_LIBS+=-framework CoreAudio
COCOA_LIBS+=-framework CoreAudio
endif
endif
+
+VL_OBJS+=dom0_driver.o
+
ifdef CONFIG_SLIRP
CPPFLAGS+=-I$(SRC_PATH)/slirp
SLIRP_OBJS=cksum.o if.o ip_icmp.o ip_input.o ip_output.o \
diff -r 29dc52031954 tools/ioemu/hw/pc.c
--- a/tools/ioemu/hw/pc.c Thu May 15 09:38:00 2008 +0100
+++ b/tools/ioemu/hw/pc.c Thu May 15 10:57:46 2008 +0100
@@ -43,6 +43,10 @@ static IOAPICState *ioapic;
static IOAPICState *ioapic;
#endif /* !CONFIG_DM */
static PCIDevice *i440fx_state;
+
+#ifdef CONFIG_DM
+extern int dom0_input;
+#endif /* CONFIG_DM */
static void ioport80_write(void *opaque, uint32_t addr, uint32_t data)
{
@@ -814,6 +818,9 @@ static void pc_init1(uint64_t ram_size,
CPUState *env;
NICInfo *nd;
int rc;
+#ifdef CONFIG_DM
+ unsigned long vga_pt_enabled = dom0_input;
+#endif /* CONFIG_DM */
linux_boot = (kernel_filename != NULL);
@@ -862,12 +869,18 @@ static void pc_init1(uint64_t ram_size,
}
/* VGA BIOS load */
- if (cirrus_vga_enabled) {
- snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_CIRRUS_FILENAME);
- } else {
- snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_FILENAME);
+#ifdef CONFIG_DM
+ if (!vga_pt_enabled)
+#endif /* CONFIG_DM */
+ {
+ fprintf(stderr, "Load qemu pci vga\n");
+ if (cirrus_vga_enabled) {
+ snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_CIRRUS_FILENAME);
+ } else {
+ snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_FILENAME);
+ }
+ ret = load_image(buf, phys_ram_base + vga_bios_offset);
}
- ret = load_image(buf, phys_ram_base + vga_bios_offset);
#endif /* !NOBIOS */
/* setup basic memory access */
@@ -925,22 +938,27 @@ static void pc_init1(uint64_t ram_size,
register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL);
- if (cirrus_vga_enabled) {
- if (pci_enabled) {
- pci_cirrus_vga_init(pci_bus,
- ds, NULL, ram_size,
- vga_ram_size);
+#ifdef CONFIG_DM
+ if (!vga_pt_enabled)
+#endif /* CONFIG_DM */
+ {
+ if (cirrus_vga_enabled) {
+ if (pci_enabled) {
+ pci_cirrus_vga_init(pci_bus,
+ ds, NULL, ram_size,
+ vga_ram_size);
+ } else {
+ isa_cirrus_vga_init(ds, NULL, ram_size,
+ vga_ram_size);
+ }
} else {
- isa_cirrus_vga_init(ds, NULL, ram_size,
- vga_ram_size);
- }
- } else {
- if (pci_enabled) {
- pci_vga_init(pci_bus, ds, NULL, ram_size,
- vga_ram_size, 0, 0);
- } else {
- isa_vga_init(ds, NULL, ram_size,
- vga_ram_size);
+ if (pci_enabled) {
+ pci_vga_init(pci_bus, ds, NULL, ram_size,
+ vga_ram_size, 0, 0);
+ } else {
+ isa_vga_init(ds, NULL, ram_size,
+ vga_ram_size);
+ }
}
}
diff -r 29dc52031954 tools/ioemu/vl.c
--- a/tools/ioemu/vl.c Thu May 15 09:38:00 2008 +0100
+++ b/tools/ioemu/vl.c Thu May 15 10:57:46 2008 +0100
@@ -177,6 +177,9 @@ int opengl_enabled = 1;
#else
int opengl_enabled = 0;
#endif
+#ifdef CONFIG_DM
+int dom0_input = 0;
+#endif /* CONFIG_DM */
int no_quit = 0;
CharDriverState *serial_hds[MAX_SERIAL_PORTS];
CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
@@ -6486,8 +6489,9 @@ void help(void)
"-no-quit disable SDL window close capability\n"
#endif
#ifdef CONFIG_OPENGL
- "-disable-opengl disable OpenGL rendering, using SDL"
-#endif
+ "-disable-opengl disable OpenGL rendering, using SDL\n"
+#endif
+ "-dom0-input enable dom0 controling qemu\n"
#ifdef TARGET_I386
"-no-fd-bootchk disable boot signature checking for floppy disks\n"
#endif
@@ -6667,6 +6671,9 @@ enum {
QEMU_OPTION_full_screen,
QEMU_OPTION_no_quit,
QEMU_OPTION_disable_opengl,
+#ifdef CONFIG_DM
+ QEMU_OPTION_dom0_input,
+#endif /* CONFIG_DM */
QEMU_OPTION_pidfile,
QEMU_OPTION_no_kqemu,
QEMU_OPTION_kernel_kqemu,
@@ -6765,6 +6772,7 @@ const QEMUOption qemu_options[] = {
{ "no-quit", 0, QEMU_OPTION_no_quit },
#endif
{ "disable-opengl", 0, QEMU_OPTION_disable_opengl },
+ { "dom0-input", 0, QEMU_OPTION_dom0_input },
{ "pidfile", HAS_ARG, QEMU_OPTION_pidfile },
{ "win2k-hack", 0, QEMU_OPTION_win2k_hack },
{ "usbdevice", HAS_ARG, QEMU_OPTION_usbdevice },
@@ -7516,6 +7524,11 @@ int main(int argc, char **argv)
case QEMU_OPTION_disable_opengl:
opengl_enabled = 0;
break;
+#ifdef CONFIG_DM
+ case QEMU_OPTION_dom0_input:
+ dom0_input = 1;
+ break;
+#endif /* CONFIG_DM */
case QEMU_OPTION_pidfile:
create_pidfile(optarg);
break;
@@ -7823,12 +7836,18 @@ int main(int argc, char **argv)
init_ioports();
/* terminal init */
+
#ifdef CONFIG_STUBDOM
if (xenfb_pv_display_init(ds) == 0) {
} else
#endif
if (nographic) {
+#ifdef CONFIG_DM
+ if (dom0_input == 1)
+ dom0_driver_init(ds);
+#else
dumb_display_init(ds);
+#endif /* CONFIG_DM */
} else if (vnc_display != NULL || vncunused != 0) {
int vnc_display_port;
char password[20];
diff -r 29dc52031954 tools/ioemu/vl.h
--- a/tools/ioemu/vl.h Thu May 15 09:38:00 2008 +0100
+++ b/tools/ioemu/vl.h Thu May 15 10:57:46 2008 +0100
@@ -1001,6 +1001,9 @@ void do_info_vnc(void);
void do_info_vnc(void);
int vnc_start_viewer(int port);
+/* dom0_driver.c */
+void dom0_driver_init(DisplayState *ds);
+
/* x_keymap.c */
extern uint8_t _translate_keycode(const int key);
diff -r 29dc52031954 tools/libxc/xc_hvm_build.c
--- a/tools/libxc/xc_hvm_build.c Thu May 15 09:38:00 2008 +0100
+++ b/tools/libxc/xc_hvm_build.c Thu May 15 10:57:46 2008 +0100
@@ -152,9 +152,133 @@ static int loadelfimage(
return rc;
}
+static int linux_get_vgabios(int xc_handle,
+ unsigned char *buf,
+ int len)
+{
+ char buff[1024];
+ FILE *fd;
+ int mem;
+ char *end_ptr;
+ uint32_t start, end, size;
+
+ if (!(fd = fopen("/proc/iomem", "r")))
+ return 0;
+
+ while (fgets(buff, 1024, fd))
+ if (strstr(buff, "Video ROM"))
+ break;
+
+ if (feof(fd) || ferror(fd))
+ {
+ fclose(fd);
+ return 0;
+ }
+
+ fclose(fd);
+ start = strtol(buff, &end_ptr, 16);
+ end = strtol(end_ptr + 1, NULL, 16);
+ size = end - start + 1;
+
+ if ((mem = open("/dev/mem", O_RDONLY)) < 0)
+ return 0;
+
+ if (start != lseek(mem, start, SEEK_SET))
+ {
+ close(mem);
+ return 0;
+ }
+
+ if (size != read(mem, buf, size))
+ size = 0;
+ close(mem);
+ return size;
+}
+
+static int linux_map_vga_ioport(int xc_handler,
+ uint32_t dom)
+{
+ FILE *fd = NULL;
+ char buff[256];
+ uint32_t start, end;
+ char *buff_end = NULL;
+
+ if (!(fd = fopen("/proc/ioports", "r")))
+ return -1;
+
+ while (fgets(buff, 256, fd))
+ if (strstr(buff, "vga"))
+ break;
+
+ if (feof(fd) || ferror(fd))
+ {
+ fclose(fd);
+ return -1;
+ }
+
+ fclose(fd);
+
+ start = strtol(buff, &buff_end, 16);
+ end = strtol(buff_end + 1, NULL, 16);
+
+ return xc_domain_ioport_mapping(xc_handler, dom,
+ start, start, end - start + 1, 1);
+}
+
+int setup_vga_pt(int xc_handle,
+ uint32_t dom,
+ uint32_t paddr,
+ struct hvm_info_table *hvm_info)
+{
+ int rc = 0;
+ unsigned char *bios = NULL;
+ int bios_size = 0;
+ char *va_bios = NULL;
+ uint32_t pfn = 0;
+
+ /* Allocated 128K for the vga bios */
+ if (!(bios = malloc(128 * 1024)))
+ return -1;
+
+ /* Align paddr on the first next page */
+ pfn = (paddr >> XC_PAGE_SHIFT) + 1;
+
+ bios_size = linux_get_vgabios(xc_handle, bios, 128 * 1024);
+ if (bios_size == 0)
+ {
+ rc = -1;
+ goto error;
+ }
+
+ va_bios = xc_map_foreign_range(xc_handle, dom,
+ bios_size + bios_size % XC_PAGE_SIZE,
+ PROT_READ | PROT_WRITE, pfn);
+ if (!va_bios)
+ {
+ rc = -1;
+ goto error;
+ }
+
+ memcpy(va_bios, bios, bios_size);
+ hvm_info->vga_bios_paddr = pfn << XC_PAGE_SHIFT;
+ hvm_info->vga_bios_size = bios_size;
+ munmap(va_bios, bios_size + bios_size % XC_PAGE_SIZE);
+ rc |= xc_domain_memory_mapping(xc_handle, dom,
+ 0xa0000 >> XC_PAGE_SHIFT,
+ 0xa0000 >> XC_PAGE_SHIFT,
+ (0xc0000 - 0xa0000) >> XC_PAGE_SHIFT,
+ 1);
+ rc |= linux_map_vga_ioport(xc_handle, dom);
+
+error:
+ free(bios);
+ return rc;
+}
+
static int setup_guest(int xc_handle,
uint32_t dom, int memsize,
- char *image, unsigned long image_size)
+ char *image, unsigned long image_size,
+ uint32_t *loader_end_addr)
{
xen_pfn_t *page_array = NULL;
unsigned long i, nr_pages = (unsigned long)memsize << (20 - PAGE_SHIFT);
@@ -314,6 +438,9 @@ static int setup_guest(int xc_handle,
}
free(page_array);
+
+ *loader_end_addr = elf.pend;
+
return 0;
error_out:
@@ -325,7 +452,8 @@ static int xc_hvm_build_internal(int xc_
uint32_t domid,
int memsize,
char *image,
- unsigned long image_size)
+ unsigned long image_size,
+ uint32_t *loader_end_addr)
{
if ( (image == NULL) || (image_size == 0) )
{
@@ -333,7 +461,8 @@ static int xc_hvm_build_internal(int xc_
return -1;
}
- return setup_guest(xc_handle, domid, memsize, image, image_size);
+ return setup_guest(xc_handle, domid, memsize, image, image_size,
+ loader_end_addr);
}
static inline int is_loadable_phdr(Elf32_Phdr *phdr)
@@ -348,7 +477,8 @@ int xc_hvm_build(int xc_handle,
int xc_hvm_build(int xc_handle,
uint32_t domid,
int memsize,
- const char *image_name)
+ const char *image_name,
+ uint32_t *loader_end_addr)
{
char *image;
int sts;
@@ -358,7 +488,8 @@ int xc_hvm_build(int xc_handle,
((image = xc_read_image(image_name, &image_size)) == NULL) )
return -1;
- sts = xc_hvm_build_internal(xc_handle, domid, memsize, image, image_size);
+ sts = xc_hvm_build_internal(xc_handle, domid, memsize,
+ image, image_size, loader_end_addr);
free(image);
@@ -372,7 +503,8 @@ int xc_hvm_build_mem(int xc_handle,
uint32_t domid,
int memsize,
const char *image_buffer,
- unsigned long image_size)
+ unsigned long image_size,
+ uint32_t *loader_end_addr)
{
int sts;
unsigned long img_len;
@@ -394,7 +526,7 @@ int xc_hvm_build_mem(int xc_handle,
}
sts = xc_hvm_build_internal(xc_handle, domid, memsize,
- img, img_len);
+ img, img_len, loader_end_addr);
/* xc_inflate_buffer may return the original buffer pointer (for
for already inflated buffers), so exercise some care in freeing */
diff -r 29dc52031954 tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h Thu May 15 09:38:00 2008 +0100
+++ b/tools/libxc/xenctrl.h Thu May 15 10:57:46 2008 +0100
@@ -30,6 +30,7 @@
#include <xen/xsm/acm.h>
#include <xen/xsm/acm_ops.h>
#include <xen/xsm/flask_op.h>
+#include <xen/hvm/params.h>
#ifdef __ia64__
#define XC_PAGE_SHIFT 14
diff -r 29dc52031954 tools/libxc/xenguest.h
--- a/tools/libxc/xenguest.h Thu May 15 09:38:00 2008 +0100
+++ b/tools/libxc/xenguest.h Thu May 15 10:57:46 2008 +0100
@@ -6,6 +6,8 @@
* Copyright (c) 2003-2004, K A Fraser.
*/
+#include <xen/hvm/hvm_info_table.h>
+
#ifndef XENGUEST_H
#define XENGUEST_H
@@ -13,7 +15,6 @@
#define XCFLAGS_DEBUG 2
#define XCFLAGS_HVM 4
#define XCFLAGS_STDVGA 8
-
/**
* This function will save a running domain.
@@ -128,12 +129,19 @@ int xc_hvm_build(int xc_handle,
int xc_hvm_build(int xc_handle,
uint32_t domid,
int memsize,
- const char *image_name);
+ const char *image_name,
+ uint32_t *loader_end_addr);
int xc_hvm_build_mem(int xc_handle,
uint32_t domid,
int memsize,
const char *image_buffer,
- unsigned long image_size);
+ unsigned long image_size,
+ uint32_t *loader_end_addr);
+
+int setup_vga_pt(int xc_handle,
+ uint32_t dom,
+ uint32_t paddr,
+ struct hvm_info_table *hvm_info);
#endif /* XENGUEST_H */
diff -r 29dc52031954 tools/libxc/xg_private.c
--- a/tools/libxc/xg_private.c Thu May 15 09:38:00 2008 +0100
+++ b/tools/libxc/xg_private.c Thu May 15 10:57:46 2008 +0100
@@ -193,7 +193,8 @@ __attribute__((weak))
int xc_hvm_build(int xc_handle,
uint32_t domid,
int memsize,
- const char *image_name)
+ const char *image_name,
+ uint32_t *loader_end_addr)
{
errno = ENOSYS;
return -1;
diff -r 29dc52031954 tools/python/xen/lowlevel/xc/xc.c
--- a/tools/python/xen/lowlevel/xc/xc.c Thu May 15 09:38:00 2008 +0100
+++ b/tools/python/xen/lowlevel/xc/xc.c Thu May 15 10:57:46 2008 +0100
@@ -726,17 +726,18 @@ static PyObject *pyxc_hvm_build(XcObject
int i;
#endif
char *image;
- int memsize, vcpus = 1, acpi = 0, apic = 1;
+ int memsize, vcpus = 1, acpi = 0, apic = 1, vga_pt = 0;
+ uint32_t loader_end_addr = 0;
static char *kwd_list[] = { "domid",
"memsize", "image", "vcpus", "acpi",
- "apic", NULL };
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|iii", kwd_list,
+ "apic", "vga_pt", NULL };
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|iiii", kwd_list,
&dom, &memsize,
- &image, &vcpus, &acpi, &apic) )
+ &image, &vcpus, &acpi, &apic, &vga_pt) )
return NULL;
- if ( xc_hvm_build(self->xc_handle, dom, memsize, image) != 0 )
+ if ( xc_hvm_build(self->xc_handle, dom, memsize, image, &loader_end_addr) != 0 )
return pyxc_error_to_exception();
#if !defined(__ia64__)
@@ -747,7 +748,10 @@ static PyObject *pyxc_hvm_build(XcObject
if ( va_map == NULL )
return PyErr_SetFromErrno(xc_error_obj);
va_hvm = (struct hvm_info_table *)(va_map + HVM_INFO_OFFSET);
- memset(va_hvm, 0, sizeof(*va_hvm));
+ memset(va_hvm, 0, sizeof (*va_hvm));
+ if (vga_pt)
+ setup_vga_pt(self->xc_handle, dom, loader_end_addr, va_hvm);
+
strncpy(va_hvm->signature, "HVM INFO", 8);
va_hvm->length = sizeof(struct hvm_info_table);
va_hvm->acpi_enabled = acpi;
diff -r 29dc52031954 tools/python/xen/xend/XendConfig.py
--- a/tools/python/xen/xend/XendConfig.py Thu May 15 09:38:00 2008 +0100
+++ b/tools/python/xen/xend/XendConfig.py Thu May 15 10:57:46 2008 +0100
@@ -160,6 +160,7 @@ XENAPI_PLATFORM_CFG_TYPES = {
'vhpt': int,
'guest_os_type': str,
'hap': int,
+ 'vga_passthrough' : int,
}
# Xen API console 'other_config' keys.
diff -r 29dc52031954 tools/python/xen/xend/image.py
--- a/tools/python/xen/xend/image.py Thu May 15 09:38:00 2008 +0100
+++ b/tools/python/xen/xend/image.py Thu May 15 10:57:46 2008 +0100
@@ -240,6 +240,8 @@ class ImageHandler:
vnc_config = {}
has_vnc = int(vmConfig['platform'].get('vnc', 0)) != 0
has_sdl = int(vmConfig['platform'].get('sdl', 0)) != 0
+ has_vga_passthrough = int(vmConfig['platform'].get('vga_passthrough', 0)) != 0;
+
opengl = 1
for dev_uuid in vmConfig['console_refs']:
dev_type, dev_info = vmConfig['devices'][dev_uuid]
@@ -260,7 +262,7 @@ class ImageHandler:
ret.append("-k")
ret.append(keymap)
- if has_vnc:
+ if has_vnc and not has_vga_passthrough:
if not vnc_config:
for key in ('vncunused', 'vnclisten', 'vncdisplay',
'vncpasswd'):
@@ -310,6 +312,10 @@ class ImageHandler:
if int(vmConfig['platform'].get('monitor', 0)) != 0:
ret = ret + ['-monitor', 'vc']
+
+ if has_vga_passthrough:
+ ret.append('-dom0-input');
+
return ret
def getDeviceModelArgs(self, restore = False):
@@ -536,6 +542,7 @@ class HVMImageHandler(ImageHandler):
self.apic = int(vmConfig['platform'].get('apic', 0))
self.acpi = int(vmConfig['platform'].get('acpi', 0))
self.guest_os_type = vmConfig['platform'].get('guest_os_type')
+ self.vga_pt = int(vmConfig['platform'].get('vga_passthrough', 0))
self.vmConfig = vmConfig
@@ -661,6 +668,7 @@ class HVMImageHandler(ImageHandler):
mem_mb = self.getRequiredInitialReservation() / 1024
+ log.debug(self.vmConfig)
log.debug("domid = %d", self.vm.getDomid())
log.debug("image = %s", self.loader)
log.debug("store_evtchn = %d", store_evtchn)
@@ -668,13 +676,15 @@ class HVMImageHandler(ImageHandler):
log.debug("vcpus = %d", self.vm.getVCpuCount())
log.debug("acpi = %d", self.acpi)
log.debug("apic = %d", self.apic)
+ log.debug("vga_pt = %d", self.vga_pt)
rc = xc.hvm_build(domid = self.vm.getDomid(),
image = self.loader,
memsize = mem_mb,
vcpus = self.vm.getVCpuCount(),
acpi = self.acpi,
- apic = self.apic)
+ apic = self.apic,
+ vga_pt = self.vga_pt)
rc['notes'] = { 'SUSPEND_CANCEL': 1 }
rc['store_mfn'] = xc.hvm_get_param(self.vm.getDomid(),
diff -r 29dc52031954 tools/python/xen/xm/create.py
--- a/tools/python/xen/xm/create.py Thu May 15 09:38:00 2008 +0100
+++ b/tools/python/xen/xm/create.py Thu May 15 10:57:46 2008 +0100
@@ -557,6 +557,10 @@ gopts.var('cpuid_check', val="IN[,SIN]:e
fn=append_value, default=[],
use="""Cpuid check description.""")
+gopts.var('vga_passthrough', val='VGA_PT',
+ fn=set_int, default=None,
+ use="Enable the passthrough for the graphic card.")
+
def err(msg):
"""Print an error to stderr and exit.
"""
@@ -765,7 +769,8 @@ def configure_hvm(config_image, vals):
'vnc', 'vncdisplay', 'vncunused', 'vncconsole', 'vnclisten',
'sdl', 'display', 'xauthority', 'rtc_timeoffset', 'monitor',
'acpi', 'apic', 'usb', 'usbdevice', 'keymap', 'pci', 'hpet',
- 'guest_os_type', 'hap', 'opengl', 'cpuid', 'cpuid_check']
+ 'guest_os_type', 'hap', 'opengl', 'cpuid', 'cpuid_check',
+ 'vga_passthrough' ]
for a in args:
if a in vals.__dict__ and vals.__dict__[a] is not None:
diff -r 29dc52031954 xen/include/public/hvm/hvm_info_table.h
--- a/xen/include/public/hvm/hvm_info_table.h Thu May 15 09:38:00 2008 +0100
+++ b/xen/include/public/hvm/hvm_info_table.h Thu May 15 10:57:46 2008 +0100
@@ -36,6 +36,10 @@ struct hvm_info_table {
uint8_t acpi_enabled;
uint8_t apic_mode;
uint32_t nr_vcpus;
+ uint8_t vga_pt_enable;
+ uint32_t vga_bios_paddr;
+ uint32_t vga_bios_size;
+
};
#endif /* __XEN_PUBLIC_HVM_HVM_INFO_TABLE_H__ */
[-- Attachment #3: Type: text/plain, Size: 138 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH] Pass-through a graphic card
2008-05-15 10:11 ` Jean Guyader
@ 2008-05-15 11:13 ` Samuel Thibault
2008-05-15 11:17 ` Jean Guyader
0 siblings, 1 reply; 13+ messages in thread
From: Samuel Thibault @ 2008-05-15 11:13 UTC (permalink / raw)
To: Jean Guyader; +Cc: Ian Pratt, xen-devel, Keir Fraser, Kamala Narasimhan
Jean Guyader, le Thu 15 May 2008 11:11:10 +0100, a écrit :
>
> +int get_vga_pt_enabled(void)
> +{
> + struct hvm_info_table *t = get_hvm_info_table();
> + return (t && t->vga_bios_paddr > 0);
> +}
> +
> +int get_vga_pt_bios_paddr(void)
> +{
> + struct hvm_info_table *t = get_hvm_info_table();
> + return (t ? t->vga_bios_paddr : 0);
> +}
> +
> +int get_vga_pt_bios_size(void)
> +{
> + struct hvm_info_table *t = get_hvm_info_table();
> + return (t ? t->vga_bios_size : -1);
> +}
> +
Mmm, maybe enabled and bios_size are redundant, since bios_size > 0
implies enabled?
Samuel
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH] Pass-through a graphic card
2008-05-15 11:13 ` Samuel Thibault
@ 2008-05-15 11:17 ` Jean Guyader
2008-05-16 8:59 ` Jean Guyader
0 siblings, 1 reply; 13+ messages in thread
From: Jean Guyader @ 2008-05-15 11:17 UTC (permalink / raw)
To: Samuel Thibault, Jean Guyader, xen-devel, Ian Pratt,
Keir Fraser <keir.fra>
Samuel Thibault wrote:
> Jean Guyader, le Thu 15 May 2008 11:11:10 +0100, a écrit :
>>
>> +int get_vga_pt_enabled(void)
>> +{
>> + struct hvm_info_table *t = get_hvm_info_table();
>> + return (t && t->vga_bios_paddr > 0);
>> +}
>> +
>> +int get_vga_pt_bios_paddr(void)
>> +{
>> + struct hvm_info_table *t = get_hvm_info_table();
>> + return (t ? t->vga_bios_paddr : 0);
>> +}
>> +
>> +int get_vga_pt_bios_size(void)
>> +{
>> + struct hvm_info_table *t = get_hvm_info_table();
>> + return (t ? t->vga_bios_size : -1);
>> +}
>> +
>
> Mmm, maybe enabled and bios_size are redundant, since bios_size > 0
> implies enabled?
>
Yes, but it doesn't really matter. I am rewriting the patch to not use
this thing any more.
--
Jean Guyader
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH] Pass-through a graphic card
2008-05-15 11:17 ` Jean Guyader
@ 2008-05-16 8:59 ` Jean Guyader
2008-05-16 17:15 ` Samuel Thibault
0 siblings, 1 reply; 13+ messages in thread
From: Jean Guyader @ 2008-05-16 8:59 UTC (permalink / raw)
To: Samuel Thibault, Jean Guyader, xen-devel, Ian Pratt,
Keir Fraser <keir.fra>
[-- Attachment #1: Type: text/plain, Size: 1014 bytes --]
I new version (again). Here the change for this version :
- No more modification of the hvm_info_table.
- Creatation of a SCRATCH zone for hvmloader : 0x1000.
- Copy directly the VGABIOS at the right place (0xC0000) into the
guest memory.
- Detect which graphic card are present in pci_setup().
- Remove the function cirrus_check
- Add the support for some special keys for the dom0 driver.
---
This patch is for pass-through the principal graphic card to a hvm guest.
This is what is done inside :
- We map the VGA frame buffer into the guest's memory (0xa0000 ->
0xbffff)
- We get the vga bios address into the guest memory. Etherboot has
been moved to 0xD0000 to let enough space to load the dom0 vgabios (it
could be pretty big).
- Map the vga ioport 0x03c0 -> 0x03df.
- Then we start qemu with the new option -dom0-driver to have the
dom0's keyboard and the mouse redirected into the guest.
Signed-off-by: Jean Guyader <jean.guyader@eu.citrix.com>
--
Jean Guyader
[-- Attachment #2: vga_pt5.patch --]
[-- Type: text/plain, Size: 26540 bytes --]
diff -r f65906f262f9 tools/firmware/hvmloader/config.h
--- a/tools/firmware/hvmloader/config.h Fri May 16 09:31:03 2008 +0100
+++ b/tools/firmware/hvmloader/config.h Fri May 16 09:35:12 2008 +0100
@@ -23,11 +23,12 @@
/* Memory map. */
#define HYPERCALL_PHYSICAL_ADDRESS 0x00080000
#define VGABIOS_PHYSICAL_ADDRESS 0x000C0000
-#define ETHERBOOT_PHYSICAL_ADDRESS 0x000C8000
+#define ETHERBOOT_PHYSICAL_ADDRESS 0x000D0000
#define EXTBOOT_PHYSICAL_ADDRESS 0x000DF800
#define SMBIOS_PHYSICAL_ADDRESS 0x000E9000
#define SMBIOS_MAXIMUM_SIZE 0x00001000
#define ACPI_PHYSICAL_ADDRESS 0x000EA000
#define ROMBIOS_PHYSICAL_ADDRESS 0x000F0000
+#define SCRATCH_PHYSICAL_ADDRESS 0x00010000
#endif /* __HVMLOADER_CONFIG_H__ */
diff -r f65906f262f9 tools/firmware/hvmloader/hvmloader.c
--- a/tools/firmware/hvmloader/hvmloader.c Fri May 16 09:31:03 2008 +0100
+++ b/tools/firmware/hvmloader/hvmloader.c Fri May 16 09:35:12 2008 +0100
@@ -103,12 +103,8 @@ void create_mp_tables(void);
void create_mp_tables(void);
int hvm_write_smbios_tables(void);
-static int
-cirrus_check(void)
-{
- outw(0x3C4, 0x9206);
- return inb(0x3C5) == 0x12;
-}
+static int cirrus_checked = 0;
+static int stdvga_checked = 0;
static void
init_hypercalls(void)
@@ -165,7 +161,7 @@ static void pci_setup(void)
/* Create a list of device BARs in descending order of size. */
struct bars {
uint32_t devfn, bar_reg, bar_sz;
- } *bars = (struct bars *)0xc0000;
+ } *bars = (struct bars *)SCRATCH_PHYSICAL_ADDRESS;
unsigned int i, nr_bars = 0;
/* Program PCI-ISA bridge with appropriate link routes. */
@@ -190,6 +186,15 @@ static void pci_setup(void)
device_id = pci_readw(devfn, PCI_DEVICE_ID);
if ( (vendor_id == 0xffff) && (device_id == 0xffff) )
continue;
+
+ /* Detect emulated graphic card */
+ if ( class == 0x300 )
+ {
+ if ( (vendor_id == 0x1013) && (device_id == 0xb8) )
+ cirrus_checked = 1;
+ if ( (vendor_id == 0x1234) && (device_id == 0x1111) )
+ stdvga_checked = 1;
+ }
ASSERT((devfn != PCI_ISA_DEVFN) ||
((vendor_id == 0x8086) && (device_id == 0x7000)));
@@ -464,20 +469,22 @@ int main(void)
if ( (get_vcpu_nr() > 1) || get_apic_mode() )
create_mp_tables();
- if ( cirrus_check() )
+ if ( cirrus_checked )
{
printf("Loading Cirrus VGABIOS ...\n");
memcpy((void *)VGABIOS_PHYSICAL_ADDRESS,
vgabios_cirrusvga, sizeof(vgabios_cirrusvga));
vgabios_sz = sizeof(vgabios_cirrusvga);
}
- else
+ else if ( stdvga_checked )
{
printf("Loading Standard VGABIOS ...\n");
memcpy((void *)VGABIOS_PHYSICAL_ADDRESS,
vgabios_stdvga, sizeof(vgabios_stdvga));
vgabios_sz = sizeof(vgabios_stdvga);
}
+ else
+ printf("VGABIOS must already be there ...\n");
etherboot_sz = scan_etherboot_nic((void*)ETHERBOOT_PHYSICAL_ADDRESS);
diff -r f65906f262f9 tools/firmware/hvmloader/smbios.c
--- a/tools/firmware/hvmloader/smbios.c Fri May 16 09:31:03 2008 +0100
+++ b/tools/firmware/hvmloader/smbios.c Fri May 16 09:35:12 2008 +0100
@@ -217,15 +217,16 @@ hvm_write_smbios_tables(void)
xen_version_str[sizeof(xen_version_str)-1] = '\0';
- /* NB. 0xC0000 is a safe large memory area for scratch. */
- len = write_smbios_tables((void *)0xC0000,
+ /* SCRATCH_PHYSICAL_ADDRESS is a safe large memory area for scratch. */
+ len = write_smbios_tables((void *)SCRATCH_PHYSICAL_ADDRESS,
get_vcpu_nr(), get_memsize(),
uuid, xen_version_str,
xen_major_version, xen_minor_version);
if ( len > SMBIOS_MAXIMUM_SIZE )
goto error_out;
/* Okay, not too large: copy out of scratch to final location. */
- memcpy((void *)SMBIOS_PHYSICAL_ADDRESS, (void *)0xC0000, len);
+ memcpy((void *)SMBIOS_PHYSICAL_ADDRESS,
+ (void *)SCRATCH_PHYSICAL_ADDRESS, len);
return len;
diff -r f65906f262f9 tools/ioemu/Makefile.target
--- a/tools/ioemu/Makefile.target Fri May 16 09:31:03 2008 +0100
+++ b/tools/ioemu/Makefile.target Fri May 16 09:35:12 2008 +0100
@@ -499,6 +499,9 @@ COCOA_LIBS+=-framework CoreAudio
COCOA_LIBS+=-framework CoreAudio
endif
endif
+
+VL_OBJS+=dom0_driver.o
+
ifdef CONFIG_SLIRP
CPPFLAGS+=-I$(SRC_PATH)/slirp
SLIRP_OBJS=cksum.o if.o ip_icmp.o ip_input.o ip_output.o \
diff -r f65906f262f9 tools/ioemu/dom0_driver.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/dom0_driver.c Fri May 16 09:35:12 2008 +0100
@@ -0,0 +1,204 @@
+/*
+ * QEMU dom0 /dev/input driver
+ *
+ * Copyright (c) 2008 Citrix Systems
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "vl.h"
+
+#include <sys/types.h>
+#include <linux/input.h>
+#include <linux/kd.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+#define EVENT_PATH "/dev/input/event"
+
+struct dom0_driver
+{
+ int *event_fds;
+ int event_nb;
+ int mouse_button_state;
+};
+
+static struct dom0_driver driver;
+
+static void dom0_update(DisplayState *ds, int x, int y, int w, int h)
+{
+}
+
+static void dom0_resize(DisplayState *ds, int w, int h, int linesize)
+{
+}
+
+static void dom0_refresh(DisplayState *ds)
+{
+}
+
+static void dom0_read(void *opaque)
+{
+ struct input_event event[5];
+ int i = 0;
+ int read_sz = 0;
+ int fd = *(int *)opaque;
+
+ read_sz = read(fd, event, sizeof (event));
+ for (i = 0; i < read_sz / (sizeof (struct input_event)); i++)
+ {
+ if (event[i].type == EV_KEY)
+ {
+ if (event[i].code >= BTN_MOUSE)
+ {
+ /* Mouse Key */
+ int type = 0;
+
+ switch(event[i].code)
+ {
+ case BTN_LEFT: type = MOUSE_EVENT_LBUTTON; break;
+ case BTN_RIGHT: type = MOUSE_EVENT_RBUTTON; break;
+ }
+
+ if (event[i].value)
+ driver.mouse_button_state |= type;
+ else
+ driver.mouse_button_state &= ~type;
+ kbd_mouse_event(0, 0, 0, driver.mouse_button_state);
+ }
+ else
+ {
+ /* Keyboard key */
+ int code[2] = { event[i].code, -1 };
+ int i = 0;
+
+ switch (event[i].code)
+ {
+ case KEY_F11: *code = 0X57; break; /* F11 */
+ case KEY_F12: *code = 0X58; break; /* F12 */
+ case KEY_INSERT: *code = 0X52; break;
+ case KEY_HOME: *code = 0X47; break;
+ case KEY_PAGEUP: *code = 0X49; break;
+ case KEY_DELETE: *code = 0X53; break;
+ case KEY_END: *code = 0X4F; break;
+ case KEY_PAGEDOWN: *code = 0X51; break;
+ case KEY_UP: *code = 0X48; break;
+ case KEY_LEFT: *code = 0X4B; break;
+ case KEY_DOWN: *code = 0X50; break;
+ case KEY_RIGHT: *code = 0X4D; break;
+ case KEY_RIGHTALT: *code = 0xE0; code[1] = 0x38; break;
+ }
+
+ for ( i = 0; i < 2; i++ )
+ if (code[i] != -1)
+ switch (event[i].value)
+ {
+ case 0:
+ kbd_put_keycode(code[i] & 0x7f);
+ break;
+ case 1:
+ kbd_put_keycode(code[i] | 0x80);
+ break;
+ case 2:
+ kbd_put_keycode(code[i] | 0x80);
+ kbd_put_keycode(code[i] & 0x7f);
+ break;
+ }
+ }
+ }
+
+ if (event[i].type == EV_REL)
+ {
+ /* Mouse motion */
+ int x = 0, y = 0, z = 0;
+
+ switch (event[i].code)
+ {
+ case REL_X : x = event[i].value; break;
+ case REL_Y : y = event[i].value; break;
+ case REL_WHEEL : z = -event[i].value; break;
+ }
+
+ kbd_mouse_event(x, y, z, driver.mouse_button_state);
+ }
+ }
+}
+
+static void dom0_driver_event_init()
+{
+ char dev_name[strlen(EVENT_PATH) + 3];
+ int fd = -1;
+ int i = 0;
+
+ do
+ {
+ snprintf(dev_name, sizeof (dev_name), "%s%d", EVENT_PATH, i++);
+ if ((fd = open(dev_name, O_RDONLY)) == -1)
+ return;
+ printf("Using %s\n", dev_name);
+
+ if (ioctl(fd, EVIOCGRAB, 1) == -1)
+ {
+ close(fd);
+ continue;
+ }
+
+ if (!(driver.event_fds = realloc(driver.event_fds,
+ (driver.event_nb + 1) * sizeof (int))))
+ {
+ fprintf(stderr, "dom0_driver: memory allocation failed\n");
+ exit(1);
+ }
+
+ driver.event_fds[driver.event_nb] = fd;
+ qemu_set_fd_handler(fd, dom0_read, NULL,
+ &driver.event_fds[driver.event_nb]);
+ driver.event_nb++;
+ }
+ while (1);
+}
+
+static void dom0_driver_cleanup(void)
+{
+ free(driver.event_fds);
+}
+
+void dom0_driver_init(DisplayState *ds)
+{
+ memset(&driver, 0, sizeof (driver));
+
+ dom0_driver_event_init();
+
+ ds->data = NULL;
+ ds->linesize = 0;
+ ds->depth = 0;
+ ds->dpy_update = dom0_update;
+ ds->dpy_resize = dom0_resize;
+ ds->dpy_colourdepth = NULL;
+ ds->dpy_refresh = dom0_refresh;
+
+ atexit(dom0_driver_cleanup);
+}
diff -r f65906f262f9 tools/ioemu/hw/pc.c
--- a/tools/ioemu/hw/pc.c Fri May 16 09:31:03 2008 +0100
+++ b/tools/ioemu/hw/pc.c Fri May 16 09:35:12 2008 +0100
@@ -43,6 +43,10 @@ static IOAPICState *ioapic;
static IOAPICState *ioapic;
#endif /* !CONFIG_DM */
static PCIDevice *i440fx_state;
+
+#ifdef CONFIG_DM
+extern int dom0_input;
+#endif /* CONFIG_DM */
static void ioport80_write(void *opaque, uint32_t addr, uint32_t data)
{
@@ -814,6 +818,9 @@ static void pc_init1(uint64_t ram_size,
CPUState *env;
NICInfo *nd;
int rc;
+#ifdef CONFIG_DM
+ unsigned long vga_pt_enabled = dom0_input;
+#endif /* CONFIG_DM */
linux_boot = (kernel_filename != NULL);
@@ -862,12 +869,18 @@ static void pc_init1(uint64_t ram_size,
}
/* VGA BIOS load */
- if (cirrus_vga_enabled) {
- snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_CIRRUS_FILENAME);
- } else {
- snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_FILENAME);
+#ifdef CONFIG_DM
+ if (!vga_pt_enabled)
+#endif /* CONFIG_DM */
+ {
+ fprintf(stderr, "Load qemu pci vga\n");
+ if (cirrus_vga_enabled) {
+ snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_CIRRUS_FILENAME);
+ } else {
+ snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_FILENAME);
+ }
+ ret = load_image(buf, phys_ram_base + vga_bios_offset);
}
- ret = load_image(buf, phys_ram_base + vga_bios_offset);
#endif /* !NOBIOS */
/* setup basic memory access */
@@ -925,22 +938,27 @@ static void pc_init1(uint64_t ram_size,
register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL);
- if (cirrus_vga_enabled) {
- if (pci_enabled) {
- pci_cirrus_vga_init(pci_bus,
- ds, NULL, ram_size,
- vga_ram_size);
+#ifdef CONFIG_DM
+ if (!vga_pt_enabled)
+#endif /* CONFIG_DM */
+ {
+ if (cirrus_vga_enabled) {
+ if (pci_enabled) {
+ pci_cirrus_vga_init(pci_bus,
+ ds, NULL, ram_size,
+ vga_ram_size);
+ } else {
+ isa_cirrus_vga_init(ds, NULL, ram_size,
+ vga_ram_size);
+ }
} else {
- isa_cirrus_vga_init(ds, NULL, ram_size,
- vga_ram_size);
- }
- } else {
- if (pci_enabled) {
- pci_vga_init(pci_bus, ds, NULL, ram_size,
- vga_ram_size, 0, 0);
- } else {
- isa_vga_init(ds, NULL, ram_size,
- vga_ram_size);
+ if (pci_enabled) {
+ pci_vga_init(pci_bus, ds, NULL, ram_size,
+ vga_ram_size, 0, 0);
+ } else {
+ isa_vga_init(ds, NULL, ram_size,
+ vga_ram_size);
+ }
}
}
diff -r f65906f262f9 tools/ioemu/vl.c
--- a/tools/ioemu/vl.c Fri May 16 09:31:03 2008 +0100
+++ b/tools/ioemu/vl.c Fri May 16 09:35:12 2008 +0100
@@ -177,6 +177,9 @@ int opengl_enabled = 1;
#else
int opengl_enabled = 0;
#endif
+#ifdef CONFIG_DM
+int dom0_input = 0;
+#endif /* CONFIG_DM */
int no_quit = 0;
CharDriverState *serial_hds[MAX_SERIAL_PORTS];
CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
@@ -6486,8 +6489,9 @@ void help(void)
"-no-quit disable SDL window close capability\n"
#endif
#ifdef CONFIG_OPENGL
- "-disable-opengl disable OpenGL rendering, using SDL"
-#endif
+ "-disable-opengl disable OpenGL rendering, using SDL\n"
+#endif
+ "-dom0-input enable dom0 controling qemu\n"
#ifdef TARGET_I386
"-no-fd-bootchk disable boot signature checking for floppy disks\n"
#endif
@@ -6667,6 +6671,9 @@ enum {
QEMU_OPTION_full_screen,
QEMU_OPTION_no_quit,
QEMU_OPTION_disable_opengl,
+#ifdef CONFIG_DM
+ QEMU_OPTION_dom0_input,
+#endif /* CONFIG_DM */
QEMU_OPTION_pidfile,
QEMU_OPTION_no_kqemu,
QEMU_OPTION_kernel_kqemu,
@@ -6765,6 +6772,7 @@ const QEMUOption qemu_options[] = {
{ "no-quit", 0, QEMU_OPTION_no_quit },
#endif
{ "disable-opengl", 0, QEMU_OPTION_disable_opengl },
+ { "dom0-input", 0, QEMU_OPTION_dom0_input },
{ "pidfile", HAS_ARG, QEMU_OPTION_pidfile },
{ "win2k-hack", 0, QEMU_OPTION_win2k_hack },
{ "usbdevice", HAS_ARG, QEMU_OPTION_usbdevice },
@@ -7516,6 +7524,11 @@ int main(int argc, char **argv)
case QEMU_OPTION_disable_opengl:
opengl_enabled = 0;
break;
+#ifdef CONFIG_DM
+ case QEMU_OPTION_dom0_input:
+ dom0_input = 1;
+ break;
+#endif /* CONFIG_DM */
case QEMU_OPTION_pidfile:
create_pidfile(optarg);
break;
@@ -7828,7 +7841,12 @@ int main(int argc, char **argv)
} else
#endif
if (nographic) {
+#ifdef CONFIG_DM
+ if (dom0_input == 1)
+ dom0_driver_init(ds);
+#else
dumb_display_init(ds);
+#endif /* CONFIG_DM */
} else if (vnc_display != NULL || vncunused != 0) {
int vnc_display_port;
char password[20];
diff -r f65906f262f9 tools/ioemu/vl.h
--- a/tools/ioemu/vl.h Fri May 16 09:31:03 2008 +0100
+++ b/tools/ioemu/vl.h Fri May 16 09:35:13 2008 +0100
@@ -1001,6 +1001,9 @@ void do_info_vnc(void);
void do_info_vnc(void);
int vnc_start_viewer(int port);
+/* dom0_driver.c */
+void dom0_driver_init(DisplayState *ds);
+
/* x_keymap.c */
extern uint8_t _translate_keycode(const int key);
diff -r f65906f262f9 tools/libxc/xc_hvm_build.c
--- a/tools/libxc/xc_hvm_build.c Fri May 16 09:31:03 2008 +0100
+++ b/tools/libxc/xc_hvm_build.c Fri May 16 09:35:13 2008 +0100
@@ -152,6 +152,52 @@ static int loadelfimage(
if ( entries )
free(entries);
+ return rc;
+}
+
+static int setup_vga_pt(int xc_handle,
+ uint32_t dom)
+{
+ int rc = 0;
+ unsigned char *bios = NULL;
+ int bios_size = 0;
+ char *va_bios = NULL;
+ uint32_t va_size = 0;
+
+ /* Allocated 64K for the vga bios */
+ if (!(bios = malloc(64 * 1024)))
+ return -1;
+
+#ifdef __linux__
+ bios_size = xc_get_vgabios(bios, 64 * 1024);
+#else
+ bios_size = 0;
+#endif /* __linux__ */
+
+ va_size = bios_size + bios_size % XC_PAGE_SIZE;
+ if (bios_size == 0)
+ {
+ rc = -1;
+ goto error;
+ }
+ va_bios = xc_map_foreign_range(xc_handle, dom, va_size,
+ PROT_READ | PROT_WRITE, 0xC0);
+ if (!va_bios)
+ {
+ rc = -1;
+ goto error;
+ }
+
+ memcpy(va_bios, bios, bios_size);
+ munmap(va_bios, va_size);
+ rc |= xc_domain_memory_mapping(xc_handle, dom,
+ 0xa0000 >> XC_PAGE_SHIFT,
+ 0xa0000 >> XC_PAGE_SHIFT,
+ (0xc0000 - 0xa0000) >> XC_PAGE_SHIFT, 1);
+ rc |= xc_domain_ioport_mapping(xc_handle, dom,
+ 0x3C0, 0x3C0, 32, 1);
+error:
+ free(bios);
return rc;
}
@@ -388,17 +434,20 @@ int xc_hvm_build(int xc_handle,
int xc_hvm_build(int xc_handle,
uint32_t domid,
int memsize,
- const char *image_name)
+ const char *image_name,
+ int vga_pt_enabled)
{
char *image;
- int sts;
+ int sts = 0;
unsigned long image_size;
if ( (image_name == NULL) ||
((image = xc_read_image(image_name, &image_size)) == NULL) )
return -1;
- sts = xc_hvm_build_internal(xc_handle, domid, memsize, image, image_size);
+ sts |= xc_hvm_build_internal(xc_handle, domid, memsize, image, image_size);
+ if ( vga_pt_enabled )
+ sts |= setup_vga_pt(xc_handle, domid);
free(image);
diff -r f65906f262f9 tools/libxc/xc_linux.c
--- a/tools/libxc/xc_linux.c Fri May 16 09:31:03 2008 +0100
+++ b/tools/libxc/xc_linux.c Fri May 16 09:35:13 2008 +0100
@@ -518,6 +518,30 @@ int xc_gnttab_set_max_grants(int xcg_han
return 0;
}
+int xc_get_vgabios(unsigned char *buf,
+ int len)
+{
+ int mem;
+ uint32_t start, end, size;
+
+ start = 0xC0000;
+ end = 0xCAFFF;
+ size = end - start + 1;
+ if (len < size)
+ return 0;
+ if ((mem = open("/dev/mem", O_RDONLY)) < 0)
+ return 0;
+ if (start != lseek(mem, start, SEEK_SET))
+ {
+ close(mem);
+ return 0;
+ }
+ if (size != read(mem, buf, size))
+ size = 0;
+ close(mem);
+ return size;
+}
+
/*
* Local variables:
* mode: C
diff -r f65906f262f9 tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h Fri May 16 09:31:03 2008 +0100
+++ b/tools/libxc/xenctrl.h Fri May 16 09:35:13 2008 +0100
@@ -138,6 +138,10 @@ int xc_waitdomain(
int domain,
int *status,
int options);
+
+int xc_get_vgabios(
+ unsigned char *bios,
+ int len);
#endif /* __linux__ */
diff -r f65906f262f9 tools/libxc/xenguest.h
--- a/tools/libxc/xenguest.h Fri May 16 09:31:03 2008 +0100
+++ b/tools/libxc/xenguest.h Fri May 16 09:35:13 2008 +0100
@@ -128,7 +128,8 @@ int xc_hvm_build(int xc_handle,
int xc_hvm_build(int xc_handle,
uint32_t domid,
int memsize,
- const char *image_name);
+ const char *image_name,
+ int vga_pt_enabled);
int xc_hvm_build_mem(int xc_handle,
uint32_t domid,
diff -r f65906f262f9 tools/libxc/xg_private.c
--- a/tools/libxc/xg_private.c Fri May 16 09:31:03 2008 +0100
+++ b/tools/libxc/xg_private.c Fri May 16 09:35:13 2008 +0100
@@ -193,7 +193,8 @@ __attribute__((weak))
int xc_hvm_build(int xc_handle,
uint32_t domid,
int memsize,
- const char *image_name)
+ const char *image_name,
+ int vga_pt_enabled)
{
errno = ENOSYS;
return -1;
diff -r f65906f262f9 tools/python/xen/lowlevel/xc/xc.c
--- a/tools/python/xen/lowlevel/xc/xc.c Fri May 16 09:31:03 2008 +0100
+++ b/tools/python/xen/lowlevel/xc/xc.c Fri May 16 09:35:13 2008 +0100
@@ -726,17 +726,17 @@ static PyObject *pyxc_hvm_build(XcObject
int i;
#endif
char *image;
- int memsize, vcpus = 1, acpi = 0, apic = 1;
+ int memsize, vcpus = 1, acpi = 0, apic = 1, vga_pt = 0;
static char *kwd_list[] = { "domid",
"memsize", "image", "vcpus", "acpi",
- "apic", NULL };
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|iii", kwd_list,
+ "apic", "vga_pt", NULL };
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|iiii", kwd_list,
&dom, &memsize,
- &image, &vcpus, &acpi, &apic) )
+ &image, &vcpus, &acpi, &apic, &vga_pt) )
return NULL;
- if ( xc_hvm_build(self->xc_handle, dom, memsize, image) != 0 )
+ if ( xc_hvm_build(self->xc_handle, dom, memsize, image, vga_pt) != 0 )
return pyxc_error_to_exception();
#if !defined(__ia64__)
diff -r f65906f262f9 tools/python/xen/xend/XendConfig.py
--- a/tools/python/xen/xend/XendConfig.py Fri May 16 09:31:03 2008 +0100
+++ b/tools/python/xen/xend/XendConfig.py Fri May 16 09:35:13 2008 +0100
@@ -160,6 +160,7 @@ XENAPI_PLATFORM_CFG_TYPES = {
'vhpt': int,
'guest_os_type': str,
'hap': int,
+ 'vga_passthrough' : int,
}
# Xen API console 'other_config' keys.
diff -r f65906f262f9 tools/python/xen/xend/image.py
--- a/tools/python/xen/xend/image.py Fri May 16 09:31:03 2008 +0100
+++ b/tools/python/xen/xend/image.py Fri May 16 09:35:13 2008 +0100
@@ -240,6 +240,8 @@ class ImageHandler:
vnc_config = {}
has_vnc = int(vmConfig['platform'].get('vnc', 0)) != 0
has_sdl = int(vmConfig['platform'].get('sdl', 0)) != 0
+ has_vga_passthrough = int(vmConfig['platform'].get('vga_passthrough', 0)) != 0;
+
opengl = 1
for dev_uuid in vmConfig['console_refs']:
dev_type, dev_info = vmConfig['devices'][dev_uuid]
@@ -260,7 +262,7 @@ class ImageHandler:
ret.append("-k")
ret.append(keymap)
- if has_vnc:
+ if has_vnc and not has_vga_passthrough:
if not vnc_config:
for key in ('vncunused', 'vnclisten', 'vncdisplay',
'vncpasswd'):
@@ -310,6 +312,10 @@ class ImageHandler:
if int(vmConfig['platform'].get('monitor', 0)) != 0:
ret = ret + ['-monitor', 'vc']
+
+ if has_vga_passthrough:
+ ret.append('-dom0-input');
+
return ret
def getDeviceModelArgs(self, restore = False):
@@ -536,6 +542,7 @@ class HVMImageHandler(ImageHandler):
self.apic = int(vmConfig['platform'].get('apic', 0))
self.acpi = int(vmConfig['platform'].get('acpi', 0))
self.guest_os_type = vmConfig['platform'].get('guest_os_type')
+ self.vga_pt = int(vmConfig['platform'].get('vga_passthrough', 0))
self.vmConfig = vmConfig
@@ -668,13 +675,15 @@ class HVMImageHandler(ImageHandler):
log.debug("vcpus = %d", self.vm.getVCpuCount())
log.debug("acpi = %d", self.acpi)
log.debug("apic = %d", self.apic)
+ log.debug("vga_pt = %d", self.vga_pt)
rc = xc.hvm_build(domid = self.vm.getDomid(),
image = self.loader,
memsize = mem_mb,
vcpus = self.vm.getVCpuCount(),
acpi = self.acpi,
- apic = self.apic)
+ apic = self.apic,
+ vga_pt = self.vga_pt)
rc['notes'] = { 'SUSPEND_CANCEL': 1 }
rc['store_mfn'] = xc.hvm_get_param(self.vm.getDomid(),
diff -r f65906f262f9 tools/python/xen/xm/create.py
--- a/tools/python/xen/xm/create.py Fri May 16 09:31:03 2008 +0100
+++ b/tools/python/xen/xm/create.py Fri May 16 09:35:13 2008 +0100
@@ -557,6 +557,10 @@ gopts.var('cpuid_check', val="IN[,SIN]:e
fn=append_value, default=[],
use="""Cpuid check description.""")
+gopts.var('vga_passthrough', val='VGA_PT',
+ fn=set_int, default=None,
+ use="Enable the passthrough for the graphic card.")
+
def err(msg):
"""Print an error to stderr and exit.
"""
@@ -765,7 +769,8 @@ def configure_hvm(config_image, vals):
'vnc', 'vncdisplay', 'vncunused', 'vncconsole', 'vnclisten',
'sdl', 'display', 'xauthority', 'rtc_timeoffset', 'monitor',
'acpi', 'apic', 'usb', 'usbdevice', 'keymap', 'pci', 'hpet',
- 'guest_os_type', 'hap', 'opengl', 'cpuid', 'cpuid_check']
+ 'guest_os_type', 'hap', 'opengl', 'cpuid', 'cpuid_check',
+ 'vga_passthrough' ]
for a in args:
if a in vals.__dict__ and vals.__dict__[a] is not None:
[-- Attachment #3: Type: text/plain, Size: 138 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
^ permalink raw reply [flat|nested] 13+ messages in thread