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

[Minios-devel] [PATCH v2 05/22] mini-os: add boot code for HVMlite support



A HVMlite domain is always starting in 32 bit mode. Add the appropriate
boot code to arch/x86 for the non-paravirtualized case.

For this boot code to become active we need to suppress the pv related
elfnotes and add an appropriate elfnote for HVMlite.

As the HVMlite boot code is more or less the same for 32- and 64-bit
Mini-OS #include the new code from x86_[32|64].S in order to avoid
error prone code duplication. The specific parts of 32- or 64-bit code
are added to x86_[32|64].S

This enables Mini-OS to start the boot process in HVMlite mode until it
enters C code. This is working for 32- and for 64-bit mode.

Signed-off-by: Juergen Gross <jgross@xxxxxxxx>
---
V2: add some comments as requested by Samuel Thibault
---
 Makefile           |   2 +-
 arch/x86/arch.mk   |   4 +
 arch/x86/mm.c      |  31 +++++
 arch/x86/setup.c   |   4 +-
 arch/x86/x86_32.S  |  31 ++++-
 arch/x86/x86_64.S  |  35 ++++-
 arch/x86/x86_hvm.S |  88 +++++++++++++
 include/compiler.h |   1 +
 include/x86/desc.h | 367 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/x86/os.h   |   5 +
 minios.mk          |   2 +-
 11 files changed, 556 insertions(+), 14 deletions(-)
 create mode 100644 arch/x86/x86_hvm.S
 create mode 100644 include/x86/desc.h

diff --git a/Makefile b/Makefile
index 779bc91..b783684 100644
--- a/Makefile
+++ b/Makefile
@@ -24,7 +24,7 @@ include minios.mk
 LDLIBS := 
 APP_LDLIBS := 
 LDARCHLIB := -L$(OBJ_DIR)/$(TARGET_ARCH_DIR) -l$(ARCH_LIB_NAME)
-LDFLAGS_FINAL := -T $(TARGET_ARCH_DIR)/minios-$(MINIOS_TARGET_ARCH).lds
+LDFLAGS_FINAL := -T $(TARGET_ARCH_DIR)/minios-$(MINIOS_TARGET_ARCH).lds 
$(ARCH_LDFLAGS_FINAL)
 
 # Prefix for global API names. All other symbols are localised before
 # linking with EXTRA_OBJS.
diff --git a/arch/x86/arch.mk b/arch/x86/arch.mk
index 81e8118..673a19d 100644
--- a/arch/x86/arch.mk
+++ b/arch/x86/arch.mk
@@ -20,3 +20,7 @@ EXTRA_INC += $(TARGET_ARCH_FAM)/$(MINIOS_TARGET_ARCH)
 EXTRA_SRC += arch/$(EXTRA_INC)
 endif
 
+ifeq ($(CONFIG_PARAVIRT),n)
+ARCH_LDFLAGS_FINAL := --oformat=elf32-i386
+ARCH_AS_DEPS += x86_hvm.S
+endif
diff --git a/arch/x86/mm.c b/arch/x86/mm.c
index 88a928d..fe18f53 100644
--- a/arch/x86/mm.c
+++ b/arch/x86/mm.c
@@ -56,6 +56,37 @@ unsigned long mfn_zero;
 extern char stack[];
 extern void page_walk(unsigned long va);
 
+#ifndef CONFIG_PARAVIRT
+#include <mini-os/desc.h>
+user_desc gdt[NR_GDT_ENTRIES] =
+{
+    [GDTE_CS64_DPL0] = INIT_GDTE_SYM(0, 0xfffff, COMMON, CODE, DPL0, R, L),
+    [GDTE_CS32_DPL0] = INIT_GDTE_SYM(0, 0xfffff, COMMON, CODE, DPL0, R, D),
+    [GDTE_DS32_DPL0] = INIT_GDTE_SYM(0, 0xfffff, COMMON, DATA, DPL0, B, W),
+
+    [GDTE_CS64_DPL3] = INIT_GDTE_SYM(0, 0xfffff, COMMON, CODE, DPL3, R, L),
+    [GDTE_CS32_DPL3] = INIT_GDTE_SYM(0, 0xfffff, COMMON, CODE, DPL3, R, D),
+    [GDTE_DS32_DPL3] = INIT_GDTE_SYM(0, 0xfffff, COMMON, DATA, DPL3, B, W),
+
+    /* [GDTE_TSS]     */
+    /* [GDTE_TSS + 1] */
+};
+
+desc_ptr gdt_ptr =
+{
+    .limit = sizeof(gdt) - 1,
+    .base = (unsigned long)&gdt,
+};
+
+gate_desc idt[256] = { };
+
+desc_ptr idt_ptr =
+{
+    .limit = sizeof(idt) - 1,
+    .base = (unsigned long)&idt,
+};
+#endif
+
 /*
  * Make pt_pfn a new 'level' page table frame and hook it into the page
  * table at offset in previous level MFN (pref_l_mfn). pt_pfn is a guest
diff --git a/arch/x86/setup.c b/arch/x86/setup.c
index 5e87dd1..30a9143 100644
--- a/arch/x86/setup.c
+++ b/arch/x86/setup.c
@@ -94,9 +94,10 @@ static inline void sse_init(void) {
  * INITIAL C ENTRY POINT.
  */
 void
