Skip to content
Snippets Groups Projects
Commit 731a7378 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'x86-trampoline-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 trampoline rework from H. Peter Anvin:
 "This code reworks all the "trampoline"/"realmode" code (various bits
  that need to live in the first megabyte of memory, most but not all of
  which runs in real mode at some point) in the kernel into a single
  object.  The main reason for doing this is that it eliminates the last
  place in the kernel where we needed pages to be mapped RWX.  This code
  separates all that code into proper R/RW/RX pages."

Fix up conflicts in arch/x86/kernel/Makefile (mca removed next to reboot
code), and arch/x86/kernel/reboot.c (reboot code moved around in one
branch, modified in this one), and arch/x86/tools/relocs.c (mostly same
code came in earlier due to working around the ld bugs just before the
3.4 release).

Also remove stale x86-relocs entry from scripts/.gitignore as per Peter
Anvin.

* commit '61f54461': (36 commits)
  x86, realmode: Move end signature into header.S
  x86, relocs: When printing an error, say relative or absolute
  x86, relocs: More relocations which may end up as absolute
  x86, relocs: Workaround for binutils 2.22.52.0.1 section bug
  xen-acpi-processor: Add missing #include <xen/xen.h>
  acpi, bgrd: Add missing <linux/io.h> to drivers/acpi/bgrt.c
  x86, realmode: Change EFER to a single u64 field
  x86, realmode: Move kernel/realmode.c to realmode/init.c
  x86, realmode: Move not-common bits out of trampoline_common.S
  x86, realmode: Mask out EFER.LMA when saving trampoline EFER
  x86, realmode: Fix no cache bits test in reboot_32.S
  x86, realmode: Make sure all generated files are listed in targets
  x86, realmode: build fix: remove duplicate build
  x86, realmode: read cr4 and EFER from kernel for 64-bit trampoline
  x86, realmode: fixes compilation issue in tboot.c
  x86, realmode: move relocs from scripts/ to arch/x86/tools
  x86, realmode: header for trampoline code
  x86, realmode: flattened rm hierachy
  x86, realmode: don't copy real_mode_header
  x86, realmode: fix 64-bit wakeup sequence
  ...
parents 87a5af24 61f54461
No related branches found
No related tags found
No related merge requests found
Showing
with 76 additions and 99 deletions
obj-$(CONFIG_KVM) += kvm/ obj-$(CONFIG_KVM) += kvm/
# Xen paravirtualization support # Xen paravirtualization support
...@@ -7,6 +6,7 @@ obj-$(CONFIG_XEN) += xen/ ...@@ -7,6 +6,7 @@ obj-$(CONFIG_XEN) += xen/
# lguest paravirtualization support # lguest paravirtualization support
obj-$(CONFIG_LGUEST_GUEST) += lguest/ obj-$(CONFIG_LGUEST_GUEST) += lguest/
obj-y += realmode/
obj-y += kernel/ obj-y += kernel/
obj-y += mm/ obj-y += mm/
......
...@@ -29,7 +29,6 @@ ...@@ -29,7 +29,6 @@
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/mmu.h> #include <asm/mmu.h>
#include <asm/mpspec.h> #include <asm/mpspec.h>
#include <asm/trampoline.h>
#define COMPILER_DEPENDENT_INT64 long long #define COMPILER_DEPENDENT_INT64 long long
#define COMPILER_DEPENDENT_UINT64 unsigned long long #define COMPILER_DEPENDENT_UINT64 unsigned long long
...@@ -118,7 +117,6 @@ static inline void acpi_disable_pci(void) ...@@ -118,7 +117,6 @@ static inline void acpi_disable_pci(void)
extern int acpi_suspend_lowlevel(void); extern int acpi_suspend_lowlevel(void);
extern const unsigned char acpi_wakeup_code[]; extern const unsigned char acpi_wakeup_code[];
#define acpi_wakeup_address (__pa(TRAMPOLINE_SYM(acpi_wakeup_code)))
/* early initialization routine */ /* early initialization routine */
extern void acpi_reserve_wakeup_memory(void); extern void acpi_reserve_wakeup_memory(void);
......
...@@ -544,13 +544,16 @@ static inline void load_sp0(struct tss_struct *tss, ...@@ -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) ...@@ -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);
......
#ifndef _ARCH_X86_REALMODE_H
#define _ARCH_X86_REALMODE_H
#include <linux/types.h>
#include <asm/io.h>
/* This must match data at realmode.S */
struct real_mode_header {
u32 text_start;
u32 ro_end;
/* SMP trampoline */
u32 trampoline_start;
u32 trampoline_status;
u32 trampoline_header;
#ifdef CONFIG_X86_64
u32 trampoline_pgd;
#endif
/* ACPI S3 wakeup */
#ifdef CONFIG_ACPI_SLEEP
u32 wakeup_start;
u32 wakeup_header;
#endif
/* APM/BIOS reboot */
#ifdef CONFIG_X86_32
u32 machine_real_restart_asm;
#endif
};
/* This must match data at trampoline_32/64.S */
struct trampoline_header {
#ifdef CONFIG_X86_32
u32 start;
u16 gdt_pad;
u16 gdt_limit;
u32 gdt_base;
#else
u64 start;
u64 efer;
u32 cr4;
#endif
};
extern struct real_mode_header *real_mode_header;
extern unsigned char real_mode_blob_end[];
extern unsigned long init_rsp;
extern unsigned long initial_code;
extern unsigned long initial_gs;
extern unsigned char real_mode_blob[];
extern unsigned char real_mode_relocs[];
#ifdef CONFIG_X86_32
extern unsigned char startup_32_smp[];
extern unsigned char boot_gdt[];
#else
extern unsigned char secondary_startup_64[];
#endif
extern void __init setup_real_mode(void);
#endif /* _ARCH_X86_REALMODE_H */
#ifndef _ASM_X86_TRAMPOLINE_H
#define _ASM_X86_TRAMPOLINE_H
#ifndef __ASSEMBLY__
#include <linux/types.h>
#include <asm/io.h>
/*
* Trampoline 80x86 program as an array. These are in the init rodata
* segment, but that's okay, because we only care about the relative
* addresses of the symbols.
*/
extern const unsigned char x86_trampoline_start [];
extern const unsigned char x86_trampoline_end [];
extern unsigned char *x86_trampoline_base;
extern unsigned long init_rsp;
extern unsigned long initial_code;
extern unsigned long initial_gs;
extern void __init setup_trampolines(void);
extern const unsigned char trampoline_data[];
extern const unsigned char trampoline_status[];
#define TRAMPOLINE_SYM(x) \
((void *)(x86_trampoline_base + \
((const unsigned char *)(x) - x86_trampoline_start)))
/* Address of the SMP trampoline */
static inline unsigned long trampoline_address(void)
{
return virt_to_phys(TRAMPOLINE_SYM(trampoline_data));
}
#endif /* __ASSEMBLY__ */
#endif /* _ASM_X86_TRAMPOLINE_H */
...@@ -35,7 +35,6 @@ obj-y += tsc.o io_delay.o rtc.o ...@@ -35,7 +35,6 @@ obj-y += tsc.o io_delay.o rtc.o
obj-y += pci-iommu_table.o obj-y += pci-iommu_table.o
obj-y += resource.o obj-y += resource.o
obj-y += trampoline.o trampoline_$(BITS).o
obj-y += process.o obj-y += process.o
obj-y += i387.o xsave.o obj-y += i387.o xsave.o
obj-y += ptrace.o obj-y += ptrace.o
...@@ -48,7 +47,6 @@ obj-$(CONFIG_STACKTRACE) += stacktrace.o ...@@ -48,7 +47,6 @@ obj-$(CONFIG_STACKTRACE) += stacktrace.o
obj-y += cpu/ obj-y += cpu/
obj-y += acpi/ obj-y += acpi/
obj-y += reboot.o obj-y += reboot.o
obj-$(CONFIG_X86_32) += reboot_32.o
obj-$(CONFIG_X86_MSR) += msr.o obj-$(CONFIG_X86_MSR) += msr.o
obj-$(CONFIG_X86_CPUID) += cpuid.o obj-$(CONFIG_X86_CPUID) += cpuid.o
obj-$(CONFIG_PCI) += early-quirks.o obj-$(CONFIG_PCI) += early-quirks.o
......
subdir- := realmode
obj-$(CONFIG_ACPI) += boot.o obj-$(CONFIG_ACPI) += boot.o
obj-$(CONFIG_ACPI_SLEEP) += sleep.o wakeup_rm.o wakeup_$(BITS).o obj-$(CONFIG_ACPI_SLEEP) += sleep.o wakeup_$(BITS).o
ifneq ($(CONFIG_ACPI_PROCESSOR),) ifneq ($(CONFIG_ACPI_PROCESSOR),)
obj-y += cstate.o obj-y += cstate.o
endif endif
$(obj)/wakeup_rm.o: $(obj)/realmode/wakeup.bin
$(obj)/realmode/wakeup.bin: FORCE
$(Q)$(MAKE) $(build)=$(obj)/realmode
wakeup.bin
wakeup.elf
wakeup.lds
#include "../../../boot/bioscall.S"
#include "../../../boot/copy.S"
#include "../../../boot/regs.c"
#include "../../../boot/video-bios.c"
#include "../../../boot/video-mode.c"
#include "../../../boot/video-vesa.c"
#include "../../../boot/video-vga.c"
...@@ -14,8 +14,9 @@ ...@@ -14,8 +14,9 @@
#include <asm/desc.h> #include <asm/desc.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/realmode.h>
#include "realmode/wakeup.h" #include "../../realmode/rm/wakeup.h"
#include "sleep.h" #include "sleep.h"
unsigned long acpi_realmode_flags; unsigned long acpi_realmode_flags;
...@@ -36,13 +37,9 @@ asmlinkage void acpi_enter_s3(void) ...@@ -36,13 +37,9 @@ asmlinkage void acpi_enter_s3(void)
*/ */
int acpi_suspend_lowlevel(void) int acpi_suspend_lowlevel(void)
{ {
struct wakeup_header *header; struct wakeup_header *header =
/* address in low memory of the wakeup routine. */ (struct wakeup_header *) __va(real_mode_header->wakeup_header);
char *acpi_realmode;
acpi_realmode = TRAMPOLINE_SYM(acpi_wakeup_code);
header = (struct wakeup_header *)(acpi_realmode + WAKEUP_HEADER_OFFSET);
if (header->signature != WAKEUP_HEADER_SIGNATURE) { if (header->signature != WAKEUP_HEADER_SIGNATURE) {
printk(KERN_ERR "wakeup header does not match\n"); printk(KERN_ERR "wakeup header does not match\n");
return -EINVAL; return -EINVAL;
...@@ -50,27 +47,6 @@ int acpi_suspend_lowlevel(void) ...@@ -50,27 +47,6 @@ int acpi_suspend_lowlevel(void)
header->video_mode = saved_video_mode; header->video_mode = saved_video_mode;
header->wakeup_jmp_seg = acpi_wakeup_address >> 4;
/*
* Set up the wakeup GDT. We set these up as Big Real Mode,
* that is, with limits set to 4 GB. At least the Lenovo
* Thinkpad X61 is known to need this for the video BIOS
* initialization quirk to work; this is likely to also
* be the case for other laptops or integrated video devices.
*/
/* GDT[0]: GDT self-pointer */
header->wakeup_gdt[0] =
(u64)(sizeof(header->wakeup_gdt) - 1) +
((u64)__pa(&header->wakeup_gdt) << 16);
/* GDT[1]: big real mode-like code segment */
header->wakeup_gdt[1] =
GDT_ENTRY(0x809b, acpi_wakeup_address, 0xfffff);
/* GDT[2]: big real mode-like data segment */
header->wakeup_gdt[2] =
GDT_ENTRY(0x8093, acpi_wakeup_address, 0xfffff);
#ifndef CONFIG_64BIT #ifndef CONFIG_64BIT
store_gdt((struct desc_ptr *)&header->pmode_gdt); store_gdt((struct desc_ptr *)&header->pmode_gdt);
...@@ -95,7 +71,6 @@ int acpi_suspend_lowlevel(void) ...@@ -95,7 +71,6 @@ int acpi_suspend_lowlevel(void)
header->pmode_cr3 = (u32)__pa(&initial_page_table); header->pmode_cr3 = (u32)__pa(&initial_page_table);
saved_magic = 0x12345678; saved_magic = 0x12345678;
#else /* CONFIG_64BIT */ #else /* CONFIG_64BIT */
header->trampoline_segment = trampoline_address() >> 4;
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
stack_start = (unsigned long)temp_stack + sizeof(temp_stack); stack_start = (unsigned long)temp_stack + sizeof(temp_stack);
early_gdt_descr.address = early_gdt_descr.address =
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
* Variables and functions used by the code in sleep.c * Variables and functions used by the code in sleep.c
*/ */
#include <asm/trampoline.h>
#include <linux/linkage.h> #include <linux/linkage.h>
#include <asm/realmode.h>
extern unsigned long saved_video_mode; extern unsigned long saved_video_mode;
extern long saved_magic; extern long saved_magic;
......
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
#include <asm/sections.h> #include <asm/sections.h>
#include <asm/e820.h> #include <asm/e820.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/trampoline.h>
#include <asm/apic.h> #include <asm/apic.h>
#include <asm/io_apic.h> #include <asm/io_apic.h>
#include <asm/bios_ebda.h> #include <asm/bios_ebda.h>
......
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
#include <asm/sections.h> #include <asm/sections.h>
#include <asm/kdebug.h> #include <asm/kdebug.h>
#include <asm/e820.h> #include <asm/e820.h>
#include <asm/trampoline.h>
#include <asm/bios_ebda.h> #include <asm/bios_ebda.h>
static void __init zap_identity_mappings(void) static void __init zap_identity_mappings(void)
......
...@@ -274,10 +274,7 @@ num_subarch_entries = (. - subarch_entries) / 4 ...@@ -274,10 +274,7 @@ num_subarch_entries = (. - subarch_entries) / 4
* If cpu hotplug is not supported then this code can go in init section * If cpu hotplug is not supported then this code can go in init section
* which will be freed later * which will be freed later
*/ */
__CPUINIT __CPUINIT
#ifdef CONFIG_SMP
ENTRY(startup_32_smp) ENTRY(startup_32_smp)
cld cld
movl $(__BOOT_DS),%eax movl $(__BOOT_DS),%eax
...@@ -288,7 +285,7 @@ ENTRY(startup_32_smp) ...@@ -288,7 +285,7 @@ ENTRY(startup_32_smp)
movl pa(stack_start),%ecx movl pa(stack_start),%ecx
movl %eax,%ss movl %eax,%ss
leal -__PAGE_OFFSET(%ecx),%esp leal -__PAGE_OFFSET(%ecx),%esp
#endif /* CONFIG_SMP */
default_entry: default_entry:
/* /*
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment