mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
bitkeeper revision 1.1599 (429b828aL4XKwdaPjLGObI37F4hwiw)
By default do not enable local APIC if disabled by the BIOS. This matches Linux behaviour and ought to improve stability on buggy hardware/firmware (laptops in particular). As in Linux, you can forcibly enable the APIC with 'lapic' command-line option, or forcibly ignore it with 'nolapic'. Signed-off-by: Keir Fraser <keir@xensource.com>
This commit is contained in:
1 parent
f279b10b57
commit
10b7bf98cb
4 files changed
+84
-50
No files matched your search
+17
-9
@@ -1770,14 +1770,25 @@ editing \path{grub.conf}.
|
||||
Select the CPU scheduler Xen should use. The current
|
||||
possibilities are `bvt' (default), `atropos' and `rrobin'.
|
||||
For more information see Section~\ref{s:sched}.
|
||||
|
||||
\item [apic\_verbosity=debug,verbose ]
|
||||
Print more detailed information about local APIC and IOAPIC configuration.
|
||||
|
||||
\item [lapic ]
|
||||
Force use of local APIC even when left disabled by uniprocessor BIOS.
|
||||
|
||||
\item [nolapic ]
|
||||
Ignore local APIC in a uniprocessor system, even if enabled by the BIOS.
|
||||
|
||||
\item [apic=bigsmp,default,es7000,summit ]
|
||||
Specify NUMA platform. This can usually be probed automatically.
|
||||
|
||||
\end{description}
|
||||
|
||||
In addition, the following platform-specific options may be specified
|
||||
on the Xen command line. Since domain 0 shares responsibility for
|
||||
booting the platform, Xen will automatically propagate these options
|
||||
to its command line.
|
||||
|
||||
These options are taken from Linux's command-line syntax with
|
||||
In addition, the following options may be specified on the Xen command
|
||||
line. Since domain 0 shares responsibility for booting the platform,
|
||||
Xen will automatically propagate these options to its command
|
||||
line. These options are taken from Linux's command-line syntax with
|
||||
unchanged semantics.
|
||||
|
||||
\begin{description}
|
||||
@@ -1792,9 +1803,6 @@ unchanged semantics.
|
||||
Instruct Xen (and domain 0) to ignore any IOAPICs that are present in
|
||||
the system, and instead continue to use the legacy PIC.
|
||||
|
||||
\item [apic=debug,verbose ]
|
||||
Print more detailed information about local APIC and IOAPIC configuration.
|
||||
|
||||
\end{description}
|
||||
|
||||
\section{XenLinux Boot Options}
|
||||
|
||||
+50
-1
@@ -99,6 +99,13 @@ void clear_local_APIC(void)
|
||||
apic_write_around(APIC_LVTPC, v | APIC_LVT_MASKED);
|
||||
}
|
||||
|
||||
/* lets not touch this if we didn't frob it */
|
||||
#ifdef CONFIG_X86_MCE_P4THERMAL
|
||||
if (maxlvt >= 5) {
|
||||
v = apic_read(APIC_LVTTHMR);
|
||||
apic_write_around(APIC_LVTTHMR, v | APIC_LVT_MASKED);
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* Clean APIC state for other OSs:
|
||||
*/
|
||||
@@ -110,6 +117,10 @@ void clear_local_APIC(void)
|
||||
if (maxlvt >= 4)
|
||||
apic_write_around(APIC_LVTPC, APIC_LVT_MASKED);
|
||||
|
||||
#ifdef CONFIG_X86_MCE_P4THERMAL
|
||||
if (maxlvt >= 5)
|
||||
apic_write_around(APIC_LVTTHMR, APIC_LVT_MASKED);
|
||||
#endif
|
||||
v = GET_APIC_VERSION(apic_read(APIC_LVR));
|
||||
if (APIC_INTEGRATED(v)) { /* !82489DX */
|
||||
if (maxlvt > 3) /* Due to Pentium errata 3AP and 11AP. */
|
||||
@@ -134,6 +145,7 @@ void __init connect_bsp_APIC(void)
|
||||
outb(0x70, 0x22);
|
||||
outb(0x01, 0x23);
|
||||
}
|
||||
enable_apic_mode();
|
||||
}
|
||||
|
||||
void disconnect_bsp_APIC(void)
|
||||
@@ -448,20 +460,45 @@ void __init setup_local_APIC (void)
|
||||
* Original code written by Keir Fraser.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Knob to control our willingness to enable the local APIC.
|
||||
*/
|
||||
int enable_local_apic __initdata = 0; /* -1=force-disable, +1=force-enable */
|
||||
|
||||
static void __init lapic_disable(char *str)
|
||||
{
|
||||
enable_local_apic = -1;
|
||||
clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
|
||||
}
|
||||
custom_param("nolapic", lapic_disable);
|
||||
|
||||
static void __init lapic_enable(char *str)
|
||||
{
|
||||
enable_local_apic = 1;
|
||||
}
|
||||
custom_param("lapic", lapic_enable);
|
||||
|
||||
static void __init apic_set_verbosity(char *str)
|
||||
{
|
||||
if (strcmp("debug", str) == 0)
|
||||
apic_verbosity = APIC_DEBUG;
|
||||
else if (strcmp("verbose", str) == 0)
|
||||
apic_verbosity = APIC_VERBOSE;
|
||||
else
|
||||
printk(KERN_WARNING "APIC Verbosity level %s not recognised"
|
||||
" use apic_verbosity=verbose or apic_verbosity=debug", str);
|
||||
}
|
||||
custom_param("apic", apic_set_verbosity);
|
||||
custom_param("apic_verbosity", apic_set_verbosity);
|
||||
|
||||
static int __init detect_init_APIC (void)
|
||||
{
|
||||
u32 h, l, features;
|
||||
extern void get_cpu_vendor(struct cpuinfo_x86*);
|
||||
|
||||
/* Disabled by kernel option? */
|
||||
if (enable_local_apic < 0)
|
||||
return -1;
|
||||
|
||||
/* Workaround for us being called before identify_cpu(). */
|
||||
get_cpu_vendor(&boot_cpu_data);
|
||||
|
||||
@@ -481,6 +518,15 @@ static int __init detect_init_APIC (void)
|
||||
}
|
||||
|
||||
if (!cpu_has_apic) {
|
||||
/*
|
||||
* Over-ride BIOS and try to enable the local
|
||||
* APIC only if "lapic" specified.
|
||||
*/
|
||||
if (enable_local_apic <= 0) {
|
||||
printk("Local APIC disabled by BIOS -- "
|
||||
"you can enable it with \"lapic\"\n");
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* Some BIOSes disable the local APIC in the
|
||||
* APIC_BASE MSR. This can only be done in
|
||||
@@ -951,6 +997,9 @@ asmlinkage void smp_error_interrupt(struct cpu_user_regs *regs)
|
||||
*/
|
||||
int __init APIC_init_uniprocessor (void)
|
||||
{
|
||||
if (enable_local_apic < 0)
|
||||
clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
|
||||
|
||||
if (!smp_found_config && !cpu_has_apic)
|
||||
return -1;
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ extern struct genapic apic_bigsmp;
|
||||
extern struct genapic apic_es7000;
|
||||
extern struct genapic apic_default;
|
||||
|
||||
struct genapic *genapic = &apic_default;
|
||||
struct genapic *genapic;
|
||||
|
||||
struct genapic *apic_probe[] __initdata = {
|
||||
&apic_summit,
|
||||
@@ -29,38 +29,28 @@ struct genapic *apic_probe[] __initdata = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
void __init generic_apic_probe(char *command_line)
|
||||
{
|
||||
char *s;
|
||||
static void __init genapic_apic_force(char *str)
|
||||
{
|
||||
int i;
|
||||
int changed = 0;
|
||||
for (i = 0; apic_probe[i]; i++)
|
||||
if (!strcmp(apic_probe[i]->name, str))
|
||||
genapic = apic_probe[i];
|
||||
}
|
||||
custom_param("apic", genapic_apic_force);
|
||||
|
||||
void __init generic_apic_probe(void)
|
||||
{
|
||||
int i;
|
||||
int changed = (genapic != NULL);
|
||||
|
||||
s = strstr(command_line, "apic=");
|
||||
if (s && (s == command_line || isspace(s[-1]))) {
|
||||
char *p = strchr(s, ' '), old;
|
||||
if (!p)
|
||||
p = strchr(s, '\0');
|
||||
old = *p;
|
||||
*p = 0;
|
||||
for (i = 0; !changed && apic_probe[i]; i++) {
|
||||
if (!strcmp(apic_probe[i]->name, s+5)) {
|
||||
changed = 1;
|
||||
genapic = apic_probe[i];
|
||||
}
|
||||
}
|
||||
if (!changed)
|
||||
printk(KERN_ERR "Unknown genapic `%s' specified.\n", s);
|
||||
*p = old;
|
||||
}
|
||||
for (i = 0; !changed && apic_probe[i]; i++) {
|
||||
if (apic_probe[i]->probe()) {
|
||||
changed = 1;
|
||||
genapic = apic_probe[i];
|
||||
}
|
||||
}
|
||||
/* Not visible without early console */
|
||||
if (!changed)
|
||||
panic("Didn't find an APIC driver");
|
||||
genapic = &apic_default;
|
||||
|
||||
printk(KERN_INFO "Using APIC driver %s\n", genapic->name);
|
||||
}
|
||||
|
||||
+3
-16
@@ -21,7 +21,7 @@
|
||||
#include <asm/e820.h>
|
||||
|
||||
extern void dmi_scan_machine(void);
|
||||
extern void generic_apic_probe(char *);
|
||||
extern void generic_apic_probe(void);
|
||||
|
||||
/*
|
||||
* opt_xenheap_megabytes: Size of Xen heap in megabytes, excluding the
|
||||
@@ -67,8 +67,6 @@ boolean_param("acpi_skip_timer_override", acpi_skip_timer_override);
|
||||
extern int skip_ioapic_setup;
|
||||
boolean_param("noapic", skip_ioapic_setup);
|
||||
|
||||
static char *xen_cmdline;
|
||||
|
||||
int early_boot = 1;
|
||||
|
||||
int ht_per_core = 1;
|
||||
@@ -179,8 +177,7 @@ static void __init start_of_day(void)
|
||||
|
||||
dmi_scan_machine();
|
||||
|
||||
if ( xen_cmdline != NULL )
|
||||
generic_apic_probe(xen_cmdline);
|
||||
generic_apic_probe();
|
||||
|
||||
acpi_boot_table_init();
|
||||
acpi_boot_init();
|
||||
@@ -251,10 +248,7 @@ void __init __start_xen(multiboot_info_t *mbi)
|
||||
|
||||
/* Parse the command-line options. */
|
||||
if ( (mbi->flags & MBI_CMDLINE) && (mbi->cmdline != 0) )
|
||||
{
|
||||
xen_cmdline = __va(mbi->cmdline);
|
||||
cmdline_parse(xen_cmdline);
|
||||
}
|
||||
cmdline_parse(__va(mbi->cmdline));
|
||||
|
||||
/* Must do this early -- e.g., spinlocks rely on get_current(). */
|
||||
set_current(&idle0_exec_domain);
|
||||
@@ -436,13 +430,6 @@ void __init __start_xen(multiboot_info_t *mbi)
|
||||
strcat(cmdline, " acpi=");
|
||||
strcat(cmdline, acpi_param);
|
||||
}
|
||||
if ( !strstr(cmdline, "apic=") )
|
||||
{
|
||||
if ( apic_verbosity == APIC_VERBOSE )
|
||||
strcat(cmdline, " apic=verbose");
|
||||
else if ( apic_verbosity == APIC_DEBUG )
|
||||
strcat(cmdline, " apic=debug");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||