direct-io.hg

changeset 5211:b2310e7dbfdc

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>
author kaf24@firebug.cl.cam.ac.uk
date Mon May 30 21:15:54 2005 +0000 (2005-05-30)
parents 80f5e85981da
children 0c6cce9d9b82
files docs/src/user.tex xen/arch/x86/apic.c xen/arch/x86/genapic/probe.c xen/arch/x86/setup.c
line diff
     1.1 --- a/docs/src/user.tex	Mon May 30 20:36:03 2005 +0000
     1.2 +++ b/docs/src/user.tex	Mon May 30 21:15:54 2005 +0000
     1.3 @@ -1770,14 +1770,25 @@ editing \path{grub.conf}.
     1.4   Select the CPU scheduler Xen should use.  The current
     1.5   possibilities are `bvt' (default), `atropos' and `rrobin'. 
     1.6   For more information see Section~\ref{s:sched}. 
     1.7 +
     1.8 +\item [apic\_verbosity=debug,verbose ]
     1.9 + Print more detailed information about local APIC and IOAPIC configuration.
    1.10 +
    1.11 +\item [lapic ]
    1.12 + Force use of local APIC even when left disabled by uniprocessor BIOS.
    1.13 +
    1.14 +\item [nolapic ]
    1.15 + Ignore local APIC in a uniprocessor system, even if enabled by the BIOS.
    1.16 +
    1.17 +\item [apic=bigsmp,default,es7000,summit ]
    1.18 + Specify NUMA platform. This can usually be probed automatically.
    1.19 +
    1.20  \end{description} 
    1.21  
    1.22 -In addition, the following platform-specific options may be specified
    1.23 -on the Xen command line. Since domain 0 shares responsibility for
    1.24 -booting the platform, Xen will automatically propagate these options
    1.25 -to its command line.
    1.26 -
    1.27 -These options are taken from Linux's command-line syntax with
    1.28 +In addition, the following options may be specified on the Xen command
    1.29 +line. Since domain 0 shares responsibility for booting the platform,
    1.30 +Xen will automatically propagate these options to its command
    1.31 +line. These options are taken from Linux's command-line syntax with
    1.32  unchanged semantics.
    1.33  
    1.34  \begin{description}
    1.35 @@ -1792,9 +1803,6 @@ unchanged semantics.
    1.36   Instruct Xen (and domain 0) to ignore any IOAPICs that are present in
    1.37   the system, and instead continue to use the legacy PIC.
    1.38  
    1.39 -\item [apic=debug,verbose ]
    1.40 - Print more detailed information about local APIC and IOAPIC configuration.
    1.41 -
    1.42  \end{description} 
    1.43  
    1.44  \section{XenLinux Boot Options}
     2.1 --- a/xen/arch/x86/apic.c	Mon May 30 20:36:03 2005 +0000
     2.2 +++ b/xen/arch/x86/apic.c	Mon May 30 21:15:54 2005 +0000
     2.3 @@ -99,6 +99,13 @@ void clear_local_APIC(void)
     2.4          apic_write_around(APIC_LVTPC, v | APIC_LVT_MASKED);
     2.5      }
     2.6  
     2.7 +/* lets not touch this if we didn't frob it */
     2.8 +#ifdef CONFIG_X86_MCE_P4THERMAL
     2.9 +    if (maxlvt >= 5) {
    2.10 +        v = apic_read(APIC_LVTTHMR);
    2.11 +        apic_write_around(APIC_LVTTHMR, v | APIC_LVT_MASKED);
    2.12 +    }
    2.13 +#endif
    2.14      /*
    2.15       * Clean APIC state for other OSs:
    2.16       */
    2.17 @@ -110,6 +117,10 @@ void clear_local_APIC(void)
    2.18      if (maxlvt >= 4)
    2.19          apic_write_around(APIC_LVTPC, APIC_LVT_MASKED);
    2.20  
    2.21 +#ifdef CONFIG_X86_MCE_P4THERMAL
    2.22 +    if (maxlvt >= 5)
    2.23 +        apic_write_around(APIC_LVTTHMR, APIC_LVT_MASKED);
    2.24 +#endif
    2.25      v = GET_APIC_VERSION(apic_read(APIC_LVR));
    2.26      if (APIC_INTEGRATED(v)) {	/* !82489DX */
    2.27          if (maxlvt > 3)        /* Due to Pentium errata 3AP and 11AP. */
    2.28 @@ -134,6 +145,7 @@ void __init connect_bsp_APIC(void)
    2.29          outb(0x70, 0x22);
    2.30          outb(0x01, 0x23);
    2.31      }
    2.32 +    enable_apic_mode();
    2.33  }
    2.34  
    2.35  void disconnect_bsp_APIC(void)
    2.36 @@ -448,20 +460,45 @@ void __init setup_local_APIC (void)
    2.37   * Original code written by Keir Fraser.
    2.38   */
    2.39  
    2.40 +/*
    2.41 + * Knob to control our willingness to enable the local APIC.
    2.42 + */
    2.43 +int enable_local_apic __initdata = 0; /* -1=force-disable, +1=force-enable */
    2.44 +
    2.45 +static void __init lapic_disable(char *str)
    2.46 +{
    2.47 +    enable_local_apic = -1;
    2.48 +    clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
    2.49 +}
    2.50 +custom_param("nolapic", lapic_disable);
    2.51 +
    2.52 +static void __init lapic_enable(char *str)
    2.53 +{
    2.54 +    enable_local_apic = 1;
    2.55 +}
    2.56 +custom_param("lapic", lapic_enable);
    2.57 +
    2.58  static void __init apic_set_verbosity(char *str)
    2.59  {
    2.60      if (strcmp("debug", str) == 0)
    2.61          apic_verbosity = APIC_DEBUG;
    2.62      else if (strcmp("verbose", str) == 0)
    2.63          apic_verbosity = APIC_VERBOSE;
    2.64 +    else
    2.65 +        printk(KERN_WARNING "APIC Verbosity level %s not recognised"
    2.66 +               " use apic_verbosity=verbose or apic_verbosity=debug", str);
    2.67  }
    2.68 -custom_param("apic", apic_set_verbosity);
    2.69 +custom_param("apic_verbosity", apic_set_verbosity);
    2.70  
    2.71  static int __init detect_init_APIC (void)
    2.72  {
    2.73      u32 h, l, features;
    2.74      extern void get_cpu_vendor(struct cpuinfo_x86*);
    2.75  
    2.76 +    /* Disabled by kernel option? */
    2.77 +    if (enable_local_apic < 0)
    2.78 +        return -1;
    2.79 +
    2.80      /* Workaround for us being called before identify_cpu(). */
    2.81      get_cpu_vendor(&boot_cpu_data);
    2.82  
    2.83 @@ -482,6 +519,15 @@ static int __init detect_init_APIC (void
    2.84  
    2.85      if (!cpu_has_apic) {
    2.86          /*
    2.87 +         * Over-ride BIOS and try to enable the local
    2.88 +         * APIC only if "lapic" specified.
    2.89 +         */
    2.90 +        if (enable_local_apic <= 0) {
    2.91 +            printk("Local APIC disabled by BIOS -- "
    2.92 +                   "you can enable it with \"lapic\"\n");
    2.93 +            return -1;
    2.94 +        }
    2.95 +        /*
    2.96           * Some BIOSes disable the local APIC in the
    2.97           * APIC_BASE MSR. This can only be done in
    2.98           * software for Intel P6 or later and AMD K7
    2.99 @@ -951,6 +997,9 @@ asmlinkage void smp_error_interrupt(stru
   2.100   */
   2.101  int __init APIC_init_uniprocessor (void)
   2.102  {
   2.103 +    if (enable_local_apic < 0)
   2.104 +        clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
   2.105 +
   2.106      if (!smp_found_config && !cpu_has_apic)
   2.107          return -1;
   2.108  
     3.1 --- a/xen/arch/x86/genapic/probe.c	Mon May 30 20:36:03 2005 +0000
     3.2 +++ b/xen/arch/x86/genapic/probe.c	Mon May 30 21:15:54 2005 +0000
     3.3 @@ -19,7 +19,7 @@ extern struct genapic apic_bigsmp;
     3.4  extern struct genapic apic_es7000;
     3.5  extern struct genapic apic_default;
     3.6  
     3.7 -struct genapic *genapic = &apic_default;
     3.8 +struct genapic *genapic;
     3.9  
    3.10  struct genapic *apic_probe[] __initdata = { 
    3.11  	&apic_summit,
    3.12 @@ -29,38 +29,28 @@ struct genapic *apic_probe[] __initdata 
    3.13  	NULL,
    3.14  };
    3.15  
    3.16 -void __init generic_apic_probe(char *command_line) 
    3.17 -{ 
    3.18 -	char *s;
    3.19 +static void __init genapic_apic_force(char *str)
    3.20 +{
    3.21  	int i;
    3.22 -	int changed = 0;
    3.23 +	for (i = 0; apic_probe[i]; i++)
    3.24 +		if (!strcmp(apic_probe[i]->name, str))
    3.25 +			genapic = apic_probe[i];
    3.26 +}
    3.27 +custom_param("apic", genapic_apic_force);
    3.28  
    3.29 -	s = strstr(command_line, "apic=");
    3.30 -	if (s && (s == command_line || isspace(s[-1]))) { 
    3.31 -		char *p = strchr(s, ' '), old; 
    3.32 -		if (!p)
    3.33 -			p = strchr(s, '\0'); 
    3.34 -		old = *p; 
    3.35 -		*p = 0; 
    3.36 -		for (i = 0; !changed && apic_probe[i]; i++) {
    3.37 -			if (!strcmp(apic_probe[i]->name, s+5)) { 
    3.38 -				changed = 1;
    3.39 -				genapic = apic_probe[i];
    3.40 -			}
    3.41 -		}
    3.42 -		if (!changed)
    3.43 -			printk(KERN_ERR "Unknown genapic `%s' specified.\n", s);
    3.44 -		*p = old;
    3.45 -	} 
    3.46 +void __init generic_apic_probe(void) 
    3.47 +{ 
    3.48 +	int i;
    3.49 +	int changed = (genapic != NULL);
    3.50 +
    3.51  	for (i = 0; !changed && apic_probe[i]; i++) { 
    3.52  		if (apic_probe[i]->probe()) {
    3.53  			changed = 1;
    3.54  			genapic = apic_probe[i]; 
    3.55  		} 
    3.56  	}
    3.57 -	/* Not visible without early console */ 
    3.58  	if (!changed) 
    3.59 -		panic("Didn't find an APIC driver"); 
    3.60 +		genapic = &apic_default;
    3.61  
    3.62  	printk(KERN_INFO "Using APIC driver %s\n", genapic->name);
    3.63  } 
     4.1 --- a/xen/arch/x86/setup.c	Mon May 30 20:36:03 2005 +0000
     4.2 +++ b/xen/arch/x86/setup.c	Mon May 30 21:15:54 2005 +0000
     4.3 @@ -21,7 +21,7 @@
     4.4  #include <asm/e820.h>
     4.5  
     4.6  extern void dmi_scan_machine(void);
     4.7 -extern void generic_apic_probe(char *);
     4.8 +extern void generic_apic_probe(void);
     4.9  
    4.10  /*
    4.11   * opt_xenheap_megabytes: Size of Xen heap in megabytes, excluding the
    4.12 @@ -67,8 +67,6 @@ boolean_param("acpi_skip_timer_override"
    4.13  extern int skip_ioapic_setup;
    4.14  boolean_param("noapic", skip_ioapic_setup);
    4.15  
    4.16 -static char *xen_cmdline;
    4.17 -
    4.18  int early_boot = 1;
    4.19  
    4.20  int ht_per_core = 1;
    4.21 @@ -179,8 +177,7 @@ static void __init start_of_day(void)
    4.22  
    4.23      dmi_scan_machine();
    4.24  
    4.25 -    if ( xen_cmdline != NULL )
    4.26 -        generic_apic_probe(xen_cmdline);
    4.27 +    generic_apic_probe();
    4.28  
    4.29      acpi_boot_table_init();
    4.30      acpi_boot_init();
    4.31 @@ -251,10 +248,7 @@ void __init __start_xen(multiboot_info_t
    4.32  
    4.33      /* Parse the command-line options. */
    4.34      if ( (mbi->flags & MBI_CMDLINE) && (mbi->cmdline != 0) )
    4.35 -    {
    4.36 -        xen_cmdline = __va(mbi->cmdline);
    4.37 -        cmdline_parse(xen_cmdline);
    4.38 -    }
    4.39 +        cmdline_parse(__va(mbi->cmdline));
    4.40  
    4.41      /* Must do this early -- e.g., spinlocks rely on get_current(). */
    4.42      set_current(&idle0_exec_domain);
    4.43 @@ -436,13 +430,6 @@ void __init __start_xen(multiboot_info_t
    4.44              strcat(cmdline, " acpi=");
    4.45              strcat(cmdline, acpi_param);
    4.46          }
    4.47 -        if ( !strstr(cmdline, "apic=") )
    4.48 -        {
    4.49 -            if ( apic_verbosity == APIC_VERBOSE )
    4.50 -                strcat(cmdline, " apic=verbose");
    4.51 -            else if ( apic_verbosity == APIC_DEBUG )
    4.52 -                strcat(cmdline, " apic=debug");
    4.53 -        }
    4.54      }
    4.55  
    4.56      /*