mirror of
https://github.com/rd-stuffs/msm-4.14.git
synced 2025-02-20 11:45:48 +08:00
x86, realmode: read cr4 and EFER from kernel for 64-bit trampoline
This patch changes 64-bit trampoline so that CR4 and EFER are provided by the kernel instead of using fixed values. Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@intel.com> Link: http://lkml.kernel.org/r/1336501366-28617-24-git-send-email-jarkko.sakkinen@intel.com Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
This commit is contained in:
parent
bf8b88e977
commit
cda846f101
@ -544,13 +544,16 @@ static inline void load_sp0(struct tss_struct *tss,
|
|||||||
* enable), so that any CPU's that boot up
|
* enable), so that any CPU's that boot up
|
||||||
* after us can get the correct flags.
|
* after us can get the correct flags.
|
||||||
*/
|
*/
|
||||||
extern unsigned long mmu_cr4_features;
|
extern unsigned long mmu_cr4_features;
|
||||||
|
extern u32 *trampoline_cr4_features;
|
||||||
|
|
||||||
static inline void set_in_cr4(unsigned long mask)
|
static inline void set_in_cr4(unsigned long mask)
|
||||||
{
|
{
|
||||||
unsigned long cr4;
|
unsigned long cr4;
|
||||||
|
|
||||||
mmu_cr4_features |= mask;
|
mmu_cr4_features |= mask;
|
||||||
|
if (trampoline_cr4_features)
|
||||||
|
*trampoline_cr4_features = mmu_cr4_features;
|
||||||
cr4 = read_cr4();
|
cr4 = read_cr4();
|
||||||
cr4 |= mask;
|
cr4 |= mask;
|
||||||
write_cr4(cr4);
|
write_cr4(cr4);
|
||||||
@ -561,6 +564,8 @@ static inline void clear_in_cr4(unsigned long mask)
|
|||||||
unsigned long cr4;
|
unsigned long cr4;
|
||||||
|
|
||||||
mmu_cr4_features &= ~mask;
|
mmu_cr4_features &= ~mask;
|
||||||
|
if (trampoline_cr4_features)
|
||||||
|
*trampoline_cr4_features = mmu_cr4_features;
|
||||||
cr4 = read_cr4();
|
cr4 = read_cr4();
|
||||||
cr4 &= ~mask;
|
cr4 &= ~mask;
|
||||||
write_cr4(cr4);
|
write_cr4(cr4);
|
||||||
|
@ -24,18 +24,22 @@ struct real_mode_header {
|
|||||||
#ifdef CONFIG_X86_32
|
#ifdef CONFIG_X86_32
|
||||||
u32 machine_real_restart_asm;
|
u32 machine_real_restart_asm;
|
||||||
#endif
|
#endif
|
||||||
} __attribute__((__packed__));
|
};
|
||||||
|
|
||||||
/* This must match data at trampoline_32/64.S */
|
/* This must match data at trampoline_32/64.S */
|
||||||
struct trampoline_header {
|
struct trampoline_header {
|
||||||
#ifdef CONFIG_X86_32
|
#ifdef CONFIG_X86_32
|
||||||
u32 start;
|
u32 start;
|
||||||
|
u16 gdt_pad;
|
||||||
u16 gdt_limit;
|
u16 gdt_limit;
|
||||||
u32 gdt_base;
|
u32 gdt_base;
|
||||||
#else
|
#else
|
||||||
u64 start;
|
u64 start;
|
||||||
|
u32 cr4;
|
||||||
|
u32 efer_low;
|
||||||
|
u32 efer_high;
|
||||||
#endif
|
#endif
|
||||||
} __attribute__((__packed__));
|
};
|
||||||
|
|
||||||
extern struct real_mode_header *real_mode_header;
|
extern struct real_mode_header *real_mode_header;
|
||||||
extern unsigned char real_mode_blob_end[];
|
extern unsigned char real_mode_blob_end[];
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include <asm/realmode.h>
|
#include <asm/realmode.h>
|
||||||
|
|
||||||
struct real_mode_header *real_mode_header;
|
struct real_mode_header *real_mode_header;
|
||||||
|
u32 *trampoline_cr4_features;
|
||||||
|
|
||||||
void __init setup_real_mode(void)
|
void __init setup_real_mode(void)
|
||||||
{
|
{
|
||||||
@ -64,7 +65,14 @@ void __init setup_real_mode(void)
|
|||||||
trampoline_header->gdt_limit = __BOOT_DS + 7;
|
trampoline_header->gdt_limit = __BOOT_DS + 7;
|
||||||
trampoline_header->gdt_base = __pa(boot_gdt);
|
trampoline_header->gdt_base = __pa(boot_gdt);
|
||||||
#else
|
#else
|
||||||
|
if (rdmsr_safe(MSR_EFER, &trampoline_header->efer_low,
|
||||||
|
&trampoline_header->efer_high))
|
||||||
|
BUG();
|
||||||
|
|
||||||
trampoline_header->start = (u64) secondary_startup_64;
|
trampoline_header->start = (u64) secondary_startup_64;
|
||||||
|
trampoline_cr4_features = &trampoline_header->cr4;
|
||||||
|
*trampoline_cr4_features = read_cr4();
|
||||||
|
|
||||||
trampoline_pgd = (u64 *) __va(real_mode_header->trampoline_pgd);
|
trampoline_pgd = (u64 *) __va(real_mode_header->trampoline_pgd);
|
||||||
trampoline_pgd[0] = __pa(level3_ident_pgt) + _KERNPG_TABLE;
|
trampoline_pgd[0] = __pa(level3_ident_pgt) + _KERNPG_TABLE;
|
||||||
trampoline_pgd[511] = __pa(level3_kernel_pgt) + _KERNPG_TABLE;
|
trampoline_pgd[511] = __pa(level3_kernel_pgt) + _KERNPG_TABLE;
|
||||||
|
@ -975,6 +975,8 @@ void __init setup_arch(char **cmdline_p)
|
|||||||
if (boot_cpu_data.cpuid_level >= 0) {
|
if (boot_cpu_data.cpuid_level >= 0) {
|
||||||
/* A CPU has %cr4 if and only if it has CPUID */
|
/* A CPU has %cr4 if and only if it has CPUID */
|
||||||
mmu_cr4_features = read_cr4();
|
mmu_cr4_features = read_cr4();
|
||||||
|
if (trampoline_cr4_features)
|
||||||
|
*trampoline_cr4_features = mmu_cr4_features;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_X86_32
|
#ifdef CONFIG_X86_32
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
.section ".header", "a"
|
.section ".header", "a"
|
||||||
|
|
||||||
|
.balign 16
|
||||||
GLOBAL(real_mode_header)
|
GLOBAL(real_mode_header)
|
||||||
.long pa_text_start
|
.long pa_text_start
|
||||||
.long pa_ro_end
|
.long pa_ro_end
|
||||||
|
@ -34,9 +34,9 @@
|
|||||||
#include "realmode.h"
|
#include "realmode.h"
|
||||||
|
|
||||||
.text
|
.text
|
||||||
.balign PAGE_SIZE
|
|
||||||
.code16
|
.code16
|
||||||
|
|
||||||
|
.balign PAGE_SIZE
|
||||||
ENTRY(trampoline_start)
|
ENTRY(trampoline_start)
|
||||||
cli # We should be safe anyway
|
cli # We should be safe anyway
|
||||||
wbinvd
|
wbinvd
|
||||||
@ -65,8 +65,8 @@ ENTRY(trampoline_start)
|
|||||||
* to 32 bit.
|
* to 32 bit.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
lidtl tidt # load idt with 0, 0
|
lidtl tr_idt # load idt with 0, 0
|
||||||
lgdtl tgdt # load gdt with whatever is appropriate
|
lgdtl tr_gdt # load gdt with whatever is appropriate
|
||||||
|
|
||||||
movw $__KERNEL_DS, %dx # Data segment descriptor
|
movw $__KERNEL_DS, %dx # Data segment descriptor
|
||||||
|
|
||||||
@ -93,16 +93,17 @@ ENTRY(startup_32)
|
|||||||
movl %edx, %fs
|
movl %edx, %fs
|
||||||
movl %edx, %gs
|
movl %edx, %gs
|
||||||
|
|
||||||
movl $X86_CR4_PAE, %eax
|
movl pa_tr_cr4, %eax
|
||||||
movl %eax, %cr4 # Enable PAE mode
|
movl %eax, %cr4 # Enable PAE mode
|
||||||
|
|
||||||
# Setup trampoline 4 level pagetables
|
# Setup trampoline 4 level pagetables
|
||||||
movl $pa_trampoline_pgd, %eax
|
movl $pa_trampoline_pgd, %eax
|
||||||
movl %eax, %cr3
|
movl %eax, %cr3
|
||||||
|
|
||||||
|
# Set up EFER
|
||||||
|
movl pa_tr_efer, %eax
|
||||||
|
movl pa_tr_efer + 4, %edx
|
||||||
movl $MSR_EFER, %ecx
|
movl $MSR_EFER, %ecx
|
||||||
movl $((1 << _EFER_LME) | (1 << _EFER_NX)), %eax # Enable Long Mode
|
|
||||||
xorl %edx, %edx
|
|
||||||
wrmsr
|
wrmsr
|
||||||
|
|
||||||
# Enable paging and in turn activate Long Mode
|
# Enable paging and in turn activate Long Mode
|
||||||
@ -124,23 +125,4 @@ ENTRY(startup_64)
|
|||||||
# Now jump into the kernel using virtual addresses
|
# Now jump into the kernel using virtual addresses
|
||||||
jmpq *tr_start(%rip)
|
jmpq *tr_start(%rip)
|
||||||
|
|
||||||
.section ".rodata","a"
|
|
||||||
.balign 16
|
|
||||||
tidt:
|
|
||||||
.word 0 # idt limit = 0
|
|
||||||
.word 0, 0 # idt base = 0L
|
|
||||||
|
|
||||||
# Duplicate the global descriptor table
|
|
||||||
# so the kernel can live anywhere
|
|
||||||
.balign 16
|
|
||||||
.globl tgdt
|
|
||||||
tgdt:
|
|
||||||
.short tgdt_end - tgdt - 1 # gdt limit
|
|
||||||
.long pa_tgdt
|
|
||||||
.short 0
|
|
||||||
.quad 0x00cf9b000000ffff # __KERNEL32_CS
|
|
||||||
.quad 0x00af9b000000ffff # __KERNEL_CS
|
|
||||||
.quad 0x00cf93000000ffff # __KERNEL_DS
|
|
||||||
tgdt_end:
|
|
||||||
|
|
||||||
#include "trampoline_common.S"
|
#include "trampoline_common.S"
|
||||||
|
@ -1,5 +1,20 @@
|
|||||||
.section ".rodata","a"
|
.section ".rodata","a"
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_64
|
||||||
|
# Duplicate the global descriptor table
|
||||||
|
# so the kernel can live anywhere
|
||||||
|
.balign 16
|
||||||
|
.globl tr_gdt
|
||||||
|
tr_gdt:
|
||||||
|
.short tr_gdt_end - tr_gdt - 1 # gdt limit
|
||||||
|
.long pa_tr_gdt
|
||||||
|
.short 0
|
||||||
|
.quad 0x00cf9b000000ffff # __KERNEL32_CS
|
||||||
|
.quad 0x00af9b000000ffff # __KERNEL_CS
|
||||||
|
.quad 0x00cf93000000ffff # __KERNEL_DS
|
||||||
|
tr_gdt_end:
|
||||||
|
#endif
|
||||||
|
|
||||||
.balign 4
|
.balign 4
|
||||||
tr_idt: .fill 1, 6, 0
|
tr_idt: .fill 1, 6, 0
|
||||||
|
|
||||||
@ -8,12 +23,16 @@ tr_idt: .fill 1, 6, 0
|
|||||||
.balign 4
|
.balign 4
|
||||||
GLOBAL(trampoline_status) .space 4
|
GLOBAL(trampoline_status) .space 4
|
||||||
|
|
||||||
|
.balign 8
|
||||||
GLOBAL(trampoline_header)
|
GLOBAL(trampoline_header)
|
||||||
#ifdef CONFIG_X86_32
|
#ifdef CONFIG_X86_32
|
||||||
tr_start: .space 4
|
tr_start: .space 4
|
||||||
|
tr_gdt_pad: .space 2
|
||||||
tr_gdt: .space 6
|
tr_gdt: .space 6
|
||||||
#else
|
#else
|
||||||
tr_start: .space 8
|
tr_start: .space 8
|
||||||
|
GLOBAL(tr_cr4) .space 4
|
||||||
|
GLOBAL(tr_efer) .space 8
|
||||||
#endif
|
#endif
|
||||||
END(trampoline_header)
|
END(trampoline_header)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user