[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 1/3] x86: real mode support



Add infrastructure to return back to real mode in order to obtain
certain pieces of information from the BIOS.

Along the way it turned out helpful to convert x86-32's boot code to
use SYM_PHYS() just like x86-64 has been doing for a while.

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

Index: 2007-02-27/xen/arch/x86/Makefile
===================================================================
--- 2007-02-27.orig/xen/arch/x86/Makefile       2007-02-28 12:08:24.000000000 
+0100
+++ 2007-02-27/xen/arch/x86/Makefile    2007-02-20 15:52:10.000000000 +0100
@@ -78,6 +78,8 @@ xen.lds: $(TARGET_SUBARCH)/xen.lds.S $(H
 boot/mkelf32: boot/mkelf32.c
        $(HOSTCC) $(HOSTCFLAGS) -o $@ $<
 
+boot/$(TARGET_SUBARCH).o: boot/realmode.S
+
 .PHONY: clean
 clean::
        rm -f asm-offsets.s xen.lds boot/*.o boot/*~ boot/core boot/mkelf32
Index: 2007-02-27/xen/arch/x86/boot/realmode.S
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ 2007-02-27/xen/arch/x86/boot/realmode.S     2007-02-22 13:35:18.000000000 
+0100
@@ -0,0 +1,120 @@
+#define REALMODE_SEG   0x1000
+#define REALMODE_BASE  (REALMODE_SEG << 4)
+
+       .section .init.data, "aw"
+       .align 8
+gdt16_table:
+       .quad 0
+       .quad 0x00cf9a000000ffff        /* 0xe008 ring 0 4.00GB code at 0x0 */
+       .quad 0x00cf92000000ffff        /* 0xe010 ring 0 4.00GB data at 0x0 */
+       /* 0xe018 ring 0 64kB 16-bit code at REALMODE_BASE */
+#define __HYPERVISOR_CS16 (__HYPERVISOR_CS + 0x10)
+       .quad 0x00009a000000ffff + (REALMODE_BASE << 16)
+       /* 0xe020 ring 0 64kB 16-bit data at REALMODE_BASE */
+#define __HYPERVISOR_DS16 (__HYPERVISOR_DS32 + 0x10)
+       .quad 0x000092000000ffff + (REALMODE_BASE << 16)
+#if __HYPERVISOR_CS32 != __HYPERVISOR_CS
+/* This doesn't work properly with gas up to at least 2.17.50 as of Feb 2007.
+   Using .skip or .fill also doesn't work up to 2.15 or 2.16. Use as' -K
+   option to be pointed at the problematic construct (.word with its operand
+   being the difference of two symbols) below.
+       .org gdt16_table + (__HYPERVISOR_CS32 - FIRST_RESERVED_GDT_BYTE) */
+       .rept (__HYPERVISOR_CS32 - __HYPERVISOR_DS16) / 8 - 1
+       .quad 0
+       .endr
+       .quad 0x00cf9a000000ffff        /* 0xe038 ring 0 4.00GB code at 0x0 */
+#endif
+.Lgdt16_end:
+
+       .word 0
+gdt16: .word FIRST_RESERVED_GDT_BYTE + .Lgdt16_end - gdt16_table - 1
+       .long SYM_PHYS(gdt16_table) - FIRST_RESERVED_GDT_BYTE
+
+#define SYM_REAL(x) ((x) - .L__realtext)
+
+       .section .init.text, "ax"
+       .code32
+realmode:
+       pushal
+       movl    %esp, %ebp
+       sgdt    SYM_PHYS(.Lgdt)
+       sidt    SYM_PHYS(.Lidt)
+       testl   $MBI_CMDLINE, MBI_flags(%ebx)
+       movl    MBI_cmdline(%ebx), %esi
+       jz      1f
+       testl   %esi, %esi
+       jz      1f
+       movl    $REALMODE_BASE + 0x10000, %edi
+       movl    %edi, SYM_PHYS(cmd_line_ptr)
+0:
+       lodsb
+       stosb
+       testb   %al, %al
+       jnz     0b
+1:
+       movl    $SYM_PHYS(.L__realtext), %esi
+       movl    $REALMODE_BASE, %edi
+       movl    $SYM_PHYS(__end_realmode), %ecx
+       subl    %esi, %ecx
+       rep movsb
+       movl    9*4(%ebp), %edi
+       subl    $SYM_PHYS(.L__realtext), %edi
+       lgdt    SYM_PHYS(gdt16)
+       movl    $__HYPERVISOR_DS16, %ecx
+       mov     %ecx, %ss
+       xorl    %esp, %esp
+       mov     %ecx, %ds
+       mov     %ecx, %es
+       ljmpl   $__HYPERVISOR_CS16, $SYM_REAL(.Ltext16)
+
+protmode:
+       movl    $__HYPERVISOR_DS32, %ecx
+       mov     %ecx, %ss
+       movl    %ebp, %esp
+       mov     %ecx, %ds
+       mov     %ecx, %es
+       movl    $REALMODE_BASE + SYM_PHYS(.L__realdata), %esi
+       subl    $SYM_PHYS(.L__realtext), %esi
+       movl    $SYM_PHYS(.L__realdata), %edi
+       movl    $SYM_PHYS(__end_realmode), %ecx
+       subl    %edi, %ecx
+       rep movsb
+       mov     %ecx, %fs
+       mov     %ecx, %gs
+       popal
+       ret     $4
+
+       .section .real.text, "ax"
+.L__realtext:
+       .code16
+.Ltext16:
+       mov     %cr0, %eax
+       andb    $~1, %al
+       mov     %eax, %cr0
+       ljmpw   $REALMODE_SEG, $SYM_REAL(.Lrealmode)
+.Lrealmode:
+       mov     %cs, %cx
+       mov     %cx, %ss
+       mov     %cx, %ds
+       mov     %cx, %es
+
+       pushal
+       callw   *%di
+       popal
+
+       pushw   $0
+       popfw
+       lgdtl   %cs:SYM_REAL(.Lgdt)
+       lidtl   %cs:SYM_REAL(.Lidt)
+       mov     %cr0, %eax
+       orb     $1, %al
+       mov     %eax, %cr0
+       ljmpl   $__HYPERVISOR_CS32, $SYM_PHYS(protmode)
+
+       .section .real.data, "aw"
+.L__realdata:
+       .align 4
+cmd_line_ptr: .long 0
+.Lgdt: .skip 2+4
+.Lidt: .skip 2+4
+       .previous
Index: 2007-02-27/xen/arch/x86/boot/x86_32.S
===================================================================
--- 2007-02-27.orig/xen/arch/x86/boot/x86_32.S  2007-02-28 12:08:24.000000000 
+0100
+++ 2007-02-27/xen/arch/x86/boot/x86_32.S       2007-02-21 18:08:18.000000000 
+0100
@@ -10,6 +10,8 @@
                 
         .text
 
+#define SYM_PHYS(sym) (sym - __PAGE_OFFSET)
+
 ENTRY(start)
         jmp __start
 
@@ -28,7 +30,7 @@ ENTRY(start)
 not_multiboot_msg:
         .asciz "ERR: Not a Multiboot bootloader!"
 not_multiboot:
-        mov     $not_multiboot_msg-__PAGE_OFFSET,%esi
+        mov     $SYM_PHYS(not_multiboot_msg),%esi
         mov     $0xB8000,%edi  # VGA framebuffer
 1:      mov     (%esi),%bl
         test    %bl,%bl        # Terminate on '\0' sentinel
@@ -47,14 +49,14 @@ not_multiboot:
         
 __start:
         /* Set up a few descriptors: on entry only CS is guaranteed good. */
-        lgdt    %cs:nopaging_gdt_descr-__PAGE_OFFSET
+        lgdt    %cs:SYM_PHYS(nopaging_gdt_descr)
         mov     $(__HYPERVISOR_DS),%ecx
         mov     %ecx,%ds
         mov     %ecx,%es
         mov     %ecx,%fs
         mov     %ecx,%gs
-        ljmp    $(__HYPERVISOR_CS),$(1f)-__PAGE_OFFSET
-1:      lss     stack_start-__PAGE_OFFSET,%esp
+        ljmp    $(__HYPERVISOR_CS),$SYM_PHYS(1f)
+1:      lss     SYM_PHYS(stack_start),%esp
         add     $(STACK_SIZE-CPUINFO_sizeof-__PAGE_OFFSET),%esp
 
         /* Reset EFLAGS (subsumes CLI and CLD). */
@@ -66,7 +68,7 @@ __start:
 
         /* Set up CR4, except global flag which Intel requires should be     */
         /* left until after paging is enabled (IA32 Manual Vol. 3, Sec. 2.5) */
-        mov     mmu_cr4_features-__PAGE_OFFSET,%ecx
+        mov     SYM_PHYS(mmu_cr4_features),%ecx
         and     $0x7f,%cl   # CR4.PGE (global enable)
         mov     %ecx,%cr4
 
@@ -78,19 +80,19 @@ __start:
         jne     not_multiboot
 
         /* Initialize BSS (no nasty surprises!) */
-        mov     $__bss_start-__PAGE_OFFSET,%edi
-        mov     $_end-__PAGE_OFFSET,%ecx
+        mov     $SYM_PHYS(__bss_start),%edi
+        mov     $SYM_PHYS(_end),%ecx
         sub     %edi,%ecx
         xor     %eax,%eax
         rep     stosb
 
         /* Save the Multiboot info structure for later use. */
-        add     $__PAGE_OFFSET,%ebx
-        push    %ebx
+        lea     __PAGE_OFFSET(%ebx),%eax
+        push    %eax
 
 #ifdef CONFIG_X86_PAE
         /* Initialize low and high mappings of all memory with 2MB pages */
-        mov     $idle_pg_table_l2-__PAGE_OFFSET,%edi
+        mov     $SYM_PHYS(idle_pg_table_l2),%edi
         mov     $0xe3,%eax                  /* PRESENT+RW+A+D+2MB */
 1:      mov     %eax,__PAGE_OFFSET>>18(%edi) /* high mapping */
         stosl                                /* low mapping */
@@ -105,7 +107,7 @@ __start:
         jne     1b
 #else
         /* Initialize low and high mappings of all memory with 4MB pages */
-        mov     $idle_pg_table-__PAGE_OFFSET,%edi
+        mov     $SYM_PHYS(idle_pg_table),%edi
         mov     $0xe3,%eax                  /* PRESENT+RW+A+D+4MB */
 1:      mov     %eax,__PAGE_OFFSET>>20(%edi) /* high mapping */
         stosl                                /* low mapping */
@@ -123,7 +125,7 @@ __start:
         mov     $(__HYPERVISOR_CS << 16),%eax
         mov     %dx,%ax            /* selector = 0x0010 = cs */
         mov     $0x8E00,%dx        /* interrupt gate - dpl=0, present */
-        lea     idt_table-__PAGE_OFFSET,%edi
+        lea     SYM_PHYS(idt_table),%edi
         mov     $256,%ecx
 1:      mov     %eax,(%edi)
         mov     %edx,4(%edi)
@@ -149,7 +151,7 @@ start_paging:
 no_execute_disable:
         pop     %ebx
 #endif
-        mov     $idle_pg_table-__PAGE_OFFSET,%eax
+        mov     $SYM_PHYS(idle_pg_table),%eax
         mov     %eax,%cr3
         mov     $0x80050033,%eax /* hi-to-lo: PG,AM,WP,NE,ET,MP,PE */
         mov     %eax,%cr0
@@ -212,7 +214,7 @@ gdt_descr:
         .word   0
 nopaging_gdt_descr:
         .word   LAST_RESERVED_GDT_BYTE
-        .long   gdt_table - FIRST_RESERVED_GDT_BYTE - __PAGE_OFFSET
+        .long   SYM_PHYS(gdt_table) - FIRST_RESERVED_GDT_BYTE
         
         .align PAGE_SIZE, 0
 /* NB. Rings != 0 get access up to MACH2PHYS_VIRT_END. This allows access to */
@@ -236,10 +238,10 @@ ENTRY(gdt_table)
 #ifdef CONFIG_X86_PAE
 ENTRY(idle_pg_table)
 ENTRY(idle_pg_table_l3)
-        .long idle_pg_table_l2 + 0*PAGE_SIZE + 0x01 - __PAGE_OFFSET, 0
-        .long idle_pg_table_l2 + 1*PAGE_SIZE + 0x01 - __PAGE_OFFSET, 0
-        .long idle_pg_table_l2 + 2*PAGE_SIZE + 0x01 - __PAGE_OFFSET, 0
-        .long idle_pg_table_l2 + 3*PAGE_SIZE + 0x01 - __PAGE_OFFSET, 0
+        .long SYM_PHYS(idle_pg_table_l2) + 0*PAGE_SIZE + 0x01, 0
+        .long SYM_PHYS(idle_pg_table_l2) + 1*PAGE_SIZE + 0x01, 0
+        .long SYM_PHYS(idle_pg_table_l2) + 2*PAGE_SIZE + 0x01, 0
+        .long SYM_PHYS(idle_pg_table_l2) + 3*PAGE_SIZE + 0x01, 0
 .section ".bss.page_aligned","w"
 ENTRY(idle_pg_table_l2)
         .fill 4*PAGE_SIZE,1,0
@@ -253,3 +255,8 @@ ENTRY(idle_pg_table_l2)
 .section ".bss.stack_aligned","w"
 ENTRY(cpu0_stack)
         .fill STACK_SIZE,1,0
+
+#define __HYPERVISOR_CS32 __HYPERVISOR_CS
+#define __HYPERVISOR_DS32 __HYPERVISOR_DS
+
+#include "realmode.S"
Index: 2007-02-27/xen/arch/x86/boot/x86_64.S
===================================================================
--- 2007-02-27.orig/xen/arch/x86/boot/x86_64.S  2007-02-28 12:08:24.000000000 
+0100
+++ 2007-02-27/xen/arch/x86/boot/x86_64.S       2007-02-21 17:54:29.000000000 
+0100
@@ -72,6 +72,8 @@ __start:
         /* Save the Multiboot info structure for later use. */
         mov     %ebx,SYM_PHYS(multiboot_ptr)
 
+        lss     SYM_PHYS(.Lstack_start),%esp
+
         /* We begin by interrogating the CPU for the presence of long mode. */
         mov     $0x80000000,%eax
         cpuid
@@ -200,7 +202,7 @@ multiboot_ptr:
         .word   0
 nopaging_gdt_descr:
         .word   LAST_RESERVED_GDT_BYTE
-        .quad   gdt_table - FIRST_RESERVED_GDT_BYTE - __PAGE_OFFSET
+        .quad   SYM_PHYS(gdt_table) - FIRST_RESERVED_GDT_BYTE
 
 cpuid_ext_features:
         .long   0
@@ -217,6 +219,9 @@ idt_descr:
 
 ENTRY(stack_start)
         .quad   cpu0_stack
+.Lstack_start:
+       .long   SYM_PHYS(cpu0_stack) + STACK_SIZE - CPUINFO_sizeof
+       .word   __HYPERVISOR_DS32
 
 high_start:
         .quad   __high_start
@@ -256,14 +261,14 @@ ENTRY(compat_gdt_table)
         .align PAGE_SIZE, 0
 ENTRY(idle_pg_table)
 ENTRY(idle_pg_table_4)
-        .quad idle_pg_table_l3 - __PAGE_OFFSET + 7 # PML4[0]
+        .quad SYM_PHYS(idle_pg_table_l3) + 7 # PML4[0]
         .fill 261,8,0
-        .quad idle_pg_table_l3 - __PAGE_OFFSET + 7 # PML4[262]
+        .quad SYM_PHYS(idle_pg_table_l3) + 7 # PML4[262]
 
 /* Initial PDP -- level-3 page table. */
         .align PAGE_SIZE, 0
 ENTRY(idle_pg_table_l3)
-        .quad idle_pg_table_l2 - __PAGE_OFFSET + 7
+        .quad SYM_PHYS(idle_pg_table_l2) + 7
 
 /* Initial PDE -- level-2 page table. Maps first 1GB physical memory. */
         .align PAGE_SIZE, 0
@@ -283,3 +288,5 @@ ENTRY(idle_pg_table_l2)
 .section ".bss.stack_aligned","w"
 ENTRY(cpu0_stack)
         .fill STACK_SIZE,1,0
+
+#include "realmode.S"
Index: 2007-02-27/xen/arch/x86/x86_32/asm-offsets.c
===================================================================
--- 2007-02-27.orig/xen/arch/x86/x86_32/asm-offsets.c   2007-02-28 
12:08:44.000000000 +0100
+++ 2007-02-27/xen/arch/x86/x86_32/asm-offsets.c        2007-02-28 
12:09:45.000000000 +0100
@@ -7,6 +7,7 @@
 #include <xen/config.h>
 #include <xen/perfc.h>
 #include <xen/sched.h>
+#include <xen/multiboot.h>
 #include <asm/fixmap.h>
 #include <asm/hardirq.h>
 
@@ -100,6 +101,10 @@ void __dummy__(void)
     DEFINE(CPUINFO_sizeof, sizeof(struct cpu_info));
     BLANK();
 
+    OFFSET(MBI_flags, multiboot_info_t, flags);
+    OFFSET(MBI_cmdline, multiboot_info_t, cmdline);
+    BLANK();
+
     OFFSET(TRAPBOUNCE_error_code, struct trap_bounce, error_code);
     OFFSET(TRAPBOUNCE_flags, struct trap_bounce, flags);
     OFFSET(TRAPBOUNCE_cs, struct trap_bounce, cs);
Index: 2007-02-27/xen/arch/x86/x86_32/xen.lds.S
===================================================================
--- 2007-02-27.orig/xen/arch/x86/x86_32/xen.lds.S       2007-02-28 
12:08:24.000000000 +0100
+++ 2007-02-27/xen/arch/x86/x86_32/xen.lds.S    2007-02-21 09:58:21.000000000 
+0100
@@ -63,6 +63,10 @@ SECTIONS
   __initcall_start = .;
   .initcall.init : { *(.initcall1.init) } :text
   __initcall_end = .;
+  . = ALIGN(16);
+  .real.text : { *(.real.text) } :text
+  .real.data : { *(.real.data) } :text
+  __end_realmode = .;
   . = ALIGN(PAGE_SIZE);
   __init_end = .;
 
Index: 2007-02-27/xen/arch/x86/x86_64/asm-offsets.c
===================================================================
--- 2007-02-27.orig/xen/arch/x86/x86_64/asm-offsets.c   2007-02-28 
12:08:44.000000000 +0100
+++ 2007-02-27/xen/arch/x86/x86_64/asm-offsets.c        2007-02-28 
12:09:50.000000000 +0100
@@ -7,6 +7,7 @@
 #include <xen/config.h>
 #include <xen/perfc.h>
 #include <xen/sched.h>
+#include <xen/multiboot.h>
 #ifdef CONFIG_COMPAT
 #include <compat/xen.h>
 #endif
@@ -113,6 +114,10 @@ void __dummy__(void)
     DEFINE(CPUINFO_sizeof, sizeof(struct cpu_info));
     BLANK();
 
+    OFFSET(MBI_flags, multiboot_info_t, flags);
+    OFFSET(MBI_cmdline, multiboot_info_t, cmdline);
+    BLANK();
+
     OFFSET(TRAPBOUNCE_error_code, struct trap_bounce, error_code);
     OFFSET(TRAPBOUNCE_flags, struct trap_bounce, flags);
     OFFSET(TRAPBOUNCE_cs, struct trap_bounce, cs);
Index: 2007-02-27/xen/arch/x86/x86_64/xen.lds.S
===================================================================
--- 2007-02-27.orig/xen/arch/x86/x86_64/xen.lds.S       2007-02-28 
12:08:24.000000000 +0100
+++ 2007-02-27/xen/arch/x86/x86_64/xen.lds.S    2007-02-21 10:10:04.000000000 
+0100
@@ -61,6 +61,10 @@ SECTIONS
   __initcall_start = .;
   .initcall.init : { *(.initcall1.init) } :text
   __initcall_end = .;
+  . = ALIGN(16);
+  .real.text : { *(.real.text) } :text
+  .real.data : { *(.real.data) } :text
+  __end_realmode = .;
   . = ALIGN(PAGE_SIZE);
   __init_end = .;
 



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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.