Skip to contentSkip to conversation

Pass-through a graphic card

PATCH In review Jean Guyader 3 participants 13 messages May 9, 2008 – May 16, 2008 Arm/actions semi architecture

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Pass-through a graphic card

Hi folk,

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.
- We disable the vga code into xen, hvm.c:313
- Then we start qemu with the new option -enable-dom0 to have the
dom0's keyboard and the mouse redirected into the guest.

This patch work only with the principal graphic card and you must have a box with vt-d.

---

Here an example of how to enable the feature :
--------------
kernel = "/usr/lib/xen/boot/hvmloader" builder='hvm'
memory = 512
name = "winxp"
vif=[ 'type=ioemu,bridge=eth0,mac=00:16:3E:2E:26:BE' ] disk=['file:/mnt/img/winxp/disk.img,ioemu:hda,w'] boot="c"
vnc=0
timer_mode=2
pci = [ '0a:01.0' ]
vga_pass through=1
--------------

Be careful, vnc must be at 0. 0a:01.0 is the pci id of my graphic card, of course it must be hide with pciback.

Thanks for your comments.

Signature · 1 line
Jean Guyader
tools/firmware/hvmloader/config.h +1 -1
diff -r 810d8c3ac992 tools/firmware/hvmloader/config.h
@@ -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
tools/firmware/hvmloader/hvmloader.c +10 -1
diff -r 810d8c3ac992 tools/firmware/hvmloader/hvmloader.c
@@ -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,
tools/firmware/hvmloader/util.c +18 -0
diff -r 810d8c3ac992 tools/firmware/hvmloader/util.c
@@ -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();
tools/firmware/hvmloader/util.h +3 -0
diff -r 810d8c3ac992 tools/firmware/hvmloader/util.h
@@ -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);
tools/ioemu/Makefile.target +3 -0
diff -r 810d8c3ac992 tools/ioemu/Makefile.target
@@ -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 \
tools/ioemu/hw/pc.c +38 -20

78 lines not on this page · raw message

tools/ioemu/vl.c +25 -3
diff -r 810d8c3ac992 tools/ioemu/vl.c
@@ -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)
tools/ioemu/vl.h +3 -0
diff -r 810d8c3ac992 tools/ioemu/vl.h
@@ -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);
 
tools/libxc/xc_hvm_build.c +134 -9

206 lines not on this page · raw message

tools/libxc/xenctrl.h +1 -0
diff -r 810d8c3ac992 tools/libxc/xenctrl.h
@@ -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
tools/libxc/xenguest.h +6 -3
diff -r 810d8c3ac992 tools/libxc/xenguest.h
@@ -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 */
tools/libxc/xg_private.c +2 -1
diff -r 810d8c3ac992 tools/libxc/xg_private.c
@@ -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;
tools/python/xen/lowlevel/xc/xc.c +12 -6
diff -r 810d8c3ac992 tools/python/xen/lowlevel/xc/xc.c
@@ -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;
tools/python/xen/xend/XendConfig.py +1 -0
diff -r 810d8c3ac992 tools/python/xen/xend/XendConfig.py
@@ -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.
tools/python/xen/xend/image.py +9 -1
diff -r 810d8c3ac992 tools/python/xen/xend/image.py
@@ -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(),
tools/python/xen/xm/create.py +6 -1
diff -r 810d8c3ac992 tools/python/xen/xm/create.py
@@ -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:
xen/arch/x86/hvm/hvm.c +2 -1
diff -r 810d8c3ac992 xen/arch/x86/hvm/hvm.c
@@ -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);
xen/include/public/hvm/hvm_info_table.h +3 -0
diff -r 810d8c3ac992 xen/include/public/hvm/hvm_info_table.h
@@ -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__ */
xen/include/public/hvm/params.h +4 -1
diff -r 810d8c3ac992 xen/include/public/hvm/params.h
@@ -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__ */

_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel

#1 lore raw

Sorry, I forgot a file in my previous patch.

Signature · 1 line
Jean Guyader
tools/firmware/hvmloader/config.h +1 -1
diff -r 810d8c3ac992 tools/firmware/hvmloader/config.h
@@ -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
tools/firmware/hvmloader/hvmloader.c +10 -1
diff -r 810d8c3ac992 tools/firmware/hvmloader/hvmloader.c
@@ -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,
tools/firmware/hvmloader/util.c +18 -0
diff -r 810d8c3ac992 tools/firmware/hvmloader/util.c
@@ -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();
tools/firmware/hvmloader/util.h +3 -0
diff -r 810d8c3ac992 tools/firmware/hvmloader/util.h
@@ -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);
tools/ioemu/Makefile.target +3 -0
diff -r 810d8c3ac992 tools/ioemu/Makefile.target
@@ -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 \
tools/ioemu/dom0_driver.c new file +151 -0

