* Attempt rebooting via port CF9 if it seems to be available
[not found] ` <alpine.LFD.2.00.0811111802440.4480@localhost.localdomain>
@ 2008-11-12 0:25 ` H. Peter Anvin
2008-11-12 18:49 ` Andrey Borzenkov
0 siblings, 1 reply; 2+ messages in thread
From: H. Peter Anvin @ 2008-11-12 0:25 UTC (permalink / raw)
To: Len Brown
Cc: Matthew Garrett, Ingo Molnar, Eric W. Biederman, Avi Kivity,
Andrey Borzenkov, linux-acpi, Len Brown, Thomas Gleixner,
Eduardo Habkost, Andrew Morton, Linux Kernel Mailing List
[-- Attachment #1: Type: text/plain, Size: 855 bytes --]
Looking at doing the port CF9 fallback, I stumbled onto something fishy.
I wonder if anyone here happens to have any idea why we turn off
caching in machine_real_restart()? Jumping to the BIOS is *not* a
reset; we jump to the decompressed BIOS on low memory which is usually
shadowed, not to the BIOS entry point. In that way, it's more of an
INIT than a reset, and disabling caching seems broken.
Either way, here is a preliminary patch to do the CF9 if safe, and then
falling back to keyboard reboot. I'm a bit concerned about how to test
it, of course; this stuff is sensitive and just about impossible to test
except on millions of machines at once...
If you have any machines (especially problematic ones) and find that
this patch either helps or hurts or do nothing, please do let me know so
I have any idea of the extent of coverage.
-hpa
[-- Attachment #2: 0001-x86-attempt-reboot-via-port-CF9-if-we-have-standard.patch --]
[-- Type: text/x-patch, Size: 5294 bytes --]
>From 14d7ca5c575853664d8fe4f225a77b8df1b7de7d Mon Sep 17 00:00:00 2001
From: H. Peter Anvin <hpa@zytor.com>
Date: Tue, 11 Nov 2008 16:19:48 -0800
Subject: [PATCH] x86: attempt reboot via port CF9 if we have standard PCI ports
Impact: Changes reboot behavior.
If port CF9 seems to be safe to touch, attempt it before trying the
keyboard controller. Port CF9 is not available on all chipsets (a
significant but decreasing number of modern chipsets don't implement
it), but port CF9 itself should in general be safe to poke (no ill
effects if unimplemented) on any system which has PCI Configuration
Method #1 or #2, as it falls inside the PCI configuration port range
in both cases. No chipset without PCI is known to have port CF9,
either, although an explicit "pci=bios" would mean we miss this and
therefore don't use port CF9. An explicit "reboot=pci" can be used to
force the use of port CF9.
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
---
arch/x86/include/asm/emergency-restart.h | 4 ++-
arch/x86/kernel/reboot.c | 34 +++++++++++++++++++++++------
arch/x86/pci/direct.c | 4 ++-
arch/x86/pci/pci.h | 1 +
4 files changed, 34 insertions(+), 9 deletions(-)
diff --git a/arch/x86/include/asm/emergency-restart.h b/arch/x86/include/asm/emergency-restart.h
index 94826cf..cc70c1c 100644
--- a/arch/x86/include/asm/emergency-restart.h
+++ b/arch/x86/include/asm/emergency-restart.h
@@ -8,7 +8,9 @@ enum reboot_type {
BOOT_BIOS = 'b',
#endif
BOOT_ACPI = 'a',
- BOOT_EFI = 'e'
+ BOOT_EFI = 'e',
+ BOOT_CF9 = 'p',
+ BOOT_CF9_COND = 'q',
};
extern enum reboot_type reboot_type;
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index 34f8d37..ddc9389 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -29,14 +29,17 @@ EXPORT_SYMBOL(pm_power_off);
static const struct desc_ptr no_idt = {};
static int reboot_mode;
-enum reboot_type reboot_type = BOOT_KBD;
+enum reboot_type reboot_type = BOOT_CF9_COND;
int reboot_force;
#if defined(CONFIG_X86_32) && defined(CONFIG_SMP)
static int reboot_cpu = -1;
#endif
-/* reboot=b[ios] | s[mp] | t[riple] | k[bd] | e[fi] [, [w]arm | [c]old]
+/* This is set by the PCI code if either type 1 or type 2 PCI is detected */
+bool port_cf9_safe = false;
+
+/* reboot=b[ios] | s[mp] | t[riple] | k[bd] | e[fi] [, [w]arm | [c]old] | p[ci]
warm Don't set the cold reboot flag
cold Set the cold reboot flag
bios Reboot by jumping through the BIOS (only for X86_32)
@@ -45,6 +48,7 @@ static int reboot_cpu = -1;
kbd Use the keyboard controller. cold reset (default)
acpi Use the RESET_REG in the FADT
efi Use efi reset_system runtime service
+ pci Use the so-called "PCI reset register", CF9
force Avoid anything that could hang.
*/
static int __init reboot_setup(char *str)
@@ -79,6 +83,7 @@ static int __init reboot_setup(char *str)
case 'k':
case 't':
case 'e':
+ case 'p':
reboot_type = *str;
break;
@@ -379,28 +384,43 @@ static void native_machine_emergency_restart(void)
load_idt(&no_idt);
__asm__ __volatile__("int3");
- reboot_type = BOOT_KBD;
+ reboot_type = BOOT_CF9_COND;
break;
#ifdef CONFIG_X86_32
case BOOT_BIOS:
machine_real_restart(jump_to_bios, sizeof(jump_to_bios));
- reboot_type = BOOT_KBD;
+ reboot_type = BOOT_CF9_COND;
break;
#endif
case BOOT_ACPI:
acpi_reboot();
- reboot_type = BOOT_KBD;
+ reboot_type = BOOT_CF9_COND;
break;
-
case BOOT_EFI:
if (efi_enabled)
- efi.reset_system(reboot_mode ? EFI_RESET_WARM : EFI_RESET_COLD,
+ efi.reset_system(reboot_mode ?
+ EFI_RESET_WARM :
+ EFI_RESET_COLD,
EFI_SUCCESS, 0, NULL);
+ reboot_type = BOOT_CF9_COND;
+ break;
+
+ case BOOT_CF9:
+ port_cf9_safe = true;
+ /* fall through */
+ case BOOT_CF9_COND:
+ if (port_cf9_safe) {
+ u8 cf9 = inb(0xcf9) & ~6;
+ outb(cf9|2, 0xcf9); /* Request hard reset */
+ udelay(50);
+ outb(cf9|6, 0xcf9); /* Actually do the reset */
+ udelay(50);
+ }
reboot_type = BOOT_KBD;
break;
}
diff --git a/arch/x86/pci/direct.c b/arch/x86/pci/direct.c
index 9915293..9a5af6c 100644
--- a/arch/x86/pci/direct.c
+++ b/arch/x86/pci/direct.c
@@ -173,7 +173,7 @@ static int pci_conf2_write(unsigned int seg, unsigned int bus,
#undef PCI_CONF2_ADDRESS
-static struct pci_raw_ops pci_direct_conf2 = {
+struct pci_raw_ops pci_direct_conf2 = {
.read = pci_conf2_read,
.write = pci_conf2_write,
};
@@ -289,6 +289,7 @@ int __init pci_direct_probe(void)
if (pci_check_type1()) {
raw_pci_ops = &pci_direct_conf1;
+ port_cf9_safe = true;
return 1;
}
release_resource(region);
@@ -305,6 +306,7 @@ int __init pci_direct_probe(void)
if (pci_check_type2()) {
raw_pci_ops = &pci_direct_conf2;
+ port_cf9_safe = true;
return 2;
}
diff --git a/arch/x86/pci/pci.h b/arch/x86/pci/pci.h
index 15b9cf6..1959018 100644
--- a/arch/x86/pci/pci.h
+++ b/arch/x86/pci/pci.h
@@ -96,6 +96,7 @@ extern struct pci_raw_ops *raw_pci_ops;
extern struct pci_raw_ops *raw_pci_ext_ops;
extern struct pci_raw_ops pci_direct_conf1;
+extern bool port_cf9_safe;
/* arch_initcall level */
extern int pci_direct_probe(void);
--
1.5.6.5
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: Attempt rebooting via port CF9 if it seems to be available
2008-11-12 0:25 ` Attempt rebooting via port CF9 if it seems to be available H. Peter Anvin
@ 2008-11-12 18:49 ` Andrey Borzenkov
0 siblings, 0 replies; 2+ messages in thread
From: Andrey Borzenkov @ 2008-11-12 18:49 UTC (permalink / raw)
To: H. Peter Anvin
Cc: Len Brown, Matthew Garrett, Ingo Molnar, Avi Kivity, linux-acpi,
Len Brown, Eduardo Habkost, Andrew Morton,
Linux Kernel Mailing List
[-- Attachment #1: Type: text/plain, Size: 999 bytes --]
On Wednesday 12 November 2008, H. Peter Anvin wrote:
> Looking at doing the port CF9 fallback, I stumbled onto something fishy.
>
> I wonder if anyone here happens to have any idea why we turn off
> caching in machine_real_restart()? Jumping to the BIOS is *not* a
> reset; we jump to the decompressed BIOS on low memory which is usually
> shadowed, not to the BIOS entry point. In that way, it's more of an
> INIT than a reset, and disabling caching seems broken.
>
> Either way, here is a preliminary patch to do the CF9 if safe, and then
> falling back to keyboard reboot. I'm a bit concerned about how to test
> it, of course; this stuff is sensitive and just about impossible to test
> except on millions of machines at once...
>
> If you have any machines (especially problematic ones) and find that
> this patch either helps or hurts or do nothing, please do let me know so
> I have any idea of the extent of coverage.
>
Works here both with default and reboot=p.
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2008-11-12 18:49 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <007e7d616a5d1c2e16ad627d03f8b97799445e71.1226032943.git.len.brown@intel.com>
[not found] ` <200811080930.21462.arvidjaar@mail.ru>
[not found] ` <alpine.LFD.2.00.0811080208590.3092@localhost.localdomain>
[not found] ` <200811081050.25477.arvidjaar@mail.ru>
[not found] ` <20081108115956.GE8354@elte.hu>
[not found] ` <4916B38B.7050905@redhat.com>
[not found] ` <4916B4DB.90602@zytor.com>
[not found] ` <20081110083938.GD22392@elte.hu>
[not found] ` <20081110115732.GA30181@srcf.ucam.org>
[not found] ` <20081110125630.GC28643@elte.hu>
[not found] ` <20081110130029.GC30894@srcf.ucam.org>
[not found] ` <alpine.LFD.2.00.0811111802440.4480@localhost.localdomain>
2008-11-12 0:25 ` Attempt rebooting via port CF9 if it seems to be available H. Peter Anvin
2008-11-12 18:49 ` Andrey Borzenkov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox