]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
kvm tools: Fix VESA BIOS mode info
authorCyrill Gorcunov <gorcunov@gmail.com>
Fri, 4 Nov 2011 06:48:06 +0000 (10:48 +0400)
committerPekka Enberg <penberg@kernel.org>
Fri, 4 Nov 2011 07:00:20 +0000 (09:00 +0200)
Some VGA data such as VESA info needs a proper tuning for addresses
passed on kernel requests.  We returned linear addresses there while
spec points out that far pointers are needed.

This fixes a long-standing issue that caused Linux kernel to never exit
the mode scanning loop in arch/x86/boot/video-vesa.c::vesa_probe()
because returned mode info table segment/offset pair was bogus. The
issue triggered on some machines when CONFIG_FB_VESA was disabled.

Also use already VESA structures defined in <boot/vesa.h> header now
that we no longer use the struct to store VESA BIOS data.

Reported-by: Pekka Enberg <penberg@kernel.org>
CC: Sasha Levin <levinsasha928@gmail.com>
CC: Ingo Molnar <mingo@elte.hu>
CC: Asias He <asias.hejun@gmail.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
[ penberg@kernel.org: minor cleanups to setup_vga_rom() ]
Signed-off-by: Pekka Enberg <penberg@kernel.org>
tools/kvm/Makefile
tools/kvm/bios.c
tools/kvm/bios/int10.c
tools/kvm/include/kvm/bios.h

index d4598caa69327b84ac1c81f0ff170e5563dcc553..20389f9c7b24198500bc9d90fa3f1ba389c152ce 100644 (file)
@@ -225,6 +225,7 @@ BIOS_CFLAGS += -march=i386
 BIOS_CFLAGS += -mregparm=3
 
 BIOS_CFLAGS += -fno-stack-protector
+BIOS_CFLAGS += -I../../arch/$(ARCH)
 
 bios.o: bios/bios.bin bios/bios-rom.h
 
index 6aefd1bdc19b5f26745b8d4488f5c04262b27770..47b1f5445d1d353615ab0fe10c6d9383ac23b26e 100644 (file)
@@ -103,6 +103,20 @@ static void e820_setup(struct kvm *kvm)
        e820->nr_map                    = i;
 }
 
+static void setup_vga_rom(struct kvm *kvm)
+{
+       u16 *mode;
+       void *p;
+
+       p = guest_flat_to_host(kvm, VGA_ROM_OEM_STRING);
+       memset(p, 0, VGA_ROM_OEM_STRING_SIZE);
+       strncpy(p, "KVM VESA", VGA_ROM_OEM_STRING_SIZE);
+
+       mode = guest_flat_to_host(kvm, VGA_ROM_MODES);
+       mode[0] = 0x0112;
+       mode[1] = 0xffff;
+}
+
 /**
  * setup_bios - inject BIOS into guest memory
  * @kvm - guest system descriptor
@@ -137,6 +151,9 @@ void setup_bios(struct kvm *kvm)
        /* E820 memory map must be present */
        e820_setup(kvm);
 
+       /* VESA needs own tricks */
+       setup_vga_rom(kvm);
+
        /*
         * Setup a *fake* real mode vector table, it has only
         * one real hadler which does just iret
index 32f7c923d459bf6ee83c8ff6be0373084d369572..7cc0b3f2162ebabcb875c89ef19ca51426b6d039 100644 (file)
@@ -4,59 +4,17 @@
 
 #include "bios/memcpy.h"
 
-#define VESA_MAGIC ('V' + ('E' << 8) + ('S' << 16) + ('A' << 24))
-
-/* VESA General Information table */
-struct vesa_general_info {
-       u32     signature;              /* 0 Magic number = "VESA" */
-       u16     version;                /* 4 */
-       void    *vendor_string;         /* 6 */
-       u32     capabilities;           /* 10 */
-       void    *video_mode_ptr;        /* 14 */
-       u16     total_memory;           /* 18 */
-       u16     modes[2];               /* 20 */
-       char    oem_string[11];         /* 24 */
-
-       u8      reserved[223];          /* 35 */
-} __attribute__ ((packed));
-
-struct vminfo {
-       u16     mode_attr;              /* 0 */
-       u8      win_attr[2];            /* 2 */
-       u16     win_grain;              /* 4 */
-       u16     win_size;               /* 6 */
-       u16     win_seg[2];             /* 8 */
-       u32     win_scheme;             /* 12 */
-       u16     logical_scan;           /* 16 */
-
-       u16     h_res;                  /* 18 */
-       u16     v_res;                  /* 20 */
-       u8      char_width;             /* 22 */
-       u8      char_height;            /* 23 */
-       u8      memory_planes;          /* 24 */
-       u8      bpp;                    /* 25 */
-       u8      banks;                  /* 26 */
-       u8      memory_layout;          /* 27 */
-       u8      bank_size;              /* 28 */
-       u8      image_planes;           /* 29 */
-       u8      page_function;          /* 30 */
-
-       u8      rmask;                  /* 31 */
-       u8      rpos;                   /* 32 */
-       u8      gmask;                  /* 33 */
-       u8      gpos;                   /* 34 */
-       u8      bmask;                  /* 35 */
-       u8      bpos;                   /* 36 */
-       u8      resv_mask;              /* 37 */
-       u8      resv_pos;               /* 38 */
-       u8      dcm_info;               /* 39 */
-
-       u32     lfb_ptr;                /* 40 Linear frame buffer address */
-       u32     offscreen_ptr;          /* 44 Offscreen memory address */
-       u16     offscreen_size;         /* 48 */
-
-       u8      reserved[206];          /* 50 */
-};
+#include <boot/vesa.h>
+
+static far_ptr gen_far_ptr(unsigned int pa)
+{
+       far_ptr ptr;
+
+       ptr.seg = (pa >> 4);
+       ptr.off = pa - (ptr.seg << 4);
+
+       return ptr;
+}
 
 static inline void outb(unsigned short port, unsigned char val)
 {
@@ -76,9 +34,9 @@ static inline void int10_putchar(struct biosregs *args)
 
 static void vbe_get_mode(struct biosregs *args)
 {
-       struct vminfo *info = (struct vminfo *) args->edi;
+       struct vesa_mode_info *info = (struct vesa_mode_info *) args->edi;
 
-       *info = (struct vminfo) {
+       *info = (struct vesa_mode_info) {
                .mode_attr              = 0xd9, /* 11011011 */
                .logical_scan           = VESA_WIDTH*4,
                .h_res                  = VESA_WIDTH,
@@ -105,12 +63,10 @@ static void vbe_get_info(struct biosregs *args)
        info = (struct vesa_general_info) {
                .signature              = VESA_MAGIC,
                .version                = 0x102,
-               .vendor_string          = &infop->oem_string,
+               .vendor_string          = gen_far_ptr(VGA_ROM_BEGIN),
                .capabilities           = 0x10,
-               .video_mode_ptr         = &infop->modes,
+               .video_mode_ptr         = gen_far_ptr(VGA_ROM_MODES),
                .total_memory           = (4 * VESA_WIDTH * VESA_HEIGHT) / 0x10000,
-               .oem_string             = "KVM VESA",
-               .modes                  = { 0x0112, 0xffff },
        };
 
        memcpy16(args->es, infop, args->ds, &info, sizeof(info));
index 39cc972e9cc34cf2d9fd50e74827b7ec5016b776..c12fba731f254dd9d300c1f5394bf50a6d46fd43 100644 (file)
 #define VGA_RAM_END                    0x000bffff
 
 #define VGA_ROM_BEGIN                  0x000c0000
+#define VGA_ROM_OEM_STRING             VGA_ROM_BEGIN
+#define VGA_ROM_OEM_STRING_SIZE                16
+#define VGA_ROM_MODES                  (VGA_ROM_OEM_STRING + VGA_ROM_OEM_STRING_SIZE)
+#define VGA_ROM_MODES_SIZE             32
 #define VGA_ROM_END                    0x000c7fff
 
 /* we handle one page only */