151 lines not on this page · raw message

tools/ioemu/hw/pc.c +38 -20

78 lines not on this page · raw message

tools/ioemu/vl.c +25 -3
diff -r 810d8c3ac992 tools/ioemu/vl.c
@@ -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)
tools/ioemu/vl.h +3 -0
diff -r 810d8c3ac992 tools/ioemu/vl.h
@@ -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);
 
tools/libxc/xc_hvm_build.c +134 -9

206 lines not on this page · raw message

tools/libxc/xenctrl.h +1 -0
diff -r 810d8c3ac992 tools/libxc/xenctrl.h
@@ -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
tools/libxc/xenguest.h +6 -3
diff -r 810d8c3ac992 tools/libxc/xenguest.h
@@ -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 */
tools/libxc/xg_private.c +2 -1
diff -r 810d8c3ac992 tools/libxc/xg_private.c
@@ -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;
tools/python/xen/lowlevel/xc/xc.c +12 -6
diff -r 810d8c3ac992 tools/python/xen/lowlevel/xc/xc.c
@@ -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;
tools/python/xen/xend/XendConfig.py +1 -0
diff -r 810d8c3ac992 tools/python/xen/xend/XendConfig.py
@@ -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.
tools/python/xen/xend/image.py +9 -1
diff -r 810d8c3ac992 tools/python/xen/xend/image.py
@@ -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(),
tools/python/xen/xm/create.py +6 -1
diff -r 810d8c3ac992 tools/python/xen/xm/create.py
@@ -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:
xen/arch/x86/hvm/hvm.c +2 -1
diff -r 810d8c3ac992 xen/arch/x86/hvm/hvm.c
@@ -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);
xen/include/public/hvm/hvm_info_table.h +3 -0
diff -r 810d8c3ac992 xen/include/public/hvm/hvm_info_table.h
@@ -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__ */
xen/include/public/hvm/params.h +4 -1
diff -r 810d8c3ac992 xen/include/public/hvm/params.h
@@ -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__ */

_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel

#3 lore raw
In reply to Jean Guyader
Quoted 2 lines · 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

Quoted 1 line

Be careful, vnc must be at 0.

Can't you have the dom0 option override the vnc option?

tools/libxc/xc_hvm_build.c static int loadelfimage( · line 187

Quoted 6 lines
tools/libxc/xc_hvm_build.c +6 -0
+    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.

tools/libxc/xc_hvm_build.c static int loadelfimage( · line 248

Quoted 9 lines
tools/libxc/xc_hvm_build.c +9 -0
+    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?

tools/libxc/xc_hvm_build.c static int loadelfimage( · line 260

Quoted 12 lines
tools/libxc/xc_hvm_build.c +12 -0
+                                   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?

tools/libxc/xc_hvm_build.c static int setup_guest(int xc_handle, · line 308

Quoted 8 lines
tools/libxc/xc_hvm_build.c +1 -1
@@ -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

#2 lore raw
In reply to Jean Guyader

tools/ioemu/dom0_driver.c line 46

Quoted 8 lines · Jean Guyader, le Fri 09 May 2008 12:18:15 +0100, a écrit :
tools/ioemu/dom0_driver.c new file +8 -0
+#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

#4 lore raw
In reply to Jean Guyader

Here, a new patch with the modifications that Samuel suggested.

Signature · 1 line
Jean Guyader
tools/firmware/hvmloader/config.h +1 -1
diff -r 810d8c3ac992 tools/firmware/hvmloader/config.h
@@ -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
tools/firmware/hvmloader/hvmloader.c +10 -1
diff -r 810d8c3ac992 tools/firmware/hvmloader/hvmloader.c
@@ -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,
tools/firmware/hvmloader/util.c +18 -0
diff -r 810d8c3ac992 tools/firmware/hvmloader/util.c
@@ -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();
tools/firmware/hvmloader/util.h +3 -0
diff -r 810d8c3ac992 tools/firmware/hvmloader/util.h
@@ -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);
tools/ioemu/Makefile.target +3 -0
diff -r 810d8c3ac992 tools/ioemu/Makefile.target
@@ -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 \
tools/ioemu/dom0_driver.c new file +163 -0

163 lines not on this page · raw message

tools/ioemu/hw/pc.c +38 -20

78 lines not on this page · raw message

tools/ioemu/vl.c +24 -3
diff -r 810d8c3ac992 tools/ioemu/vl.c
@@ -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)
tools/ioemu/vl.h +3 -0
diff -r 810d8c3ac992 tools/ioemu/vl.h
@@ -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);
 
tools/libxc/xc_hvm_build.c +134 -8

199 lines not on this page · raw message

tools/libxc/xenctrl.h +1 -0
diff -r 810d8c3ac992 tools/libxc/xenctrl.h
@@ -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
tools/libxc/xenguest.h +6 -3
diff -r 810d8c3ac992 tools/libxc/xenguest.h
@@ -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 */
tools/libxc/xg_private.c +2 -1
diff -r 810d8c3ac992 tools/libxc/xg_private.c
@@ -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;
tools/python/xen/lowlevel/xc/xc.c +12 -6
diff -r 810d8c3ac992 tools/python/xen/lowlevel/xc/xc.c
@@ -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;
tools/python/xen/xend/XendConfig.py +1 -0
diff -r 810d8c3ac992 tools/python/xen/xend/XendConfig.py
@@ -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.
tools/python/xen/xend/image.py +13 -3
diff -r 810d8c3ac992 tools/python/xen/xend/image.py
@@ -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(),
tools/python/xen/xm/create.py +6 -1
diff -r 810d8c3ac992 tools/python/xen/xm/create.py
@@ -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:
xen/arch/x86/hvm/hvm.c +2 -1
diff -r 810d8c3ac992 xen/arch/x86/hvm/hvm.c
@@ -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);
xen/include/public/hvm/hvm_info_table.h +3 -0
diff -r 810d8c3ac992 xen/include/public/hvm/hvm_info_table.h
@@ -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__ */
xen/include/public/hvm/params.h +4 -1
diff -r 810d8c3ac992 xen/include/public/hvm/params.h
@@ -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__ */

_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel

#5 lore raw
Quoted 2 lines · Jean Guyader

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.

Signature · 4 lines
|: 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 :|
#6 lore raw
In reply to Jean Guyader

tools/ioemu/dom0_driver.c line 69

Quoted 11 lines · Jean Guyader

Here, a new patch with the modifications that Samuel suggested.

tools/ioemu/dom0_driver.c new file +8 -0
+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.

Quoted 5 lines
tools/ioemu/dom0_driver.c new file +5 -0
+static void dom0_driver_event_init()
+{
+    char                dev_name[strlen(EVENT_PATH) + 3];
+    int                 fd = -1;
+    int                 i = 0;

tools/ioemu/dom0_driver.c line 132

Quoted 10 lines
tools/ioemu/dom0_driver.c new file +10 -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...

Quoted 1 line

+ ioctl(fd, EVIOCGRAB, 1);

ioctls can fail.

Quoted 12 lines
tools/ioemu/dom0_driver.c new file +7 -0
+        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

tools/ioemu/hw/pc.c static void pc_init1(uint64_t ram_size, · line 823

Quoted 10 lines
tools/ioemu/hw/pc.c +7 -0
@@ -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.

Quoted 12 lines
tools/ioemu/hw/pc.c +8 -0
@@ -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;

tools/ioemu/hw/pc.c static int loadelfimage( · line 172

Quoted 10 lines
tools/ioemu/hw/pc.c +10 -0
+    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)

Quoted 5 lines
tools/ioemu/hw/pc.c +5 -0
+    {
+        fclose(fd);
+        return 0; 
+    }
+

tools/ioemu/hw/pc.c static int loadelfimage( · line 187

Quoted 10 lines
tools/ioemu/hw/pc.c +10 -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.

Quoted 6 lines
tools/ioemu/hw/pc.c +6 -0
+static int  linux_map_vga_ioport(int            xc_handler,
+                                 uint32_t       dom)
+{
+    FILE        *fd = NULL;
+    char        buff[256];
+    uint32_t    start, end;

tools/ioemu/hw/pc.c static int loadelfimage( · line 203

Quoted 10 lines
tools/ioemu/hw/pc.c +10 -0
+    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)

Quoted 34 lines
tools/ioemu/hw/pc.c +33 -0
+    {
+        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);

tools/ioemu/hw/pc.c static int loadelfimage( · line 247

Quoted 10 lines
tools/ioemu/hw/pc.c +10 -0
+
+    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.

tools/ioemu/hw/pc.c int xc_hvm_build(int xc_handle, · line 477

Quoted 10 lines
tools/ioemu/hw/pc.c +3 -2
@@ -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

Signature · 4 lines
|: 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 :|
#7 lore raw

Thanks for the feedbacks.

Here a new version of this patch with more error handling.

Signature · 1 line
Jean Guyader
tools/firmware/hvmloader/config.h +1 -1
diff -r 810d8c3ac992 tools/firmware/hvmloader/config.h
@@ -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
tools/firmware/hvmloader/hvmloader.c +10 -1
diff -r 810d8c3ac992 tools/firmware/hvmloader/hvmloader.c
@@ -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,
tools/firmware/hvmloader/util.c +18 -0
diff -r 810d8c3ac992 tools/firmware/hvmloader/util.c
@@ -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();
tools/firmware/hvmloader/util.h +3 -0
diff -r 810d8c3ac992 tools/firmware/hvmloader/util.h
@@ -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);
tools/ioemu/Makefile.target +3 -0
diff -r 810d8c3ac992 tools/ioemu/Makefile.target
@@ -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 \
tools/ioemu/dom0_driver.c new file +172 -0

172 lines not on this page · raw message

tools/ioemu/hw/pc.c +44 -20

84 lines not on this page · raw message

tools/ioemu/vl.c +21 -2
diff -r 810d8c3ac992 tools/ioemu/vl.c
@@ -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];
tools/ioemu/vl.h +3 -0
diff -r 810d8c3ac992 tools/ioemu/vl.h
@@ -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);
 
tools/libxc/xc_hvm_build.c +145 -7

208 lines not on this page · raw message

tools/libxc/xenctrl.h +1 -0
diff -r 810d8c3ac992 tools/libxc/xenctrl.h
@@ -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
tools/libxc/xenguest.h +6 -3
diff -r 810d8c3ac992 tools/libxc/xenguest.h
@@ -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 */
tools/libxc/xg_private.c +2 -1
diff -r 810d8c3ac992 tools/libxc/xg_private.c
@@ -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;
tools/python/xen/lowlevel/xc/xc.c +12 -6
diff -r 810d8c3ac992 tools/python/xen/lowlevel/xc/xc.c
@@ -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;
tools/python/xen/xend/XendConfig.py +1 -0
diff -r 810d8c3ac992 tools/python/xen/xend/XendConfig.py
@@ -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.
tools/python/xen/xend/image.py +12 -2
diff -r 810d8c3ac992 tools/python/xen/xend/image.py
@@ -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(),
tools/python/xen/xm/create.py +6 -1
diff -r 810d8c3ac992 tools/python/xen/xm/create.py
@@ -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:
xen/arch/x86/hvm/hvm.c +2 -1
diff -r 810d8c3ac992 xen/arch/x86/hvm/hvm.c
@@ -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);
xen/include/public/hvm/hvm_info_table.h +3 -0
diff -r 810d8c3ac992 xen/include/public/hvm/hvm_info_table.h
@@ -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__ */
xen/include/public/hvm/params.h +4 -1
diff -r 810d8c3ac992 xen/include/public/hvm/params.h
@@ -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__ */

_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel

#8 lore raw
In reply to Jean Guyader

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.

Signature · 1 line
Jean Guyader
tools/firmware/hvmloader/config.h +1 -1
diff -r 29dc52031954 tools/firmware/hvmloader/config.h
@@ -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
tools/firmware/hvmloader/hvmloader.c +10 -1
diff -r 29dc52031954 tools/firmware/hvmloader/hvmloader.c
@@ -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,
tools/firmware/hvmloader/util.c +18 -0
diff -r 29dc52031954 tools/firmware/hvmloader/util.c
@@ -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();
tools/firmware/hvmloader/util.h +3 -0
diff -r 29dc52031954 tools/firmware/hvmloader/util.h
@@ -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);
tools/ioemu/Makefile.target +3 -0
diff -r 29dc52031954 tools/ioemu/Makefile.target
@@ -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 \
tools/ioemu/hw/pc.c +38 -20

84 lines not on this page · raw message

tools/ioemu/vl.c +21 -2
diff -r 29dc52031954 tools/ioemu/vl.c
@@ -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];
tools/ioemu/vl.h +3 -0
diff -r 29dc52031954 tools/ioemu/vl.h
@@ -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);
 
tools/libxc/xc_hvm_build.c +139 -7

196 lines not on this page · raw message

tools/libxc/xenctrl.h +1 -0
diff -r 29dc52031954 tools/libxc/xenctrl.h
@@ -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
tools/libxc/xenguest.h +11 -3
diff -r 29dc52031954 tools/libxc/xenguest.h
@@ -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 */
tools/libxc/xg_private.c +2 -1
diff -r 29dc52031954 tools/libxc/xg_private.c
@@ -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;
tools/python/xen/lowlevel/xc/xc.c +10 -6
diff -r 29dc52031954 tools/python/xen/lowlevel/xc/xc.c
@@ -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;
tools/python/xen/xend/XendConfig.py +1 -0
diff -r 29dc52031954 tools/python/xen/xend/XendConfig.py
@@ -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.
tools/python/xen/xend/image.py +12 -2
diff -r 29dc52031954 tools/python/xen/xend/image.py
@@ -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(),
tools/python/xen/xm/create.py +6 -1
diff -r 29dc52031954 tools/python/xen/xm/create.py
@@ -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:
xen/include/public/hvm/hvm_info_table.h +4 -0
diff -r 29dc52031954 xen/include/public/hvm/hvm_info_table.h
@@ -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__ */

_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel

#9 lore raw
Quoted 9 lines · Jean Guyader, le Thu 15 May 2008 11:11:10 +0100, a écrit :
tools/firmware/hvmloader/util.c +8 -0
+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)
+{

tools/firmware/hvmloader/util.c int get_vcpu_nr(void) · line 614

Quoted 10 lines
tools/firmware/hvmloader/util.c +10 -0
+    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

#10 lore raw
Quoted 15 lines · Samuel Thibault
Quoted 14 lines · Jean Guyader, le Thu 15 May 2008 11:11:10 +0100, a écrit :
tools/firmware/hvmloader/util.c +13 -0
+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)
Quoted 9 lines

