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-changelog

[Xen-changelog] [xen-unstable] x86-64: enable hypervisor output on VESA

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] x86-64: enable hypervisor output on VESA frame buffer
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Thu, 16 Aug 2007 07:40:27 -0700
Delivery-date: Thu, 16 Aug 2007 07:42:28 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1186996146 -3600
# Node ID f2649861d59428f16f6f7705e6de47d2cc02c3ae
# Parent  c362bcee8047d3d30b8c7655d26d8a8702371b6f
x86-64: enable hypervisor output on VESA frame buffer

This is x86-64 only for now due to the virtual address space
constraints on x86-32.

New options 'vesa-ram', 'vesa-map', 'vesa-mtrr' are close equivalents
to the vesafb Linux options 'vtotal', 'vremap', 'mtrr'.

Also the font can be specified: font=8x{8,14,16}.

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 xen/arch/x86/setup.c       |    6 
 xen/drivers/char/console.c |   14 --
 xen/drivers/video/Makefile |   12 +
 xen/drivers/video/vesa.c   |  307 +++++++++++++++++++++++++++++++++++++++++++++
 xen/drivers/video/vga.c    |  112 +++++++---------
 xen/include/xen/vga.h      |    8 -
 6 files changed, 380 insertions(+), 79 deletions(-)

diff -r c362bcee8047 -r f2649861d594 xen/arch/x86/setup.c
--- a/xen/arch/x86/setup.c      Sun Aug 12 16:09:13 2007 +0100
+++ b/xen/arch/x86/setup.c      Mon Aug 13 10:09:06 2007 +0100
@@ -106,6 +106,8 @@ extern void trap_init(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];
 
@@ -901,6 +903,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", 
@@ -966,6 +969,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;
diff -r c362bcee8047 -r f2649861d594 xen/drivers/char/console.c
--- a/xen/drivers/char/console.c        Sun Aug 12 16:09:13 2007 +0100
+++ b/xen/drivers/char/console.c        Mon Aug 13 10:09:06 2007 +0100
@@ -331,13 +331,11 @@ static long guest_console_write(XEN_GUES
         kbuf[kcount] = '\0';
 
         sercon_puts(kbuf);
-
-        for ( kptr = kbuf; *kptr != '\0'; kptr++ )
-        {
-            vga_putchar(*kptr);
-            if ( opt_console_to_ring )
+        vga_puts(kbuf);
+
+        if ( opt_console_to_ring )
+            for ( kptr = kbuf; *kptr != '\0'; kptr++ )
                 putchar_console_ring(*kptr);
-        }
 
         if ( opt_console_to_ring )
             send_guest_global_virq(dom0, VIRQ_CON_RING);
@@ -404,12 +402,10 @@ static void __putstr(const char *str)
     int c;
 
     sercon_puts(str);
+    vga_puts(str);
 
     while ( (c = *str++) != '\0' )
-    {
-        vga_putchar(c);
         putchar_console_ring(c);
-    }
 
     send_guest_global_virq(dom0, VIRQ_CON_RING);
 }
diff -r c362bcee8047 -r f2649861d594 xen/drivers/video/Makefile
--- a/xen/drivers/video/Makefile        Sun Aug 12 16:09:13 2007 +0100
+++ b/xen/drivers/video/Makefile        Mon Aug 13 10:09:06 2007 +0100
@@ -1,4 +1,8 @@ obj-y += font_8x14.o
-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
+vesa.o: font.h
diff -r c362bcee8047 -r f2649861d594 xen/drivers/video/vesa.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/drivers/video/vesa.c  Mon Aug 13 10:09:06 2007 +0100
@@ -0,0 +1,307 @@
+/******************************************************************************
+ * 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 "font.h"
+
+#define vlfb_info    vga_console_info.u.vesa_lfb
+#define text_columns (vlfb_info.width / font->width)
+#define text_rows    (vlfb_info.height / font->height)
+
+static void vesa_redraw_puts(const char *s);
+static void vesa_scroll_puts(const char *s);
+
+static unsigned char *lfb, *lbuf, *text_buf;
+static const struct font_desc *font;
+static bool_t vga_compat;
+static unsigned int pixel_on;
+static unsigned int xpos, ypos;
+
+static unsigned int vram_total;
+integer_param("vesa-ram", vram_total);
+
+static unsigned int vram_remap;
+integer_param("vesa-map", vram_remap);
+
+static int font_height;
+static void __init parse_font_height(const char *s)
+{
+    if ( simple_strtoul(s, &s, 10) == 8 && (*s++ == 'x') )
+        font_height = simple_strtoul(s, &s, 10);
+    if ( *s != '\0' )
+        font_height = 0;
+}
+custom_param("font", parse_font_height);
+
+void __init vesa_early_init(void)
+{
+    unsigned int vram_vmode;
+
+    /* XXX vga_compat = !(boot_video_info.capabilities & 2); */
+
+    if ( (vlfb_info.bits_per_pixel < 8) || (vlfb_info.bits_per_pixel > 32) )
+        return;
+
+    if ( font_height == 0 ) /* choose a sensible default */
+        font = ((vlfb_info.height <= 600) ? &font_vga_8x8 :
+                (vlfb_info.height <= 768) ? &font_vga_8x14 : &font_vga_8x16);
+    else if ( font_height <= 8 )
+        font = &font_vga_8x8;
+    else if ( font_height <= 14 )
+        font = &font_vga_8x14;
+    else
+        font = &font_vga_8x16;
+
+    /*   vram_vmode -- that is the amount of memory needed for the
+     *                 used video mode, i.e. the minimum amount of
+     *                 memory we need. */
+    vram_vmode = vlfb_info.height * vlfb_info.bytes_per_line;
+
+    /*   vram_total -- all video memory we have. Used for mtrr
+     *                 entries. */
+    vram_total = vram_total ? (vram_total << 20) : (vlfb_info.lfb_size << 16);
+    vram_total = max_t(unsigned int, vram_total, vram_vmode);
+
+    /*   vram_remap -- the amount of video memory we are going to
+     *                 use for vesafb.  With modern cards it is no
+     *                 option to simply use vram_total as that
+     *                 wastes plenty of kernel address space. */
+    vram_remap = (vram_remap ?
+                  (vram_remap << 20) :
+                  ((vram_vmode + (1 << L2_PAGETABLE_SHIFT) - 1) &
+                   ~((1 << L2_PAGETABLE_SHIFT) - 1)));
+    vram_remap = max_t(unsigned int, vram_remap, vram_vmode);
+    vram_remap = min_t(unsigned int, vram_remap, vram_total);
+}
+
+void __init vesa_init(void)
+{
+    if ( !font )
+        goto fail;
+
+    lbuf = xmalloc_bytes(vlfb_info.bytes_per_line);
+    if ( !lbuf )
+        goto fail;
+
+    text_buf = xmalloc_bytes(text_columns * text_rows);
+    if ( !text_buf )
+        goto fail;
+
+    if ( map_pages_to_xen(IOREMAP_VIRT_START,
+                          vlfb_info.lfb_base >> PAGE_SHIFT,
+                          vram_remap >> PAGE_SHIFT,
+                          PAGE_HYPERVISOR_NOCACHE) )
+        goto fail;
+
+    lfb = memset((void *)IOREMAP_VIRT_START, 0, vram_remap);
+    memset(text_buf, 0, text_columns * text_rows);
+
+    vga_puts = vesa_redraw_puts;
+
+    printk(XENLOG_INFO "vesafb: framebuffer at 0x%x, mapped to 0x%p, "
+           "using %uk, total %uk\n",
+           vlfb_info.lfb_base, lfb,
+           vram_remap >> 10, vram_total >> 10);
+    printk(XENLOG_INFO "vesafb: mode is %dx%dx%u, linelength=%d, font %ux%u\n",
+           vlfb_info.width, vlfb_info.height,
+           vlfb_info.bits_per_pixel, vlfb_info.bytes_per_line,
+           font->width, font->height);
+    printk(XENLOG_INFO "vesafb: %scolor: size=%d:%d:%d:%d, "
+           "shift=%d:%d:%d:%d\n",
+           vlfb_info.bits_per_pixel > 8 ? "True" :
+           vga_compat ? "Pseudo" : "Static Pseudo",
+           vlfb_info.rsvd_size, vlfb_info.red_size,
+           vlfb_info.green_size, vlfb_info.blue_size,
+           vlfb_info.rsvd_pos, vlfb_info.red_pos,
+           vlfb_info.green_pos, vlfb_info.blue_pos);
+
+    if ( vlfb_info.bits_per_pixel > 8 )
+    {
+        /* Light grey in truecolor. */
+        unsigned int grey = 0xaaaaaaaa;
+        pixel_on = 
+            ((grey >> (32 - vlfb_info.  red_size)) << vlfb_info.  red_pos) |
+            ((grey >> (32 - vlfb_info.green_size)) << vlfb_info.green_pos) |
+            ((grey >> (32 - vlfb_info. blue_size)) << vlfb_info. blue_pos);
+    }
+    else
+    {
+        /* White(ish) in default pseudocolor palette. */
+        pixel_on = 7;
+    }
+
+    return;
+
+ fail:
+    xfree(lbuf);
+    xfree(text_buf);
+}
+
+void __init vesa_endboot(void)
+{
+    xpos = 0;
+    vga_puts = vesa_scroll_puts;
+}
+
+#if defined(CONFIG_X86)
+
+#include <asm/mtrr.h>
+
+static unsigned int vesa_mtrr;
+integer_param("vesa-mtrr", vesa_mtrr);
+
+void __init vesa_mtrr_init(void)
+{
+    static const int mtrr_types[] = {
+        0, MTRR_TYPE_UNCACHABLE, MTRR_TYPE_WRBACK,
+        MTRR_TYPE_WRCOMB, MTRR_TYPE_WRTHROUGH };
+    unsigned int size_total;
+    int rc, type;
+
+    if ( !lfb || (vesa_mtrr == 0) || (vesa_mtrr >= ARRAY_SIZE(mtrr_types)) )
+        return;
+
+    type = mtrr_types[vesa_mtrr];
+    if ( !type )
+        return;
+
+    /* Find the largest power-of-two */
+    size_total = vram_total;
+    while ( size_total & (size_total - 1) )
+        size_total &= size_total - 1;
+
+    /* Try and find a power of two to add */
+    do {
+        rc = mtrr_add(vlfb_info.lfb_base, size_total, type, 1);
+        size_total >>= 1;
+    } while ( (size_total >= PAGE_SIZE) && (rc == -EINVAL) );
+}
+
+static void lfb_flush(void)
+{
+    if ( vesa_mtrr == 3 )
+        __asm__ __volatile__ ("sfence" : : : "memory");
+}
+
+#else /* !defined(CONFIG_X86) */
+
+#define lfb_flush() ((void)0)
+
+#endif
+
+/* Render one line of text to given linear framebuffer line. */
+static void vesa_show_line(
+    const unsigned char *text_line,
+    unsigned char *video_line,
+    unsigned int nr_chars)
+{
+    unsigned int i, j, b, bpp, pixel;
+
+    bpp = (vlfb_info.bits_per_pixel + 7) >> 3;
+
+    for ( i = 0; i < font->height; i++ )
+    {
+        unsigned char *ptr = lbuf;
+
+        for ( j = 0; j < nr_chars; j++ )
+        {
+            const unsigned char *bits = font->data;
+            bits += ((text_line[j] * font->height + i) *
+                     ((font->width + 7) >> 3));
+            for ( b = font->width; b--; )
+            {
+                pixel = test_bit(b, bits) ? pixel_on : 0;
+                memcpy(ptr, &pixel, bpp);
+                ptr += bpp;
+            }
+        }
+
+        memset(ptr, 0, (vlfb_info.width - nr_chars * font->width) * bpp);
+        memcpy(video_line, lbuf, vlfb_info.width * bpp);
+        video_line += vlfb_info.bytes_per_line;
+    }
+}
+
+/* Fast mode which redraws all modified parts of a 2D text buffer. */
+static void vesa_redraw_puts(const char *s)
+{
+    unsigned int i, min_redraw_y = ypos;
+    char c;
+
+    /* Paste characters into text buffer. */
+    while ( (c = *s++) != '\0' )
+    {
+        if ( (c == '\n') || (xpos >= text_columns) )
+        {
+            if ( ++ypos >= text_rows )
+            {
+                min_redraw_y = 0;
+                ypos = text_rows - 1;
+                memmove(text_buf, text_buf + text_columns,
+                        ypos * text_columns);
+                memset(text_buf + ypos * text_columns, 0, xpos);
+            }
+            xpos = 0;
+        }
+
+        if ( c != '\n' )
+            text_buf[xpos++ + ypos * text_columns] = c;
+    }
+
+    /* Render modified section of text buffer to VESA linear framebuffer. */
+    for ( i = min_redraw_y; i <= ypos; i++ )
+        vesa_show_line(text_buf + i * text_columns,
+                       lfb + i * font->height * vlfb_info.bytes_per_line,
+                       text_columns);
+
+    lfb_flush();
+}
+
+/* Slower line-based scroll mode which interacts better with dom0. */
+static void vesa_scroll_puts(const char *s)
+{
+    unsigned int i;
+    char c;
+
+    while ( (c = *s++) != '\0' )
+    {
+        if ( (c == '\n') || (xpos >= text_columns) )
+        {
+            unsigned int bytes = (vlfb_info.width *
+                                  ((vlfb_info.bits_per_pixel + 7) >> 3));
+            unsigned char *src = lfb + font->height * vlfb_info.bytes_per_line;
+            unsigned char *dst = lfb;
+            
+            /* New line: scroll all previous rows up one line. */
+            for ( i = font->height; i < vlfb_info.height; i++ )
+            {
+                memcpy(dst, src, bytes);
+                src += vlfb_info.bytes_per_line;
+                dst += vlfb_info.bytes_per_line;
+            }
+
+            /* Render new line. */
+            vesa_show_line(
+                text_buf,
+                lfb + (text_rows-1) * font->height * vlfb_info.bytes_per_line,
+                xpos);
+
+            xpos = 0;
+        }
+
+        if ( c != '\n' )
+            text_buf[xpos++] = c;
+    }
+
+    lfb_flush();
+}
diff -r c362bcee8047 -r f2649861d594 xen/drivers/video/vga.c
--- a/xen/drivers/video/vga.c   Sun Aug 12 16:09:13 2007 +0100
+++ b/xen/drivers/video/vga.c   Mon Aug 13 10:09:06 2007 +0100
@@ -10,22 +10,20 @@
 #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"
 
 /* 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 vgacon_keep;
+static unsigned int xpos, ypos;
+static unsigned char *video;
 
-static int xpos, ypos;
-static unsigned char *video;
+static void vga_text_puts(const char *s);
+static void vga_noop_puts(const char *s) {}
+void (*vga_puts)(const char *) = vga_noop_puts;
 
 /*
  * 'vga=<mode-specifier>[,keep]' where <mode-specifier> is one of:
@@ -55,10 +53,16 @@ string_param("vga", opt_vga);
 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)
+
+#ifdef CONFIG_X86_64
+void vesa_early_init(void);
+void vesa_endboot(void);
+#else
+#define vesa_early_init() ((void)0)
+#define vesa_endboot()    ((void)0)
+#endif
 
 void __init vga_init(void)
 {
@@ -76,77 +80,61 @@ void __init vga_init(void)
     switch ( vga_console_info.video_type )
     {
     case XEN_VGATYPE_TEXT_MODE_3:
-        if ( memory_is_conventional_ram(0xB8000) )
+        if ( memory_is_conventional_ram(0xB8000) ||
+             ((video = ioremap(0xB8000, 0x8000)) == NULL) )
             return;
-        video = ioremap(0xB8000, 0x8000);
-        if ( video == NULL )
-            return;
-        /* Disable cursor. */
-        outw(0x200a, 0x3d4);
-        memset(video, 0, VIDEO_SIZE);
+        outw(0x200a, 0x3d4); /* disable cursor */
+        columns = vga_console_info.u.text_mode_3.columns;
+        lines   = vga_console_info.u.text_mode_3.rows;
+        memset(video, 0, columns * lines * 2);
+        vga_puts = vga_text_puts;
         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 )
-            return;
-        memset(video, 0, vga_console_info.u.vesa_lfb.lfb_size);
+        vesa_early_init();
         break;
-#else
-        return;
-#endif
     default:
         memset(&vga_console_info, 0, sizeof(vga_console_info));
-        return;
+        break;
     }
-
-    vgacon_enabled = 1;
 }
 
 void __init vga_endboot(void)
 {
-    if ( !vgacon_enabled )
+    if ( vga_puts == vga_noop_puts )
         return;
 
     printk("Xen is %s VGA console.\n",
            vgacon_keep ? "keeping" : "relinquishing");
 
-    vgacon_enabled = vgacon_keep;
+    vesa_endboot();
+
+    if ( !vgacon_keep )
+        vga_puts = vga_noop_puts;
 }
 
+static void vga_text_puts(const char *s)
+{
+    char c;
 
-static void put_newline(void)
-{
-    xpos = 0;
-    ypos++;
+    while ( (c = *s++) != '\0' )
+    {
+        if ( (c == '\n') || (xpos >= columns) )
+        {
+            if ( ++ypos >= lines )
+            {
+                ypos = lines - 1;
+                memmove(video, video + 2 * columns, ypos * 2 * columns);
+                memset(video + ypos * 2 * columns, 0, 2 * xpos);
+            }
+            xpos = 0;
+        }
 
-    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);
-    }
-}
-
-void vga_putchar(int c)
-{
-    if ( !vgacon_enabled )
-        return;
-
-    if ( c == '\n' )
-    {
-        put_newline();
-    }
-    else
-    {
-        if ( xpos >= COLUMNS )
-            put_newline();
-        video[(xpos + ypos * COLUMNS) * 2]     = c & 0xFF;
-        video[(xpos + ypos * COLUMNS) * 2 + 1] = ATTRIBUTE;
-        ++xpos;
+        if ( c != '\n' )
+        {
+            video[(xpos + ypos * columns) * 2]     = c;
+            video[(xpos + ypos * columns) * 2 + 1] = ATTRIBUTE;
+            xpos++;
+        }
     }
 }
 
diff -r c362bcee8047 -r f2649861d594 xen/include/xen/vga.h
--- a/xen/include/xen/vga.h     Sun Aug 12 16:09:13 2007 +0100
+++ b/xen/include/xen/vga.h     Mon Aug 13 10:09:06 2007 +0100
@@ -15,11 +15,11 @@ extern struct xen_vga_console_info vga_c
 extern struct xen_vga_console_info vga_console_info;
 void vga_init(void);
 void vga_endboot(void);
-void vga_putchar(int c);
+extern void (*vga_puts)(const char *);
 #else
-#define vga_init()     ((void)0)
-#define vga_endboot()  ((void)0)
-#define vga_putchar(c) ((void)0)
+#define vga_init()    ((void)0)
+#define vga_endboot() ((void)0)
+#define vga_puts(s)   ((void)0)
 #endif
 
 #endif /* _XEN_VGA_H */

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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] x86-64: enable hypervisor output on VESA frame buffer, Xen patchbot-unstable <=