WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH] x86-64: enable hypervsior output on VESA frame buffe

To: <xen-devel@xxxxxxxxxxxxxxxxxxx>
Subject: [Xen-devel] [PATCH] x86-64: enable hypervsior output on VESA frame buffer
From: "Jan Beulich" <jbeulich@xxxxxxxxxx>
Date: Thu, 09 Aug 2007 13:25:41 +0100
Delivery-date: Thu, 09 Aug 2007 05:21:57 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
This is x86-64 only for now due to the virtual address space
constraints on x86-32.

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>

Index: 2007-08-08/xen/arch/x86/setup.c
===================================================================
--- 2007-08-08.orig/xen/arch/x86/setup.c        2007-08-06 15:08:41.000000000 
+0200
+++ 2007-08-08/xen/arch/x86/setup.c     2007-08-08 11:57:50.000000000 +0200
@@ -106,6 +106,8 @@ extern void init_IRQ(void);
 extern void trap_init(void);
 extern void early_time_init(void);
 extern void early_cpu_init(void);
+extern void vesa_init(void);
+extern void vesa_mtrr_init(void);
 
 struct tss_struct init_tss[NR_CPUS];
 
@@ -882,6 +884,7 @@ void __init __start_xen(unsigned long mb
 #ifdef __x86_64__
     init_xenheap_pages(xen_phys_start, __pa(&_start));
     nr_pages += (__pa(&_start) - xen_phys_start) >> PAGE_SHIFT;
+    vesa_init();
 #endif
     xenheap_phys_start = xen_phys_start;
     printk("Xen heap: %luMB (%lukB)\n", 
@@ -947,6 +950,9 @@ void __init __start_xen(unsigned long mb
         set_in_cr4(X86_CR4_OSFXSR);
     if ( cpu_has_xmm )
         set_in_cr4(X86_CR4_OSXMMEXCPT);
+#ifdef CONFIG_X86_64
+    vesa_mtrr_init();
+#endif
 
     if ( opt_nosmp )
         max_cpus = 0;
Index: 2007-08-08/xen/arch/x86/string.c
===================================================================
--- 2007-08-08.orig/xen/arch/x86/string.c       2005-11-17 15:51:04.000000000 
+0100
+++ 2007-08-08/xen/arch/x86/string.c    2007-08-08 11:57:50.000000000 +0200
@@ -11,10 +11,18 @@
 #undef memcpy
 void *memcpy(void *dest, const void *src, size_t n)
 {
-    int d0, d1, d2;
+    long d0, d1, d2;
 
     __asm__ __volatile__ (
-        "   rep ; movsl      ; "
+#ifdef __i386__
+        "   rep movsl        ; "
+#else
+        "   rep movsq        ; "
+        "   testb $4,%b4     ; "
+        "   je 0f            ; "
+        "   movsl            ; "
+        "0:                  ; "
+#endif
         "   testb $2,%b4     ; "
         "   je 1f            ; "
         "   movsw            ; "
@@ -23,7 +31,7 @@ void *memcpy(void *dest, const void *src
         "   movsb            ; "
         "2:                    "
         : "=&c" (d0), "=&D" (d1), "=&S" (d2)
-        : "0" (n/4), "q" (n), "1" (dest), "2" (src)
+        : "0" (n/sizeof(long)), "q" (n), "1" (dest), "2" (src)
         : "memory");
 
     return dest;
@@ -32,10 +40,10 @@ void *memcpy(void *dest, const void *src
 #undef memset
 void *memset(void *s, int c, size_t n)
 {
-    int d0, d1;
+    long d0, d1;
 
     __asm__ __volatile__ (
-        "rep ; stosb"
+        "rep stosb"
         : "=&c" (d0), "=&D" (d1)
         : "a" (c), "1" (s), "0" (n)
         : "memory");
@@ -46,14 +54,14 @@ void *memset(void *s, int c, size_t n)
 #undef memmove
 void *memmove(void *dest, const void *src, size_t n)
 {
-    int d0, d1, d2;
+    long d0, d1, d2;
  
     if ( dest < src )
         return memcpy(dest, src, n);
 
     __asm__ __volatile__ (
         "   std         ; "
-        "   rep ; movsb ; "
+        "   rep movsb   ; "
         "   cld           "
         : "=&c" (d0), "=&S" (d1), "=&D" (d2)
         : "0" (n), "1" (n-1+(const char *)src), "2" (n-1+(char *)dest)
Index: 2007-08-08/xen/drivers/video/Makefile
===================================================================
--- 2007-08-08.orig/xen/drivers/video/Makefile  2006-08-16 08:58:13.000000000 
+0200
+++ 2007-08-08/xen/drivers/video/Makefile       2007-08-08 11:57:50.000000000 
+0200
@@ -1,4 +1,9 @@
-obj-y += font_8x14.o
-obj-y += font_8x16.o
-obj-y += font_8x8.o
-obj-y += vga.o
+obj-y                := vga.o
+obj-$(CONFIG_X86_64) += font_8x14.o
+obj-$(CONFIG_X86_64) += font_8x16.o
+obj-$(CONFIG_X86_64) += font_8x8.o
+obj-$(CONFIG_X86_64) += vesa.o
+
+# extra dependencies
+vga.o: vesa.h
+vesa.o: font.h vesa.h
Index: 2007-08-08/xen/drivers/video/vesa.c
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ 2007-08-08/xen/drivers/video/vesa.c 2007-08-08 11:57:50.000000000 +0200
@@ -0,0 +1,304 @@
+/******************************************************************************
+ * vesa.c
+ *
+ * VESA linear frame buffer handling.
+ */
+
+#include <xen/config.h>
+#include <xen/compile.h>
+#include <xen/init.h>
+#include <xen/lib.h>
+#include <xen/mm.h>
+#include <xen/errno.h>
+#include <xen/console.h>
+#include <xen/vga.h>
+#include <asm/mtrr.h>
+#include "font.h"
+#include "vesa.h"
+
+#define vesa_lfb_info vga_console_info.u.vesa_lfb
+
+static unsigned char *lfb, *lbuf;
+static const struct font_desc *font;
+static bool_t vga_compat, redraw = 1;
+
+static unsigned int vram_total;
+integer_param("vesa-ram", vram_total);
+
+static unsigned int vram_remap;
+integer_param("vesa-map", vram_remap);
+
+static int vesa_mtrr;
+integer_param("vesa-mtrr", vesa_mtrr);
+
+static char __initdata opt_font[30] = "";
+string_param("font", opt_font);
+
+int __init vesa_early_init(void)
+{
+    int type;
+
+    /* XXX vga_compat = !(boot_video_info.capabilities & 2); */
+
+    if ( vesa_lfb_info.bits_per_pixel < 8 || vesa_lfb_info.bits_per_pixel > 32 
)
+        return -ENOSYS;
+
+    type = 0;
+    if ( opt_font )
+    {
+        const char *ptr;
+
+        if ( simple_strtoul(opt_font, &ptr, 10) == 8 &&
+             *ptr == 'x' )
+            type = simple_strtoul(ptr, &ptr, 10);
+        if ( *ptr )
+            type = 0;
+    }
+    switch ( type )
+    {
+    case 0:
+        switch ( vesa_lfb_info.height )
+        {
+        case 1 ... 600:
+            font = &font_vga_8x8;
+            break;
+        case 601 ... 768:
+            font = &font_vga_8x14;
+            break;
+        default:
+            font = &font_vga_8x16;
+            break;
+        }
+        break;
+    case 1 ... 8:
+        font = &font_vga_8x8;
+        break;
+    case 9 ... 14:
+        font = &font_vga_8x14;
+        break;
+    default:
+        font = &font_vga_8x16;
+        break;
+    }
+
+    return vesa_lfb_info.width / font->width;
+}
+
+void __init vesa_init(void)
+{
+    unsigned int size_vmode, size_remap, size_total;
+
+    if ( !font ||
+         vga_set_lines(vesa_lfb_info.height / font->height) < 0 )
+        return;
+
+    lbuf = xmalloc_bytes(vesa_lfb_info.bytes_per_line);
+    if ( !lbuf )
+        return;
+
+
+    /*   size_vmode -- that is the amount of memory needed for the
+     *                 used video mode, i.e. the minimum amount of
+     *                 memory we need. */
+    size_vmode = vesa_lfb_info.height * vesa_lfb_info.bytes_per_line;
+
+    /*   size_total -- all video memory we have. Used for mtrr
+     *                 entries. */
+    size_total = vesa_lfb_info.lfb_size << 16;
+    if ( vram_total )
+        size_total = vram_total << 20;
+    if ( size_total < size_vmode )
+        size_total = size_vmode;
+
+    /*   size_remap -- the amount of video memory we are going to
+     *                 use for vesafb.  With modern cards it is no
+     *                 option to simply use size_total as that
+     *                 wastes plenty of kernel address space. */
+    if ( vram_remap )
+        size_remap = vram_remap << 20;
+    else
+        size_remap = (size_vmode + (1 << L2_PAGETABLE_SHIFT) - 1) &
+                     ~((1 << L2_PAGETABLE_SHIFT) - 1);
+    if ( size_remap < size_vmode )
+        size_remap = size_vmode;
+    if ( size_remap > size_total )
+        size_remap = size_total;
+
+    if ( map_pages_to_xen(IOREMAP_VIRT_START,
+                          vesa_lfb_info.lfb_base >> PAGE_SHIFT,
+                          size_remap >> PAGE_SHIFT,
+                          PAGE_HYPERVISOR_NOCACHE) )
+        return;
+
+    lfb = memset((void *)IOREMAP_VIRT_START, 0x33, size_remap);
+
+    printk(KERN_INFO "vesafb: framebuffer at 0x%x, mapped to 0x%p, "
+           "using %uk, total %uk\n",
+           vesa_lfb_info.lfb_base, lfb,
+           size_remap >> 10, size_total >> 10);
+    printk(KERN_INFO "vesafb: mode is %dx%dx%u, linelength=%d, font %ux%u\n",
+           vesa_lfb_info.width, vesa_lfb_info.height,
+           vesa_lfb_info.bits_per_pixel, vesa_lfb_info.bytes_per_line,
+           font->width, font->height);
+    printk(KERN_INFO "vesafb: %scolor: "
+           "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
+           vesa_lfb_info.bits_per_pixel > 8 ? "True" :
+                                              vga_compat ? "Pseudo" :
+                                                           "Static Pseudo",
+           vesa_lfb_info.rsvd_size, vesa_lfb_info.red_size,
+           vesa_lfb_info.green_size, vesa_lfb_info.blue_size,
+           vesa_lfb_info.rsvd_pos, vesa_lfb_info.red_pos,
+           vesa_lfb_info.green_pos, vesa_lfb_info.blue_pos);
+}
+
+void __init vesa_mtrr_init(void)
+{
+    int type;
+
+    if ( !lfb )
+        return;
+
+    switch ( vesa_mtrr )
+    {
+    case 1:
+        type = MTRR_TYPE_UNCACHABLE;
+        break;
+    case 2:
+        type = MTRR_TYPE_WRBACK;
+        break;
+    case 3:
+        type = MTRR_TYPE_WRCOMB;
+        break;
+    case 4:
+        type = MTRR_TYPE_WRTHROUGH;
+        break;
+    default:
+        return;
+    }
+
+    if ( type )
+    {
+        unsigned int size_vmode, size_total;
+        int rc;
+
+        /*   size_vmode -- that is the amount of memory needed for the
+         *                 used video mode, i.e. the minimum amount of
+         *                 memory we need. */
+        size_vmode = vesa_lfb_info.height * vesa_lfb_info.bytes_per_line;
+
+        /*   size_total -- all video memory we have. Used for mtrr
+         *                 entries. */
+        size_total = vesa_lfb_info.lfb_size << 16;
+        if ( vram_total )
+            size_total = vram_total << 20;
+        if ( size_total < size_vmode )
+            size_total = size_vmode;
+
+        /* Find the largest power-of-two */
+        while ( size_total & (size_total - 1) )
+            size_total &= size_total - 1;
+
+        /* Try and find a power of two to add */
+        do {
+            rc = mtrr_add(vesa_lfb_info.lfb_base,
+                          size_total, type, 1);
+            size_total >>= 1;
+        } while ( size_total >= PAGE_SIZE && rc == -EINVAL );
+    }
+}
+
+void __init vesa_endboot(void)
+{
+     redraw = 0;
+}
+
+/* Note that 'video' points to character/attribute pairs. */
+static void vesa_show_line(const unsigned char *video, unsigned char *pfb,
+                           unsigned int x, unsigned int y)
+{
+    const unsigned char *line;
+    unsigned int i, bytes = (vesa_lfb_info.bits_per_pixel + 7) >> 3;
+    unsigned int pixel = ((0xaaaaaaaa >> (32 - vesa_lfb_info.  red_size)) << 
vesa_lfb_info.  red_pos)
+                       | ((0xaaaaaaaa >> (32 - vesa_lfb_info.green_size)) << 
vesa_lfb_info.green_pos)
+                       | ((0xaaaaaaaa >> (32 - vesa_lfb_info. blue_size)) << 
vesa_lfb_info. blue_pos);
+
+    line = video + y * (vesa_lfb_info.width / font->width) * 2;
+    for ( i = 0; i < font->height; ++i )
+    {
+        unsigned char *ptr = lbuf;
+        unsigned int j;
+
+        for ( j = 0; j < x; ++j )
+        {
+            const unsigned char *bits = font->data;
+            unsigned int b;
+
+            bits += (line[j * 2] * font->height + i) * ((font->width + 7) >> 
3);
+            for ( b = font->width; b--; ptr += bytes )
+            {
+
+                if ( !test_bit(b, bits) )
+                {
+                    if ( bytes > 1 )
+                    {
+                       memset(ptr, 0, bytes);
+                       continue;
+                    }
+                    pixel = line[j * 2 + 1] >> 4;
+                }
+                else if ( bytes == 1 )
+                    pixel = line[j * 2 + 1] & 0xf;
+                memcpy(ptr, &pixel, bytes);
+            }
+        }
+        memset(ptr, 0, (vesa_lfb_info.width - j * font->width) * bytes);
+        memcpy(pfb, lbuf, vesa_lfb_info.width * bytes);
+        pfb += vesa_lfb_info.bytes_per_line;
+    }
+}
+
+void vesa_show(const unsigned char *video, unsigned int x, unsigned int y)
+{
+    static unsigned int last_y;
+    unsigned char *pfb = lfb;
+
+    if ( !lfb )
+        return;
+
+    if ( y == last_y && y + 1 == vesa_lfb_info.height / font->height )
+    {
+        unsigned int i;
+
+        /*
+         * Make room for a new line. Prefer redraw for performance reasons,
+         * but do not disturb what the guest may have drawn.
+         */
+        if ( redraw )
+        {
+            for ( i = 0; i < y; ++i )
+            {
+                vesa_show_line(video, pfb, vesa_lfb_info.width / font->width, 
i);
+                pfb += vesa_lfb_info.bytes_per_line * font->height;
+            }
+        }
+        else
+        {
+            unsigned int bytes = vesa_lfb_info.width *
+                                 ((vesa_lfb_info.bits_per_pixel + 7) >> 3);
+
+            for ( i = font->height; i < vesa_lfb_info.height; ++i )
+            {
+                memcpy(pfb, lfb + vesa_lfb_info.bytes_per_line * i, bytes);
+                pfb += vesa_lfb_info.bytes_per_line;
+            }
+        }
+    }
+    else
+        pfb += vesa_lfb_info.bytes_per_line * y * font->height;
+    last_y = y;
+
+    vesa_show_line(video, pfb, x, y);
+
+    if ( vesa_mtrr == 3 )
+        __asm__ __volatile__ ("sfence" : : : "memory");
+}
Index: 2007-08-08/xen/drivers/video/vesa.h
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ 2007-08-08/xen/drivers/video/vesa.h 2007-08-08 11:57:50.000000000 +0200
@@ -0,0 +1,30 @@
+#ifndef __X86_VESA_H__
+#define __X86_VESA_H__
+
+int vga_set_lines(unsigned int lines);
+
+#ifdef CONFIG_X86_64
+
+int vesa_early_init(void);
+void vesa_endboot(void);
+void vesa_show(const unsigned char *line, unsigned int x, unsigned int y);
+
+#else
+
+static inline int vesa_early_init(void)
+{
+       return -ENOSYS;
+}
+
+static inline void vesa_endboot(void)
+{
+}
+
+static inline void vesa_show(const unsigned char *line,
+                             unsigned int x, unsigned int y)
+{
+}
+
+#endif
+
+#endif /* __X86_VESA_H__ */
Index: 2007-08-08/xen/drivers/video/vga.c
===================================================================
--- 2007-08-08.orig/xen/drivers/video/vga.c     2007-06-20 08:32:49.000000000 
+0200
+++ 2007-08-08/xen/drivers/video/vga.c  2007-08-08 12:02:59.000000000 +0200
@@ -10,21 +10,18 @@
 #include <xen/lib.h>
 #include <xen/mm.h>
 #include <xen/errno.h>
-#include <xen/event.h>
-#include <xen/spinlock.h>
 #include <xen/console.h>
 #include <xen/vga.h>
 #include <asm/io.h>
-#include "font.h"
+#include "vesa.h"
 
 /* Filled in by arch boot code. */
 struct xen_vga_console_info vga_console_info;
 
 static int vgacon_enabled = 0;
 static int vgacon_keep    = 0;
-/*static const struct font_desc *font;*/
 
-static int xpos, ypos;
+static unsigned int xpos, ypos;
 static unsigned char *video;
 
 /*
@@ -55,14 +52,14 @@ static char opt_vga[30] = "";
 string_param("vga", opt_vga);
 
 /* VGA text-mode definitions. */
-#define COLUMNS vga_console_info.u.text_mode_3.columns
-#define LINES   vga_console_info.u.text_mode_3.rows
+static unsigned int COLUMNS, LINES;
 #define ATTRIBUTE   7
 #define VIDEO_SIZE  (COLUMNS * LINES * 2)
 
 void __init vga_init(void)
 {
     char *p;
+    int rc;
 
     /* Look for 'keep' in comma-separated options. */
     for ( p = opt_vga; p != NULL; p = strchr(p, ',') )
@@ -83,20 +80,16 @@ void __init vga_init(void)
             return;
         /* Disable cursor. */
         outw(0x200a, 0x3d4);
+        COLUMNS = vga_console_info.u.text_mode_3.columns;
+        LINES = vga_console_info.u.text_mode_3.rows;
         memset(video, 0, VIDEO_SIZE);
         break;
     case XEN_VGATYPE_VESA_LFB:
-#if 0
-        /* XXX Implement me! */
-        video = ioremap(vga_console_info.u.vesa_lfb.lfb_base,
-                        vga_console_info.u.vesa_lfb.lfb_size);
-        if ( video == NULL )
+        rc = vesa_early_init();
+        if ( rc <= 0 )
             return;
-        memset(video, 0, vga_console_info.u.vesa_lfb.lfb_size);
+        COLUMNS = rc;
         break;
-#else
-        return;
-#endif
     default:
         memset(&vga_console_info, 0, sizeof(vga_console_info));
         return;
@@ -107,11 +100,12 @@ void __init vga_init(void)
 
 void __init vga_endboot(void)
 {
-    if ( !vgacon_enabled )
+    if ( !vgacon_enabled || !video )
         return;
 
     printk("Xen is %s VGA console.\n",
            vgacon_keep ? "keeping" : "relinquishing");
+    vesa_endboot();
 
     vgacon_enabled = vgacon_keep;
 }
@@ -119,20 +113,22 @@ void __init vga_endboot(void)
 
 static void put_newline(void)
 {
-    xpos = 0;
-    ypos++;
+    vesa_show(video, xpos, ypos);
 
-    if ( ypos >= LINES )
+    if ( ++ypos >= LINES )
     {
-        ypos = LINES-1;
-        memmove((char*)video, 
-                (char*)video + 2*COLUMNS, (LINES-1)*2*COLUMNS);
-        memset((char*)video + (LINES-1)*2*COLUMNS, 0, 2*COLUMNS);
+        ypos = LINES - 1;
+        memmove(video, video + 2 * COLUMNS, ypos * 2 * COLUMNS);
+        memset(video + ypos * 2 * COLUMNS, 0, 2 * xpos);
     }
+    xpos = 0;
 }
 
 void vga_putchar(int c)
 {
+    if ( !video )
+        return;
+
     if ( !vgacon_enabled )
         return;
 
@@ -150,6 +146,18 @@ void vga_putchar(int c)
     }
 }
 
+int __init vga_set_lines(unsigned int lines)
+{
+    /* Must be done here - xmalloc() cannot be used in vga_init(). */
+    BUG_ON(LINES);
+    LINES = lines;
+    video = xmalloc_bytes(VIDEO_SIZE);
+    if ( !video )
+        return -ENOMEM;
+    memset(video, 0, VIDEO_SIZE);
+    return 0;
+}
+
 int __init fill_console_start_info(struct dom0_vga_console_info *ci)
 {
     memcpy(ci, &vga_console_info, sizeof(*ci));



_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-devel] [PATCH] x86-64: enable hypervsior output on VESA frame buffer, Jan Beulich <=