-arch_init(start_info_t *si)
+arch_init(void *par)
 {
        static char hello[] = "Bootstrapping...\n";
+       start_info_t *si;
 
        (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(hello), hello);
 
@@ -111,6 +112,7 @@ arch_init(start_info_t *si)
        /* Copy the start_info struct to a globally-accessible area. */
        /* WARN: don't do printk before here, it uses information from
           shared_info. Use xprintk instead. */
+       si = par;
        memcpy(&start_info, si, sizeof(*si));
 
        /* print out some useful information  */
diff --git a/arch/x86/x86_32.S b/arch/x86/x86_32.S
index 6dc985a..6f38708 100644
--- a/arch/x86/x86_32.S
+++ b/arch/x86/x86_32.S
@@ -1,20 +1,31 @@
 #include <mini-os/os.h>
 #include <mini-os/x86/arch_limits.h>
 #include <mini-os/asm_macros.h>
+#include <mini-os/arch_mm.h>
+#include <mini-os/desc.h>
+#include <xen/arch-x86_32.h>
 #include <xen/elfnote.h>
 #include <xen/arch-x86_32.h>
 
+#ifdef CONFIG_PARAVIRT
 ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS, .asciz "Mini-OS")
 ELFNOTE(Xen, XEN_ELFNOTE_LOADER, .asciz "generic")
 ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, _WORD hypercall_page)
 ELFNOTE(Xen, XEN_ELFNOTE_XEN_VERSION, .asciz "xen-3.0")
 ELFNOTE(Xen, XEN_ELFNOTE_PAE_MODE, .asciz "yes")
+.text
 
-.globl _start, shared_info, hypercall_page
+.globl _start
                         
 _start:
-        cld
         lss stack_start,%esp
+#else
+
+#include "x86_hvm.S"
+        movl stack_start,%esp
+
+#endif
+        cld
         andl $(~(__STACK_SIZE-1)), %esp
         push %esi 
         call arch_init
@@ -22,14 +33,15 @@ _start:
 stack_start:
        .long stack+(2*__STACK_SIZE), __KERNEL_SS
 
+.globl shared_info, hypercall_page
         /* Unpleasant -- the PTE that maps this page is actually overwritten */
         /* to map the real shared-info page! :-)                             */
-        .org 0x1000
+        .align __PAGE_SIZE
 shared_info:
-        .org 0x2000
+        .fill __PAGE_SIZE,1,0
 
 hypercall_page:
-        .org 0x3000
+        .fill __PAGE_SIZE,1,0
 
 ES             = 0x20
 ORIG_EAX       = 0x24
@@ -300,3 +312,12 @@ ENTRY(__arch_switch_threads)
     popl %ebx
     popl %ebp
     ret
+
+#ifndef CONFIG_PARAVIRT
+.data
+.globl page_table_base
+        .align __PAGE_SIZE
+page_table_base:
+        PTE(page_table_l2 + L3_PROT)
+        .align __PAGE_SIZE, 0
+#endif
diff --git a/arch/x86/x86_64.S b/arch/x86/x86_64.S
index 8ed452f..373f400 100644
--- a/arch/x86/x86_64.S
+++ b/arch/x86/x86_64.S
@@ -1,19 +1,29 @@
 #include <mini-os/os.h>
 #include <mini-os/x86/arch_limits.h>
 #include <mini-os/asm_macros.h>
+#include <mini-os/arch_mm.h>
+#include <mini-os/desc.h>
+#include <xen/features.h>
 #include <xen/elfnote.h>
 #include <xen/features.h>
 
+#define ENTRY(X) .globl X ; X :
+
+#ifdef CONFIG_PARAVIRT
 ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS, .asciz "Mini-OS")
 ELFNOTE(Xen, XEN_ELFNOTE_LOADER, .asciz "generic")
 ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, _WORD hypercall_page)
 ELFNOTE(Xen, XEN_ELFNOTE_XEN_VERSION, .asciz "xen-3.0")
+.text
 
-#define ENTRY(X) .globl X ; X :
-.globl _start, shared_info, hypercall_page
-
+.globl _start
 
 _start:
+#else
+
+#include "x86_hvm.S"
+
+#endif
         cld
         movq stack_start(%rip),%rsp
         andq $(~(__STACK_SIZE-1)), %rsp
@@ -23,14 +33,15 @@ _start:
 stack_start:
         .quad stack+(2*__STACK_SIZE)
 
+.globl shared_info, hypercall_page
         /* Unpleasant -- the PTE that maps this page is actually overwritten */
         /* to map the real shared-info page! :-)                             */
-        .org 0x1000
+        .align __PAGE_SIZE
 shared_info:
-        .org 0x2000
+        .fill __PAGE_SIZE,1,0
 
 hypercall_page:
-        .org 0x3000
+        .fill __PAGE_SIZE,1,0
 
 
 #define XEN_GET_VCPU_INFO(reg) movq HYPERVISOR_shared_info,reg
@@ -378,3 +389,15 @@ ENTRY(__arch_switch_threads)
        popq %rbx
        popq %rbp
        ret
+
+#ifndef CONFIG_PARAVIRT
+.data
+.globl page_table_base
+        .align __PAGE_SIZE
+page_table_l3:
+        PTE(page_table_l2 + L3_PROT)
+        .align __PAGE_SIZE, 0
+page_table_base:
+        PTE(page_table_l3 + L4_PROT)
+        .align __PAGE_SIZE, 0
+#endif
diff --git a/arch/x86/x86_hvm.S b/arch/x86/x86_hvm.S
new file mode 100644
index 0000000..6e8ad98
--- /dev/null
+++ b/arch/x86/x86_hvm.S
@@ -0,0 +1,88 @@
+/* Included by x86_[32|64].S */
+
+        ELFNOTE(Xen, XEN_ELFNOTE_PHYS32_ENTRY, .long _start)
+.text
+        .code32                 /* Always starts in 32bit flat mode. */
+
+.globl _start
+
+_start:
+        mov $(X86_CR4_PAE | X86_CR4_OSFXSR), %eax
+        mov %eax, %cr4
+        mov $page_table_base, %eax
+        mov %eax, %cr3
+
+#ifdef __x86_64__               /* EFER.LME = 1 */
+        mov $MSR_EFER, %ecx
+        rdmsr
+        bts $_EFER_LME, %eax
+        wrmsr
+#endif /* __x86_64__ */
+
+        mov %cr0, %eax
+        or $X86_CR0_PG, %eax
+        mov %eax, %cr0
+
+        lgdt gdt_ptr
+
+        /* Load code segment. */
+        ljmp $__KERN_CS, $1f
+#ifdef __x86_64__
+        .code64
+#endif
+
+        /* Load data segments. */
+1:
+        mov $__USER_DS, %eax
+        mov %eax, %ds
+        mov %eax, %es
+        mov %eax, %fs
+        mov %eax, %gs
+        mov $__KERN_DS, %eax
+        mov %eax, %ss
+
+        mov %ebx, %esi
+
+.data
+/*
+ * Macro to create a sequence of page table entries.
+ * As a loop can be done via recursion only and the nesting level is limited
+ * we treat the first 32 PTEs in a special way limiting nesting level to 64
+ * in case of a complete page table (512 PTEs) to be filled.
+ * prot: protection bits in all PTEs
+ * addr: physical address of the area to map
+ * incr: increment of address for each PTE
+ * idx:  index of first PTE in page table
+ * end:  index of last PTE in page table + 1
+ */
+        .macro PTES prot, addr, incr, idx, end
+        .ifgt \end-\idx-32
+        PTES \prot, \addr, \incr, \idx, "(\idx+32)"
+        PTES \prot, "(\addr+32*\incr)", \incr, "(\idx+32)", \end
+        .else
+        PTE(\addr + \prot)
+        .if \end-\idx-1
+        PTES \prot, "(\addr+\incr)", \incr, "(\idx+1)", \end
+        .endif
+        .endif
+        .endm
+        .align __PAGE_SIZE
+page_table_virt_l1:
+        PTE(0)
+        .align __PAGE_SIZE, 0
+page_table_l1:
+        PTES L1_PROT, 0x00000000, 0x00001000, 0, L1_PAGETABLE_ENTRIES
+        .align __PAGE_SIZE, 0
+page_table_l2:
+        /* Map the first 1GB of memory (on 32 bit 16MB less). */
+        PTE(page_table_l1 + L2_PROT)
+#ifdef __x86_64__
+        PTES L2_PROT|_PAGE_PSE, 0x00200000, 0x00200000, 1, L2_PAGETABLE_ENTRIES
+#else
+        /* At 3f000000 virtual kernel area is starting. */
+        PTES L2_PROT|_PAGE_PSE, 0x00200000, 0x00200000, 1, 
l2_table_offset(VIRT_KERNEL_AREA)
+        PTE(page_table_virt_l1 + L2_PROT)
+#endif
+        .align __PAGE_SIZE, 0
+
+.text
diff --git a/include/compiler.h b/include/compiler.h
index 4188277..0cbad98 100644
--- a/include/compiler.h
+++ b/include/compiler.h
@@ -6,5 +6,6 @@
 #endif
 #define unlikely(x)  __builtin_expect(!!(x),0)
 #define likely(x)    __builtin_expect(!!(x),1)
+#define __packed     __attribute__((__packed__))
 
 #endif /* __MINIOS_COMPILER_H_ */
diff --git a/include/x86/desc.h b/include/x86/desc.h
new file mode 100644
index 0000000..b9b921b
--- /dev/null
+++ b/include/x86/desc.h
@@ -0,0 +1,367 @@
+/* -*-  Mode:C; c-basic-offset:4; tab-width:4 -*-
+ *
+ * (C) 2016 - Juergen Gross, SUSE Linux GmbH
+ * based on some header files from Xen Test Framework by Andrew Cooper
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _DESC_H_
+#define _DESC_H_
+
+/*
+ * Count the number of varadic arguments provided.
+ *
+ * <pre>
+ *   VA_NARGS()     => 0
+ *   VA_NARGS(x)    => 1
+ *   VA_NARGS(x, y) => 2
+ * </pre>
+ *
+ * Currently functions for 0 to 11 arguments.
+ */
+#define VA_NARGS_(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, N, ...) N
+#define VA_NARGS(...) \
+    VA_NARGS_(X,##__VA_ARGS__, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
+
+/*
+ * Call a macro variation, based on the number of varadic arguments.
+ *
+ * @param macro Partial token to call a variation of.
+ * @param c1    Constant parameter to pass through.
+ * @param ...   Varadic arguments to pass through.
+ *
+ * Tokenises 'macro' with the count of varadic arguments, passing 'c1' and the
+ * varadic arguments.
+ *
+ * <pre>
+ *   VAR_MACRO_C1(m, c)          => m0(c)
+ *   VAR_MACRO_C1(m, c, x)       => m1(c, x)
+ *   VAR_MACRO_C1(m, c, x, y)    => m2(c, x, y)
+ *   VAR_MACRO_C1(m, c, x, y, z) => m3(c, x, y, z)
+ * </pre>
+ */
+#define VAR_MACRO_C1__(macro, c1, count, ...) macro##count(c1, ##__VA_ARGS__)
+#define VAR_MACRO_C1_(macro, c1, count, ...)        \
+    VAR_MACRO_C1__(macro, c1, count, ##__VA_ARGS__)
+#define VAR_MACRO_C1(macro, c1, ...)                                \
+    VAR_MACRO_C1_(macro, c1, VA_NARGS(__VA_ARGS__), ##__VA_ARGS__)
+
+/*
+ * GDT layout:
+ *
+ *  0 - null
+ *  1 - 64bit supervisor code
+ *  2 - 32bit supervisor code
+ *  3 - 32bit supervisor data
+ *  4 - 64bit userspace code
+ *  5 - 32bit userspace code
+ *  6 - 32bit userspace data
+ *  7 - TSS (two slots in long mode)
+ *
+ *  9-12 - Available for test use
+ */
+
+#define GDTE_CS64_DPL0 1
+#define GDTE_CS32_DPL0 2
+#define GDTE_DS32_DPL0 3
+#define GDTE_CS64_DPL3 4
+#define GDTE_CS32_DPL3 5
+#define GDTE_DS32_DPL3 6
+
+#define GDTE_TSS 7
+
+#define GDTE_AVAIL0     9
+#define GDTE_AVAIL1    10
+#define GDTE_AVAIL2    11
+#define GDTE_AVAIL3    12
+
+#define NR_GDT_ENTRIES 13
+
+#ifdef __x86_64__
+
+#define __KERN_CS (GDTE_CS64_DPL0 * 8)
+#define __KERN_DS (0)
+#define __USER_CS (GDTE_CS64_DPL3 * 8 + 3)
+#define __USER_DS (GDTE_DS32_DPL3 * 8 + 3)
+
+#else /* __x86_64__ */
+
+#define __KERN_CS (GDTE_CS32_DPL0 * 8)
+#define __KERN_DS (GDTE_DS32_DPL0 * 8)
+#define __USER_CS (GDTE_CS32_DPL3 * 8 + 3)
+#define __USER_DS (GDTE_DS32_DPL3 * 8 + 3)
+
+#endif /* __x86_64__ */
+
+#ifndef __ASSEMBLY__
+/* 8 byte user segment descriptor (GDT/LDT entries with .s = 1) */
+struct __packed seg_desc32 {
+    union {
+        /* Raw backing integers. */
+        struct {
+            uint32_t lo, hi;
+        };
+        /* Common named fields. */
+        struct {
+            uint16_t limit0;
+            uint16_t base0;
+            uint8_t  base1;
+            unsigned type: 4;
+            unsigned s: 1, dpl: 2, p: 1;
+            unsigned limit: 4;
+            unsigned avl: 1, l: 1, d: 1, g: 1;
+            uint8_t base2;
+        };
+        /* Code segment specific field names. */
+        struct {
+            uint16_t limit0;
+            uint16_t base0;
+            uint8_t  base1;
+            unsigned a: 1, r: 1, c: 1, x: 1;
+            unsigned s: 1, dpl: 2, p: 1;
+            unsigned limit: 4;
+            unsigned avl: 1, l: 1, d: 1, g: 1;
+            uint8_t base2;
+        } code;
+        /* Data segment specific field names. */
+        struct {
+            uint16_t limit0;
+            uint16_t base0;
+            uint8_t  base1;
+            unsigned a: 1, w: 1, e: 1, x: 1;
+            unsigned s: 1, dpl: 2, p: 1;
+            unsigned limit: 4;
+            unsigned avl: 1, _r0: 1, b: 1, g: 1;
+            uint8_t base2;
+        } data;
+    };
+};
+
+/* 8-byte gate - Protected mode IDT entry, GDT task/call gate. */
+struct __packed seg_gate32 {
+    union {
+        struct {
+            uint32_t lo, hi;
+        };
+        struct {
+            uint16_t offset0;
+            uint16_t selector;
+            uint8_t  _r0;
+            unsigned type: 4, s: 1, dpl: 2, p: 1;
+            uint16_t offset1;
+        };
+    };
+};
+
+/* 16-byte gate - Long mode IDT entry. */
+struct __packed seg_gate64 {
+    union {
+        struct {
+            uint64_t lo, hi;
+        };
+        struct {
+            uint16_t offset0;
+            uint16_t selector;
+            unsigned ist: 3, _r0: 5, type: 4, s: 1, dpl: 2, p: 1;
+            uint16_t offset1;
+            uint32_t offset2;
+            uint32_t _r1;
+        };
+    };
+};
+
+/* GDT/LDT attribute flags for user segments */
+
+/* Common */
+#define SEG_ATTR_G      0x8000 /* Granularity of limit (0 = 1, 1 = 4K) */
+#define SEG_ATTR_AVL    0x1000 /* Available for software use */
+#define SEG_ATTR_P      0x0080 /* Present? */
+#define SEG_ATTR_S      0x0010 /* !System desc (0 = system, 1 = user) */
+#define SEG_ATTR_A      0x0001 /* Accessed? (set by hardware) */
+
+#define SEG_ATTR_COMMON 0x8091 /* Commonly set bits (G P S A) */
+
+#define SEG_ATTR_DPL0   0x0000 /* Descriptor privilege level 0 */
+#define SEG_ATTR_DPL1   0x0020 /* Descriptor privilege level 1 */
+#define SEG_ATTR_DPL2   0x0040 /* Descriptor privilege level 2 */
+#define SEG_ATTR_DPL3   0x0060 /* Descriptor privilege level 3 */
+#define SEG_ATTR_CODE   0x0008 /* Type (0 = data, 1 = code)    */
+#define SEG_ATTR_DATA   0x0000 /* Type (0 = data, 1 = code)    */
+
+/* Code segments */
+#define SEG_ATTR_D      0x4000 /* Default operand size (0 = 16bit, 1 = 32bit) 
*/
+#define SEG_ATTR_L      0x2000 /* Long segment? (1 = 64bit) */
+#define SEG_ATTR_C      0x0004 /* Conforming? (0 = non, 1 = conforming) */
+#define SEG_ATTR_R      0x0002 /* Readable? (0 = XO seg, 1 = RX seg) */
+
+/* Data segments */
+#define SEG_ATTR_B      0x4000 /* 'Big' flag.
+                                *    - For %ss, default operand size.
+                                *    - For expand-down segment, sets upper 
bound. */
+#define SEG_ATTR_E      0x0004 /* Expand-down? (0 = normal, 1 = expand-down) */
+#define SEG_ATTR_W      0x0002 /* Writable? (0 = RO seg, 1 = RW seg) */
+
+/*
+ * Initialise an LDT/GDT entry using a raw attribute number.
+ *
+ * @param base  Segment base.
+ * @param limit Segment limit.
+ * @param attr  Segment attributes.
+ */
+#define INIT_GDTE(base, limit, attr) { { {                            \
+     .lo = (((base) & 0xffff) << 16) | ((limit) & 0xffff),            \
+     .hi = ((base) & 0xff000000) | ((limit) & 0xf0000) |              \
+           (((attr) & 0xf0ff) << 8) | (((base) & 0xff0000) >> 16)     \
+     } } }
+
+/*
+ * Tokenise and OR together.
+ *
+ * For each varadic parameter, tokenise with 't' and OR together.
+ *
+ * @param t   Common stem partial token.
+ * @param ... Partial tokens.
+ *
+ * Example:
+ * <pre>
+ *   TOK_OR(t, x, y)    => (t ## x | t ## y)
+ *   TOK_OR(t, x, y, z) => (t ## x | t ## y | t ## z)
+ * </pre>
+ */
+#define TOK_OR0(t)         (0)
+#define TOK_OR1(t, x)      (t ## x)
+#define TOK_OR2(t, x, ...) (t ## x | TOK_OR1(t, ##__VA_ARGS__))
+#define TOK_OR3(t, x, ...) (t ## x | TOK_OR2(t, ##__VA_ARGS__))
+#define TOK_OR4(t, x, ...) (t ## x | TOK_OR3(t, ##__VA_ARGS__))
+#define TOK_OR5(t, x, ...) (t ## x | TOK_OR4(t, ##__VA_ARGS__))
+#define TOK_OR6(t, x, ...) (t ## x | TOK_OR5(t, ##__VA_ARGS__))
+#define TOK_OR7(t, x, ...) (t ## x | TOK_OR6(t, ##__VA_ARGS__))
+#define TOK_OR8(t, x, ...) (t ## x | TOK_OR7(t, ##__VA_ARGS__))
+#define TOK_OR(t, ...)     VAR_MACRO_C1(TOK_OR, t, ##__VA_ARGS__)
+
+/*
+ * Initialise an LDT/GDT entry using SEG_ATTR_ mnemonics.
+ *
+ * @param base  Segment base.
+ * @param limit Segment limit.
+ * @param ...   Partial SEG_ATTR_ tokens for attributes.
+ *
+ * Example usage:
+ * - INIT_GDTE_SYM(0, 0xfffff, P)
+ *   - uses @ref SEG_ATTR_P
+ *
+ * - INIT_GDTE_SYM(0, 0xfffff, CODE, L)
+ *   - uses @ref SEG_ATTR_CODE and @ref SEG_ATTR_L
+ */
+#define INIT_GDTE_SYM(base, limit, ...) \
+    INIT_GDTE(base, limit, TOK_OR(SEG_ATTR_, ##__VA_ARGS__))
+
+/* Long mode lgdt/lidt table pointer. */
+struct __packed desc_ptr64 {
+    uint16_t limit;
+    uint64_t base;
+};
+
+/* Protected mode lgdt/lidt table pointer. */
+struct __packed desc_ptr32 {
+    uint16_t limit;
+    uint32_t base;
+};
+
+struct __packed hw_tss32 {
+    uint16_t link; uint16_t _r0;
+
+    uint32_t esp0;
+    uint16_t ss0; uint16_t _r1;
+
+    uint32_t esp1;
+    uint16_t ss1; uint16_t _r2;
+
+    uint32_t esp2;
+    uint16_t ss2; uint16_t _r3;
+
+    uint32_t cr3;
+    uint32_t eip;
+    uint32_t eflags;
+    uint32_t eax;
+    uint32_t ecx;
+    uint32_t edx;
+    uint32_t ebx;
+    uint32_t esp;
+    uint32_t ebp;
+    uint32_t esi;
+    uint32_t edi;
+
+    uint16_t es; uint16_t _r4;
+    uint16_t cs; uint16_t _r5;
+    uint16_t ss; uint16_t _r6;
+    uint16_t ds; uint16_t _r7;
+    uint16_t fs; uint16_t _r8;
+    uint16_t gs; uint16_t _r9;
+    uint16_t ldtr; uint16_t _r10;
+    uint16_t t; uint16_t iopb;
+};
+
+struct __packed hw_tss64 {
+    uint16_t link; uint16_t _r0;
+
+    uint64_t rsp0;
+    uint64_t rsp1;
+    uint64_t rsp2;
+
+    uint64_t _r1;
+
+    uint64_t ist[7]; /* 1-based structure */
+
+    uint64_t _r2;
+
+    uint16_t t;
+    uint16_t iopb;
+};
+
+#define X86_TSS_INVALID_IO_BITMAP 0x8000
+
+#if defined(__x86_64__)
+
+typedef struct desc_ptr64 desc_ptr;
+typedef struct seg_desc32 user_desc;
+typedef struct seg_gate64 gate_desc;
+typedef struct hw_tss64 hw_tss;
+
+#elif defined(__i386__)
+
+typedef struct desc_ptr32 desc_ptr;
+typedef struct seg_desc32 user_desc;
+typedef struct seg_gate32 gate_desc;
+typedef struct hw_tss32 hw_tss;
+
+#endif
+
+extern user_desc gdt[NR_GDT_ENTRIES];
+extern desc_ptr  gdt_ptr;
+
+extern gate_desc idt[256];
+extern desc_ptr  idt_ptr;
+
+extern hw_tss tss;
+
+#endif
+
+#endif /* _DESC_H_ */
diff --git a/include/x86/os.h b/include/x86/os.h
index ee9050b..eeefbe2 100644
--- a/include/x86/os.h
+++ b/include/x86/os.h
@@ -24,7 +24,12 @@
 #endif
 #include <xen/xen.h>
 
+#define MSR_EFER          0xc0000080
+#define _EFER_LME         8             /* Long mode enable */
 
+#define X86_CR0_PG        0x80000000    /* Paging */
+#define X86_CR4_PAE       0x00000020    /* enable physical address extensions 
*/
+#define X86_CR4_OSFXSR    0x00000200    /* enable fast FPU save and restore */
 
 #define __KERNEL_CS  FLAT_KERNEL_CS
 #define __KERNEL_DS  FLAT_KERNEL_DS
diff --git a/minios.mk b/minios.mk
index 1d1cc99..9ff6bf7 100644
--- a/minios.mk
+++ b/minios.mk
@@ -68,7 +68,7 @@ HEAD_OBJ := $(OBJ_DIR)/$(TARGET_ARCH_DIR)/$(HEAD_ARCH_OBJ)
 $(OBJ_DIR)/%.o: %.c $(HDRS) Makefile $(EXTRA_DEPS)
        $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
 
-$(OBJ_DIR)/%.o: %.S $(HDRS) Makefile $(EXTRA_DEPS)
+$(OBJ_DIR)/%.o: %.S $(HDRS) Makefile $(EXTRA_DEPS) $(ARCH_AS_DEPS)
        $(CC) $(ASFLAGS) $(CPPFLAGS) -c $< -o $@
 
 
-- 
2.6.6


_______________________________________________
Minios-devel mailing list
Minios-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/cgi-bin/mailman/listinfo/minios-devel

 


Rackspace

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