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
|