diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-18 14:05:47 -0700 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-18 14:05:47 -0700 | 
| commit | 78f28b7c555359c67c2a0d23f7436e915329421e (patch) | |
| tree | 7f8197f82f83c0c19fd9bc85b5d10b5a755d0656 | |
| parent | 3240a77b515f4a15e24d8a3a2135bc87b02cf1d6 (diff) | |
| parent | 7bd867dfb4e0357e06a3211ab2bd0e714110def3 (diff) | |
| download | olio-linux-3.10-78f28b7c555359c67c2a0d23f7436e915329421e.tar.xz olio-linux-3.10-78f28b7c555359c67c2a0d23f7436e915329421e.zip  | |
Merge branch 'x86-platform-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'x86-platform-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (38 commits)
  x86: Move get/set_wallclock to x86_platform_ops
  x86: platform: Fix section annotations
  x86: apic namespace cleanup
  x86: Distangle ioapic and i8259
  x86: Add Moorestown early detection
  x86: Add hardware_subarch ID for Moorestown
  x86: Add early platform detection
  x86: Move tsc_init to late_time_init
  x86: Move tsc_calibration to x86_init_ops
  x86: Replace the now identical time_32/64.c by time.c
  x86: time_32/64.c unify profile_pc
  x86: Move calibrate_cpu to tsc.c
  x86: Make timer setup and global variables the same in time_32/64.c
  x86: Remove mca bus ifdef from timer interrupt
  x86: Simplify timer_ack magic in time_32.c
  x86: Prepare unification of time_32/64.c
  x86: Remove do_timer hook
  x86: Add timer_init to x86_init_ops
  x86: Move percpu clockevents setup to x86_init_ops
  x86: Move xen_post_allocator_init into xen_pagetable_setup_done
  ...
Fix up conflicts in arch/x86/include/asm/io_apic.h
56 files changed, 756 insertions, 907 deletions
diff --git a/Documentation/x86/boot.txt b/Documentation/x86/boot.txt index 8da3a795083..30b43e1b269 100644 --- a/Documentation/x86/boot.txt +++ b/Documentation/x86/boot.txt @@ -599,6 +599,7 @@ Protocol:	2.07+    0x00000000	The default x86/PC environment    0x00000001	lguest    0x00000002	Xen +  0x00000003	Moorestown MID  Field name:	hardware_subarch_data  Type:		write (subarch-dependent) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index e5deee2dfcf..51c59015b28 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -325,6 +325,7 @@ config X86_EXTENDED_PLATFORM  		SGI 320/540 (Visual Workstation)  		Summit/EXA (IBM x440)  		Unisys ES7000 IA32 series +		Moorestown MID devices  	  If you have one of these systems, or if you want to build a  	  generic distribution kernel, say Y here - otherwise say N. @@ -384,6 +385,18 @@ config X86_ELAN  	  If unsure, choose "PC-compatible" instead. +config X86_MRST +       bool "Moorestown MID platform" +	depends on X86_32 +	depends on X86_EXTENDED_PLATFORM +	---help--- +	  Moorestown is Intel's Low Power Intel Architecture (LPIA) based Moblin +	  Internet Device(MID) platform. Moorestown consists of two chips: +	  Lincroft (CPU core, graphics, and memory controller) and Langwell IOH. +	  Unlike standard x86 PCs, Moorestown does not have many legacy devices +	  nor standard legacy replacement devices/features. e.g. Moorestown does +	  not contain i8259, i8254, HPET, legacy BIOS, most of the io ports. +  config X86_RDC321X  	bool "RDC R-321x SoC"  	depends on X86_32 diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index 586b7adb8e5..c6d21b18806 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -70,9 +70,6 @@ static inline void default_inquire_remote_apic(int apicid)   */  #ifdef CONFIG_PARAVIRT  #include <asm/paravirt.h> -#else -#define setup_boot_clock setup_boot_APIC_clock -#define setup_secondary_clock setup_secondary_APIC_clock  #endif  #ifdef CONFIG_X86_64 @@ -252,6 +249,8 @@ static inline void lapic_shutdown(void) { }  static inline void init_apic_mappings(void) { }  static inline void disable_local_APIC(void) { }  static inline void apic_disable(void) { } +# define setup_boot_APIC_clock x86_init_noop +# define setup_secondary_APIC_clock x86_init_noop  #endif /* !CONFIG_X86_LOCAL_APIC */  #ifdef CONFIG_X86_64 @@ -300,7 +299,7 @@ struct apic {  	int (*cpu_present_to_apicid)(int mps_cpu);  	physid_mask_t (*apicid_to_cpu_present)(int phys_apicid);  	void (*setup_portio_remap)(void); -	int (*check_phys_apicid_present)(int boot_cpu_physical_apicid); +	int (*check_phys_apicid_present)(int phys_apicid);  	void (*enable_apic_mode)(void);  	int (*phys_pkg_id)(int cpuid_apic, int index_msb); @@ -434,7 +433,7 @@ extern struct apic apic_x2apic_uv_x;  DECLARE_PER_CPU(int, x2apic_extra_bits);  extern int default_cpu_present_to_apicid(int mps_cpu); -extern int default_check_phys_apicid_present(int boot_cpu_physical_apicid); +extern int default_check_phys_apicid_present(int phys_apicid);  #endif  static inline void default_wait_for_init_deassert(atomic_t *deassert) @@ -550,9 +549,9 @@ static inline int __default_cpu_present_to_apicid(int mps_cpu)  }  static inline int -__default_check_phys_apicid_present(int boot_cpu_physical_apicid) +__default_check_phys_apicid_present(int phys_apicid)  { -	return physid_isset(boot_cpu_physical_apicid, phys_cpu_present_map); +	return physid_isset(phys_apicid, phys_cpu_present_map);  }  #ifdef CONFIG_X86_32 @@ -562,13 +561,13 @@ static inline int default_cpu_present_to_apicid(int mps_cpu)  }  static inline int -default_check_phys_apicid_present(int boot_cpu_physical_apicid) +default_check_phys_apicid_present(int phys_apicid)  { -	return __default_check_phys_apicid_present(boot_cpu_physical_apicid); +	return __default_check_phys_apicid_present(phys_apicid);  }  #else  extern int default_cpu_present_to_apicid(int mps_cpu); -extern int default_check_phys_apicid_present(int boot_cpu_physical_apicid); +extern int default_check_phys_apicid_present(int phys_apicid);  #endif  static inline physid_mask_t default_apicid_to_cpu_present(int phys_apicid) diff --git a/arch/x86/include/asm/bootparam.h b/arch/x86/include/asm/bootparam.h index 6ca20218dd7..6be33d83c71 100644 --- a/arch/x86/include/asm/bootparam.h +++ b/arch/x86/include/asm/bootparam.h @@ -110,4 +110,14 @@ struct boot_params {  	__u8  _pad9[276];				/* 0xeec */  } __attribute__((packed)); +enum { +	X86_SUBARCH_PC = 0, +	X86_SUBARCH_LGUEST, +	X86_SUBARCH_XEN, +	X86_SUBARCH_MRST, +	X86_NR_SUBARCHS, +}; + + +  #endif /* _ASM_X86_BOOTPARAM_H */ diff --git a/arch/x86/include/asm/do_timer.h b/arch/x86/include/asm/do_timer.h deleted file mode 100644 index 23ecda0b28a..00000000000 --- a/arch/x86/include/asm/do_timer.h +++ /dev/null @@ -1,16 +0,0 @@ -/* defines for inline arch setup functions */ -#include <linux/clockchips.h> - -#include <asm/i8259.h> -#include <asm/i8253.h> - -/** - * do_timer_interrupt_hook - hook into timer tick - * - * Call the pit clock event handler. see asm/i8253.h - **/ - -static inline void do_timer_interrupt_hook(void) -{ -	global_clock_event->event_handler(global_clock_event); -} diff --git a/arch/x86/include/asm/e820.h b/arch/x86/include/asm/e820.h index 7ecba4d8508..40b4e614fe7 100644 --- a/arch/x86/include/asm/e820.h +++ b/arch/x86/include/asm/e820.h @@ -126,8 +126,6 @@ extern void e820_reserve_resources(void);  extern void e820_reserve_resources_late(void);  extern void setup_memory_map(void);  extern char *default_machine_specific_memory_setup(void); -extern char *machine_specific_memory_setup(void); -extern char *memory_setup(void);  #endif /* __KERNEL__ */  #endif /* __ASSEMBLY__ */ diff --git a/arch/x86/include/asm/hypervisor.h b/arch/x86/include/asm/hypervisor.h index 369f5c5d09a..b78c0941e42 100644 --- a/arch/x86/include/asm/hypervisor.h +++ b/arch/x86/include/asm/hypervisor.h @@ -20,7 +20,7 @@  #ifndef ASM_X86__HYPERVISOR_H  #define ASM_X86__HYPERVISOR_H -extern unsigned long get_hypervisor_tsc_freq(void);  extern void init_hypervisor(struct cpuinfo_x86 *c); +extern void init_hypervisor_platform(void);  #endif diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h index 85232d32fcb..7c7c16cde1f 100644 --- a/arch/x86/include/asm/io_apic.h +++ b/arch/x86/include/asm/io_apic.h @@ -143,6 +143,8 @@ extern int noioapicreroute;  /* 1 if the timer IRQ uses the '8259A Virtual Wire' mode */  extern int timer_through_8259; +extern void io_apic_disable_legacy(void); +  /*   * If we use the IO-APIC for IRQ routing, disable automatic   * assignment of PCI IRQ's. @@ -176,6 +178,7 @@ extern int setup_ioapic_entry(int apic, int irq,  			      int polarity, int vector, int pin);  extern void ioapic_write_entry(int apic, int pin,  			       struct IO_APIC_route_entry e); +extern void setup_ioapic_ids_from_mpc(void);  struct mp_ioapic_gsi{  	int gsi_base; @@ -187,12 +190,14 @@ int mp_find_ioapic_pin(int ioapic, int gsi);  void __init mp_register_ioapic(int id, u32 address, u32 gsi_base);  #else  /* !CONFIG_X86_IO_APIC */ +  #define io_apic_assign_pci_irqs 0 +#define setup_ioapic_ids_from_mpc x86_init_noop  static const int timer_through_8259 = 0;  static inline void ioapic_init_mappings(void)	{ }  static inline void ioapic_insert_resources(void) { } -  static inline void probe_nr_irqs_gsi(void)	{ } +  #endif  #endif /* _ASM_X86_IO_APIC_H */ diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h index f38481bcd45..ddda6cbed6f 100644 --- a/arch/x86/include/asm/irq.h +++ b/arch/x86/include/asm/irq.h @@ -37,7 +37,6 @@ extern void fixup_irqs(void);  #endif  extern void (*generic_interrupt_extension)(void); -extern void init_IRQ(void);  extern void native_init_IRQ(void);  extern bool handle_irq(unsigned irq, struct pt_regs *regs); @@ -47,4 +46,6 @@ extern unsigned int do_IRQ(struct pt_regs *regs);  extern DECLARE_BITMAP(used_vectors, NR_VECTORS);  extern int vector_used_by_percpu_irq(unsigned int vector); +extern void init_ISA_irqs(void); +  #endif /* _ASM_X86_IRQ_H */ diff --git a/arch/x86/include/asm/mpspec.h b/arch/x86/include/asm/mpspec.h index e2a1bb6d71e..79c94500c0b 100644 --- a/arch/x86/include/asm/mpspec.h +++ b/arch/x86/include/asm/mpspec.h @@ -4,6 +4,7 @@  #include <linux/init.h>  #include <asm/mpspec_def.h> +#include <asm/x86_init.h>  extern int apic_version[MAX_APICS];  extern int pic_mode; @@ -41,9 +42,6 @@ extern int quad_local_to_mp_bus_id [NR_CPUS/4][4];  #endif /* CONFIG_X86_64 */ -extern void early_find_smp_config(void); -extern void early_get_smp_config(void); -  #if defined(CONFIG_MCA) || defined(CONFIG_EISA)  extern int mp_bus_id_to_type[MAX_MP_BUSSES];  #endif @@ -52,20 +50,55 @@ extern DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);  extern unsigned int boot_cpu_physical_apicid;  extern unsigned int max_physical_apicid; -extern int smp_found_config;  extern int mpc_default_type;  extern unsigned long mp_lapic_addr; -extern void get_smp_config(void); +#ifdef CONFIG_X86_LOCAL_APIC +extern int smp_found_config; +#else +# define smp_found_config 0 +#endif + +static inline void get_smp_config(void) +{ +	x86_init.mpparse.get_smp_config(0); +} + +static inline void early_get_smp_config(void) +{ +	x86_init.mpparse.get_smp_config(1); +} + +static inline void find_smp_config(void) +{ +	x86_init.mpparse.find_smp_config(1); +} + +static inline void early_find_smp_config(void) +{ +	x86_init.mpparse.find_smp_config(0); +}  #ifdef CONFIG_X86_MPPARSE -extern void find_smp_config(void);  extern void early_reserve_e820_mpc_new(void);  extern int enable_update_mptable; +extern int default_mpc_apic_id(struct mpc_cpu *m); +extern void default_smp_read_mpc_oem(struct mpc_table *mpc); +# ifdef CONFIG_X86_IO_APIC +extern void default_mpc_oem_bus_info(struct mpc_bus *m, char *str); +# else +#  define default_mpc_oem_bus_info NULL +# endif +extern void default_find_smp_config(unsigned int reserve); +extern void default_get_smp_config(unsigned int early);  #else -static inline void find_smp_config(void) { }  static inline void early_reserve_e820_mpc_new(void) { }  #define enable_update_mptable 0 +#define default_mpc_apic_id NULL +#define default_smp_read_mpc_oem NULL +#define default_mpc_oem_bus_info NULL +#define default_find_smp_config x86_init_uint_noop +#define default_get_smp_config x86_init_uint_noop  #endif  void __cpuinit generic_processor_info(int apicid, int version); diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h index 40d6586af25..8aebcc41041 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h @@ -24,22 +24,6 @@ static inline void load_sp0(struct tss_struct *tss,  	PVOP_VCALL2(pv_cpu_ops.load_sp0, tss, thread);  } -#define ARCH_SETUP			pv_init_ops.arch_setup(); -static inline unsigned long get_wallclock(void) -{ -	return PVOP_CALL0(unsigned long, pv_time_ops.get_wallclock); -} - -static inline int set_wallclock(unsigned long nowtime) -{ -	return PVOP_CALL1(int, pv_time_ops.set_wallclock, nowtime); -} - -static inline void (*choose_time_init(void))(void) -{ -	return pv_time_ops.time_init; -} -  /* The paravirtualized CPUID instruction. */  static inline void __cpuid(unsigned int *eax, unsigned int *ebx,  			   unsigned int *ecx, unsigned int *edx) @@ -245,7 +229,6 @@ static inline unsigned long long paravirt_sched_clock(void)  {  	return PVOP_CALL0(unsigned long long, pv_time_ops.sched_clock);  } -#define calibrate_tsc() (pv_time_ops.get_tsc_khz())  static inline unsigned long long paravirt_read_pmc(int counter)  { @@ -363,34 +346,6 @@ static inline void slow_down_io(void)  #endif  } -#ifdef CONFIG_X86_LOCAL_APIC -static inline void setup_boot_clock(void) -{ -	PVOP_VCALL0(pv_apic_ops.setup_boot_clock); -} - -static inline void setup_secondary_clock(void) -{ -	PVOP_VCALL0(pv_apic_ops.setup_secondary_clock); -} -#endif - -static inline void paravirt_post_allocator_init(void) -{ -	if (pv_init_ops.post_allocator_init) -		(*pv_init_ops.post_allocator_init)(); -} - -static inline void paravirt_pagetable_setup_start(pgd_t *base) -{ -	(*pv_mmu_ops.pagetable_setup_start)(base); -} - -static inline void paravirt_pagetable_setup_done(pgd_t *base) -{ -	(*pv_mmu_ops.pagetable_setup_done)(base); -} -  #ifdef CONFIG_SMP  static inline void startup_ipi_hook(int phys_apicid, unsigned long start_eip,  				    unsigned long start_esp) @@ -948,6 +903,8 @@ static inline unsigned long __raw_local_irq_save(void)  #undef PVOP_VCALL4  #undef PVOP_CALL4 +extern void default_banner(void); +  #else  /* __ASSEMBLY__ */  #define _PVSITE(ptype, clobbers, ops, word, algn)	\ @@ -1088,5 +1045,7 @@ static inline unsigned long __raw_local_irq_save(void)  #endif	/* CONFIG_X86_32 */  #endif /* __ASSEMBLY__ */ -#endif /* CONFIG_PARAVIRT */ +#else  /* CONFIG_PARAVIRT */ +# define default_banner x86_init_noop +#endif /* !CONFIG_PARAVIRT */  #endif /* _ASM_X86_PARAVIRT_H */ diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h index 25402d0006e..dd0f5b32489 100644 --- a/arch/x86/include/asm/paravirt_types.h +++ b/arch/x86/include/asm/paravirt_types.h @@ -78,14 +78,6 @@ struct pv_init_ops {  	 */  	unsigned (*patch)(u8 type, u16 clobber, void *insnbuf,  			  unsigned long addr, unsigned len); - -	/* Basic arch-specific setup */ -	void (*arch_setup)(void); -	char *(*memory_setup)(void); -	void (*post_allocator_init)(void); - -	/* Print a banner to identify the environment */ -	void (*banner)(void);  }; @@ -96,12 +88,6 @@ struct pv_lazy_ops {  };  struct pv_time_ops { -	void (*time_init)(void); - -	/* Set and set time of day */ -	unsigned long (*get_wallclock)(void); -	int (*set_wallclock)(unsigned long); -  	unsigned long long (*sched_clock)(void);  	unsigned long (*get_tsc_khz)(void);  }; @@ -203,8 +189,6 @@ struct pv_cpu_ops {  };  struct pv_irq_ops { -	void (*init_IRQ)(void); -  	/*  	 * Get/set interrupt state.  save_fl and restore_fl are only  	 * expected to use X86_EFLAGS_IF; all other bits @@ -229,9 +213,6 @@ struct pv_irq_ops {  struct pv_apic_ops {  #ifdef CONFIG_X86_LOCAL_APIC -	void (*setup_boot_clock)(void); -	void (*setup_secondary_clock)(void); -  	void (*startup_ipi_hook)(int phys_apicid,  				 unsigned long start_eip,  				 unsigned long start_esp); @@ -239,15 +220,6 @@ struct pv_apic_ops {  };  struct pv_mmu_ops { -	/* -	 * Called before/after init_mm pagetable setup. setup_start -	 * may reset %cr3, and may pre-install parts of the pagetable; -	 * pagetable setup is expected to preserve any existing -	 * mapping. -	 */ -	void (*pagetable_setup_start)(pgd_t *pgd_base); -	void (*pagetable_setup_done)(pgd_t *pgd_base); -  	unsigned long (*read_cr2)(void);  	void (*write_cr2)(unsigned long); diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 4c5b51fdc78..af6fd360ab3 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -56,16 +56,6 @@ extern struct list_head pgd_list;  #define pte_update(mm, addr, ptep)              do { } while (0)  #define pte_update_defer(mm, addr, ptep)        do { } while (0) -static inline void __init paravirt_pagetable_setup_start(pgd_t *base) -{ -	native_pagetable_setup_start(base); -} - -static inline void __init paravirt_pagetable_setup_done(pgd_t *base) -{ -	native_pagetable_setup_done(base); -} -  #define pgd_val(x)	native_pgd_val(x)  #define __pgd(x)	native_make_pgd(x) diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h index 54cb697f490..7b467bf3c68 100644 --- a/arch/x86/include/asm/pgtable_types.h +++ b/arch/x86/include/asm/pgtable_types.h @@ -299,8 +299,8 @@ void set_pte_vaddr(unsigned long vaddr, pte_t pte);  extern void native_pagetable_setup_start(pgd_t *base);  extern void native_pagetable_setup_done(pgd_t *base);  #else -static inline void native_pagetable_setup_start(pgd_t *base) {} -static inline void native_pagetable_setup_done(pgd_t *base) {} +#define native_pagetable_setup_start x86_init_pgd_noop +#define native_pagetable_setup_done  x86_init_pgd_noop  #endif  struct seq_file; diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h index 4093d1ed6db..18e496c98ff 100644 --- a/arch/x86/include/asm/setup.h +++ b/arch/x86/include/asm/setup.h @@ -5,43 +5,6 @@  #define COMMAND_LINE_SIZE 2048 -#ifndef __ASSEMBLY__ - -/* - * Any setup quirks to be performed? - */ -struct mpc_cpu; -struct mpc_bus; -struct mpc_oemtable; - -struct x86_quirks { -	int (*arch_pre_time_init)(void); -	int (*arch_time_init)(void); -	int (*arch_pre_intr_init)(void); -	int (*arch_intr_init)(void); -	int (*arch_trap_init)(void); -	char * (*arch_memory_setup)(void); -	int (*mach_get_smp_config)(unsigned int early); -	int (*mach_find_smp_config)(unsigned int reserve); - -	int *mpc_record; -	int (*mpc_apic_id)(struct mpc_cpu *m); -	void (*mpc_oem_bus_info)(struct mpc_bus *m, char *name); -	void (*mpc_oem_pci_bus)(struct mpc_bus *m); -	void (*smp_read_mpc_oem)(struct mpc_oemtable *oemtable, -				unsigned short oemsize); -	int (*setup_ioapic_ids)(void); -}; - -extern void x86_quirk_intr_init(void); - -extern void x86_quirk_trap_init(void); - -extern void x86_quirk_pre_time_init(void); -extern void x86_quirk_time_init(void); - -#endif /* __ASSEMBLY__ */ -  #ifdef __i386__  #include <linux/pfn.h> @@ -61,6 +24,7 @@ extern void x86_quirk_time_init(void);  #ifndef __ASSEMBLY__  #include <asm/bootparam.h> +#include <asm/x86_init.h>  /* Interrupt control for vSMPowered x86_64 systems */  #ifdef CONFIG_X86_64 @@ -79,11 +43,16 @@ static inline void visws_early_detect(void) { }  static inline int is_visws_box(void) { return 0; }  #endif -extern struct x86_quirks *x86_quirks;  extern unsigned long saved_video_mode; -#ifndef CONFIG_PARAVIRT -#define paravirt_post_allocator_init()	do {} while (0) +extern void reserve_standard_io_resources(void); +extern void i386_reserve_resources(void); +extern void setup_default_timer_irq(void); + +#ifdef CONFIG_X86_MRST +extern void x86_mrst_early_setup(void); +#else +static inline void x86_mrst_early_setup(void) { }  #endif  #ifndef _SETUP diff --git a/arch/x86/include/asm/time.h b/arch/x86/include/asm/time.h index 50c733aac42..7bdec4e9b73 100644 --- a/arch/x86/include/asm/time.h +++ b/arch/x86/include/asm/time.h @@ -4,60 +4,7 @@  extern void hpet_time_init(void);  #include <asm/mc146818rtc.h> -#ifdef CONFIG_X86_32 -#include <linux/efi.h> - -static inline unsigned long native_get_wallclock(void) -{ -	unsigned long retval; - -	if (efi_enabled) -		retval = efi_get_time(); -	else -		retval = mach_get_cmos_time(); - -	return retval; -} - -static inline int native_set_wallclock(unsigned long nowtime) -{ -	int retval; - -	if (efi_enabled) -		retval = efi_set_rtc_mmss(nowtime); -	else -		retval = mach_set_rtc_mmss(nowtime); - -	return retval; -} - -#else -extern void native_time_init_hook(void); - -static inline unsigned long native_get_wallclock(void) -{ -	return mach_get_cmos_time(); -} - -static inline int native_set_wallclock(unsigned long nowtime) -{ -	return mach_set_rtc_mmss(nowtime); -} - -#endif  extern void time_init(void); -#ifdef CONFIG_PARAVIRT -#include <asm/paravirt.h> -#else /* !CONFIG_PARAVIRT */ - -#define get_wallclock() native_get_wallclock() -#define set_wallclock(x) native_set_wallclock(x) -#define choose_time_init() hpet_time_init - -#endif /* CONFIG_PARAVIRT */ - -extern unsigned long __init calibrate_cpu(void); -  #endif /* _ASM_X86_TIME_H */ diff --git a/arch/x86/include/asm/timer.h b/arch/x86/include/asm/timer.h index 20ca9c4d468..5469630b27f 100644 --- a/arch/x86/include/asm/timer.h +++ b/arch/x86/include/asm/timer.h @@ -8,20 +8,16 @@  #define TICK_SIZE (tick_nsec / 1000)  unsigned long long native_sched_clock(void); -unsigned long native_calibrate_tsc(void); +extern int recalibrate_cpu_khz(void); -#ifdef CONFIG_X86_32 +#if defined(CONFIG_X86_32) && defined(CONFIG_X86_IO_APIC)  extern int timer_ack; -extern irqreturn_t timer_interrupt(int irq, void *dev_id); -#endif /* CONFIG_X86_32 */ -extern int recalibrate_cpu_khz(void); +#else +# define timer_ack (0) +#endif  extern int no_timer_check; -#ifndef CONFIG_PARAVIRT -#define calibrate_tsc() native_calibrate_tsc() -#endif -  /* Accelerators for sched_clock()   * convert from cycles(64bits) => nanoseconds (64bits)   *  basic equation: diff --git a/arch/x86/include/asm/tsc.h b/arch/x86/include/asm/tsc.h index 38ae163cc91..c0427295e8f 100644 --- a/arch/x86/include/asm/tsc.h +++ b/arch/x86/include/asm/tsc.h @@ -48,7 +48,8 @@ static __always_inline cycles_t vget_cycles(void)  extern void tsc_init(void);  extern void mark_tsc_unstable(char *reason);  extern int unsynchronized_tsc(void); -int check_tsc_unstable(void); +extern int check_tsc_unstable(void); +extern unsigned long native_calibrate_tsc(void);  /*   * Boot-time check whether the TSCs are synchronized across diff --git a/arch/x86/include/asm/vmware.h b/arch/x86/include/asm/vmware.h index c11b7e100d8..e49ed6d2fd4 100644 --- a/arch/x86/include/asm/vmware.h +++ b/arch/x86/include/asm/vmware.h @@ -20,7 +20,7 @@  #ifndef ASM_X86__VMWARE_H  #define ASM_X86__VMWARE_H -extern unsigned long vmware_get_tsc_khz(void); +extern void vmware_platform_setup(void);  extern int vmware_platform(void);  extern void vmware_set_feature_bits(struct cpuinfo_x86 *c); diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h new file mode 100644 index 00000000000..2c756fd4ab0 --- /dev/null +++ b/arch/x86/include/asm/x86_init.h @@ -0,0 +1,133 @@ +#ifndef _ASM_X86_PLATFORM_H +#define _ASM_X86_PLATFORM_H + +#include <asm/pgtable_types.h> +#include <asm/bootparam.h> + +struct mpc_bus; +struct mpc_cpu; +struct mpc_table; + +/** + * struct x86_init_mpparse - platform specific mpparse ops + * @mpc_record:			platform specific mpc record accounting + * @setup_ioapic_ids:		platform specific ioapic id override + * @mpc_apic_id:		platform specific mpc apic id assignment + * @smp_read_mpc_oem:		platform specific oem mpc table setup + * @mpc_oem_pci_bus:		platform specific pci bus setup (default NULL) + * @mpc_oem_bus_info:		platform specific mpc bus info + * @find_smp_config:		find the smp configuration + * @get_smp_config:		get the smp configuration + */ +struct x86_init_mpparse { +	void (*mpc_record)(unsigned int mode); +	void (*setup_ioapic_ids)(void); +	int (*mpc_apic_id)(struct mpc_cpu *m); +	void (*smp_read_mpc_oem)(struct mpc_table *mpc); +	void (*mpc_oem_pci_bus)(struct mpc_bus *m); +	void (*mpc_oem_bus_info)(struct mpc_bus *m, char *name); +	void (*find_smp_config)(unsigned int reserve); +	void (*get_smp_config)(unsigned int early); +}; + +/** + * struct x86_init_resources - platform specific resource related ops + * @probe_roms:			probe BIOS roms + * @reserve_resources:		reserve the standard resources for the + *				platform + * @memory_setup:		platform specific memory setup + * + */ +struct x86_init_resources { +	void (*probe_roms)(void); +	void (*reserve_resources)(void); +	char *(*memory_setup)(void); +}; + +/** + * struct x86_init_irqs - platform specific interrupt setup + * @pre_vector_init:		init code to run before interrupt vectors + *				are set up. + * @intr_init:			interrupt init code + * @trap_init:			platform specific trap setup + */ +struct x86_init_irqs { +	void (*pre_vector_init)(void); +	void (*intr_init)(void); +	void (*trap_init)(void); +}; + +/** + * struct x86_init_oem - oem platform specific customizing functions + * @arch_setup:			platform specific architecure setup + * @banner:			print a platform specific banner + */ +struct x86_init_oem { +	void (*arch_setup)(void); +	void (*banner)(void); +}; + +/** + * struct x86_init_paging - platform specific paging functions + * @pagetable_setup_start:	platform specific pre paging_init() call + * @pagetable_setup_done:	platform specific post paging_init() call + */ +struct x86_init_paging { +	void (*pagetable_setup_start)(pgd_t *base); +	void (*pagetable_setup_done)(pgd_t *base); +}; + +/** + * struct x86_init_timers - platform specific timer setup + * @setup_perpcu_clockev:	set up the per cpu clock event device for the + *				boot cpu + * @tsc_pre_init:		platform function called before TSC init + * @timer_init:			initialize the platform timer (default PIT/HPET) + */ +struct x86_init_timers { +	void (*setup_percpu_clockev)(void); +	void (*tsc_pre_init)(void); +	void (*timer_init)(void); +}; + +/** + * struct x86_init_ops - functions for platform specific setup + * + */ +struct x86_init_ops { +	struct x86_init_resources	resources; +	struct x86_init_mpparse		mpparse; +	struct x86_init_irqs		irqs; +	struct x86_init_oem		oem; +	struct x86_init_paging		paging; +	struct x86_init_timers		timers; +}; + +/** + * struct x86_cpuinit_ops - platform specific cpu hotplug setups + * @setup_percpu_clockev:	set up the per cpu clock event device + */ +struct x86_cpuinit_ops { +	void (*setup_percpu_clockev)(void); +}; + +/** + * struct x86_platform_ops - platform specific runtime functions + * @calibrate_tsc:		calibrate TSC + * @get_wallclock:		get time from HW clock like RTC etc. + * @set_wallclock:		set time back to HW clock + */ +struct x86_platform_ops { +	unsigned long (*calibrate_tsc)(void); +	unsigned long (*get_wallclock)(void); +	int (*set_wallclock)(unsigned long nowtime); +}; + +extern struct x86_init_ops x86_init; +extern struct x86_cpuinit_ops x86_cpuinit; +extern struct x86_platform_ops x86_platform; + +extern void x86_init_noop(void); +extern void x86_init_uint_noop(unsigned int unused); + +#endif diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 832cb838cb4..4ba419b668a 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -31,8 +31,8 @@ GCOV_PROFILE_paravirt.o		:= n  obj-y			:= process_$(BITS).o signal.o entry_$(BITS).o  obj-y			+= traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o -obj-y			+= time_$(BITS).o ioport.o ldt.o dumpstack.o -obj-y			+= setup.o i8259.o irqinit.o +obj-y			+= time.o ioport.o ldt.o dumpstack.o +obj-y			+= setup.o x86_init.o i8259.o irqinit.o  obj-$(CONFIG_X86_VISWS)	+= visws_quirks.o  obj-$(CONFIG_X86_32)	+= probe_roms_32.o  obj-$(CONFIG_X86_32)	+= sys_i386_32.o i386_ksyms_32.o @@ -105,6 +105,7 @@ obj-$(CONFIG_SCx200)		+= scx200.o  scx200-y			+= scx200_32.o  obj-$(CONFIG_OLPC)		+= olpc.o +obj-$(CONFIG_X86_MRST)		+= mrst.o  microcode-y				:= microcode_core.o  microcode-$(CONFIG_MICROCODE_INTEL)	+= microcode_intel.o diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 159740decc4..a34601f5298 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -36,6 +36,7 @@  #include <linux/mm.h>  #include <asm/perf_counter.h> +#include <asm/x86_init.h>  #include <asm/pgalloc.h>  #include <asm/atomic.h>  #include <asm/mpspec.h> @@ -1709,7 +1710,7 @@ int __init APIC_init_uniprocessor(void)  	localise_nmi_watchdog();  #endif -	setup_boot_clock(); +	x86_init.timers.setup_percpu_clockev();  #ifdef CONFIG_X86_64  	check_nmi_watchdog();  #endif diff --git a/arch/x86/kernel/apic/bigsmp_32.c b/arch/x86/kernel/apic/bigsmp_32.c index 676cdac385c..77a06413b6b 100644 --- a/arch/x86/kernel/apic/bigsmp_32.c +++ b/arch/x86/kernel/apic/bigsmp_32.c @@ -112,7 +112,7 @@ static physid_mask_t bigsmp_ioapic_phys_id_map(physid_mask_t phys_map)  	return physids_promote(0xFFL);  } -static int bigsmp_check_phys_apicid_present(int boot_cpu_physical_apicid) +static int bigsmp_check_phys_apicid_present(int phys_apicid)  {  	return 1;  } diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 3c8f9e75d03..809e1cf86d6 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -96,6 +96,11 @@ struct mpc_intsrc mp_irqs[MAX_IRQ_SOURCES];  /* # of MP IRQ source entries */  int mp_irq_entries; +/* Number of legacy interrupts */ +static int nr_legacy_irqs __read_mostly = NR_IRQS_LEGACY; +/* GSI interrupts */ +static int nr_irqs_gsi = NR_IRQS_LEGACY; +  #if defined (CONFIG_MCA) || defined (CONFIG_EISA)  int mp_bus_id_to_type[MAX_MP_BUSSES];  #endif @@ -173,6 +178,12 @@ static struct irq_cfg irq_cfgx[NR_IRQS] = {  	[15] = { .vector = IRQ15_VECTOR, },  }; +void __init io_apic_disable_legacy(void) +{ +	nr_legacy_irqs = 0; +	nr_irqs_gsi = 0; +} +  int __init arch_early_irq_init(void)  {  	struct irq_cfg *cfg; @@ -190,7 +201,7 @@ int __init arch_early_irq_init(void)  		desc->chip_data = &cfg[i];  		zalloc_cpumask_var_node(&cfg[i].domain, GFP_NOWAIT, node);  		zalloc_cpumask_var_node(&cfg[i].old_domain, GFP_NOWAIT, node); -		if (i < NR_IRQS_LEGACY) +		if (i < nr_legacy_irqs)  			cpumask_setall(cfg[i].domain);  	} @@ -867,7 +878,7 @@ static int __init find_isa_irq_apic(int irq, int type)   */  static int EISA_ELCR(unsigned int irq)  { -	if (irq < NR_IRQS_LEGACY) { +	if (irq < nr_legacy_irqs) {  		unsigned int port = 0x4d0 + (irq >> 3);  		return (inb(port) >> (irq & 7)) & 1;  	} @@ -1464,7 +1475,7 @@ static void setup_IO_APIC_irq(int apic_id, int pin, unsigned int irq, struct irq  	}  	ioapic_register_intr(irq, desc, trigger); -	if (irq < NR_IRQS_LEGACY) +	if (irq < nr_legacy_irqs)  		disable_8259A_irq(irq);  	ioapic_write_entry(apic_id, pin, entry); @@ -1831,7 +1842,7 @@ __apicdebuginit(void) print_PIC(void)  	unsigned int v;  	unsigned long flags; -	if (apic_verbosity == APIC_QUIET) +	if (apic_verbosity == APIC_QUIET || !nr_legacy_irqs)  		return;  	printk(KERN_DEBUG "\nprinting PIC contents\n"); @@ -1894,6 +1905,10 @@ void __init enable_IO_APIC(void)  		spin_unlock_irqrestore(&ioapic_lock, flags);  		nr_ioapic_registers[apic] = reg_01.bits.entries+1;  	} + +	if (!nr_legacy_irqs) +		return; +  	for(apic = 0; apic < nr_ioapics; apic++) {  		int pin;  		/* See if any of the pins is in ExtINT mode */ @@ -1948,6 +1963,9 @@ void disable_IO_APIC(void)  	 */  	clear_IO_APIC(); +	if (!nr_legacy_irqs) +		return; +  	/*  	 * If the i8259 is routed through an IOAPIC  	 * Put that IOAPIC in virtual wire mode @@ -1994,7 +2012,7 @@ void disable_IO_APIC(void)   * by Matt Domsch <Matt_Domsch@dell.com>  Tue Dec 21 12:25:05 CST 1999   */ -static void __init setup_ioapic_ids_from_mpc(void) +void __init setup_ioapic_ids_from_mpc(void)  {  	union IO_APIC_reg_00 reg_00;  	physid_mask_t phys_id_present_map; @@ -2003,9 +2021,8 @@ static void __init setup_ioapic_ids_from_mpc(void)  	unsigned char old_id;  	unsigned long flags; -	if (x86_quirks->setup_ioapic_ids && x86_quirks->setup_ioapic_ids()) +	if (acpi_ioapic)  		return; -  	/*  	 * Don't check I/O APIC IDs for xAPIC systems.  They have  	 * no meaning without the serial APIC bus. @@ -2179,7 +2196,7 @@ static unsigned int startup_ioapic_irq(unsigned int irq)  	struct irq_cfg *cfg;  	spin_lock_irqsave(&ioapic_lock, flags); -	if (irq < NR_IRQS_LEGACY) { +	if (irq < nr_legacy_irqs) {  		disable_8259A_irq(irq);  		if (i8259A_irq_pending(irq))  			was_pending = 1; @@ -2657,7 +2674,7 @@ static inline void init_IO_APIC_traps(void)  			 * so default to an old-fashioned 8259  			 * interrupt if we can..  			 */ -			if (irq < NR_IRQS_LEGACY) +			if (irq < nr_legacy_irqs)  				make_8259A_irq(irq);  			else  				/* Strange. Oh, well.. */ @@ -2993,7 +3010,7 @@ out:   * the I/O APIC in all cases now.  No actual device should request   * it anyway.  --macro   */ -#define PIC_IRQS	(1 << PIC_CASCADE_IR) +#define PIC_IRQS	(1UL << PIC_CASCADE_IR)  void __init setup_IO_APIC(void)  { @@ -3001,21 +3018,19 @@ void __init setup_IO_APIC(void)  	/*  	 * calling enable_IO_APIC() is moved to setup_local_APIC for BP  	 */ - -	io_apic_irqs = ~PIC_IRQS; +	io_apic_irqs = nr_legacy_irqs ? ~PIC_IRQS : ~0UL;  	apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n");  	/*           * Set up IO-APIC IRQ routing.           */ -#ifdef CONFIG_X86_32 -	if (!acpi_ioapic) -		setup_ioapic_ids_from_mpc(); -#endif +	x86_init.mpparse.setup_ioapic_ids(); +  	sync_Arb_IDs();  	setup_IO_APIC_irqs();  	init_IO_APIC_traps(); -	check_timer(); +	if (nr_legacy_irqs) +		check_timer();  }  /* @@ -3116,7 +3131,6 @@ static int __init ioapic_init_sysfs(void)  device_initcall(ioapic_init_sysfs); -static int nr_irqs_gsi = NR_IRQS_LEGACY;  /*   * Dynamic irq allocate and deallocation   */ @@ -3856,7 +3870,7 @@ static int __io_apic_set_pci_routing(struct device *dev, int irq,  	/*  	 * IRQs < 16 are already in the irq_2_pin[] map  	 */ -	if (irq >= NR_IRQS_LEGACY) { +	if (irq >= nr_legacy_irqs) {  		cfg = desc->chip_data;  		if (add_pin_to_irq_node_nopanic(cfg, node, ioapic, pin)) {  			printk(KERN_INFO "can not add pin %d for irq %d\n", diff --git a/arch/x86/kernel/apic/numaq_32.c b/arch/x86/kernel/apic/numaq_32.c index ca96e68f0d2..efa00e2b850 100644 --- a/arch/x86/kernel/apic/numaq_32.c +++ b/arch/x86/kernel/apic/numaq_32.c @@ -66,7 +66,6 @@ struct mpc_trans {  	unsigned short			trans_reserved;  }; -/* x86_quirks member */  static int				mpc_record;  static struct mpc_trans			*translation_table[MAX_MPC_ENTRY]; @@ -130,10 +129,9 @@ void __cpuinit numaq_tsc_disable(void)  	}  } -static int __init numaq_pre_time_init(void) +static void __init numaq_tsc_init(void)  {  	numaq_tsc_disable(); -	return 0;  }  static inline int generate_logical_apicid(int quad, int phys_apicid) @@ -177,6 +175,19 @@ static void mpc_oem_pci_bus(struct mpc_bus *m)  	quad_local_to_mp_bus_id[quad][local] = m->busid;  } +/* + * Called from mpparse code. + * mode = 0: prescan + * mode = 1: one mpc entry scanned + */ +static void numaq_mpc_record(unsigned int mode) +{ +	if (!mode) +		mpc_record = 0; +	else +		mpc_record++; +} +  static void __init MP_translation_info(struct mpc_trans *m)  {  	printk(KERN_INFO @@ -206,9 +217,9 @@ static int __init mpf_checksum(unsigned char *mp, int len)  /*   * Read/parse the MPC oem tables   */ -static void __init - smp_read_mpc_oem(struct mpc_oemtable *oemtable, unsigned short oemsize) +static void __init smp_read_mpc_oem(struct mpc_table *mpc)  { +	struct mpc_oemtable *oemtable = (void *)(long)mpc->oemptr;  	int count = sizeof(*oemtable);	/* the header size */  	unsigned char *oemptr = ((unsigned char *)oemtable) + count; @@ -250,29 +261,6 @@ static void __init  	}  } -static int __init numaq_setup_ioapic_ids(void) -{ -	/* so can skip it */ -	return 1; -} - -static struct x86_quirks numaq_x86_quirks __initdata = { -	.arch_pre_time_init		= numaq_pre_time_init, -	.arch_time_init			= NULL, -	.arch_pre_intr_init		= NULL, -	.arch_memory_setup		= NULL, -	.arch_intr_init			= NULL, -	.arch_trap_init			= NULL, -	.mach_get_smp_config		= NULL, -	.mach_find_smp_config		= NULL, -	.mpc_record			= &mpc_record, -	.mpc_apic_id			= mpc_apic_id, -	.mpc_oem_bus_info		= mpc_oem_bus_info, -	.mpc_oem_pci_bus		= mpc_oem_pci_bus, -	.smp_read_mpc_oem		= smp_read_mpc_oem, -	.setup_ioapic_ids		= numaq_setup_ioapic_ids, -}; -  static __init void early_check_numaq(void)  {  	/* @@ -286,8 +274,15 @@ static __init void early_check_numaq(void)  	if (smp_found_config)  		early_get_smp_config(); -	if (found_numaq) -		x86_quirks = &numaq_x86_quirks; +	if (found_numaq) { +		x86_init.mpparse.mpc_record = numaq_mpc_record; +		x86_init.mpparse.setup_ioapic_ids = x86_init_noop; +		x86_init.mpparse.mpc_apic_id = mpc_apic_id; +		x86_init.mpparse.smp_read_mpc_oem = smp_read_mpc_oem; +		x86_init.mpparse.mpc_oem_pci_bus = mpc_oem_pci_bus; +		x86_init.mpparse.mpc_oem_bus_info = mpc_oem_bus_info; +		x86_init.timers.tsc_pre_init = numaq_tsc_init; +	}  }  int __init get_memcfg_numaq(void) @@ -418,7 +413,7 @@ static inline physid_mask_t numaq_apicid_to_cpu_present(int logical_apicid)  /* Where the IO area was mapped on multiquad, always 0 otherwise */  void *xquad_portio; -static inline int numaq_check_phys_apicid_present(int boot_cpu_physical_apicid) +static inline int numaq_check_phys_apicid_present(int phys_apicid)  {  	return 1;  } diff --git a/arch/x86/kernel/apic/summit_32.c b/arch/x86/kernel/apic/summit_32.c index eafdfbd1ea9..645ecc4ff0b 100644 --- a/arch/x86/kernel/apic/summit_32.c +++ b/arch/x86/kernel/apic/summit_32.c @@ -272,7 +272,7 @@ static physid_mask_t summit_apicid_to_cpu_present(int apicid)  	return physid_mask_of_physid(0);  } -static int summit_check_phys_apicid_present(int boot_cpu_physical_apicid) +static int summit_check_phys_apicid_present(int physical_apicid)  {  	return 1;  } diff --git a/arch/x86/kernel/cpu/hypervisor.c b/arch/x86/kernel/cpu/hypervisor.c index 93ba8eeb100..08be922de33 100644 --- a/arch/x86/kernel/cpu/hypervisor.c +++ b/arch/x86/kernel/cpu/hypervisor.c @@ -34,13 +34,6 @@ detect_hypervisor_vendor(struct cpuinfo_x86 *c)  		c->x86_hyper_vendor = X86_HYPER_VENDOR_NONE;  } -unsigned long get_hypervisor_tsc_freq(void) -{ -	if (boot_cpu_data.x86_hyper_vendor == X86_HYPER_VENDOR_VMWARE) -		return vmware_get_tsc_khz(); -	return 0; -} -  static inline void __cpuinit  hypervisor_set_feature_bits(struct cpuinfo_x86 *c)  { @@ -55,3 +48,10 @@ void __cpuinit init_hypervisor(struct cpuinfo_x86 *c)  	detect_hypervisor_vendor(c);  	hypervisor_set_feature_bits(c);  } + +void __init init_hypervisor_platform(void) +{ +	init_hypervisor(&boot_cpu_data); +	if (boot_cpu_data.x86_hyper_vendor == X86_HYPER_VENDOR_VMWARE) +		vmware_platform_setup(); +} diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c index bc24f514ec9..0a46b4df5d8 100644 --- a/arch/x86/kernel/cpu/vmware.c +++ b/arch/x86/kernel/cpu/vmware.c @@ -24,6 +24,7 @@  #include <linux/dmi.h>  #include <asm/div64.h>  #include <asm/vmware.h> +#include <asm/x86_init.h>  #define CPUID_VMWARE_INFO_LEAF	0x40000000  #define VMWARE_HYPERVISOR_MAGIC	0x564D5868 @@ -47,21 +48,29 @@ static inline int __vmware_platform(void)  	return eax != (uint32_t)-1 && ebx == VMWARE_HYPERVISOR_MAGIC;  } -static unsigned long __vmware_get_tsc_khz(void) +static unsigned long vmware_get_tsc_khz(void)  {  	uint64_t tsc_hz;  	uint32_t eax, ebx, ecx, edx;  	VMWARE_PORT(GETHZ, eax, ebx, ecx, edx); -	if (ebx == UINT_MAX) -		return 0;  	tsc_hz = eax | (((uint64_t)ebx) << 32);  	do_div(tsc_hz, 1000);  	BUG_ON(tsc_hz >> 32);  	return tsc_hz;  } +void __init vmware_platform_setup(void) +{ +	uint32_t eax, ebx, ecx, edx; + +	VMWARE_PORT(GETHZ, eax, ebx, ecx, edx); + +	if (ebx != UINT_MAX) +		x86_platform.calibrate_tsc = vmware_get_tsc_khz; +} +  /*   * While checking the dmi string infomation, just checking the product   * serial key should be enough, as this will always have a VMware @@ -87,12 +96,6 @@ int vmware_platform(void)  	return 0;  } -unsigned long vmware_get_tsc_khz(void) -{ -	BUG_ON(!vmware_platform()); -	return __vmware_get_tsc_khz(); -} -  /*   * VMware hypervisor takes care of exporting a reliable TSC to the guest.   * Still, due to timing difference when running on virtual cpus, the TSC can diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index 147005a1cc3..a3210ce1ecc 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -1455,28 +1455,11 @@ char *__init default_machine_specific_memory_setup(void)  	return who;  } -char *__init __attribute__((weak)) machine_specific_memory_setup(void) -{ -	if (x86_quirks->arch_memory_setup) { -		char *who = x86_quirks->arch_memory_setup(); - -		if (who) -			return who; -	} -	return default_machine_specific_memory_setup(); -} - -/* Overridden in paravirt.c if CONFIG_PARAVIRT */ -char * __init __attribute__((weak)) memory_setup(void) -{ -	return machine_specific_memory_setup(); -} -  void __init setup_memory_map(void)  {  	char *who; -	who = memory_setup(); +	who = x86_init.resources.memory_setup();  	memcpy(&e820_saved, &e820, sizeof(struct e820map));  	printk(KERN_INFO "BIOS-provided physical RAM map:\n");  	e820_print_map(who); diff --git a/arch/x86/kernel/efi.c b/arch/x86/kernel/efi.c index fe26ba3e345..ad5bd988fb7 100644 --- a/arch/x86/kernel/efi.c +++ b/arch/x86/kernel/efi.c @@ -42,6 +42,7 @@  #include <asm/time.h>  #include <asm/cacheflush.h>  #include <asm/tlbflush.h> +#include <asm/x86_init.h>  #define EFI_DEBUG	1  #define PFX 		"EFI: " @@ -453,6 +454,9 @@ void __init efi_init(void)  	if (add_efi_memmap)  		do_add_efi_memmap(); +	x86_platform.get_wallclock = efi_get_time; +	x86_platform.set_wallclock = efi_set_rtc_mmss; +  	/* Setup for EFI runtime service */  	reboot_type = BOOT_EFI; diff --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c index 3f8579f8d42..4f8e2507e8f 100644 --- a/arch/x86/kernel/head32.c +++ b/arch/x86/kernel/head32.c @@ -11,8 +11,21 @@  #include <asm/setup.h>  #include <asm/sections.h>  #include <asm/e820.h> -#include <asm/bios_ebda.h> +#include <asm/page.h>  #include <asm/trampoline.h> +#include <asm/apic.h> +#include <asm/io_apic.h> +#include <asm/bios_ebda.h> + +static void __init i386_default_early_setup(void) +{ +	/* Initilize 32bit specific setup functions */ +	x86_init.resources.probe_roms = probe_roms; +	x86_init.resources.reserve_resources = i386_reserve_resources; +	x86_init.mpparse.setup_ioapic_ids = setup_ioapic_ids_from_mpc; + +	reserve_ebda_region(); +}  void __init i386_start_kernel(void)  { @@ -29,7 +42,16 @@ void __init i386_start_kernel(void)  		reserve_early(ramdisk_image, ramdisk_end, "RAMDISK");  	}  #endif -	reserve_ebda_region(); + +	/* Call the subarch specific early setup function */ +	switch (boot_params.hdr.hardware_subarch) { +	case X86_SUBARCH_MRST: +		x86_mrst_early_setup(); +		break; +	default: +		i386_default_early_setup(); +		break; +	}  	/*  	 * At this point everything still needed from the boot loader diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index 70eaa852c73..0b06cd778fd 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c @@ -23,8 +23,8 @@  #include <asm/sections.h>  #include <asm/kdebug.h>  #include <asm/e820.h> -#include <asm/bios_ebda.h>  #include <asm/trampoline.h> +#include <asm/bios_ebda.h>  static void __init zap_identity_mappings(void)  { diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S index 7ffec6b3b33..b766e8c7252 100644 --- a/arch/x86/kernel/head_32.S +++ b/arch/x86/kernel/head_32.S @@ -157,6 +157,7 @@ subarch_entries:  	.long default_entry		/* normal x86/PC */  	.long lguest_entry		/* lguest hypervisor */  	.long xen_entry			/* Xen hypervisor */ +	.long default_entry		/* Moorestown MID */  num_subarch_entries = (. - subarch_entries) / 4  .previous  #endif /* CONFIG_PARAVIRT */ diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c index ccf8ab54f31..300883112e3 100644 --- a/arch/x86/kernel/irqinit.c +++ b/arch/x86/kernel/irqinit.c @@ -116,7 +116,7 @@ int vector_used_by_percpu_irq(unsigned int vector)  	return 0;  } -static void __init init_ISA_irqs(void) +void __init init_ISA_irqs(void)  {  	int i; @@ -140,8 +140,10 @@ static void __init init_ISA_irqs(void)  	}  } -/* Overridden in paravirt.c */ -void init_IRQ(void) __attribute__((weak, alias("native_init_IRQ"))); +void __init init_IRQ(void) +{ +	x86_init.irqs.intr_init(); +}  static void __init smp_intr_init(void)  { @@ -213,32 +215,12 @@ static void __init apic_intr_init(void)  #endif  } -/** - * x86_quirk_pre_intr_init - initialisation prior to setting up interrupt vectors - * - * Description: - *	Perform any necessary interrupt initialisation prior to setting up - *	the "ordinary" interrupt call gates.  For legacy reasons, the ISA - *	interrupts should be initialised here if the machine emulates a PC - *	in any way. - **/ -static void __init x86_quirk_pre_intr_init(void) -{ -#ifdef CONFIG_X86_32 -	if (x86_quirks->arch_pre_intr_init) { -		if (x86_quirks->arch_pre_intr_init()) -			return; -	} -#endif -	init_ISA_irqs(); -} -  void __init native_init_IRQ(void)  {  	int i;  	/* Execute any quirks before the call gates are initialised: */ -	x86_quirk_pre_intr_init(); +	x86_init.irqs.pre_vector_init();  	apic_intr_init(); @@ -258,12 +240,6 @@ void __init native_init_IRQ(void)  #ifdef CONFIG_X86_32  	/* -	 * Call quirks after call gates are initialised (usually add in -	 * the architecture specific gates): -	 */ -	x86_quirk_intr_init(); - -	/*  	 * External FPU? Set up irq13 if so, for  	 * original braindamaged IBM FERR coupling.  	 */ diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c index e5efcdcca31..feaeb0d3aa4 100644 --- a/arch/x86/kernel/kvmclock.c +++ b/arch/x86/kernel/kvmclock.c @@ -22,6 +22,8 @@  #include <asm/msr.h>  #include <asm/apic.h>  #include <linux/percpu.h> + +#include <asm/x86_init.h>  #include <asm/reboot.h>  #define KVM_SCALE 22 @@ -182,12 +184,13 @@ void __init kvmclock_init(void)  	if (kvmclock && kvm_para_has_feature(KVM_FEATURE_CLOCKSOURCE)) {  		if (kvm_register_clock("boot clock"))  			return; -		pv_time_ops.get_wallclock = kvm_get_wallclock; -		pv_time_ops.set_wallclock = kvm_set_wallclock;  		pv_time_ops.sched_clock = kvm_clock_read; -		pv_time_ops.get_tsc_khz = kvm_get_tsc_khz; +		x86_platform.calibrate_tsc = kvm_get_tsc_khz; +		x86_platform.get_wallclock = kvm_get_wallclock; +		x86_platform.set_wallclock = kvm_set_wallclock;  #ifdef CONFIG_X86_LOCAL_APIC -		pv_apic_ops.setup_secondary_clock = kvm_setup_secondary_clock; +		x86_cpuinit.setup_percpu_clockev = +			kvm_setup_secondary_clock;  #endif  #ifdef CONFIG_SMP  		smp_ops.smp_prepare_boot_cpu = kvm_smp_prepare_boot_cpu; diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index fcd513bf284..5be95ef4ffe 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c @@ -45,6 +45,11 @@ static int __init mpf_checksum(unsigned char *mp, int len)  	return sum & 0xFF;  } +int __init default_mpc_apic_id(struct mpc_cpu *m) +{ +	return m->apicid; +} +  static void __init MP_processor_info(struct mpc_cpu *m)  {  	int apicid; @@ -55,10 +60,7 @@ static void __init MP_processor_info(struct mpc_cpu *m)  		return;  	} -	if (x86_quirks->mpc_apic_id) -		apicid = x86_quirks->mpc_apic_id(m); -	else -		apicid = m->apicid; +	apicid = x86_init.mpparse.mpc_apic_id(m);  	if (m->cpuflag & CPU_BOOTPROCESSOR) {  		bootup_cpu = " (Bootup-CPU)"; @@ -70,16 +72,18 @@ static void __init MP_processor_info(struct mpc_cpu *m)  }  #ifdef CONFIG_X86_IO_APIC -static void __init MP_bus_info(struct mpc_bus *m) +void __init default_mpc_oem_bus_info(struct mpc_bus *m, char *str)  { -	char str[7];  	memcpy(str, m->bustype, 6);  	str[6] = 0; +	apic_printk(APIC_VERBOSE, "Bus #%d is %s\n", m->busid, str); +} -	if (x86_quirks->mpc_oem_bus_info) -		x86_quirks->mpc_oem_bus_info(m, str); -	else -		apic_printk(APIC_VERBOSE, "Bus #%d is %s\n", m->busid, str); +static void __init MP_bus_info(struct mpc_bus *m) +{ +	char str[7]; + +	x86_init.mpparse.mpc_oem_bus_info(m, str);  #if MAX_MP_BUSSES < 256  	if (m->busid >= MAX_MP_BUSSES) { @@ -96,8 +100,8 @@ static void __init MP_bus_info(struct mpc_bus *m)  		mp_bus_id_to_type[m->busid] = MP_BUS_ISA;  #endif  	} else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI) - 1) == 0) { -		if (x86_quirks->mpc_oem_pci_bus) -			x86_quirks->mpc_oem_pci_bus(m); +		if (x86_init.mpparse.mpc_oem_pci_bus) +			x86_init.mpparse.mpc_oem_pci_bus(m);  		clear_bit(m->busid, mp_bus_not_pci);  #if defined(CONFIG_EISA) || defined(CONFIG_MCA) @@ -291,6 +295,8 @@ static void __init smp_dump_mptable(struct mpc_table *mpc, unsigned char *mpt)  			1, mpc, mpc->length, 1);  } +void __init default_smp_read_mpc_oem(struct mpc_table *mpc) { } +  static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early)  {  	char str[16]; @@ -312,16 +318,13 @@ static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early)  	if (early)  		return 1; -	if (mpc->oemptr && x86_quirks->smp_read_mpc_oem) { -		struct mpc_oemtable *oem_table = (void *)(long)mpc->oemptr; -		x86_quirks->smp_read_mpc_oem(oem_table, mpc->oemsize); -	} +	if (mpc->oemptr) +		x86_init.mpparse.smp_read_mpc_oem(mpc);  	/*  	 *      Now process the configuration blocks.  	 */ -	if (x86_quirks->mpc_record) -		*x86_quirks->mpc_record = 0; +	x86_init.mpparse.mpc_record(0);  	while (count < mpc->length) {  		switch (*mpt) { @@ -353,8 +356,7 @@ static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early)  			count = mpc->length;  			break;  		} -		if (x86_quirks->mpc_record) -			(*x86_quirks->mpc_record)++; +		x86_init.mpparse.mpc_record(1);  	}  #ifdef CONFIG_X86_BIGSMP @@ -608,7 +610,7 @@ static int __init check_physptr(struct mpf_intel *mpf, unsigned int early)  /*   * Scan the memory blocks for an SMP configuration block.   */ -static void __init __get_smp_config(unsigned int early) +void __init default_get_smp_config(unsigned int early)  {  	struct mpf_intel *mpf = mpf_found; @@ -625,11 +627,6 @@ static void __init __get_smp_config(unsigned int early)  	if (acpi_lapic && acpi_ioapic)  		return; -	if (x86_quirks->mach_get_smp_config) { -		if (x86_quirks->mach_get_smp_config(early)) -			return; -	} -  	printk(KERN_INFO "Intel MultiProcessor Specification v1.%d\n",  	       mpf->specification);  #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_32) @@ -670,16 +667,6 @@ static void __init __get_smp_config(unsigned int early)  	 */  } -void __init early_get_smp_config(void) -{ -	__get_smp_config(1); -} - -void __init get_smp_config(void) -{ -	__get_smp_config(0); -} -  static void __init smp_reserve_bootmem(struct mpf_intel *mpf)  {  	unsigned long size = get_mpc_size(mpf->physptr); @@ -745,14 +732,10 @@ static int __init smp_scan_config(unsigned long base, unsigned long length,  	return 0;  } -static void __init __find_smp_config(unsigned int reserve) +void __init default_find_smp_config(unsigned int reserve)  {  	unsigned int address; -	if (x86_quirks->mach_find_smp_config) { -		if (x86_quirks->mach_find_smp_config(reserve)) -			return; -	}  	/*  	 * FIXME: Linux assumes you have 640K of base ram..  	 * this continues the error... @@ -787,16 +770,6 @@ static void __init __find_smp_config(unsigned int reserve)  		smp_scan_config(address, 0x400, reserve);  } -void __init early_find_smp_config(void) -{ -	__find_smp_config(0); -} - -void __init find_smp_config(void) -{ -	__find_smp_config(1); -} -  #ifdef CONFIG_X86_IO_APIC  static u8 __initdata irq_used[MAX_IRQ_SOURCES]; diff --git a/arch/x86/kernel/mrst.c b/arch/x86/kernel/mrst.c new file mode 100644 index 00000000000..3b7078abc87 --- /dev/null +++ b/arch/x86/kernel/mrst.c @@ -0,0 +1,24 @@ +/* + * mrst.c: Intel Moorestown platform specific setup code + * + * (C) Copyright 2008 Intel Corporation + * Author: Jacob Pan (jacob.jun.pan@intel.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; version 2 + * of the License. + */ +#include <linux/init.h> + +#include <asm/setup.h> + +/* + * Moorestown specific x86_init function overrides and early setup + * calls. + */ +void __init x86_mrst_early_setup(void) +{ +	x86_init.resources.probe_roms = x86_init_noop; +	x86_init.resources.reserve_resources = x86_init_noop; +} diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c index f5b0b4a01fb..1b1739d1631 100644 --- a/arch/x86/kernel/paravirt.c +++ b/arch/x86/kernel/paravirt.c @@ -54,17 +54,12 @@ u64 _paravirt_ident_64(u64 x)  	return x;  } -static void __init default_banner(void) +void __init default_banner(void)  {  	printk(KERN_INFO "Booting paravirtualized kernel on %s\n",  	       pv_info.name);  } -char *memory_setup(void) -{ -	return pv_init_ops.memory_setup(); -} -  /* Simple instruction patching code. */  #define DEF_NATIVE(ops, name, code)					\  	extern const char start_##ops##_##name[], end_##ops##_##name[];	\ @@ -188,11 +183,6 @@ unsigned paravirt_patch_insns(void *insnbuf, unsigned len,  	return insn_len;  } -void init_IRQ(void) -{ -	pv_irq_ops.init_IRQ(); -} -  static void native_flush_tlb(void)  {  	__native_flush_tlb(); @@ -218,13 +208,6 @@ extern void native_irq_enable_sysexit(void);  extern void native_usergs_sysret32(void);  extern void native_usergs_sysret64(void); -static int __init print_banner(void) -{ -	pv_init_ops.banner(); -	return 0; -} -core_initcall(print_banner); -  static struct resource reserve_ioports = {  	.start = 0,  	.end = IO_SPACE_LIMIT, @@ -320,21 +303,13 @@ struct pv_info pv_info = {  struct pv_init_ops pv_init_ops = {  	.patch = native_patch, -	.banner = default_banner, -	.arch_setup = paravirt_nop, -	.memory_setup = machine_specific_memory_setup,  };  struct pv_time_ops pv_time_ops = { -	.time_init = hpet_time_init, -	.get_wallclock = native_get_wallclock, -	.set_wallclock = native_set_wallclock,  	.sched_clock = native_sched_clock, -	.get_tsc_khz = native_calibrate_tsc,  };  struct pv_irq_ops pv_irq_ops = { -	.init_IRQ = native_init_IRQ,  	.save_fl = __PV_IS_CALLEE_SAVE(native_save_fl),  	.restore_fl = __PV_IS_CALLEE_SAVE(native_restore_fl),  	.irq_disable = __PV_IS_CALLEE_SAVE(native_irq_disable), @@ -409,8 +384,6 @@ struct pv_cpu_ops pv_cpu_ops = {  struct pv_apic_ops pv_apic_ops = {  #ifdef CONFIG_X86_LOCAL_APIC -	.setup_boot_clock = setup_boot_APIC_clock, -	.setup_secondary_clock = setup_secondary_APIC_clock,  	.startup_ipi_hook = paravirt_nop,  #endif  }; @@ -424,13 +397,6 @@ struct pv_apic_ops pv_apic_ops = {  #endif  struct pv_mmu_ops pv_mmu_ops = { -#ifndef CONFIG_X86_64 -	.pagetable_setup_start = native_pagetable_setup_start, -	.pagetable_setup_done = native_pagetable_setup_done, -#else -	.pagetable_setup_start = paravirt_nop, -	.pagetable_setup_done = paravirt_nop, -#endif  	.read_cr2 = native_read_cr2,  	.write_cr2 = native_write_cr2, diff --git a/arch/x86/kernel/rtc.c b/arch/x86/kernel/rtc.c index bf67dcb4a44..1cfbbfc3ae2 100644 --- a/arch/x86/kernel/rtc.c +++ b/arch/x86/kernel/rtc.c @@ -8,6 +8,7 @@  #include <linux/pnp.h>  #include <asm/vsyscall.h> +#include <asm/x86_init.h>  #include <asm/time.h>  #ifdef CONFIG_X86_32 @@ -165,13 +166,13 @@ void rtc_cmos_write(unsigned char val, unsigned char addr)  }  EXPORT_SYMBOL(rtc_cmos_write); -static int set_rtc_mmss(unsigned long nowtime) +int update_persistent_clock(struct timespec now)  {  	unsigned long flags;  	int retval;  	spin_lock_irqsave(&rtc_lock, flags); -	retval = set_wallclock(nowtime); +	retval = x86_platform.set_wallclock(now.tv_sec);  	spin_unlock_irqrestore(&rtc_lock, flags);  	return retval; @@ -183,18 +184,13 @@ void read_persistent_clock(struct timespec *ts)  	unsigned long retval, flags;  	spin_lock_irqsave(&rtc_lock, flags); -	retval = get_wallclock(); +	retval = x86_platform.get_wallclock();  	spin_unlock_irqrestore(&rtc_lock, flags);  	ts->tv_sec = retval;  	ts->tv_nsec = 0;  } -int update_persistent_clock(struct timespec now) -{ -	return set_rtc_mmss(now.tv_sec); -} -  unsigned long long native_read_tsc(void)  {  	return __native_read_tsc(); diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 19f15c4076f..a55f6609fe1 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -109,10 +109,6 @@  #include <asm/numa_64.h>  #endif -#ifndef ARCH_SETUP -#define ARCH_SETUP -#endif -  /*   * end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries.   * The direct mapping extends to max_pfn_mapped, so that we can directly access @@ -134,9 +130,9 @@ int default_cpu_present_to_apicid(int mps_cpu)  	return __default_cpu_present_to_apicid(mps_cpu);  } -int default_check_phys_apicid_present(int boot_cpu_physical_apicid) +int default_check_phys_apicid_present(int phys_apicid)  { -	return __default_check_phys_apicid_present(boot_cpu_physical_apicid); +	return __default_check_phys_apicid_present(phys_apicid);  }  #endif @@ -172,13 +168,6 @@ static struct resource bss_resource = {  #ifdef CONFIG_X86_32 -static struct resource video_ram_resource = { -	.name	= "Video RAM area", -	.start	= 0xa0000, -	.end	= 0xbffff, -	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM -}; -  /* cpu data as detected by the assembly code in head.S */  struct cpuinfo_x86 new_cpu_data __cpuinitdata = {0, 0, 0, 0, -1, 1, 0, 0, -1};  /* common cpu data for all cpus */ @@ -606,7 +595,7 @@ static struct resource standard_io_resources[] = {  		.flags = IORESOURCE_BUSY | IORESOURCE_IO }  }; -static void __init reserve_standard_io_resources(void) +void __init reserve_standard_io_resources(void)  {  	int i; @@ -638,10 +627,6 @@ static int __init setup_elfcorehdr(char *arg)  early_param("elfcorehdr", setup_elfcorehdr);  #endif -static struct x86_quirks default_x86_quirks __initdata; - -struct x86_quirks *x86_quirks __initdata = &default_x86_quirks; -  #ifdef CONFIG_X86_RESERVE_LOW_64K  static int __init dmi_low_memory_corruption(const struct dmi_system_id *d)  { @@ -773,7 +758,7 @@ void __init setup_arch(char **cmdline_p)  	}  #endif -	ARCH_SETUP +	x86_init.oem.arch_setup();  	setup_memory_map();  	parse_setup_data(); @@ -844,11 +829,9 @@ void __init setup_arch(char **cmdline_p)  	 * VMware detection requires dmi to be available, so this  	 * needs to be done after dmi_scan_machine, for the BP.  	 */ -	init_hypervisor(&boot_cpu_data); +	init_hypervisor_platform(); -#ifdef CONFIG_X86_32 -	probe_roms(); -#endif +	x86_init.resources.probe_roms();  	/* after parse_early_param, so could debug it */  	insert_resource(&iomem_resource, &code_resource); @@ -983,10 +966,9 @@ void __init setup_arch(char **cmdline_p)  	kvmclock_init();  #endif -	paravirt_pagetable_setup_start(swapper_pg_dir); +	x86_init.paging.pagetable_setup_start(swapper_pg_dir);  	paging_init(); -	paravirt_pagetable_setup_done(swapper_pg_dir); -	paravirt_post_allocator_init(); +	x86_init.paging.pagetable_setup_done(swapper_pg_dir);  	tboot_probe(); @@ -1003,13 +985,11 @@ void __init setup_arch(char **cmdline_p)  	 */  	acpi_boot_init(); -#if defined(CONFIG_X86_MPPARSE) || defined(CONFIG_X86_VISWS)  	/*  	 * get boot-time SMP configuration:  	 */  	if (smp_found_config)  		get_smp_config(); -#endif  	prefill_possible_map(); @@ -1028,10 +1008,7 @@ void __init setup_arch(char **cmdline_p)  	e820_reserve_resources();  	e820_mark_nosave_regions(max_low_pfn); -#ifdef CONFIG_X86_32 -	request_resource(&iomem_resource, &video_ram_resource); -#endif -	reserve_standard_io_resources(); +	x86_init.resources.reserve_resources();  	e820_setup_gap(); @@ -1043,78 +1020,22 @@ void __init setup_arch(char **cmdline_p)  	conswitchp = &dummy_con;  #endif  #endif +	x86_init.oem.banner();  }  #ifdef CONFIG_X86_32 -/** - * x86_quirk_intr_init - post gate setup interrupt initialisation - * - * Description: - *	Fill in any interrupts that may have been left out by the general - *	init_IRQ() routine.  interrupts having to do with the machine rather - *	than the devices on the I/O bus (like APIC interrupts in intel MP - *	systems) are started here. - **/ -void __init x86_quirk_intr_init(void) -{ -	if (x86_quirks->arch_intr_init) { -		if (x86_quirks->arch_intr_init()) -			return; -	} -} - -/** - * x86_quirk_trap_init - initialise system specific traps - * - * Description: - *	Called as the final act of trap_init().  Used in VISWS to initialise - *	the various board specific APIC traps. - **/ -void __init x86_quirk_trap_init(void) -{ -	if (x86_quirks->arch_trap_init) { -		if (x86_quirks->arch_trap_init()) -			return; -	} -} - -static struct irqaction irq0  = { -	.handler = timer_interrupt, -	.flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_IRQPOLL | IRQF_TIMER, -	.name = "timer" +static struct resource video_ram_resource = { +	.name	= "Video RAM area", +	.start	= 0xa0000, +	.end	= 0xbffff, +	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM  }; -/** - * x86_quirk_pre_time_init - do any specific initialisations before. - * - **/ -void __init x86_quirk_pre_time_init(void) +void __init i386_reserve_resources(void)  { -	if (x86_quirks->arch_pre_time_init) -		x86_quirks->arch_pre_time_init(); +	request_resource(&iomem_resource, &video_ram_resource); +	reserve_standard_io_resources();  } -/** - * x86_quirk_time_init - do any specific initialisations for the system timer. - * - * Description: - *	Must plug the system timer interrupt source at HZ into the IRQ listed - *	in irq_vectors.h:TIMER_IRQ - **/ -void __init x86_quirk_time_init(void) -{ -	if (x86_quirks->arch_time_init) { -		/* -		 * A nonzero return code does not mean failure, it means -		 * that the architecture quirk does not want any -		 * generic (timer) setup to be performed after this: -		 */ -		if (x86_quirks->arch_time_init()) -			return; -	} - -	irq0.mask = cpumask_of_cpu(0); -	setup_irq(0, &irq0); -}  #endif /* CONFIG_X86_32 */ diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index a25eeec0008..09c5e077dff 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -324,7 +324,7 @@ notrace static void __cpuinit start_secondary(void *unused)  	/* enable local interrupts */  	local_irq_enable(); -	setup_secondary_clock(); +	x86_cpuinit.setup_percpu_clockev();  	wmb();  	cpu_idle(); @@ -1114,7 +1114,7 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)  	printk(KERN_INFO "CPU%d: ", 0);  	print_cpu_info(&cpu_data(0)); -	setup_boot_clock(); +	x86_init.timers.setup_percpu_clockev();  	if (is_uv_system())  		uv_system_init(); diff --git a/arch/x86/kernel/time.c b/arch/x86/kernel/time.c new file mode 100644 index 00000000000..e293ac56c72 --- /dev/null +++ b/arch/x86/kernel/time.c @@ -0,0 +1,121 @@ +/* + *  Copyright (c) 1991,1992,1995  Linus Torvalds + *  Copyright (c) 1994  Alan Modra + *  Copyright (c) 1995  Markus Kuhn + *  Copyright (c) 1996  Ingo Molnar + *  Copyright (c) 1998  Andrea Arcangeli + *  Copyright (c) 2002,2006  Vojtech Pavlik + *  Copyright (c) 2003  Andi Kleen + * + */ + +#include <linux/clockchips.h> +#include <linux/interrupt.h> +#include <linux/time.h> +#include <linux/mca.h> + +#include <asm/vsyscall.h> +#include <asm/x86_init.h> +#include <asm/i8259.h> +#include <asm/i8253.h> +#include <asm/timer.h> +#include <asm/hpet.h> +#include <asm/time.h> + +#if defined(CONFIG_X86_32) && defined(CONFIG_X86_IO_APIC) +int timer_ack; +#endif + +#ifdef CONFIG_X86_64 +volatile unsigned long __jiffies __section_jiffies = INITIAL_JIFFIES; +#endif + +unsigned long profile_pc(struct pt_regs *regs) +{ +	unsigned long pc = instruction_pointer(regs); + +	if (!user_mode_vm(regs) && in_lock_functions(pc)) { +#ifdef CONFIG_FRAME_POINTER +		return *(unsigned long *)(regs->bp + sizeof(long)); +#else +		unsigned long *sp = (unsigned long *)regs->sp; +		/* +		 * Return address is either directly at stack pointer +		 * or above a saved flags. Eflags has bits 22-31 zero, +		 * kernel addresses don't. +		 */ +		if (sp[0] >> 22) +			return sp[0]; +		if (sp[1] >> 22) +			return sp[1]; +#endif +	} +	return pc; +} +EXPORT_SYMBOL(profile_pc); + +/* + * Default timer interrupt handler for PIT/HPET + */ +static irqreturn_t timer_interrupt(int irq, void *dev_id) +{ +	/* Keep nmi watchdog up to date */ +	inc_irq_stat(irq0_irqs); + +	/* Optimized out for !IO_APIC and x86_64 */ +	if (timer_ack) { +		/* +		 * Subtle, when I/O APICs are used we have to ack timer IRQ +		 * manually to deassert NMI lines for the watchdog if run +		 * on an 82489DX-based system. +		 */ +		spin_lock(&i8259A_lock); +		outb(0x0c, PIC_MASTER_OCW3); +		/* Ack the IRQ; AEOI will end it automatically. */ +		inb(PIC_MASTER_POLL); +		spin_unlock(&i8259A_lock); +	} + +	global_clock_event->event_handler(global_clock_event); + +	/* MCA bus quirk: Acknowledge irq0 by setting bit 7 in port 0x61 */ +	if (MCA_bus) +		outb_p(inb_p(0x61)| 0x80, 0x61); + +	return IRQ_HANDLED; +} + +static struct irqaction irq0  = { +	.handler = timer_interrupt, +	.flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_IRQPOLL | IRQF_TIMER, +	.name = "timer" +}; + +void __init setup_default_timer_irq(void) +{ +	irq0.mask = cpumask_of_cpu(0); +	setup_irq(0, &irq0); +} + +/* Default timer init function */ +void __init hpet_time_init(void) +{ +	if (!hpet_enable()) +		setup_pit_timer(); +	setup_default_timer_irq(); +} + +static __init void x86_late_time_init(void) +{ +	x86_init.timers.timer_init(); +	tsc_init(); +} + +/* + * Initialize TSC and delay the periodic timer init to + * late x86_late_time_init() so ioremap works. + */ +void __init time_init(void) +{ +	late_time_init = x86_late_time_init; +} diff --git a/arch/x86/kernel/time_32.c b/arch/x86/kernel/time_32.c deleted file mode 100644 index 5c5d87f0b2e..00000000000 --- a/arch/x86/kernel/time_32.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - *  Copyright (C) 1991, 1992, 1995  Linus Torvalds - * - * This file contains the PC-specific time handling details: - * reading the RTC at bootup, etc.. - * 1994-07-02    Alan Modra - *	fixed set_rtc_mmss, fixed time.year for >= 2000, new mktime - * 1995-03-26    Markus Kuhn - *      fixed 500 ms bug at call to set_rtc_mmss, fixed DS12887 - *      precision CMOS clock update - * 1996-05-03    Ingo Molnar - *      fixed time warps in do_[slow|fast]_gettimeoffset() - * 1997-09-10	Updated NTP code according to technical memorandum Jan '96 - *		"A Kernel Model for Precision Timekeeping" by Dave Mills - * 1998-09-05    (Various) - *	More robust do_fast_gettimeoffset() algorithm implemented - *	(works with APM, Cyrix 6x86MX and Centaur C6), - *	monotonic gettimeofday() with fast_get_timeoffset(), - *	drift-proof precision TSC calibration on boot - *	(C. Scott Ananian <cananian@alumni.princeton.edu>, Andrew D. - *	Balsa <andrebalsa@altern.org>, Philip Gladstone <philip@raptor.com>; - *	ported from 2.0.35 Jumbo-9 by Michael Krause <m.krause@tu-harburg.de>). - * 1998-12-16    Andrea Arcangeli - *	Fixed Jumbo-9 code in 2.1.131: do_gettimeofday was missing 1 jiffy - *	because was not accounting lost_ticks. - * 1998-12-24 Copyright (C) 1998  Andrea Arcangeli - *	Fixed a xtime SMP race (we need the xtime_lock rw spinlock to - *	serialize accesses to xtime/lost_ticks). - */ - -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/time.h> -#include <linux/mca.h> - -#include <asm/setup.h> -#include <asm/hpet.h> -#include <asm/time.h> -#include <asm/timer.h> - -#include <asm/do_timer.h> - -int timer_ack; - -unsigned long profile_pc(struct pt_regs *regs) -{ -	unsigned long pc = instruction_pointer(regs); - -#ifdef CONFIG_SMP -	if (!user_mode_vm(regs) && in_lock_functions(pc)) { -#ifdef CONFIG_FRAME_POINTER -		return *(unsigned long *)(regs->bp + sizeof(long)); -#else -		unsigned long *sp = (unsigned long *)®s->sp; - -		/* Return address is either directly at stack pointer -		   or above a saved flags. Eflags has bits 22-31 zero, -		   kernel addresses don't. */ -		if (sp[0] >> 22) -			return sp[0]; -		if (sp[1] >> 22) -			return sp[1]; -#endif -	} -#endif -	return pc; -} -EXPORT_SYMBOL(profile_pc); - -/* - * This is the same as the above, except we _also_ save the current - * Time Stamp Counter value at the time of the timer interrupt, so that - * we later on can estimate the time of day more exactly. - */ -irqreturn_t timer_interrupt(int irq, void *dev_id) -{ -	/* Keep nmi watchdog up to date */ -	inc_irq_stat(irq0_irqs); - -#ifdef CONFIG_X86_IO_APIC -	if (timer_ack) { -		/* -		 * Subtle, when I/O APICs are used we have to ack timer IRQ -		 * manually to deassert NMI lines for the watchdog if run -		 * on an 82489DX-based system. -		 */ -		spin_lock(&i8259A_lock); -		outb(0x0c, PIC_MASTER_OCW3); -		/* Ack the IRQ; AEOI will end it automatically. */ -		inb(PIC_MASTER_POLL); -		spin_unlock(&i8259A_lock); -	} -#endif - -	do_timer_interrupt_hook(); - -#ifdef CONFIG_MCA -	if (MCA_bus) { -		/* The PS/2 uses level-triggered interrupts.  You can't -		turn them off, nor would you want to (any attempt to -		enable edge-triggered interrupts usually gets intercepted by a -		special hardware circuit).  Hence we have to acknowledge -		the timer interrupt.  Through some incredibly stupid -		design idea, the reset for IRQ 0 is done by setting the -		high bit of the PPI port B (0x61).  Note that some PS/2s, -		notably the 55SX, work fine if this is removed.  */ - -		u8 irq_v = inb_p(0x61);		/* read the current state */ -		outb_p(irq_v | 0x80, 0x61);	/* reset the IRQ */ -	} -#endif - -	return IRQ_HANDLED; -} - -/* Duplicate of time_init() below, with hpet_enable part added */ -void __init hpet_time_init(void) -{ -	if (!hpet_enable()) -		setup_pit_timer(); -	x86_quirk_time_init(); -} - -/* - * This is called directly from init code; we must delay timer setup in the - * HPET case as we can't make the decision to turn on HPET this early in the - * boot process. - * - * The chosen time_init function will usually be hpet_time_init, above, but - * in the case of virtual hardware, an alternative function may be substituted. - */ -void __init time_init(void) -{ -	x86_quirk_pre_time_init(); -	tsc_init(); -	late_time_init = choose_time_init(); -} diff --git a/arch/x86/kernel/time_64.c b/arch/x86/kernel/time_64.c deleted file mode 100644 index 5ba343e6184..00000000000 --- a/arch/x86/kernel/time_64.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - *  "High Precision Event Timer" based timekeeping. - * - *  Copyright (c) 1991,1992,1995  Linus Torvalds - *  Copyright (c) 1994  Alan Modra - *  Copyright (c) 1995  Markus Kuhn - *  Copyright (c) 1996  Ingo Molnar - *  Copyright (c) 1998  Andrea Arcangeli - *  Copyright (c) 2002,2006  Vojtech Pavlik - *  Copyright (c) 2003  Andi Kleen - *  RTC support code taken from arch/i386/kernel/timers/time_hpet.c - */ - -#include <linux/clockchips.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/module.h> -#include <linux/time.h> -#include <linux/mca.h> -#include <linux/nmi.h> - -#include <asm/i8253.h> -#include <asm/hpet.h> -#include <asm/vgtod.h> -#include <asm/time.h> -#include <asm/timer.h> - -volatile unsigned long __jiffies __section_jiffies = INITIAL_JIFFIES; - -unsigned long profile_pc(struct pt_regs *regs) -{ -	unsigned long pc = instruction_pointer(regs); - -	/* Assume the lock function has either no stack frame or a copy -	   of flags from PUSHF -	   Eflags always has bits 22 and up cleared unlike kernel addresses. */ -	if (!user_mode_vm(regs) && in_lock_functions(pc)) { -#ifdef CONFIG_FRAME_POINTER -		return *(unsigned long *)(regs->bp + sizeof(long)); -#else -		unsigned long *sp = (unsigned long *)regs->sp; -		if (sp[0] >> 22) -			return sp[0]; -		if (sp[1] >> 22) -			return sp[1]; -#endif -	} -	return pc; -} -EXPORT_SYMBOL(profile_pc); - -static irqreturn_t timer_interrupt(int irq, void *dev_id) -{ -	inc_irq_stat(irq0_irqs); - -	global_clock_event->event_handler(global_clock_event); - -#ifdef CONFIG_MCA -	if (MCA_bus) { -		u8 irq_v = inb_p(0x61);       /* read the current state */ -		outb_p(irq_v|0x80, 0x61);     /* reset the IRQ */ -	} -#endif - -	return IRQ_HANDLED; -} - -/* calibrate_cpu is used on systems with fixed rate TSCs to determine - * processor frequency */ -#define TICK_COUNT 100000000 -unsigned long __init calibrate_cpu(void) -{ -	int tsc_start, tsc_now; -	int i, no_ctr_free; -	unsigned long evntsel3 = 0, pmc3 = 0, pmc_now = 0; -	unsigned long flags; - -	for (i = 0; i < 4; i++) -		if (avail_to_resrv_perfctr_nmi_bit(i)) -			break; -	no_ctr_free = (i == 4); -	if (no_ctr_free) { -		WARN(1, KERN_WARNING "Warning: AMD perfctrs busy ... " -		     "cpu_khz value may be incorrect.\n"); -		i = 3; -		rdmsrl(MSR_K7_EVNTSEL3, evntsel3); -		wrmsrl(MSR_K7_EVNTSEL3, 0); -		rdmsrl(MSR_K7_PERFCTR3, pmc3); -	} else { -		reserve_perfctr_nmi(MSR_K7_PERFCTR0 + i); -		reserve_evntsel_nmi(MSR_K7_EVNTSEL0 + i); -	} -	local_irq_save(flags); -	/* start measuring cycles, incrementing from 0 */ -	wrmsrl(MSR_K7_PERFCTR0 + i, 0); -	wrmsrl(MSR_K7_EVNTSEL0 + i, 1 << 22 | 3 << 16 | 0x76); -	rdtscl(tsc_start); -	do { -		rdmsrl(MSR_K7_PERFCTR0 + i, pmc_now); -		tsc_now = get_cycles(); -	} while ((tsc_now - tsc_start) < TICK_COUNT); - -	local_irq_restore(flags); -	if (no_ctr_free) { -		wrmsrl(MSR_K7_EVNTSEL3, 0); -		wrmsrl(MSR_K7_PERFCTR3, pmc3); -		wrmsrl(MSR_K7_EVNTSEL3, evntsel3); -	} else { -		release_perfctr_nmi(MSR_K7_PERFCTR0 + i); -		release_evntsel_nmi(MSR_K7_EVNTSEL0 + i); -	} - -	return pmc_now * tsc_khz / (tsc_now - tsc_start); -} - -static struct irqaction irq0 = { -	.handler	= timer_interrupt, -	.flags		= IRQF_DISABLED | IRQF_IRQPOLL | IRQF_NOBALANCING | IRQF_TIMER, -	.name		= "timer" -}; - -void __init hpet_time_init(void) -{ -	if (!hpet_enable()) -		setup_pit_timer(); - -	setup_irq(0, &irq0); -} - -void __init time_init(void) -{ -	tsc_init(); - -	late_time_init = choose_time_init(); -} diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 83264922a87..7dc0de9d1ed 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -59,6 +59,7 @@  #include <asm/mach_traps.h>  #ifdef CONFIG_X86_64 +#include <asm/x86_init.h>  #include <asm/pgalloc.h>  #include <asm/proto.h>  #else @@ -972,7 +973,5 @@ void __init trap_init(void)  	 */  	cpu_init(); -#ifdef CONFIG_X86_32 -	x86_quirk_trap_init(); -#endif +	x86_init.irqs.trap_init();  } diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index fc3672a303d..17409e8d109 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -17,6 +17,8 @@  #include <asm/time.h>  #include <asm/delay.h>  #include <asm/hypervisor.h> +#include <asm/nmi.h> +#include <asm/x86_init.h>  unsigned int __read_mostly cpu_khz;	/* TSC clocks / usec, not used here */  EXPORT_SYMBOL(cpu_khz); @@ -400,15 +402,9 @@ unsigned long native_calibrate_tsc(void)  {  	u64 tsc1, tsc2, delta, ref1, ref2;  	unsigned long tsc_pit_min = ULONG_MAX, tsc_ref_min = ULONG_MAX; -	unsigned long flags, latch, ms, fast_calibrate, hv_tsc_khz; +	unsigned long flags, latch, ms, fast_calibrate;  	int hpet = is_hpet_enabled(), i, loopmin; -	hv_tsc_khz = get_hypervisor_tsc_freq(); -	if (hv_tsc_khz) { -		printk(KERN_INFO "TSC: Frequency read from the hypervisor\n"); -		return hv_tsc_khz; -	} -  	local_irq_save(flags);  	fast_calibrate = quick_pit_calibrate();  	local_irq_restore(flags); @@ -566,7 +562,7 @@ int recalibrate_cpu_khz(void)  	unsigned long cpu_khz_old = cpu_khz;  	if (cpu_has_tsc) { -		tsc_khz = calibrate_tsc(); +		tsc_khz = x86_platform.calibrate_tsc();  		cpu_khz = tsc_khz;  		cpu_data(0).loops_per_jiffy =  			cpufreq_scale(cpu_data(0).loops_per_jiffy, @@ -860,15 +856,71 @@ static void __init init_tsc_clocksource(void)  	clocksource_register(&clocksource_tsc);  } +#ifdef CONFIG_X86_64 +/* + * calibrate_cpu is used on systems with fixed rate TSCs to determine + * processor frequency + */ +#define TICK_COUNT 100000000 +static unsigned long __init calibrate_cpu(void) +{ +	int tsc_start, tsc_now; +	int i, no_ctr_free; +	unsigned long evntsel3 = 0, pmc3 = 0, pmc_now = 0; +	unsigned long flags; + +	for (i = 0; i < 4; i++) +		if (avail_to_resrv_perfctr_nmi_bit(i)) +			break; +	no_ctr_free = (i == 4); +	if (no_ctr_free) { +		WARN(1, KERN_WARNING "Warning: AMD perfctrs busy ... " +		     "cpu_khz value may be incorrect.\n"); +		i = 3; +		rdmsrl(MSR_K7_EVNTSEL3, evntsel3); +		wrmsrl(MSR_K7_EVNTSEL3, 0); +		rdmsrl(MSR_K7_PERFCTR3, pmc3); +	} else { +		reserve_perfctr_nmi(MSR_K7_PERFCTR0 + i); +		reserve_evntsel_nmi(MSR_K7_EVNTSEL0 + i); +	} +	local_irq_save(flags); +	/* start measuring cycles, incrementing from 0 */ +	wrmsrl(MSR_K7_PERFCTR0 + i, 0); +	wrmsrl(MSR_K7_EVNTSEL0 + i, 1 << 22 | 3 << 16 | 0x76); +	rdtscl(tsc_start); +	do { +		rdmsrl(MSR_K7_PERFCTR0 + i, pmc_now); +		tsc_now = get_cycles(); +	} while ((tsc_now - tsc_start) < TICK_COUNT); + +	local_irq_restore(flags); +	if (no_ctr_free) { +		wrmsrl(MSR_K7_EVNTSEL3, 0); +		wrmsrl(MSR_K7_PERFCTR3, pmc3); +		wrmsrl(MSR_K7_EVNTSEL3, evntsel3); +	} else { +		release_perfctr_nmi(MSR_K7_PERFCTR0 + i); +		release_evntsel_nmi(MSR_K7_EVNTSEL0 + i); +	} + +	return pmc_now * tsc_khz / (tsc_now - tsc_start); +} +#else +static inline unsigned long calibrate_cpu(void) { return cpu_khz; } +#endif +  void __init tsc_init(void)  {  	u64 lpj;  	int cpu; +	x86_init.timers.tsc_pre_init(); +  	if (!cpu_has_tsc)  		return; -	tsc_khz = calibrate_tsc(); +	tsc_khz = x86_platform.calibrate_tsc();  	cpu_khz = tsc_khz;  	if (!tsc_khz) { @@ -876,11 +928,9 @@ void __init tsc_init(void)  		return;  	} -#ifdef CONFIG_X86_64  	if (cpu_has(&boot_cpu_data, X86_FEATURE_CONSTANT_TSC) &&  			(boot_cpu_data.x86_vendor == X86_VENDOR_AMD))  		cpu_khz = calibrate_cpu(); -#endif  	printk("Detected %lu.%03lu MHz processor.\n",  			(unsigned long)cpu_khz / 1000, diff --git a/arch/x86/kernel/visws_quirks.c b/arch/x86/kernel/visws_quirks.c index 31ffc24eec4..f068553a1b1 100644 --- a/arch/x86/kernel/visws_quirks.c +++ b/arch/x86/kernel/visws_quirks.c @@ -30,6 +30,7 @@  #include <asm/setup.h>  #include <asm/apic.h>  #include <asm/e820.h> +#include <asm/time.h>  #include <asm/io.h>  #include <linux/kernel_stat.h> @@ -53,7 +54,7 @@ int is_visws_box(void)  	return visws_board_type >= 0;  } -static int __init visws_time_init(void) +static void __init visws_time_init(void)  {  	printk(KERN_INFO "Starting Cobalt Timer system clock\n"); @@ -66,21 +67,13 @@ static int __init visws_time_init(void)  	/* Enable (unmask) the timer interrupt */  	co_cpu_write(CO_CPU_CTRL, co_cpu_read(CO_CPU_CTRL) & ~CO_CTRL_TIMEMASK); -	/* -	 * Zero return means the generic timer setup code will set up -	 * the standard vector: -	 */ -	return 0; +	setup_default_timer_irq();  } -static int __init visws_pre_intr_init(void) +/* Replaces the default init_ISA_irqs in the generic setup */ +static void __init visws_pre_intr_init(void)  {  	init_VISWS_APIC_irqs(); - -	/* -	 * We dont want ISA irqs to be set up by the generic code: -	 */ -	return 1;  }  /* Quirk for machine specific memory setup. */ @@ -156,12 +149,8 @@ static void visws_machine_power_off(void)  	outl(PIIX_SPECIAL_STOP, 0xCFC);  } -static int __init visws_get_smp_config(unsigned int early) +static void __init visws_get_smp_config(unsigned int early)  { -	/* -	 * Prevent MP-table parsing by the generic code: -	 */ -	return 1;  }  /* @@ -208,7 +197,7 @@ static void __init MP_processor_info(struct mpc_cpu *m)  	apic_version[m->apicid] = ver;  } -static int __init visws_find_smp_config(unsigned int reserve) +static void __init visws_find_smp_config(unsigned int reserve)  {  	struct mpc_cpu *mp = phys_to_virt(CO_CPU_TAB_PHYS);  	unsigned short ncpus = readw(phys_to_virt(CO_CPU_NUM_PHYS)); @@ -230,21 +219,9 @@ static int __init visws_find_smp_config(unsigned int reserve)  		MP_processor_info(mp++);  	mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; - -	return 1;  } -static int visws_trap_init(void); - -static struct x86_quirks visws_x86_quirks __initdata = { -	.arch_time_init		= visws_time_init, -	.arch_pre_intr_init	= visws_pre_intr_init, -	.arch_memory_setup	= visws_memory_setup, -	.arch_intr_init		= NULL, -	.arch_trap_init		= visws_trap_init, -	.mach_get_smp_config	= visws_get_smp_config, -	.mach_find_smp_config	= visws_find_smp_config, -}; +static void visws_trap_init(void);  void __init visws_early_detect(void)  { @@ -257,11 +234,14 @@ void __init visws_early_detect(void)  		return;  	/* -	 * Install special quirks for timer, interrupt and memory setup: -	 * Fall back to generic behavior for traps: -	 * Override generic MP-table parsing: +	 * Override the default platform setup functions  	 */ -	x86_quirks = &visws_x86_quirks; +	x86_init.resources.memory_setup = visws_memory_setup; +	x86_init.mpparse.get_smp_config = visws_get_smp_config; +	x86_init.mpparse.find_smp_config = visws_find_smp_config; +	x86_init.irqs.pre_vector_init = visws_pre_intr_init; +	x86_init.irqs.trap_init = visws_trap_init; +	x86_init.timers.timer_init = visws_time_init;  	/*  	 * Install reboot quirks: @@ -400,12 +380,10 @@ static __init void cobalt_init(void)  		co_apic_read(CO_APIC_ID));  } -static int __init visws_trap_init(void) +static void __init visws_trap_init(void)  {  	lithium_init();  	cobalt_init(); - -	return 1;  }  /* diff --git a/arch/x86/kernel/vmi_32.c b/arch/x86/kernel/vmi_32.c index 95a7289e4b0..31e6f6cfe53 100644 --- a/arch/x86/kernel/vmi_32.c +++ b/arch/x86/kernel/vmi_32.c @@ -817,15 +817,15 @@ static inline int __init activate_vmi(void)  		vmi_timer_ops.set_alarm = vmi_get_function(VMI_CALL_SetAlarm);  		vmi_timer_ops.cancel_alarm =  			 vmi_get_function(VMI_CALL_CancelAlarm); -		pv_time_ops.time_init = vmi_time_init; -		pv_time_ops.get_wallclock = vmi_get_wallclock; -		pv_time_ops.set_wallclock = vmi_set_wallclock; +		x86_init.timers.timer_init = vmi_time_init;  #ifdef CONFIG_X86_LOCAL_APIC -		pv_apic_ops.setup_boot_clock = vmi_time_bsp_init; -		pv_apic_ops.setup_secondary_clock = vmi_time_ap_init; +		x86_init.timers.setup_percpu_clockev = vmi_time_bsp_init; +		x86_cpuinit.setup_percpu_clockev = vmi_time_ap_init;  #endif  		pv_time_ops.sched_clock = vmi_sched_clock; -		pv_time_ops.get_tsc_khz = vmi_tsc_khz; +		x86_platform.calibrate_tsc = vmi_tsc_khz; +		x86_platform.get_wallclock = vmi_get_wallclock; +		x86_platform.set_wallclock = vmi_set_wallclock;  		/* We have true wallclock functions; disable CMOS clock sync */  		no_sync_cmos_clock = 1; diff --git a/arch/x86/kernel/vmiclock_32.c b/arch/x86/kernel/vmiclock_32.c index 2b3eb82efee..611b9e2360d 100644 --- a/arch/x86/kernel/vmiclock_32.c +++ b/arch/x86/kernel/vmiclock_32.c @@ -68,7 +68,7 @@ unsigned long long vmi_sched_clock(void)  	return cycles_2_ns(vmi_timer_ops.get_cycle_counter(VMI_CYCLES_AVAILABLE));  } -/* paravirt_ops.get_tsc_khz = vmi_tsc_khz */ +/* x86_platform.calibrate_tsc = vmi_tsc_khz */  unsigned long vmi_tsc_khz(void)  {  	unsigned long long khz; diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c new file mode 100644 index 00000000000..4449a4a2c2e --- /dev/null +++ b/arch/x86/kernel/x86_init.c @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2009 Thomas Gleixner <tglx@linutronix.de> + * + *  For licencing details see kernel-base/COPYING + */ +#include <linux/init.h> + +#include <asm/bios_ebda.h> +#include <asm/paravirt.h> +#include <asm/mpspec.h> +#include <asm/setup.h> +#include <asm/apic.h> +#include <asm/e820.h> +#include <asm/time.h> +#include <asm/irq.h> +#include <asm/tsc.h> + +void __cpuinit x86_init_noop(void) { } +void __init x86_init_uint_noop(unsigned int unused) { } +void __init x86_init_pgd_noop(pgd_t *unused) { } + +/* + * The platform setup functions are preset with the default functions + * for standard PC hardware. + */ +struct x86_init_ops x86_init __initdata = { + +	.resources = { +		.probe_roms		= x86_init_noop, +		.reserve_resources	= reserve_standard_io_resources, +		.memory_setup		= default_machine_specific_memory_setup, +	}, + +	.mpparse = { +		.mpc_record		= x86_init_uint_noop, +		.setup_ioapic_ids	= x86_init_noop, +		.mpc_apic_id		= default_mpc_apic_id, +		.smp_read_mpc_oem	= default_smp_read_mpc_oem, +		.mpc_oem_bus_info	= default_mpc_oem_bus_info, +		.find_smp_config	= default_find_smp_config, +		.get_smp_config		= default_get_smp_config, +	}, + +	.irqs = { +		.pre_vector_init	= init_ISA_irqs, +		.intr_init		= native_init_IRQ, +		.trap_init		= x86_init_noop, +	}, + +	.oem = { +		.arch_setup		= x86_init_noop, +		.banner			= default_banner, +	}, + +	.paging = { +		.pagetable_setup_start	= native_pagetable_setup_start, +		.pagetable_setup_done	= native_pagetable_setup_done, +	}, + +	.timers = { +		.setup_percpu_clockev	= setup_boot_APIC_clock, +		.tsc_pre_init		= x86_init_noop, +		.timer_init		= hpet_time_init, +	}, +}; + +struct x86_cpuinit_ops x86_cpuinit __cpuinitdata = { +	.setup_percpu_clockev		= setup_secondary_APIC_clock, +}; + +struct x86_platform_ops x86_platform = { +	.calibrate_tsc			= native_calibrate_tsc, +	.get_wallclock			= mach_get_cmos_time, +	.set_wallclock			= mach_set_rtc_mmss, +}; diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index d677fa9ca65..4cb7d5d18b8 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c @@ -1262,7 +1262,6 @@ __init void lguest_init(void)  	 */  	/* Interrupt-related operations */ -	pv_irq_ops.init_IRQ = lguest_init_IRQ;  	pv_irq_ops.save_fl = PV_CALLEE_SAVE(save_fl);  	pv_irq_ops.restore_fl = __PV_IS_CALLEE_SAVE(lg_restore_fl);  	pv_irq_ops.irq_disable = PV_CALLEE_SAVE(irq_disable); @@ -1270,7 +1269,6 @@ __init void lguest_init(void)  	pv_irq_ops.safe_halt = lguest_safe_halt;  	/* Setup operations */ -	pv_init_ops.memory_setup = lguest_memory_setup;  	pv_init_ops.patch = lguest_patch;  	/* Intercepts of various CPU instructions */ @@ -1320,10 +1318,11 @@ __init void lguest_init(void)  	set_lguest_basic_apic_ops();  #endif -	/* Time operations */ -	pv_time_ops.get_wallclock = lguest_get_wallclock; -	pv_time_ops.time_init = lguest_time_init; -	pv_time_ops.get_tsc_khz = lguest_tsc_khz; +	x86_init.resources.memory_setup = lguest_memory_setup; +	x86_init.irqs.intr_init = lguest_init_IRQ; +	x86_init.timers.timer_init = lguest_time_init; +	x86_platform.calibrate_tsc = lguest_tsc_khz; +	x86_platform.get_wallclock =  lguest_get_wallclock;  	/*  	 * Now is a good time to look at the implementations of these functions diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 0dd0c2c6cae..544eb749653 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -912,19 +912,9 @@ static const struct pv_info xen_info __initdata = {  static const struct pv_init_ops xen_init_ops __initdata = {  	.patch = xen_patch, - -	.banner = xen_banner, -	.memory_setup = xen_memory_setup, -	.arch_setup = xen_arch_setup, -	.post_allocator_init = xen_post_allocator_init,  };  static const struct pv_time_ops xen_time_ops __initdata = { -	.time_init = xen_time_init, - -	.set_wallclock = xen_set_wallclock, -	.get_wallclock = xen_get_wallclock, -	.get_tsc_khz = xen_tsc_khz,  	.sched_clock = xen_sched_clock,  }; @@ -990,8 +980,6 @@ static const struct pv_cpu_ops xen_cpu_ops __initdata = {  static const struct pv_apic_ops xen_apic_ops __initdata = {  #ifdef CONFIG_X86_LOCAL_APIC -	.setup_boot_clock = paravirt_nop, -	.setup_secondary_clock = paravirt_nop,  	.startup_ipi_hook = paravirt_nop,  #endif  }; @@ -1070,7 +1058,18 @@ asmlinkage void __init xen_start_kernel(void)  	pv_time_ops = xen_time_ops;  	pv_cpu_ops = xen_cpu_ops;  	pv_apic_ops = xen_apic_ops; -	pv_mmu_ops = xen_mmu_ops; + +	x86_init.resources.memory_setup = xen_memory_setup; +	x86_init.oem.arch_setup = xen_arch_setup; +	x86_init.oem.banner = xen_banner; + +	x86_init.timers.timer_init = xen_time_init; +	x86_init.timers.setup_percpu_clockev = x86_init_noop; +	x86_cpuinit.setup_percpu_clockev = x86_init_noop; + +	x86_platform.calibrate_tsc = xen_tsc_khz; +	x86_platform.get_wallclock = xen_get_wallclock; +	x86_platform.set_wallclock = xen_set_wallclock;  	/*  	 * Set up some pagetable state before starting to set any ptes. @@ -1095,6 +1094,7 @@ asmlinkage void __init xen_start_kernel(void)  	 */  	xen_setup_stackprotector(); +	xen_init_mmu_ops();  	xen_init_irq_ops();  	xen_init_cpuid_mask(); diff --git a/arch/x86/xen/irq.c b/arch/x86/xen/irq.c index cfd17799bd6..9d30105a0c4 100644 --- a/arch/x86/xen/irq.c +++ b/arch/x86/xen/irq.c @@ -1,5 +1,7 @@  #include <linux/hardirq.h> +#include <asm/x86_init.h> +  #include <xen/interface/xen.h>  #include <xen/interface/sched.h>  #include <xen/interface/vcpu.h> @@ -112,8 +114,6 @@ static void xen_halt(void)  }  static const struct pv_irq_ops xen_irq_ops __initdata = { -	.init_IRQ = xen_init_IRQ, -  	.save_fl = PV_CALLEE_SAVE(xen_save_fl),  	.restore_fl = PV_CALLEE_SAVE(xen_restore_fl),  	.irq_disable = PV_CALLEE_SAVE(xen_irq_disable), @@ -129,4 +129,5 @@ static const struct pv_irq_ops xen_irq_ops __initdata = {  void __init xen_init_irq_ops()  {  	pv_irq_ops = xen_irq_ops; +	x86_init.irqs.intr_init = xen_init_IRQ;  } diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 4ceb2858165..093dd59b538 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -1229,9 +1229,12 @@ static __init void xen_pagetable_setup_start(pgd_t *base)  {  } +static void xen_post_allocator_init(void); +  static __init void xen_pagetable_setup_done(pgd_t *base)  {  	xen_setup_shared_info(); +	xen_post_allocator_init();  }  static void xen_write_cr2(unsigned long cr2) @@ -1841,7 +1844,7 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot)  #endif  } -__init void xen_post_allocator_init(void) +static __init void xen_post_allocator_init(void)  {  	pv_mmu_ops.set_pte = xen_set_pte;  	pv_mmu_ops.set_pmd = xen_set_pmd; @@ -1875,10 +1878,7 @@ static void xen_leave_lazy_mmu(void)  	preempt_enable();  } -const struct pv_mmu_ops xen_mmu_ops __initdata = { -	.pagetable_setup_start = xen_pagetable_setup_start, -	.pagetable_setup_done = xen_pagetable_setup_done, - +static const struct pv_mmu_ops xen_mmu_ops __initdata = {  	.read_cr2 = xen_read_cr2,  	.write_cr2 = xen_write_cr2, @@ -1954,6 +1954,12 @@ const struct pv_mmu_ops xen_mmu_ops __initdata = {  	.set_fixmap = xen_set_fixmap,  }; +void __init xen_init_mmu_ops(void) +{ +	x86_init.paging.pagetable_setup_start = xen_pagetable_setup_start; +	x86_init.paging.pagetable_setup_done = xen_pagetable_setup_done; +	pv_mmu_ops = xen_mmu_ops; +}  #ifdef CONFIG_XEN_DEBUG_FS diff --git a/arch/x86/xen/mmu.h b/arch/x86/xen/mmu.h index da730262489..5fe6bc7f5ec 100644 --- a/arch/x86/xen/mmu.h +++ b/arch/x86/xen/mmu.h @@ -59,5 +59,5 @@ void  xen_ptep_modify_prot_commit(struct mm_struct *mm, unsigned long addr,  unsigned long xen_read_cr2_direct(void); -extern const struct pv_mmu_ops xen_mmu_ops; +extern void xen_init_mmu_ops(void);  #endif	/* _XEN_MMU_H */ diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h index 22494fd4c9b..355fa6b99c9 100644 --- a/arch/x86/xen/xen-ops.h +++ b/arch/x86/xen/xen-ops.h @@ -30,8 +30,6 @@ pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn);  void xen_ident_map_ISA(void);  void xen_reserve_top(void); -void xen_post_allocator_init(void); -  char * __init xen_memory_setup(void);  void __init xen_arch_setup(void);  void __init xen_init_IRQ(void);  |