Commit 339d617f authored by James Bottomley's avatar James Bottomley

boot with small GDT

Switch to larger operating GDT after moving to protected mode

This is necessary to boot on certain subarchs (voyager)
parent b24fc5b2
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
startup_32: startup_32:
cld cld
cli cli
movl $(__KERNEL_DS),%eax movl $(__BOOT_DS),%eax
movl %eax,%ds movl %eax,%ds
movl %eax,%es movl %eax,%es
movl %eax,%fs movl %eax,%fs
...@@ -74,7 +74,7 @@ startup_32: ...@@ -74,7 +74,7 @@ startup_32:
popl %esi # discard address popl %esi # discard address
popl %esi # real mode pointer popl %esi # real mode pointer
xorl %ebx,%ebx xorl %ebx,%ebx
ljmp $(__KERNEL_CS), $0x100000 ljmp $(__BOOT_CS), $0x100000
/* /*
* We come here, if we were loaded high. * We come here, if we were loaded high.
...@@ -101,7 +101,7 @@ startup_32: ...@@ -101,7 +101,7 @@ startup_32:
popl %eax # hcount popl %eax # hcount
movl $0x100000,%edi movl $0x100000,%edi
cli # make sure we don't get interrupted cli # make sure we don't get interrupted
ljmp $(__KERNEL_CS), $0x1000 # and jump to the move routine ljmp $(__BOOT_CS), $0x1000 # and jump to the move routine
/* /*
* Routine (template) for moving the decompressed kernel in place, * Routine (template) for moving the decompressed kernel in place,
...@@ -124,5 +124,5 @@ move_routine_start: ...@@ -124,5 +124,5 @@ move_routine_start:
movsl movsl
movl %ebx,%esi # Restore setup pointer movl %ebx,%esi # Restore setup pointer
xorl %ebx,%ebx xorl %ebx,%ebx
ljmp $(__KERNEL_CS), $0x100000 ljmp $(__BOOT_CS), $0x100000
move_routine_end: move_routine_end:
...@@ -299,7 +299,7 @@ long user_stack [STACK_SIZE]; ...@@ -299,7 +299,7 @@ long user_stack [STACK_SIZE];
struct { struct {
long * a; long * a;
short b; short b;
} stack_start = { & user_stack [STACK_SIZE] , __KERNEL_DS }; } stack_start = { & user_stack [STACK_SIZE] , __BOOT_DS };
static void setup_normal_output_buffer(void) static void setup_normal_output_buffer(void)
{ {
......
...@@ -894,7 +894,7 @@ flush_instr: ...@@ -894,7 +894,7 @@ flush_instr:
subw $DELTA_INITSEG, %si subw $DELTA_INITSEG, %si
shll $4, %esi # Convert to 32-bit pointer shll $4, %esi # Convert to 32-bit pointer
# NOTE: For high loaded big kernels we need a # NOTE: For high loaded big kernels we need a
# jmpi 0x100000,__KERNEL_CS # jmpi 0x100000,__BOOT_CS
# #
# but we yet haven't reloaded the CS register, so the default size # but we yet haven't reloaded the CS register, so the default size
# of the target offset still is 16 bit. # of the target offset still is 16 bit.
...@@ -905,7 +905,7 @@ flush_instr: ...@@ -905,7 +905,7 @@ flush_instr:
.byte 0x66, 0xea # prefix + jmpi-opcode .byte 0x66, 0xea # prefix + jmpi-opcode
code32: .long 0x1000 # will be set to 0x100000 code32: .long 0x1000 # will be set to 0x100000
# for big kernels # for big kernels
.word __KERNEL_CS .word __BOOT_CS
# Here's a bunch of information about your current kernel.. # Here's a bunch of information about your current kernel..
kernel_version: .ascii UTS_RELEASE kernel_version: .ascii UTS_RELEASE
...@@ -1102,13 +1102,19 @@ delay: ...@@ -1102,13 +1102,19 @@ delay:
# Descriptor tables # Descriptor tables
# #
# NOTE: if you think the GDT is large, you can make it smaller by just # NOTE: The intel manual says gdt should be sixteen bytes aligned for
# defining the KERNEL_CS and KERNEL_DS entries and shifting the gdt # efficiency reasons. However, there are machines which are known not
# address down by GDT_ENTRY_KERNEL_CS*8. This puts bogus entries into # to boot with misaligned GDTs, so alter this at your peril! If you alter
# the GDT, but those wont be used so it's not a problem. # GDT_ENTRY_BOOT_CS (in asm/segment.h) remember to leave at least two
# empty GDT entries (one for NULL and one reserved).
# #
# NOTE: On some CPUs, the GDT must be 8 byte aligned. This is
# true for the Voyager Quad CPU card which will not boot without
# This directive. 16 byte aligment is recommended by intel.
#
.align 16
gdt: gdt:
.fill GDT_ENTRY_KERNEL_CS,8,0 .fill GDT_ENTRY_BOOT_CS,8,0
.word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb) .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb)
.word 0 # base address = 0 .word 0 # base address = 0
...@@ -1121,12 +1127,17 @@ gdt: ...@@ -1121,12 +1127,17 @@ gdt:
.word 0x9200 # data read/write .word 0x9200 # data read/write
.word 0x00CF # granularity = 4096, 386 .word 0x00CF # granularity = 4096, 386
# (+5th nibble of limit) # (+5th nibble of limit)
gdt_end:
.align 4
.word 0 # alignment byte
idt_48: idt_48:
.word 0 # idt limit = 0 .word 0 # idt limit = 0
.word 0, 0 # idt base = 0L .word 0, 0 # idt base = 0L
gdt_48:
.word GDT_ENTRY_KERNEL_CS*8 + 16 - 1 # gdt limit
.word 0 # alignment byte
gdt_48:
.word gdt_end - gdt - 1 # gdt limit
.word 0, 0 # gdt base (filled in later) .word 0, 0 # gdt base (filled in later)
# Include video setup & detection code # Include video setup & detection code
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <asm/page.h> #include <asm/page.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/desc.h> #include <asm/desc.h>
#include <asm/cache.h>
#define OLD_CL_MAGIC_ADDR 0x90020 #define OLD_CL_MAGIC_ADDR 0x90020
#define OLD_CL_MAGIC 0xA33F #define OLD_CL_MAGIC 0xA33F
...@@ -46,7 +47,7 @@ startup_32: ...@@ -46,7 +47,7 @@ startup_32:
* Set segments to known values * Set segments to known values
*/ */
cld cld
movl $(__KERNEL_DS),%eax movl $(__BOOT_DS),%eax
movl %eax,%ds movl %eax,%ds
movl %eax,%es movl %eax,%es
movl %eax,%fs movl %eax,%fs
...@@ -309,7 +310,7 @@ rp_sidt: ...@@ -309,7 +310,7 @@ rp_sidt:
ENTRY(stack_start) ENTRY(stack_start)
.long init_thread_union+8192 .long init_thread_union+8192
.long __KERNEL_DS .long __BOOT_DS
/* This is the default interrupt "handler" :-) */ /* This is the default interrupt "handler" :-) */
int_msg: int_msg:
...@@ -352,12 +353,12 @@ idt_descr: ...@@ -352,12 +353,12 @@ idt_descr:
.long idt_table .long idt_table
# boot GDT descriptor (later on used by CPU#0): # boot GDT descriptor (later on used by CPU#0):
.word 0 # 32 bit align gdt_desc.address
cpu_gdt_descr: cpu_gdt_descr:
.word GDT_ENTRIES*8-1 .word GDT_ENTRIES*8-1
.long cpu_gdt_table .long cpu_gdt_table
.fill NR_CPUS-1,6,0 # space for the other GDT descriptors .fill NR_CPUS-1,8,0 # space for the other GDT descriptors
/* /*
* This is initialized to create an identity-mapping at 0-8M (for bootup * This is initialized to create an identity-mapping at 0-8M (for bootup
...@@ -408,10 +409,21 @@ ENTRY(_stext) ...@@ -408,10 +409,21 @@ ENTRY(_stext)
*/ */
.data .data
ALIGN
/* /*
* The Global Descriptor Table contains 28 quadwords, per-CPU. * The Global Descriptor Table contains 28 quadwords, per-CPU.
*/ */
#ifdef CONFIG_SMP
/*
* The boot_gdt_table must mirror the equivalent in setup.S and is
* used only by the trampoline for booting other CPUs
*/
.align L1_CACHE_BYTES
ENTRY(boot_gdt_table)
.fill GDT_ENTRY_BOOT_CS,8,0
.quad 0x00cf9a000000ffff /* kernel 4GB code at 0x00000000 */
.quad 0x00cf92000000ffff /* kernel 4GB data at 0x00000000 */
#endif
.align L1_CACHE_BYTES
ENTRY(cpu_gdt_table) ENTRY(cpu_gdt_table)
.quad 0x0000000000000000 /* NULL descriptor */ .quad 0x0000000000000000 /* NULL descriptor */
.quad 0x0000000000000000 /* 0x0b reserved */ .quad 0x0000000000000000 /* 0x0b reserved */
......
...@@ -54,7 +54,7 @@ r_base = . ...@@ -54,7 +54,7 @@ r_base = .
lmsw %ax # into protected mode lmsw %ax # into protected mode
jmp flush_instr jmp flush_instr
flush_instr: flush_instr:
ljmpl $__KERNEL_CS, $0x00100000 ljmpl $__BOOT_CS, $0x00100000
# jump to startup_32 in arch/i386/kernel/head.S # jump to startup_32 in arch/i386/kernel/head.S
idt_48: idt_48:
...@@ -67,8 +67,8 @@ idt_48: ...@@ -67,8 +67,8 @@ idt_48:
# #
gdt_48: gdt_48:
.word 0x0800 # gdt limit = 2048, 256 GDT entries .word __BOOT_DS + 7 # gdt limit
.long cpu_gdt_table-__PAGE_OFFSET # gdt base = gdt (first SMP CPU) .long boot_gdt_table-__PAGE_OFFSET # gdt base = gdt (first SMP CPU)
.globl trampoline_end .globl trampoline_end
trampoline_end: trampoline_end:
...@@ -16,6 +16,7 @@ extern struct desc_struct cpu_gdt_table[NR_CPUS][GDT_ENTRIES]; ...@@ -16,6 +16,7 @@ extern struct desc_struct cpu_gdt_table[NR_CPUS][GDT_ENTRIES];
struct Xgt_desc_struct { struct Xgt_desc_struct {
unsigned short size; unsigned short size;
unsigned long address __attribute__((packed)); unsigned long address __attribute__((packed));
unsigned short pad;
} __attribute__ ((packed)); } __attribute__ ((packed));
extern struct Xgt_desc_struct idt_descr, cpu_gdt_descr[NR_CPUS]; extern struct Xgt_desc_struct idt_descr, cpu_gdt_descr[NR_CPUS];
......
...@@ -71,6 +71,14 @@ ...@@ -71,6 +71,14 @@
#define GDT_SIZE (GDT_ENTRIES * 8) #define GDT_SIZE (GDT_ENTRIES * 8)
/* Simple and small GDT entries for booting only */
#define GDT_ENTRY_BOOT_CS 2
#define __BOOT_CS (GDT_ENTRY_BOOT_CS * 8)
#define GDT_ENTRY_BOOT_DS (GDT_ENTRY_BOOT_CS + 1)
#define __BOOT_DS (GDT_ENTRY_BOOT_DS * 8)
/* /*
* The interrupt descriptor table has room for 256 idt's, * The interrupt descriptor table has room for 256 idt's,
* the global descriptor table is dependent on the number * the global descriptor table is dependent on the number
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment