Skip to content

Commit

Permalink
Merge branch 'x86-trampoline-for-linus' of git://git.kernel.org/pub/s…
Browse files Browse the repository at this point in the history
…cm/linux/kernel/git/tip/linux-2.6-tip

* 'x86-trampoline-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  x86: Fix binutils-2.21 symbol related build failures
  x86-64, trampoline: Remove unused variable
  x86, reboot: Fix the use of passed arguments in 32-bit BIOS reboot
  x86, reboot: Move the real-mode reboot code to an assembly file
  x86: Make the GDT_ENTRY() macro in <asm/segment.h> safe for assembly
  x86, trampoline: Use the unified trampoline setup for ACPI wakeup
  x86, trampoline: Common infrastructure for low memory trampolines

Fix up trivial conflicts in arch/x86/kernel/Makefile
  • Loading branch information
Linus Torvalds committed Mar 16, 2011
2 parents fc82e1d + 2ae9d29 commit e7fd3b4
Show file tree
Hide file tree
Showing 25 changed files with 315 additions and 280 deletions.
4 changes: 0 additions & 4 deletions arch/x86/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -221,10 +221,6 @@ config X86_HT
def_bool y
depends on SMP

config X86_TRAMPOLINE
def_bool y
depends on SMP || (64BIT && ACPI_SLEEP)

config X86_32_LAZY_GS
def_bool y
depends on X86_32 && !CC_STACKPROTECTOR
Expand Down
4 changes: 3 additions & 1 deletion arch/x86/include/asm/acpi.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <asm/processor.h>
#include <asm/mmu.h>
#include <asm/mpspec.h>
#include <asm/trampoline.h>

#define COMPILER_DEPENDENT_INT64 long long
#define COMPILER_DEPENDENT_UINT64 unsigned long long
Expand Down Expand Up @@ -117,7 +118,8 @@ static inline void acpi_disable_pci(void)
extern int acpi_save_state_mem(void);
extern void acpi_restore_state_mem(void);

extern unsigned long acpi_wakeup_address;
extern const unsigned char acpi_wakeup_code[];
#define acpi_wakeup_address (__pa(TRAMPOLINE_SYM(acpi_wakeup_code)))

/* early initialization routine */
extern void acpi_reserve_wakeup_memory(void);
Expand Down
5 changes: 4 additions & 1 deletion arch/x86/include/asm/reboot.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ extern struct machine_ops machine_ops;

void native_machine_crash_shutdown(struct pt_regs *regs);
void native_machine_shutdown(void);
void machine_real_restart(const unsigned char *code, int length);
void machine_real_restart(unsigned int type);
/* These must match dispatch_table in reboot_32.S */
#define MRR_BIOS 0
#define MRR_APM 1

typedef void (*nmi_shootdown_cb)(int, struct die_args*);
void nmi_shootdown_cpus(nmi_shootdown_cb callback);
Expand Down
12 changes: 7 additions & 5 deletions arch/x86/include/asm/segment.h
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
#ifndef _ASM_X86_SEGMENT_H
#define _ASM_X86_SEGMENT_H

#include <linux/const.h>

/* Constructor for a conventional segment GDT (or LDT) entry */
/* This is a macro so it can be used in initializers */
#define GDT_ENTRY(flags, base, limit) \
((((base) & 0xff000000ULL) << (56-24)) | \
(((flags) & 0x0000f0ffULL) << 40) | \
(((limit) & 0x000f0000ULL) << (48-16)) | \
(((base) & 0x00ffffffULL) << 16) | \
(((limit) & 0x0000ffffULL)))
((((base) & _AC(0xff000000,ULL)) << (56-24)) | \
(((flags) & _AC(0x0000f0ff,ULL)) << 40) | \
(((limit) & _AC(0x000f0000,ULL)) << (48-16)) | \
(((base) & _AC(0x00ffffff,ULL)) << 16) | \
(((limit) & _AC(0x0000ffff,ULL))))

/* Simple and small GDT entries for booting only */

Expand Down
33 changes: 22 additions & 11 deletions arch/x86/include/asm/trampoline.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,36 @@

#ifndef __ASSEMBLY__

#ifdef CONFIG_X86_TRAMPOLINE
#include <linux/types.h>
#include <asm/io.h>

/*
* Trampoline 80x86 program as an array.
* 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 trampoline_data [];
extern const unsigned char trampoline_end [];
extern unsigned char *trampoline_base;
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;

#define TRAMPOLINE_SIZE roundup(trampoline_end - trampoline_data, PAGE_SIZE)
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)))

extern unsigned long setup_trampoline(void);
extern void __init reserve_trampoline_memory(void);
#else
static inline void reserve_trampoline_memory(void) {}
#endif /* CONFIG_X86_TRAMPOLINE */
/* Address of the SMP trampoline */
static inline unsigned long trampoline_address(void)
{
return virt_to_phys(TRAMPOLINE_SYM(trampoline_data));
}

#endif /* __ASSEMBLY__ */

Expand Down
4 changes: 2 additions & 2 deletions arch/x86/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ obj-y += tsc.o io_delay.o rtc.o
obj-y += pci-iommu_table.o
obj-y += resource.o

obj-$(CONFIG_X86_TRAMPOLINE) += trampoline.o
obj-y += trampoline.o trampoline_$(BITS).o
obj-y += process.o
obj-y += i387.o xsave.o
obj-y += ptrace.o
Expand All @@ -59,6 +59,7 @@ obj-$(CONFIG_STACKTRACE) += stacktrace.o
obj-y += cpu/
obj-y += acpi/
obj-y += reboot.o
obj-$(CONFIG_X86_32) += reboot_32.o
obj-$(CONFIG_MCA) += mca_32.o
obj-$(CONFIG_X86_MSR) += msr.o
obj-$(CONFIG_X86_CPUID) += cpuid.o
Expand All @@ -69,7 +70,6 @@ obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_SMP) += smpboot.o
obj-$(CONFIG_SMP) += tsc_sync.o
obj-$(CONFIG_SMP) += setup_percpu.o
obj-$(CONFIG_X86_TRAMPOLINE) += trampoline_$(BITS).o
obj-$(CONFIG_X86_MPPARSE) += mpparse.o
obj-y += apic/
obj-$(CONFIG_X86_REBOOTFIXUPS) += reboot_fixups_32.o
Expand Down
21 changes: 14 additions & 7 deletions arch/x86/kernel/acpi/realmode/wakeup.S
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,17 @@
#include <asm/page_types.h>
#include <asm/pgtable_types.h>
#include <asm/processor-flags.h>
#include "wakeup.h"

.code16
.section ".header", "a"
.section ".jump", "ax"
.globl _start
_start:
cli
jmp wakeup_code

/* This should match the structure in wakeup.h */
.section ".header", "a"
.globl wakeup_header
wakeup_header:
video_mode: .short 0 /* Video mode number */
Expand All @@ -30,14 +36,11 @@ wakeup_jmp: .byte 0xea /* ljmpw */
wakeup_jmp_off: .word 3f
wakeup_jmp_seg: .word 0
wakeup_gdt: .quad 0, 0, 0
signature: .long 0x51ee1111
signature: .long WAKEUP_HEADER_SIGNATURE

.text
.globl _start
.code16
wakeup_code:
_start:
cli
cld

/* Apparently some dimwit BIOS programmers don't know how to
Expand Down Expand Up @@ -77,12 +80,12 @@ _start:

/* Check header signature... */
movl signature, %eax
cmpl $0x51ee1111, %eax
cmpl $WAKEUP_HEADER_SIGNATURE, %eax
jne bogus_real_magic

/* Check we really have everything... */
movl end_signature, %eax
cmpl $0x65a22c82, %eax
cmpl $WAKEUP_END_SIGNATURE, %eax
jne bogus_real_magic

/* Call the C code */
Expand Down Expand Up @@ -147,3 +150,7 @@ wakeup_heap:
wakeup_stack:
.space 2048
wakeup_stack_end:

.section ".signature","a"
end_signature:
.long WAKEUP_END_SIGNATURE
5 changes: 3 additions & 2 deletions arch/x86/kernel/acpi/realmode/wakeup.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ struct wakeup_header {
extern struct wakeup_header wakeup_header;
#endif

#define HEADER_OFFSET 0x3f00
#define WAKEUP_SIZE 0x4000
#define WAKEUP_HEADER_OFFSET 8
#define WAKEUP_HEADER_SIGNATURE 0x51ee1111
#define WAKEUP_END_SIGNATURE 0x65a22c82

#endif /* ARCH_X86_KERNEL_ACPI_RM_WAKEUP_H */
28 changes: 13 additions & 15 deletions arch/x86/kernel/acpi/realmode/wakeup.lds.S
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,19 @@ ENTRY(_start)
SECTIONS
{
. = 0;
.jump : {
*(.jump)
} = 0x90909090

. = WAKEUP_HEADER_OFFSET;
.header : {
*(.header)
}

. = ALIGN(16);
.text : {
*(.text*)
}
} = 0x90909090

. = ALIGN(16);
.rodata : {
Expand All @@ -33,32 +43,20 @@ SECTIONS
*(.data*)
}

.signature : {
end_signature = .;
LONG(0x65a22c82)
}

. = ALIGN(16);
.bss : {
__bss_start = .;
*(.bss)
__bss_end = .;
}

. = HEADER_OFFSET;
.header : {
*(.header)
.signature : {
*(.signature)
}

. = ALIGN(16);
_end = .;

/DISCARD/ : {
*(.note*)
}

/*
* The ASSERT() sink to . is intentional, for binutils 2.14 compatibility:
*/
. = ASSERT(_end <= WAKEUP_SIZE, "Wakeup too big!");
}
65 changes: 7 additions & 58 deletions arch/x86/kernel/acpi/sleep.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,8 @@
#include "realmode/wakeup.h"
#include "sleep.h"

unsigned long acpi_wakeup_address;
unsigned long acpi_realmode_flags;

/* address in low memory of the wakeup routine. */
static unsigned long acpi_realmode;

#if defined(CONFIG_SMP) && defined(CONFIG_64BIT)
static char temp_stack[4096];
#endif
Expand All @@ -33,22 +29,17 @@ static char temp_stack[4096];
*
* Create an identity mapped page table and copy the wakeup routine to
* low memory.
*
* Note that this is too late to change acpi_wakeup_address.
*/
int acpi_save_state_mem(void)
{
struct wakeup_header *header;
/* address in low memory of the wakeup routine. */
char *acpi_realmode;

if (!acpi_realmode) {
printk(KERN_ERR "Could not allocate memory during boot, "
"S3 disabled\n");
return -ENOMEM;
}
memcpy((void *)acpi_realmode, &wakeup_code_start, WAKEUP_SIZE);
acpi_realmode = TRAMPOLINE_SYM(acpi_wakeup_code);

header = (struct wakeup_header *)(acpi_realmode + HEADER_OFFSET);
if (header->signature != 0x51ee1111) {
header = (struct wakeup_header *)(acpi_realmode + WAKEUP_HEADER_OFFSET);
if (header->signature != WAKEUP_HEADER_SIGNATURE) {
printk(KERN_ERR "wakeup header does not match\n");
return -EINVAL;
}
Expand All @@ -68,9 +59,7 @@ int acpi_save_state_mem(void)
/* GDT[0]: GDT self-pointer */
header->wakeup_gdt[0] =
(u64)(sizeof(header->wakeup_gdt) - 1) +
((u64)(acpi_wakeup_address +
((char *)&header->wakeup_gdt - (char *)acpi_realmode))
<< 16);
((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);
Expand All @@ -96,7 +85,7 @@ int acpi_save_state_mem(void)
header->pmode_cr3 = (u32)__pa(&initial_page_table);
saved_magic = 0x12345678;
#else /* CONFIG_64BIT */
header->trampoline_segment = setup_trampoline() >> 4;
header->trampoline_segment = trampoline_address() >> 4;
#ifdef CONFIG_SMP
stack_start = (unsigned long)temp_stack + sizeof(temp_stack);
early_gdt_descr.address =
Expand All @@ -117,46 +106,6 @@ void acpi_restore_state_mem(void)
{
}


/**
* acpi_reserve_wakeup_memory - do _very_ early ACPI initialisation
*
* We allocate a page from the first 1MB of memory for the wakeup
* routine for when we come back from a sleep state. The
* runtime allocator allows specification of <16MB pages, but not
* <1MB pages.
*/
void __init acpi_reserve_wakeup_memory(void)
{
phys_addr_t mem;

if ((&wakeup_code_end - &wakeup_code_start) > WAKEUP_SIZE) {
printk(KERN_ERR
"ACPI: Wakeup code way too big, S3 disabled.\n");
return;
}

mem = memblock_find_in_range(0, 1<<20, WAKEUP_SIZE, PAGE_SIZE);

if (mem == MEMBLOCK_ERROR) {
printk(KERN_ERR "ACPI: Cannot allocate lowmem, S3 disabled.\n");
return;
}
acpi_realmode = (unsigned long) phys_to_virt(mem);
acpi_wakeup_address = mem;
memblock_x86_reserve_range(mem, mem + WAKEUP_SIZE, "ACPI WAKEUP");
}

int __init acpi_configure_wakeup_memory(void)
{
if (acpi_realmode)
set_memory_x(acpi_realmode, WAKEUP_SIZE >> PAGE_SHIFT);

return 0;
}
arch_initcall(acpi_configure_wakeup_memory);


static int __init acpi_sleep_setup(char *str)
{
while ((str != NULL) && (*str != '\0')) {
Expand Down
3 changes: 0 additions & 3 deletions arch/x86/kernel/acpi/sleep.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,10 @@

#include <asm/trampoline.h>

extern char wakeup_code_start, wakeup_code_end;

extern unsigned long saved_video_mode;
extern long saved_magic;

extern int wakeup_pmode_return;
extern char swsusp_pg_dir[PAGE_SIZE];

extern unsigned long acpi_copy_wakeup_routine(unsigned long);
extern void wakeup_long64(void);
12 changes: 7 additions & 5 deletions arch/x86/kernel/acpi/wakeup_rm.S
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
* Wrapper script for the realmode binary as a transport object
* before copying to low memory.
*/
.section ".rodata","a"
.globl wakeup_code_start, wakeup_code_end
wakeup_code_start:
#include <asm/page_types.h>

.section ".x86_trampoline","a"
.balign PAGE_SIZE
.globl acpi_wakeup_code
acpi_wakeup_code:
.incbin "arch/x86/kernel/acpi/realmode/wakeup.bin"
wakeup_code_end:
.size wakeup_code_start, .-wakeup_code_start
.size acpi_wakeup_code, .-acpi_wakeup_code
Loading

0 comments on commit e7fd3b4

Please sign in to comment.