Merge branch 'x86/microcode' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 23 Feb 2013 03:22:52 +0000 (19:22 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 23 Feb 2013 03:22:52 +0000 (19:22 -0800)
Pull x86 microcode loading update from Peter Anvin:
 "This patchset lets us update the CPU microcode very, very early in
  initialization if the BIOS fails to do so (never happens, right?)

  This is handy for dealing with things like the Atom erratum where we
  have to run without PSE because microcode loading happens too late.

  As I mentioned in the x86/mm push request it depends on that
  infrastructure but it is otherwise a standalone feature."

* 'x86/microcode' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/Kconfig: Make early microcode loading a configuration feature
  x86/mm/init.c: Copy ucode from initrd image to kernel memory
  x86/head64.c: Early update ucode in 64-bit
  x86/head_32.S: Early update ucode in 32-bit
  x86/microcode_intel_early.c: Early update ucode on Intel's CPU
  x86/tlbflush.h: Define __native_flush_tlb_global_irq_disabled()
  x86/microcode_intel_lib.c: Early update ucode on Intel's CPU
  x86/microcode_core_early.c: Define interfaces for early loading ucode
  x86/common.c: load ucode in 64 bit or show loading ucode info in 32 bit on AP
  x86/common.c: Make have_cpuid_p() a global function
  x86/microcode_intel.h: Define functions and macros for early loading ucode
  x86, doc: Documentation for early microcode loading

1  2 
arch/x86/Kconfig
arch/x86/include/asm/processor.h
arch/x86/kernel/Makefile
arch/x86/kernel/head64.c
arch/x86/kernel/head_32.S

diff --combined arch/x86/Kconfig
@@@ -1,7 -1,7 +1,7 @@@
  # Select 32 or 64 bit
  config 64BIT
        bool "64-bit kernel" if ARCH = "x86"
 -      default ARCH = "x86_64"
 +      default ARCH != "i386"
        ---help---
          Say yes to build a 64-bit kernel - formerly known as x86_64
          Say no to build a 32-bit kernel - formerly known as i386
@@@ -28,6 -28,7 +28,6 @@@ config X8
        select HAVE_OPROFILE
        select HAVE_PCSPKR_PLATFORM
        select HAVE_PERF_EVENTS
 -      select HAVE_IRQ_WORK
        select HAVE_IOREMAP_PROT
        select HAVE_KPROBES
        select HAVE_MEMBLOCK
        select HAVE_DMA_CONTIGUOUS if !SWIOTLB
        select HAVE_KRETPROBES
        select HAVE_OPTPROBES
 +      select HAVE_KPROBES_ON_FTRACE
        select HAVE_FTRACE_MCOUNT_RECORD
        select HAVE_FENTRY if X86_64
        select HAVE_C_RECORDMCOUNT
        select HAVE_DYNAMIC_FTRACE
 +      select HAVE_DYNAMIC_FTRACE_WITH_REGS
        select HAVE_FUNCTION_TRACER
        select HAVE_FUNCTION_GRAPH_TRACER
        select HAVE_FUNCTION_GRAPH_FP_TEST
        select GENERIC_CLOCKEVENTS_BROADCAST if X86_64 || (X86_32 && X86_LOCAL_APIC)
        select GENERIC_TIME_VSYSCALL if X86_64
        select KTIME_SCALAR if X86_32
 +      select ALWAYS_USE_PERSISTENT_CLOCK
        select GENERIC_STRNCPY_FROM_USER
        select GENERIC_STRNLEN_USER
        select HAVE_CONTEXT_TRACKING if X86_64
        select MODULES_USE_ELF_RELA if X86_64
        select CLONE_BACKWARDS if X86_32
        select GENERIC_SIGALTSTACK
 +      select ARCH_USE_BUILTIN_BSWAP
  
  config INSTRUCTION_DECODER
        def_bool y
@@@ -225,7 -222,7 +225,7 @@@ config ARCH_SUPPORTS_DEBUG_PAGEALLO
  
  config HAVE_INTEL_TXT
        def_bool y
 -      depends on EXPERIMENTAL && INTEL_IOMMU && ACPI
 +      depends on INTEL_IOMMU && ACPI
  
  config X86_32_SMP
        def_bool y
@@@ -323,10 -320,6 +323,10 @@@ config X86_BIGSM
        ---help---
          This option is needed for the systems that have more than 8 CPUs
  
 +config GOLDFISH
 +       def_bool y
 +       depends on X86_GOLDFISH
 +
  if X86_32
  config X86_EXTENDED_PLATFORM
        bool "Support for extended (non-PC) x86 platforms"
@@@ -409,14 -402,6 +409,14 @@@ config X86_U
  # Following is an alphabetically sorted list of 32 bit extended platforms
  # Please maintain the alphabetic order if and when there are additions
  
 +config X86_GOLDFISH
 +       bool "Goldfish (Virtual Platform)"
 +       depends on X86_32
 +       ---help---
 +       Enable support for the Goldfish virtual platform used primarily
 +       for Android development. Unless you are building for the Android
 +       Goldfish emulator say N here.
 +
  config X86_INTEL_CE
        bool "CE4100 TV platform"
        depends on PCI
@@@ -469,16 -454,6 +469,16 @@@ config X86_MDFL
  
  endif
  
 +config X86_INTEL_LPSS
 +      bool "Intel Low Power Subsystem Support"
 +      depends on ACPI
 +      select COMMON_CLK
 +      ---help---
 +        Select to build support for Intel Low Power Subsystem such as
 +        found on Intel Lynxpoint PCH. Selecting this option enables
 +        things like clock tree (common clock framework) which are needed
 +        by the LPSS peripheral drivers.
 +
  config X86_RDC321X
        bool "RDC R-321x SoC"
        depends on X86_32
@@@ -642,7 -617,7 +642,7 @@@ config PARAVIR
  
  config PARAVIRT_SPINLOCKS
        bool "Paravirtualization layer for spinlocks"
 -      depends on PARAVIRT && SMP && EXPERIMENTAL
 +      depends on PARAVIRT && SMP
        ---help---
          Paravirtualized spinlocks allow a pvops backend to replace the
          spinlock implementation with something virtualization-friendly
@@@ -754,7 -729,7 +754,7 @@@ config GART_IOMM
  config CALGARY_IOMMU
        bool "IBM Calgary IOMMU support"
        select SWIOTLB
 -      depends on X86_64 && PCI && EXPERIMENTAL
 +      depends on X86_64 && PCI
        ---help---
          Support for hardware IOMMUs in IBM's xSeries x366 and x460
          systems. Needed to run systems with more than 3GB of memory
@@@ -796,7 -771,7 +796,7 @@@ config IOMMU_HELPE
  
  config MAXSMP
        bool "Enable Maximum number of SMP Processors and NUMA Nodes"
 -      depends on X86_64 && SMP && DEBUG_KERNEL && EXPERIMENTAL
 +      depends on X86_64 && SMP && DEBUG_KERNEL
        select CPUMASK_OFFSTACK
        ---help---
          Enable maximum number of CPUS and NUMA Nodes for this architecture.
@@@ -1054,6 -1029,24 +1054,24 @@@ config MICROCODE_OLD_INTERFAC
        def_bool y
        depends on MICROCODE
  
+ config MICROCODE_INTEL_LIB
+       def_bool y
+       depends on MICROCODE_INTEL
+ config MICROCODE_INTEL_EARLY
+       bool "Early load microcode"
+       depends on MICROCODE_INTEL && BLK_DEV_INITRD
+       default y
+       help
+         This option provides functionality to read additional microcode data
+         at the beginning of initrd image. The data tells kernel to load
+         microcode to CPU's as early as possible. No functional change if no
+         microcode data is glued to the initrd, therefore it's safe to say Y.
+ config MICROCODE_EARLY
+       def_bool y
+       depends on MICROCODE_INTEL_EARLY
  config X86_MSR
        tristate "/dev/cpu/*/msr - Model-specific register support"
        ---help---
@@@ -1132,6 -1125,7 +1150,6 @@@ config HIGHMEM64
  endchoice
  
  choice
 -      depends on EXPERIMENTAL
        prompt "Memory split" if EXPERT
        default VMSPLIT_3G
        depends on X86_32
@@@ -1208,7 -1202,7 +1226,7 @@@ config DIRECT_GBPAGE
  config NUMA
        bool "Numa Memory Allocation and Scheduler Support"
        depends on SMP
 -      depends on X86_64 || (X86_32 && HIGHMEM64G && (X86_NUMAQ || X86_BIGSMP || X86_SUMMIT && ACPI) && EXPERIMENTAL)
 +      depends on X86_64 || (X86_32 && HIGHMEM64G && (X86_NUMAQ || X86_BIGSMP || X86_SUMMIT && ACPI))
        default y if (X86_NUMAQ || X86_SUMMIT || X86_BIGSMP)
        ---help---
          Enable NUMA (Non Uniform Memory Access) support.
@@@ -1277,6 -1271,10 +1295,6 @@@ config NODES_SHIF
          Specify the maximum number of NUMA Nodes available on the target
          system.  Increases memory reserved to accommodate various tables.
  
 -config HAVE_ARCH_ALLOC_REMAP
 -      def_bool y
 -      depends on X86_32 && NUMA
 -
  config ARCH_HAVE_MEMORY_PRESENT
        def_bool y
        depends on X86_32 && DISCONTIGMEM
@@@ -1299,7 -1297,7 +1317,7 @@@ config ARCH_DISCONTIGMEM_DEFAUL
  
  config ARCH_SPARSEMEM_ENABLE
        def_bool y
 -      depends on X86_64 || NUMA || (EXPERIMENTAL && X86_32) || X86_32_NON_STANDARD
 +      depends on X86_64 || NUMA || X86_32 || X86_32_NON_STANDARD
        select SPARSEMEM_STATIC if X86_32
        select SPARSEMEM_VMEMMAP_ENABLE if X86_64
  
@@@ -1613,7 -1611,8 +1631,7 @@@ config CRASH_DUM
          For more details see Documentation/kdump/kdump.txt
  
  config KEXEC_JUMP
 -      bool "kexec jump (EXPERIMENTAL)"
 -      depends on EXPERIMENTAL
 +      bool "kexec jump"
        depends on KEXEC && HIBERNATION
        ---help---
          Jump between original kernel and kexeced kernel and invoke
@@@ -1718,7 -1717,7 +1736,7 @@@ config HOTPLUG_CP
  config BOOTPARAM_HOTPLUG_CPU0
        bool "Set default setting of cpu0_hotpluggable"
        default n
 -      depends on HOTPLUG_CPU && EXPERIMENTAL
 +      depends on HOTPLUG_CPU
        ---help---
          Set whether default state of cpu0_hotpluggable is on or off.
  
  config DEBUG_HOTPLUG_CPU0
        def_bool n
        prompt "Debug CPU0 hotplug"
 -      depends on HOTPLUG_CPU && EXPERIMENTAL
 +      depends on HOTPLUG_CPU
        ---help---
          Enabling this option offlines CPU0 (if CPU0 can be offlined) as
          soon as possible and boots up userspace with CPU0 offlined. User
@@@ -1931,7 -1930,6 +1949,7 @@@ config APM_DO_ENABL
          this feature.
  
  config APM_CPU_IDLE
 +      depends on CPU_IDLE
        bool "Make CPU Idle calls when idle"
        ---help---
          Enable calls to APM CPU Idle/CPU Busy inside the kernel's idle loop.
@@@ -2057,7 -2055,7 +2075,7 @@@ config PCI_MMCONFI
  
  config PCI_CNB20LE_QUIRK
        bool "Read CNB20LE Host Bridge Windows" if EXPERT
 -      depends on PCI && EXPERIMENTAL
 +      depends on PCI
        help
          Read the PCI windows out of the CNB20LE host bridge. This allows
          PCI hotplug to work on systems with the CNB20LE chipset which do
@@@ -2158,7 -2156,6 +2176,7 @@@ config OLPC_XO1_RT
  config OLPC_XO1_SCI
        bool "OLPC XO-1 SCI extras"
        depends on OLPC && OLPC_XO1_PM
 +      depends on INPUT=y
        select POWER_SUPPLY
        select GPIO_CS5535
        select MFD_CORE
@@@ -2208,15 -2205,6 +2226,15 @@@ config GEO
        ---help---
          This option enables system support for the Traverse Technologies GEOS.
  
 +config TS5500
 +      bool "Technologic Systems TS-5500 platform support"
 +      depends on MELAN
 +      select CHECK_SIGNATURE
 +      select NEW_LEDS
 +      select LEDS_CLASS
 +      ---help---
 +        This option enables system support for the Technologic Systems TS-5500.
 +
  endif # X86_32
  
  config AMD_NB
@@@ -2261,8 -2249,8 +2279,8 @@@ config IA32_AOU
          Support old a.out binaries in the 32bit emulation.
  
  config X86_X32
 -      bool "x32 ABI for 64-bit mode (EXPERIMENTAL)"
 -      depends on X86_64 && IA32_EMULATION && EXPERIMENTAL
 +      bool "x32 ABI for 64-bit mode"
 +      depends on X86_64 && IA32_EMULATION
        ---help---
          Include code to run binaries for the x32 native 32-bit ABI
          for 64-bit processors.  An x32 process gets access to the
@@@ -89,6 -89,7 +89,6 @@@ struct cpuinfo_x86 
        char                    wp_works_ok;    /* It doesn't on 386's */
  
        /* Problems on some 486Dx4's and old 386's: */
 -      char                    hlt_works_ok;
        char                    hard_math;
        char                    rfu;
        char                    fdiv_bug;
@@@ -164,6 -165,15 +164,6 @@@ DECLARE_PER_CPU_SHARED_ALIGNED(struct c
  
  extern const struct seq_operations cpuinfo_op;
  
 -static inline int hlt_works(int cpu)
 -{
 -#ifdef CONFIG_X86_32
 -      return cpu_data(cpu).hlt_works_ok;
 -#else
 -      return 1;
 -#endif
 -}
 -
  #define cache_line_size()     (boot_cpu_data.x86_cache_alignment)
  
  extern void cpu_detect(struct cpuinfo_x86 *c);
@@@ -180,6 -190,14 +180,14 @@@ extern void init_amd_cacheinfo(struct c
  extern void detect_extended_topology(struct cpuinfo_x86 *c);
  extern void detect_ht(struct cpuinfo_x86 *c);
  
+ #ifdef CONFIG_X86_32
+ extern int have_cpuid_p(void);
+ #else
+ static inline int have_cpuid_p(void)
+ {
+       return 1;
+ }
+ #endif
  static inline void native_cpuid(unsigned int *eax, unsigned int *ebx,
                                unsigned int *ecx, unsigned int *edx)
  {
@@@ -715,7 -733,7 +723,7 @@@ extern unsigned long               boot_option_idle_
  extern bool                   amd_e400_c1e_detected;
  
  enum idle_boot_override {IDLE_NO_OVERRIDE=0, IDLE_HALT, IDLE_NOMWAIT,
 -                       IDLE_POLL, IDLE_FORCE_MWAIT};
 +                       IDLE_POLL};
  
  extern void enable_sep_cpu(void);
  extern int sysenter_setup(void);
@@@ -934,7 -952,7 +942,7 @@@ extern void start_thread(struct pt_reg
  extern int get_tsc_mode(unsigned long adr);
  extern int set_tsc_mode(unsigned int val);
  
 -extern int amd_get_nb_id(int cpu);
 +extern u16 amd_get_nb_id(int cpu);
  
  struct aperfmperf {
        u64 aperf, mperf;
@@@ -989,11 -1007,7 +997,11 @@@ extern unsigned long arch_align_stack(u
  extern void free_init_pages(char *what, unsigned long begin, unsigned long end);
  
  void default_idle(void);
 -bool set_pm_idle_to_default(void);
 +#ifdef        CONFIG_XEN
 +bool xen_set_default_idle(void);
 +#else
 +#define xen_set_default_idle 0
 +#endif
  
  void stop_this_cpu(void *dummy);
  
diff --combined arch/x86/kernel/Makefile
@@@ -65,7 -65,8 +65,7 @@@ obj-$(CONFIG_X86_TSC)         += trace_clock.
  obj-$(CONFIG_KEXEC)           += machine_kexec_$(BITS).o
  obj-$(CONFIG_KEXEC)           += relocate_kernel_$(BITS).o crash.o
  obj-$(CONFIG_CRASH_DUMP)      += crash_dump_$(BITS).o
 -obj-$(CONFIG_KPROBES)         += kprobes.o
 -obj-$(CONFIG_OPTPROBES)               += kprobes-opt.o
 +obj-y                         += kprobes/
  obj-$(CONFIG_MODULES)         += module.o
  obj-$(CONFIG_DOUBLEFAULT)     += doublefault_32.o
  obj-$(CONFIG_KGDB)            += kgdb.o
@@@ -87,6 -88,9 +87,9 @@@ obj-$(CONFIG_PARAVIRT_CLOCK)  += pvclock
  
  obj-$(CONFIG_PCSPKR_PLATFORM) += pcspeaker.o
  
+ obj-$(CONFIG_MICROCODE_EARLY)         += microcode_core_early.o
+ obj-$(CONFIG_MICROCODE_INTEL_EARLY)   += microcode_intel_early.o
+ obj-$(CONFIG_MICROCODE_INTEL_LIB)     += microcode_intel_lib.o
  microcode-y                           := microcode_core.o
  microcode-$(CONFIG_MICROCODE_INTEL)   += microcode_intel.o
  microcode-$(CONFIG_MICROCODE_AMD)     += microcode_amd.o
diff --combined arch/x86/kernel/head64.c
@@@ -26,6 -26,7 +26,7 @@@
  #include <asm/e820.h>
  #include <asm/bios_ebda.h>
  #include <asm/bootparam_utils.h>
+ #include <asm/microcode.h>
  
  /*
   * Manage page tables very early on.
@@@ -159,12 -160,22 +160,17 @@@ void __init x86_64_start_kernel(char * 
        /* clear bss before set_intr_gate with early_idt_handler */
        clear_bss();
  
 -      for (i = 0; i < NUM_EXCEPTION_VECTORS; i++) {
 -#ifdef CONFIG_EARLY_PRINTK
 +      for (i = 0; i < NUM_EXCEPTION_VECTORS; i++)
                set_intr_gate(i, &early_idt_handlers[i]);
 -#else
 -              set_intr_gate(i, early_idt_handler);
 -#endif
 -      }
        load_idt((const struct desc_ptr *)&idt_descr);
  
        copy_bootdata(__va(real_mode_data));
  
+       /*
+        * Load microcode early on BSP.
+        */
+       load_ucode_bsp();
        if (console_loglevel == 10)
                early_printk("Kernel alive\n");
  
@@@ -144,6 -144,11 +144,11 @@@ ENTRY(startup_32
        movl %eax, pa(olpc_ofw_pgd)
  #endif
  
+ #ifdef CONFIG_MICROCODE_EARLY
+       /* Early load ucode on BSP. */
+       call load_ucode_bsp
+ #endif
  /*
   * Initialize page tables.  This creates a PDE and a set of page
   * tables, which are located immediately beyond __brk_base.  The variable
@@@ -299,53 -304,44 +304,59 @@@ ENTRY(startup_32_smp
        movl %eax,%ss
        leal -__PAGE_OFFSET(%ecx),%esp
  
+ #ifdef CONFIG_MICROCODE_EARLY
+       /* Early load ucode on AP. */
+       call load_ucode_ap
+ #endif
  default_entry:
 +#define CR0_STATE     (X86_CR0_PE | X86_CR0_MP | X86_CR0_ET | \
 +                       X86_CR0_NE | X86_CR0_WP | X86_CR0_AM | \
 +                       X86_CR0_PG)
 +      movl $(CR0_STATE & ~X86_CR0_PG),%eax
 +      movl %eax,%cr0
 +
 +/*
 + * We want to start out with EFLAGS unambiguously cleared. Some BIOSes leave
 + * bits like NT set. This would confuse the debugger if this code is traced. So
 + * initialize them properly now before switching to protected mode. That means
 + * DF in particular (even though we have cleared it earlier after copying the
 + * command line) because GCC expects it.
 + */
 +      pushl $0
 +      popfl
 +
  /*
 - *    New page tables may be in 4Mbyte page mode and may
 - *    be using the global pages. 
 + * New page tables may be in 4Mbyte page mode and may be using the global pages.
   *
 - *    NOTE! If we are on a 486 we may have no cr4 at all!
 - *    Specifically, cr4 exists if and only if CPUID exists
 - *    and has flags other than the FPU flag set.
 + * NOTE! If we are on a 486 we may have no cr4 at all! Specifically, cr4 exists
 + * if and only if CPUID exists and has flags other than the FPU flag set.
   */
 +      movl $-1,pa(X86_CPUID)          # preset CPUID level
        movl $X86_EFLAGS_ID,%ecx
        pushl %ecx
 -      popfl
 -      pushfl
 -      popl %eax
 -      pushl $0
 -      popfl
 +      popfl                           # set EFLAGS=ID
        pushfl
 -      popl %edx
 -      xorl %edx,%eax
 -      testl %ecx,%eax
 -      jz 6f                   # No ID flag = no CPUID = no CR4
 +      popl %eax                       # get EFLAGS
 +      testl $X86_EFLAGS_ID,%eax       # did EFLAGS.ID remained set?
 +      jz enable_paging                # hw disallowed setting of ID bit
 +                                      # which means no CPUID and no CR4
 +
 +      xorl %eax,%eax
 +      cpuid
 +      movl %eax,pa(X86_CPUID)         # save largest std CPUID function
  
        movl $1,%eax
        cpuid
 -      andl $~1,%edx           # Ignore CPUID.FPU
 -      jz 6f                   # No flags or only CPUID.FPU = no CR4
 +      andl $~1,%edx                   # Ignore CPUID.FPU
 +      jz enable_paging                # No flags or only CPUID.FPU = no CR4
  
        movl pa(mmu_cr4_features),%eax
        movl %eax,%cr4
  
        testb $X86_CR4_PAE, %al         # check if PAE is enabled
 -      jz 6f
 +      jz enable_paging
  
        /* Check if extended functions are implemented */
        movl $0x80000000, %eax
        /* Value must be in the range 0x80000001 to 0x8000ffff */
        subl $0x80000001, %eax
        cmpl $(0x8000ffff-0x80000001), %eax
 -      ja 6f
 +      ja enable_paging
  
        /* Clear bogus XD_DISABLE bits */
        call verify_cpu
        cpuid
        /* Execute Disable bit supported? */
        btl $(X86_FEATURE_NX & 31), %edx
 -      jnc 6f
 +      jnc enable_paging
  
        /* Setup EFER (Extended Feature Enable Register) */
        movl $MSR_EFER, %ecx
        /* Make changes effective */
        wrmsr
  
 -6:
 +enable_paging:
  
  /*
   * Enable paging
   */
        movl $pa(initial_page_table), %eax
        movl %eax,%cr3          /* set the page table pointer.. */
 -      movl %cr0,%eax
 -      orl  $X86_CR0_PG,%eax
 +      movl $CR0_STATE,%eax
        movl %eax,%cr0          /* ..and set paging (PG) bit */
        ljmp $__BOOT_CS,$1f     /* Clear prefetch and normalize %eip */
  1:
        /* Shift the stack pointer to a virtual address */
        addl $__PAGE_OFFSET, %esp
  
 -/*
 - * Initialize eflags.  Some BIOS's leave bits like NT set.  This would
 - * confuse the debugger if this code is traced.
 - * XXX - best to initialize before switching to protected mode.
 - */
 -      pushl $0
 -      popfl
 -
  /*
   * start system 32-bit setup. We need to re-do some of the things done
   * in 16-bit mode for the "real" operations.
        jz 1f                           # Did we do this already?
        call *%eax
  1:
 -      
 -/* check if it is 486 or 386. */
 +
  /*
 - * XXX - this does a lot of unnecessary setup.  Alignment checks don't
 - * apply at our cpl of 0 and the stack ought to be aligned already, and
 - * we don't need to preserve eflags.
 + * Check if it is 486
   */
 -      movl $-1,X86_CPUID      # -1 for no CPUID initially
 -      movb $3,X86             # at least 386
 -      pushfl                  # push EFLAGS
 -      popl %eax               # get EFLAGS
 -      movl %eax,%ecx          # save original EFLAGS
 -      xorl $0x240000,%eax     # flip AC and ID bits in EFLAGS
 -      pushl %eax              # copy to EFLAGS
 -      popfl                   # set EFLAGS
 -      pushfl                  # get new EFLAGS
 -      popl %eax               # put it in eax
 -      xorl %ecx,%eax          # change in flags
 -      pushl %ecx              # restore original EFLAGS
 -      popfl
 -      testl $0x40000,%eax     # check if AC bit changed
 -      je is386
 -
 -      movb $4,X86             # at least 486
 -      testl $0x200000,%eax    # check if ID bit changed
 +      cmpl $-1,X86_CPUID
        je is486
  
        /* get vendor info */
        movb %cl,X86_MASK
        movl %edx,X86_CAPABILITY
  
 -is486:        movl $0x50022,%ecx      # set AM, WP, NE and MP
 -      jmp 2f
 -
 -is386:        movl $2,%ecx            # set MP
 -2:    movl %cr0,%eax
 +is486:
 +      movb $4,X86
 +      movl $0x50022,%ecx      # set AM, WP, NE and MP
 +      movl %cr0,%eax
        andl $0x80000011,%eax   # Save PG,PE,ET
        orl %ecx,%eax
        movl %eax,%cr0
        xorl %eax,%eax                  # Clear LDT
        lldt %ax
  
 -      cld                     # gcc2 wants the direction flag cleared at all times
        pushl $0                # fake return address for unwinder
        jmp *(initial_code)