Commit 57b16594 authored by Michael D Labriola's avatar Michael D Labriola Committed by Ingo Molnar

x86/reboot: Reduce to a single DMI table for reboot quirks

This commit reduces the X86_32 reboot_dmi_table and the X86_64
pci_reboot_dmi_table into a single table with a single set of
functions (e.g., only 1 call to core_initcall).

The table entries that use set_bios_reboot are grouped together
inside a #define CONFIG_X86_32 block.

Note that there's a single entry that uses set_kbd_reboot, which
used to be available only on X86_32.  This commit moves that
entry outside the X86_32 block because it seems it never should
have been in there.  There's multiple places in reboot.c that
assume KBD is valid regardless of X86_32/X86_64.
Signed-off-by: default avatarMichael D Labriola <michael.d.labriola@gmail.com>
Cc: Matthew Garrett <mjg@redhat.com>
Link: http://lkml.kernel.org/n/tip-lv3aliubas2l3aenq8v3uklk@git.kernel.orgSigned-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 7915a2e9
...@@ -150,6 +150,80 @@ static int __init set_bios_reboot(const struct dmi_system_id *d) ...@@ -150,6 +150,80 @@ static int __init set_bios_reboot(const struct dmi_system_id *d)
return 0; return 0;
} }
extern const unsigned char machine_real_restart_asm[];
extern const u64 machine_real_restart_gdt[3];
void machine_real_restart(unsigned int type)
{
void *restart_va;
unsigned long restart_pa;
void (*restart_lowmem)(unsigned int);
u64 *lowmem_gdt;
local_irq_disable();
/* Write zero to CMOS register number 0x0f, which the BIOS POST
routine will recognize as telling it to do a proper reboot. (Well
that's what this book in front of me says -- it may only apply to
the Phoenix BIOS though, it's not clear). At the same time,
disable NMIs by setting the top bit in the CMOS address register,
as we're about to do peculiar things to the CPU. I'm not sure if
`outb_p' is needed instead of just `outb'. Use it to be on the
safe side. (Yes, CMOS_WRITE does outb_p's. - Paul G.)
*/
spin_lock(&rtc_lock);
CMOS_WRITE(0x00, 0x8f);
spin_unlock(&rtc_lock);
/*
* Switch back to the initial page table.
*/
load_cr3(initial_page_table);
/* Write 0x1234 to absolute memory location 0x472. The BIOS reads
this on booting to tell it to "Bypass memory test (also warm
boot)". This seems like a fairly standard thing that gets set by
REBOOT.COM programs, and the previous reset routine did this
too. */
*((unsigned short *)0x472) = reboot_mode;
/* Patch the GDT in the low memory trampoline */
lowmem_gdt = TRAMPOLINE_SYM(machine_real_restart_gdt);
restart_va = TRAMPOLINE_SYM(machine_real_restart_asm);
restart_pa = virt_to_phys(restart_va);
restart_lowmem = (void (*)(unsigned int))restart_pa;
/* GDT[0]: GDT self-pointer */
lowmem_gdt[0] =
(u64)(sizeof(machine_real_restart_gdt) - 1) +
((u64)virt_to_phys(lowmem_gdt) << 16);
/* GDT[1]: 64K real mode code segment */
lowmem_gdt[1] =
GDT_ENTRY(0x009b, restart_pa, 0xffff);
/* Jump to the identity-mapped low memory code */
restart_lowmem(type);
}
#ifdef CONFIG_APM_MODULE
EXPORT_SYMBOL(machine_real_restart);
#endif
#endif /* CONFIG_X86_32 */
/*
* Some Apple MacBook and MacBookPro's needs reboot=p to be able to reboot
*/
static int __init set_pci_reboot(const struct dmi_system_id *d)
{
if (reboot_type != BOOT_CF9) {
reboot_type = BOOT_CF9;
printk(KERN_INFO "%s series board detected. "
"Selecting PCI-method for reboots.\n", d->ident);
}
return 0;
}
static int __init set_kbd_reboot(const struct dmi_system_id *d) static int __init set_kbd_reboot(const struct dmi_system_id *d)
{ {
if (reboot_type != BOOT_KBD) { if (reboot_type != BOOT_KBD) {
...@@ -159,7 +233,11 @@ static int __init set_kbd_reboot(const struct dmi_system_id *d) ...@@ -159,7 +233,11 @@ static int __init set_kbd_reboot(const struct dmi_system_id *d)
return 0; return 0;
} }
/* This is a single dmi_table handling all reboot quirks. Note that
* REBOOT_BIOS is only available for 32bit
*/
static struct dmi_system_id __initdata reboot_dmi_table[] = { static struct dmi_system_id __initdata reboot_dmi_table[] = {
#ifdef CONFIG_X86_32
{ /* Handle problems with rebooting on Dell E520's */ { /* Handle problems with rebooting on Dell E520's */
.callback = set_bios_reboot, .callback = set_bios_reboot,
.ident = "Dell E520", .ident = "Dell E520",
...@@ -309,6 +387,8 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = { ...@@ -309,6 +387,8 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
DMI_MATCH(DMI_BOARD_NAME, "P4S800"), DMI_MATCH(DMI_BOARD_NAME, "P4S800"),
}, },
}, },
#endif /* CONFIG_X86_32 */
{ /* Handle reboot issue on Acer Aspire one */ { /* Handle reboot issue on Acer Aspire one */
.callback = set_kbd_reboot, .callback = set_kbd_reboot,
.ident = "Acer Aspire One A110", .ident = "Acer Aspire One A110",
...@@ -317,96 +397,6 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = { ...@@ -317,96 +397,6 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "AOA110"), DMI_MATCH(DMI_PRODUCT_NAME, "AOA110"),
}, },
}, },
{ }
};
static int __init reboot_init(void)
{
/* Only do the DMI check if reboot_type hasn't been overridden
* on the command line
*/
if (reboot_default) {
dmi_check_system(reboot_dmi_table);
}
return 0;
}
core_initcall(reboot_init);
extern const unsigned char machine_real_restart_asm[];
extern const u64 machine_real_restart_gdt[3];
void machine_real_restart(unsigned int type)
{
void *restart_va;
unsigned long restart_pa;
void (*restart_lowmem)(unsigned int);
u64 *lowmem_gdt;
local_irq_disable();
/* Write zero to CMOS register number 0x0f, which the BIOS POST
routine will recognize as telling it to do a proper reboot. (Well
that's what this book in front of me says -- it may only apply to
the Phoenix BIOS though, it's not clear). At the same time,
disable NMIs by setting the top bit in the CMOS address register,
as we're about to do peculiar things to the CPU. I'm not sure if
`outb_p' is needed instead of just `outb'. Use it to be on the
safe side. (Yes, CMOS_WRITE does outb_p's. - Paul G.)
*/
spin_lock(&rtc_lock);
CMOS_WRITE(0x00, 0x8f);
spin_unlock(&rtc_lock);
/*
* Switch back to the initial page table.
*/
load_cr3(initial_page_table);
/* Write 0x1234 to absolute memory location 0x472. The BIOS reads
this on booting to tell it to "Bypass memory test (also warm
boot)". This seems like a fairly standard thing that gets set by
REBOOT.COM programs, and the previous reset routine did this
too. */
*((unsigned short *)0x472) = reboot_mode;
/* Patch the GDT in the low memory trampoline */
lowmem_gdt = TRAMPOLINE_SYM(machine_real_restart_gdt);
restart_va = TRAMPOLINE_SYM(machine_real_restart_asm);
restart_pa = virt_to_phys(restart_va);
restart_lowmem = (void (*)(unsigned int))restart_pa;
/* GDT[0]: GDT self-pointer */
lowmem_gdt[0] =
(u64)(sizeof(machine_real_restart_gdt) - 1) +
((u64)virt_to_phys(lowmem_gdt) << 16);
/* GDT[1]: 64K real mode code segment */
lowmem_gdt[1] =
GDT_ENTRY(0x009b, restart_pa, 0xffff);
/* Jump to the identity-mapped low memory code */
restart_lowmem(type);
}
#ifdef CONFIG_APM_MODULE
EXPORT_SYMBOL(machine_real_restart);
#endif
#endif /* CONFIG_X86_32 */
/*
* Some Apple MacBook and MacBookPro's needs reboot=p to be able to reboot
*/
static int __init set_pci_reboot(const struct dmi_system_id *d)
{
if (reboot_type != BOOT_CF9) {
reboot_type = BOOT_CF9;
printk(KERN_INFO "%s series board detected. "
"Selecting PCI-method for reboots.\n", d->ident);
}
return 0;
}
static struct dmi_system_id __initdata pci_reboot_dmi_table[] = {
{ /* Handle problems with rebooting on Apple MacBook5 */ { /* Handle problems with rebooting on Apple MacBook5 */
.callback = set_pci_reboot, .callback = set_pci_reboot,
.ident = "Apple MacBook5", .ident = "Apple MacBook5",
...@@ -474,17 +464,17 @@ static struct dmi_system_id __initdata pci_reboot_dmi_table[] = { ...@@ -474,17 +464,17 @@ static struct dmi_system_id __initdata pci_reboot_dmi_table[] = {
{ } { }
}; };
static int __init pci_reboot_init(void) static int __init reboot_init(void)
{ {
/* Only do the DMI check if reboot_type hasn't been overridden /* Only do the DMI check if reboot_type hasn't been overridden
* on the command line * on the command line
*/ */
if (reboot_default) { if (reboot_default) {
dmi_check_system(pci_reboot_dmi_table); dmi_check_system(reboot_dmi_table);
} }
return 0; return 0;
} }
core_initcall(pci_reboot_init); core_initcall(reboot_init);
static inline void kb_wait(void) static inline void kb_wait(void)
{ {
......
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