diff options
Diffstat (limited to 'arch/x86/cpu/i386')
| -rw-r--r-- | arch/x86/cpu/i386/call64.S | 37 | ||||
| -rw-r--r-- | arch/x86/cpu/i386/cpu.c | 41 |
2 files changed, 30 insertions, 48 deletions
diff --git a/arch/x86/cpu/i386/call64.S b/arch/x86/cpu/i386/call64.S index d81bcc6f8f4..a9d3f16a6ad 100644 --- a/arch/x86/cpu/i386/call64.S +++ b/arch/x86/cpu/i386/call64.S @@ -7,10 +7,11 @@ */ #include <asm/msr-index.h> +#include <asm/processor.h> #include <asm/processor-flags.h> .code32 -.section .text_call64 +.section .text_call64, "ax" .globl cpu_call64 cpu_call64: /* @@ -21,17 +22,19 @@ cpu_call64: * ecx - target */ cli + pushl $0 /* top 64-bits of target */ push %ecx /* arg2 = target */ push %edx /* arg1 = setup_base */ mov %eax, %ebx - /* Load new GDT with the 64bit segments using 32bit descriptor */ - leal gdt, %eax - movl %eax, gdt+2 - lgdt gdt + # disable paging + movl %cr0, %eax + andl $~X86_CR0_PG, %eax + movl %eax, %cr0 /* Enable PAE mode */ - movl $(X86_CR4_PAE), %eax + movl %cr4, %eax + orl $X86_CR4_PAE, %eax movl %eax, %cr4 /* Enable the boot page tables */ @@ -44,12 +47,6 @@ cpu_call64: btsl $_EFER_LME, %eax wrmsr - /* After gdt is loaded */ - xorl %eax, %eax - lldt %ax - movl $0x20, %eax - ltr %ax - /* * Setup for the jump to 64bit mode * @@ -62,22 +59,18 @@ cpu_call64: */ pop %esi /* setup_base */ - pushl $0x10 - leal lret_target, %eax - pushl %eax - /* Enter paged protected Mode, activating Long Mode */ - movl $(X86_CR0_PG | X86_CR0_PE), %eax + movl %cr0, %eax + orl $X86_CR0_PG, %eax movl %eax, %cr0 /* Jump from 32bit compatibility mode into 64bit mode. */ - lret + ljmp $(X86_GDT_ENTRY_64BIT_CS * X86_GDT_ENTRY_SIZE), $lret_target -code64: +.code64 lret_target: - pop %eax /* target */ - mov %eax, %eax /* Clear bits 63:32 */ - jmp *%eax /* Jump to the 64-bit target */ + pop %rax /* target */ + jmp *%rax /* Jump to the 64-bit target */ .globl call64_stub_size call64_stub_size: diff --git a/arch/x86/cpu/i386/cpu.c b/arch/x86/cpu/i386/cpu.c index a51a24498a7..ee6dbeb5c48 100644 --- a/arch/x86/cpu/i386/cpu.c +++ b/arch/x86/cpu/i386/cpu.c @@ -35,10 +35,6 @@ DECLARE_GLOBAL_DATA_PTR; -#define CPUID_FEATURE_PAE BIT(6) -#define CPUID_FEATURE_PSE36 BIT(17) -#define CPUID_FEAURE_HTT BIT(28) - /* * Constructor for a conventional segment GDT (or LDT) entry * This is a macro so it can be used in initialisers @@ -160,6 +156,9 @@ void arch_setup_gd(gd_t *new_gd) gdt_addr[X86_GDT_ENTRY_16BIT_FLAT_CS] = GDT_ENTRY(0x809b, 0, 0xfffff); gdt_addr[X86_GDT_ENTRY_16BIT_FLAT_DS] = GDT_ENTRY(0x8093, 0, 0xfffff); + gdt_addr[X86_GDT_ENTRY_64BIT_CS] = GDT_ENTRY(0xaf9b, 0, 0xfffff); + gdt_addr[X86_GDT_ENTRY_64BIT_TS1] = GDT_ENTRY(0x8980, 0, 0xfffff); + gdt_addr[X86_GDT_ENTRY_64BIT_TS2] = 0; load_gdt(gdt_addr, X86_GDT_NUM_ENTRIES); load_ds(X86_GDT_ENTRY_32BIT_DS); @@ -409,25 +408,6 @@ static void setup_identity(void) } } -static uint cpu_cpuid_extended_level(void) -{ - return cpuid_eax(0x80000000); -} - -int cpu_phys_address_size(void) -{ - if (!has_cpuid()) - return 32; - - if (cpu_cpuid_extended_level() >= 0x80000008) - return cpuid_eax(0x80000008) & 0xff; - - if (cpuid_edx(1) & (CPUID_FEATURE_PAE | CPUID_FEATURE_PSE36)) - return 36; - - return 32; -} - static void setup_mtrr(void) { u64 mtrr_cap; @@ -589,6 +569,13 @@ int cpu_has_64bit(void) #define PAGETABLE_BASE 0x80000 #define PAGETABLE_SIZE (6 * 4096) +#define _PRES BIT(0) /* present */ +#define _RW BIT(1) /* write allowed */ +#define _US BIT(2) /* user-access allowed */ +#define _A BIT(5) /* has been accessed */ +#define _DT BIT(6) /* has been written to */ +#define _PS BIT(7) /* indicates 2MB page size here */ + /** * build_pagetable() - build a flat 4GiB page table structure for 64-bti mode * @@ -601,15 +588,17 @@ static void build_pagetable(uint32_t *pgtable) memset(pgtable, '\0', PAGETABLE_SIZE); /* Level 4 needs a single entry */ - pgtable[0] = (ulong)&pgtable[1024] + 7; + pgtable[0] = (ulong)&pgtable[1024] + _PRES + _RW + _US + _A; /* Level 3 has one 64-bit entry for each GiB of memory */ for (i = 0; i < 4; i++) - pgtable[1024 + i * 2] = (ulong)&pgtable[2048] + 0x1000 * i + 7; + pgtable[1024 + i * 2] = (ulong)&pgtable[2048] + 0x1000 * i + + _PRES + _RW + _US + _A; /* Level 2 has 2048 64-bit entries, each repesenting 2MiB */ for (i = 0; i < 2048; i++) - pgtable[2048 + i * 2] = 0x183 + (i << 21UL); + pgtable[2048 + i * 2] = _PRES + _RW + _US + _PS + _A + _DT + + (i << 21UL); } int cpu_jump_to_64bit(ulong setup_base, ulong target) |