tools/firmware/hvmloader/util.c int get_vcpu_nr(void) · line 614

Quoted 5 lines
tools/firmware/hvmloader/util.c +5 -0
+{
+    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.

Signature · 1 line
Jean Guyader
#11 lore raw

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.

Signature · 1 line
Jean Guyader
tools/firmware/hvmloader/config.h +2 -1
diff -r f65906f262f9 tools/firmware/hvmloader/config.h
@@ -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__ */
tools/firmware/hvmloader/hvmloader.c +16 -9
diff -r f65906f262f9 tools/firmware/hvmloader/hvmloader.c
@@ -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);
 
tools/firmware/hvmloader/smbios.c +4 -3
diff -r f65906f262f9 tools/firmware/hvmloader/smbios.c
@@ -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;
 
tools/ioemu/Makefile.target +3 -0
diff -r f65906f262f9 tools/ioemu/Makefile.target
@@ -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 \
tools/ioemu/dom0_driver.c new file +204 -0

204 lines not on this page · raw message

tools/ioemu/hw/pc.c +38 -20

84 lines not on this page · raw message

tools/ioemu/vl.c +20 -2
diff -r f65906f262f9 tools/ioemu/vl.c
@@ -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];
tools/ioemu/vl.h +3 -0
diff -r f65906f262f9 tools/ioemu/vl.h
@@ -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);
 
tools/libxc/xc_hvm_build.c +52 -3

75 lines not on this page · raw message

tools/libxc/xc_linux.c +24 -0
diff -r f65906f262f9 tools/libxc/xc_linux.c
@@ -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
tools/libxc/xenctrl.h +4 -0
diff -r f65906f262f9 tools/libxc/xenctrl.h
@@ -138,6 +138,10 @@ int xc_waitdomain(
     int domain,
     int *status,
     int options);
+
+int xc_get_vgabios(
+    unsigned char       *bios,
+    int                 len);
 
 #endif /* __linux__ */
 
tools/libxc/xenguest.h +2 -1
diff -r f65906f262f9 tools/libxc/xenguest.h
@@ -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,
tools/libxc/xg_private.c +2 -1
diff -r f65906f262f9 tools/libxc/xg_private.c
@@ -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;
tools/python/xen/lowlevel/xc/xc.c +5 -5
diff -r f65906f262f9 tools/python/xen/lowlevel/xc/xc.c
@@ -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__)
tools/python/xen/xend/XendConfig.py +1 -0
diff -r f65906f262f9 tools/python/xen/xend/XendConfig.py
@@ -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.
tools/python/xen/xend/image.py +11 -2
diff -r f65906f262f9 tools/python/xen/xend/image.py
@@ -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(),
tools/python/xen/xm/create.py +6 -1
diff -r f65906f262f9 tools/python/xen/xm/create.py
@@ -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:

_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel

#12 lore raw

Hello,

Quoted 2 lines · Jean Guyader, le Fri 16 May 2008 09:59:17 +0100, a écrit :

- Copy directly the VGABIOS at the right place (0xC0000) into the
guest memory.

Mmm, then can't we just map the physical 0xC0000-0xCxyzt pages?

Samuel