x86: Refactor the setup code to provide a base for embedded platforms
Subsystems (8)
cover x86: Refactor the setup code to provide a base for embedded platforms
The recently posted Moorestown support patches finally indicate the arrival of the embedded nightmare to arch/x86.
Moorestown is a SoC with a x86 core and a bunch of random peripherals glued around it. It finally gets rid of legacy hardware like PIT, 8042 et. al. but on the other hand it introduces the full embedded horror by adding random peripheral IP cores as an replacement which are glued onto the x86 CPU with duct tape and other nasty tricks.
The most remarkable achievement is the PIT replacement AHBT timer which is originally an ARM AMBA based IP core and provides random timer readout and other fancy features. It's the final prove that Intel HW folks are unable to design a working timer. Sigh, I eventually hoped that we see something usable in that area after a decade of suffering. :(
Anyway. We want to support Moorestown & Co. nevertheless, but as we have seen from the initial patches it needs to fiddle in the guts of the x86 setup code. Most of the points where it interferes are already covered by x86_quirks or paravirt modifications, but we cannot use either of those to do sane multi platform support.
The following patch series refactors the setup related x86_quirks and the setup related paravirt hooks and puts them into an extensible platform_setup infrastructure to provide a proper base for adding the Moorestown modifications. As a side effect it also unifies time_32/64.c and removes some leftovers of the pre arch/x86 era.
Note, this is not a replacement for paravirt_ops. It is just replacing the setup related paravirt stuff so it can be reused for other platforms though I have to say that it removes a fair amount of obscurity which was introduced by paravirt & Co.
The total result of this overhaul is:
arch/x86/include/asm/do_timer.h | 16 -- arch/x86/kernel/time_32.c | 137 ------------------------- arch/x86/kernel/time_64.c | 135 ------------------------ linux-2.6/arch/x86/include/asm/apic.h | 3 linux-2.6/arch/x86/include/asm/e820.h | 2 linux-2.6/arch/x86/include/asm/hypervisor.h | 2 linux-2.6/arch/x86/include/asm/io_apic.h | 3 linux-2.6/arch/x86/include/asm/irq.h | 3 linux-2.6/arch/x86/include/asm/mpspec.h | 40 ++++++- linux-2.6/arch/x86/include/asm/paravirt.h | 63 ----------- linux-2.6/arch/x86/include/asm/pgtable.h | 10 - linux-2.6/arch/x86/include/asm/pgtable_types.h | 4 linux-2.6/arch/x86/include/asm/platform.h | 130 +++++++++++++++++++++++ linux-2.6/arch/x86/include/asm/setup.h | 45 -------- linux-2.6/arch/x86/include/asm/time.h | 3 linux-2.6/arch/x86/include/asm/timer.h | 14 -- linux-2.6/arch/x86/include/asm/tsc.h | 3 linux-2.6/arch/x86/include/asm/vmware.h | 2 linux-2.6/arch/x86/kernel/Makefile | 4 linux-2.6/arch/x86/kernel/apic/apic.c | 3 linux-2.6/arch/x86/kernel/apic/io_apic.c | 11 -- linux-2.6/arch/x86/kernel/apic/numaq_32.c | 55 ++++------ linux-2.6/arch/x86/kernel/cpu/hypervisor.c | 14 +- linux-2.6/arch/x86/kernel/cpu/vmware.c | 35 +++--- linux-2.6/arch/x86/kernel/e820.c | 19 --- linux-2.6/arch/x86/kernel/head32.c | 11 +- linux-2.6/arch/x86/kernel/head64.c | 3 linux-2.6/arch/x86/kernel/irqinit.c | 36 +----- linux-2.6/arch/x86/kernel/kvmclock.c | 7 - linux-2.6/arch/x86/kernel/mpparse.c | 75 ++++--------- linux-2.6/arch/x86/kernel/paravirt.c | 34 ------ linux-2.6/arch/x86/kernel/platform_setup.c | 73 +++++++++++++ linux-2.6/arch/x86/kernel/setup.c | 111 ++------------------ linux-2.6/arch/x86/kernel/smpboot.c | 4 linux-2.6/arch/x86/kernel/time.c | 120 +++++++++++++++++++++ linux-2.6/arch/x86/kernel/traps.c | 5 linux-2.6/arch/x86/kernel/tsc.c | 69 ++++++++++-- linux-2.6/arch/x86/kernel/visws_quirks.c | 56 +++------- linux-2.6/arch/x86/kernel/vmi_32.c | 9 - linux-2.6/arch/x86/kernel/vmiclock_32.c | 2 linux-2.6/arch/x86/lguest/boot.c | 9 - linux-2.6/arch/x86/xen/enlighten.c | 23 ++-- linux-2.6/arch/x86/xen/irq.c | 5 linux-2.6/arch/x86/xen/mmu.c | 16 ++ linux-2.6/arch/x86/xen/mmu.h | 2 linux-2.6/arch/x86/xen/xen-ops.h | 2 linux-2.6/init/main.c | 2 47 files changed, 622 insertions(+), 808 deletions(-)
Thanks,
tglx
RFC PATCH 1/32 x86: Add platform_setup infrastructure
The upcoming Moorestown support brings the embedded world to x86. The setup code of x86 has already a couple of hooks which are either x86_quirks or paravirt ops. Some of those setup hooks are pretty convoluted like the timer setup and the tsc calibration code. But there are other places which could do with a cleanup.
Instead of having inline functions/macros which are modified at compile time I decided to introduce platform_setup ops which are unconditional in the code and make it clear that they can be changed either during compile time or in the early boot process. The function pointers are initialized by default functions which can be noops so that the pointer can be called unconditionally in the most cases. This also allows us to remove 32bit/64bit, paravirt and other #ifdeffery.
paravirt guests are just a hardware platform in the setup code, so we should treat them as such and not hide all behind multiple layers of indirection and compile time dependencies.
It's obvious that platform_setup.timers.timer_init() is a function pointer than late_time_init = choose_time_init() obscurity. It's also way simpler to grep for platform_setup.timers.timer_init and find all the places which modify that function pointer instead of analyzing weak functions, macros and paravirt indirections.
Note. This is not a general paravirt_ops replacement. It just will move setup related hooks which are potentially useful for other platform setup purposes as well out of the paravirt domain.
Add the base infrastructure without any functionality.
--- arch/x86/include/asm/platform.h | 23 +++++++++++++++++++++++ arch/x86/include/asm/setup.h | 2 ++ arch/x86/kernel/Makefile | 2 +- arch/x86/kernel/platform_setup.c | 17 +++++++++++++++++ 4 files changed, 43 insertions(+), 1 deletion(-)
arch/x86/include/asm/platform.h new file +23 -0
@@ -0,0 +1,23 @@ +#ifndef _ASM_X86_PLATFORM_H +#define _ASM_X86_PLATFORM_H + +/** +* struct platform_setup_quirks - platform specific quirks +* +*/ +struct platform_setup_quirks { +}; + +/** +* struct platform_setup_ops - functions for platform specific setup +* +*/ +struct platform_setup_ops { +struct platform_setup_quirks quirks; +}; + +extern struct platform_setup_ops platform_setup; + +extern void platform_setup_noop (void ); + +#endif
arch/x86/include/asm/setup.h +2 -0
@@ -7,6 +7,8 @@#ifndef __ASSEMBLY__ +#include <asm/platform.h> +/* * Any setup quirks to be performed? */
arch/x86/kernel/Makefile +1 -1
@@ -32,7 +32,7 @@ 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 += setup.o platform_setup.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
arch/x86/kernel/platform_setup.c new file +17 -0
@@ -0,0 +1,17 @@ +/* +* Copyright (C) 2009 Thomas Gleixner <[email protected]> +* +* For licencing details see kernel-base/COPYING +*/ +#include <linux/init.h> + +#include <asm/platform.h> + +void __cpuinit platform_setup_noop (void ) { } + +/* +* The platform setup functions are preset with the default functions +* for standard PC hardware. +*/ +struct __initdata platform_setup_ops platform_setup = { +};
RFC PATCH 2/32 x86: Add probe_roms to platform_setup
In reply to Thomas Gleixnerprobe_roms is only used on 32bit. Add it to the platform_setup code and remove the #ifdefs.
Default initializer is platform_setup_noop() which is overridden in the 32bit boot code.
--- arch/x86/include/asm/platform.h | 10 ++++++++++ arch/x86/kernel/head32.c | 3 +++ arch/x86/kernel/platform_setup.c | 4 ++++ arch/x86/kernel/setup.c | 4 +--- 4 files changed, 18 insertions(+), 3 deletions(-)
arch/x86/include/asm/platform.h +10 -0
@@ -9,10 +9,20 @@ struct platform_setup_quirks { };/** +* struct platform_setup_resources - platform specific resource related ops +* @probe_roms: probe BIOS roms +* +*/ +struct platform_setup_resources { +void (*probe_roms)(void ); +}; + +/** * struct platform_setup_ops - functions for platform specific setup * */ struct platform_setup_ops { +struct platform_setup_resources resources;struct platform_setup_quirks quirks; };
arch/x86/kernel/head32.c +3 -0
@@ -29,6 +29,9 @@ void __init i386_start_kernel(void) reserve_early(ramdisk_image, ramdisk_end, "RAMDISK"); }#endif +/* Initilize 32bit specific setup functions */ + platform_setup.resources.probe_roms = probe_roms; +reserve_ebda_region ();/*
arch/x86/kernel/platform_setup.c +4 -0
@@ -14,4 +14,8 @@ void __cpuinit platform_setup_noop(void)* for standard PC hardware. */ struct __initdata platform_setup_ops platform_setup = { + + .resources = { + .probe_roms = platform_setup_noop, + }, };
arch/x86/kernel/setup.c +1 -3
@@ -835,9 +835,7 @@ void __init setup_arch(char **cmdline_p)*/ init_hypervisor (&boot_cpu_data); -#ifdef CONFIG_X86_32 -probe_roms (); -#endif + platform_setup.resources.probe_roms ();/* after parse_early_param, so could debug it */ insert_resource (&iomem_resource, &code_resource);
Re: [RFC patch 02/32] x86: Add probe_roms to platform_setup
On 08/21/09 14:29, Thomas Gleixner wrote:
[argh attachments]
Quoted 7 lines
probe_romsis only used on 32bit. Add it to theplatform_setupcode and remove the #ifdefs.Default initializer is
platform_setup_noop()which is overridden in the 32bit boot code.
I realize you're aiming to make this transform have no functional side-effects, but is there a good reason why probe_roms *couldn't* be done in 64-bit? It seems to me that its useful for coverage completeness to have the 32 and 64 bit do the same thing even if its sometimes redundant.
J
Re: [RFC patch 02/32] x86: Add probe_roms to platform_setup
Quoted 2 lines · Jeremy Fitzhardinge
On 08/21/09 14:29, Thomas Gleixner wrote:
[argh attachments]
No. :)
Content-Disposition: inline;
filename=x86-add-probe-roms-to-platform-setup.patch
Quoted 8 lines
Quoted 7 lines
probe_romsis only used on 32bit. Add it to theplatform_setupcode and remove the #ifdefs.Default initializer is
platform_setup_noop()which is overridden in the 32bit boot code.
Quoted 5 lines
I realize you're aiming to make this transform have no functional side-effects, but is there a good reason why
probe_roms*couldn't* be done in 64-bit? It seems to me that its useful for coverage completeness to have the 32 and 64 bit do the same thing even if its sometimes redundant.
Yes. I aimed for functional equivilance in the first place and this is a RFC so any improvements are welcome.
Thanks,
tglx
cover x86/boot: Moorestown patch set based on platform_set abstraction
Based on platform_setup patchset posted by tglx (http://lkml.org/lkml/2009/8/21/358)
These Moorestown patches have become much simplified once ported to the new platform_setup layer.
Now the platform feature flags are less useful, in fact they
are only used in separating ioapic and 8259 now, so once the interrupt controller code is drivernized, we would not need the platform feature flags in the core.
Thanks,
Jacob
Re: [RFC PATCH 0/7] x86/boot: Moorestown patch set based on platform_set abstraction
Quoted 9 lines · Jacob jun
Based on
platform_setuppatchset posted by tglx (http://lkml.org/lkml/2009/8/21/358)These Moorestown patches have become much simplified once ported to the new
platform_setuplayer.Now the platform feature flags are less useful, in fact they
are only used in separating ioapic and 8259 now, so once the interrupt controller code is drivernized, we would not need the platform feature flags in the core.
I don't think that we need big changes in the ioapic code. All you need can be done with way simpler tweaking.
Thanks,
tglx
RFC PATCH 2/7 x86: introduce a set of platform feature flags
In reply to Thomas GleixnerQuoted 1 line
From
8c587b87eef49660b498dd3728dab73a254b7ea9Mon Sep 17 00:00:00 2001
From: Jacob Pan <[email protected]>
Date: Thu, 11 Jun 2009 09:37:26 -0700
Subject: [PATCH] x86: introduce a set of platform feature flags
This patch introduces a set of x86 pc platform feature flags. the intention is to clean up setup code based on the availability of patform features.
With the introduction of non-PC x86 platforms, these flags will also pave the way for cleaner integration.
The current feature flags are not a complete set of all possible PC features only the ones relavent to system setup, such as resource allocation, are included.
--- arch/x86/Kconfig | 13 +++- arch/x86/include/asm/platform_feature.h | 68 +++++++++++++++++++ arch/x86/kernel/.gitignore | 1 + arch/x86/kernel/Makefile | 11 +++ arch/x86/kernel/mkx86pcflags.pl | 32 +++++++++ arch/x86/kernel/platform_info.c | 112 +++++++++++++++++++++++++++++++ 6 files changed, 236 insertions(+), 1 deletions(-) create mode 100644 arch/x86/include/asm/platform_feature.h create mode 100644 arch/x86/kernel/mkx86pcflags.pl create mode 100644 arch/x86/kernel/platform_info.c
arch/x86/Kconfig +12 -1
@@ -1658,7 +1658,18 @@ config CMDLINE_OVERRIDE This is used to work around broken boot loaders. This should be set to 'N' under normal conditions. - +config MRST + bool "Moorestown MID platform" + default n + depends on X86_32 + select SFI + 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. endmenu config ARCH_ENABLE_MEMORY_HOTPLUG
arch/x86/include/asm/platform_feature.h new file +68 -0
68 lines not on this page · raw message
arch/x86/kernel/.gitignore +1 -0
@@ -1,3 +1,4 @@ vsyscall.lds vsyscall_32.lds vmlinux.lds +x86pcflags.c
arch/x86/kernel/Makefile +11 -0
@@ -54,6 +54,7 @@ obj-$(CONFIG_IA32_EMULATION) += tls.o obj-y += step.o obj-$(CONFIG_STACKTRACE) += stacktrace.o obj-y += cpu/ +obj-y += platform_info.o x86pcflags.o obj-y += acpi/ obj-y += reboot.o obj-$(CONFIG_MCA) += mca_32.o
@@ -114,6 +115,16 @@ obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) += check.o obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o +quiet_cmd_mkx86pcflags = MKFEATURE $@ + cmd_mkx86pcflags = $(PERL) $(srctree)/$(src)/mkx86pcflags.pl $< $@ + +platform_feature = $(src)/../include/asm/platform_feature.h + + +targets += x86pcflags.c +$(obj)/x86pcflags.c: $(platform_feature) $(src)/mkx86pcflags.pl FORCE + $(call if_changed,mkx86pcflags) + ### # 64 bit specific files ifeq ($(CONFIG_X86_64),y)
arch/x86/kernel/mkx86pcflags.pl new file +32 -0
@@ -0,0 +1,32 @@ +#!/usr/bin/perl +# +# Generate the x86_platform_available_feature[] array from arch/x86/include/asm/platform_feature.h +# + +($in, $out) = @ARGV; + +open(IN, "< $in\0") or die "$0: cannot open: $in: $!\n"; +open(OUT, "> $out\0") or die "$0: cannot create: $out: $!\n"; + +print OUT "#include <asm/platform_feature.h>\n\n"; +print OUT "const char * const x86_platform_available_feature[N_PLATFORM_CAPINTS*32] = {\n"; + +while (defined($line = <IN>)) { + if ($line =~ /^\s*\#\s*define\s+(X86_PLATFORM_FEATURE_(\S+))\s+(.*)$/) { + $macro = $1; + $feature = $2; + $tail = $3; + if ($tail =~ /\/\*\s*\"([^"]*)\".*\*\//) { + $feature = $1; + } + + if ($feature ne '') { + printf OUT "\t%-32s = \"%s\",\n", + "[$macro]", "\L$feature"; + } + } +} +print OUT "};\n"; + +close(IN); +close(OUT);
arch/x86/kernel/platform_info.c new file +112 -0
112 lines not on this page · raw message
Signature · 1 line
1.5.6.5
RFC PATCH 3/7 x86: add moorestown specific platform setup code
In reply to Thomas GleixnerQuoted 1 line
From
dbb97928dc27061b56fc86b9b37f71f54bbafb59Mon Sep 17 00:00:00 2001
From: Jacob Pan <[email protected]>
Date: Fri, 28 Aug 2009 08:31:45 -0700
Subject: [PATCH] x86: add moorestown specific platform setup code
This patch fills in platform_setup functions for Moorestown. The abstraction is used to integarte into pc compaitible boot flow.
--- arch/x86/include/asm/setup.h | 8 ++ arch/x86/kernel/Makefile | 1 + arch/x86/kernel/mrst.c | 149 ++++++++++++++++++++++++++++++++++++++++++ arch/x86/kernel/setup.c | 1 + 4 files changed, 159 insertions(+), 0 deletions(-) create mode 100644 arch/x86/kernel/mrst.c
arch/x86/include/asm/setup.h +8 -0
@@ -49,6 +49,14 @@ extern void reserve_standard_io_resources(void);extern void i386_reserve_resources (void );extern void setup_default_timer_irq (void ); +#ifdef CONFIG_MRST +extern void mrst_early_detect (void ); +extern void setup_mrst_default_feature (void ); +#else +static inline void mrst_early_detect (void ) { } +static inline void setup_mrst_default_feature (void ) { }; +#endif +#ifndef _SETUP/*
arch/x86/kernel/Makefile +1 -0
@@ -105,6 +105,7 @@ obj-$(CONFIG_SCx200) += scx200.o scx200-y += scx200_32.o obj-$(CONFIG_OLPC) += olpc.o +obj-$(CONFIG_MRST) += mrst.o microcode-y := microcode_core.o microcode-$(CONFIG_MICROCODE_INTEL) += microcode_intel.o
arch/x86/kernel/mrst.c new file +149 -0
149 lines not on this page · raw message
arch/x86/kernel/setup.c +1 -0
@@ -692,6 +692,7 @@ void __init setup_arch(char **cmdline_p)#ifdef CONFIG_X86_32 memcpy (&boot_cpu_data, &new_cpu_data,sizeof (new_cpu_data));visws_early_detect (); +mrst_early_detect ();#else printk (KERN_INFO "Command line: %s\n" , boot_command_line);#endif
Signature · 1 line
1.5.6.5
Re: [RFC PATCH 3/7] x86: add moorestown specific platform setup code
Quoted 7 lines · Jacob jun
Quoted 1 line
From
dbb97928dc27061b56fc86b9b37f71f54bbafb59Mon Sep 17 00:00:00 2001From: Jacob Pan <[email protected]>
Date: Fri, 28 Aug 2009 08:31:45 -0700
Subject: [PATCH] x86: add moorestown specific platform setup codeThis patch fills in
platform_setupfunctions for Moorestown. The abstraction is used to integarte into pc compaitible boot flow.
Your patch series is horrible as it breaks left and right. Patches need to be ordered so they compile and boot in any stage.
Quoted 14 lines
Signed-off-by Jacob Pan <[email protected]>--- arch/x86/include/asm/setup.h | 8 ++ arch/x86/kernel/Makefile | 1 + arch/x86/kernel/mrst.c | 149 ++++++++++++++++++++++++++++++++++++++++++ arch/x86/kernel/setup.c | 1 + 4 files changed, 159 insertions(+), 0 deletions(-) create mode 100644 arch/x86/kernel/mrst.carch/x86/include/asm/setup.h +0
-0
arch/x86/include/asm/setup.h extern void reserve_standard_io_resources(void); · line 54
Quoted 6 lines
arch/x86/include/asm/setup.h +3
-0@@ -49,6 +49,14 @@ extern void reserve_standard_io_resources(void);extern void i386_reserve_resources (void );extern void setup_default_timer_irq (void ); +#ifdef CONFIG_MRST +extern void mrst_early_detect (void ); +extern void setup_mrst_default_feature (void );
Why ? The function is inline in mrst.c.
Quoted 24 lines
arch/x86/include/asm/setup.h +23
-0+++ b/arch/x86/kernel/mrst.c@@ -0,0 +1,149 @@ +/* +* mrst.c: Intel Moorestown platform specific setup code +* +* (C) Copyright 2008 Intel Corporation +* Author: Jacob Pan ([email protected]) +* +* 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. +* +* Note: +* +*/ + +#include <linux/stackprotector.h> +#include <linux/spi/spi.h> +#include <linux/i2c.h> +#include <linux/sfi.h> +#include <linux/i2c/pca953x.h> +#include <linux/spi/langwell_pmic_gpio.h> +#include <linux/gpio_keys.h>
arch/x86/include/asm/setup.h line 32
Quoted 10 lines
arch/x86/include/asm/setup.h +10
-0+#include <linux/input.h> +#include <linux/platform_device.h> +#include <linux/pci.h> + +#include <asm/platform_feature.h> +#include <asm/apb_timer.h> +#include <asm/apic.h> +#include <asm/hw_irq.h> +#include <asm/setup.h> +#include <asm/io.h>
Do we really need that whole bunch of includes ?
arch/x86/include/asm/setup.h line 34
Quoted 2 lines
arch/x86/include/asm/setup.h +2
-0+#define LANGWELL_GPIO_ALT_ADDR 0xff12c038 +#define MRST_I2C_BUSNUM 3
That should be in the appropriate header file aside of being unused.
arch/x86/include/asm/setup.h line 38
Quoted 4 lines
arch/x86/include/asm/setup.h +4
-0+static inline void __init mrst_pre_intr_init (void ) +{ +pre_init_apic_IRQ (); +}
Later on you assign that function to:
arch/x86/include/asm/setup.h line 39
Quoted 1 line
arch/x86/include/asm/setup.h +1
-0+ platform_setup.irqs.pre_vector_init = mrst_pre_intr_init;
I don't think that's correct. You need the early setup of the APIC when you setup the APBT timer, but that's way after pre_vector_init.
Please do not use random platform functions just because they are available.
The setup of the APIC to make your timer work should be done either in context of the timer init function or in some appropriate place before that.
arch/x86/include/asm/setup.h line 42
Quoted 3 lines
arch/x86/include/asm/setup.h +3
-0+/* +* the secondary clock in Moorestown can be APBT or LAPIC clock, default to +* APBT but cmdline option can also override it.
We have the platform functions to avoid constructs like this. If you set the function pointer to mrst_setup_secondary_clock in your platform init the you can check the disable_apbt_percpu there or restore the default in the function which evaluates the command line option.
arch/x86/include/asm/setup.h line 44
Quoted 2 lines
arch/x86/include/asm/setup.h +2
-0+*/ +static void __init mrst_setup_secondary_clock (void )
Needs to be __cpuinit. If you have CPU_HOTPLUG enabled, which you need for suspend/hibernate this function will be gone at the point you access it.
arch/x86/include/asm/setup.h line 55
Quoted 11 lines
arch/x86/include/asm/setup.h +11
-0+{ +if (disable_apbt_percpu) +return setup_secondary_APIC_clock (); +else { +#ifdef CONFIG_CC_STACKPROTECTOR +/* +* TBD: +* this is to avoid false stack corruption panic since +* request_irq will be called early for secondary apbt clock. +*/ +boot_init_stack_canary ();
Eeek. Why is this related to request_irq ?
arch/x86/include/asm/setup.h line 67
Quoted 12 lines
arch/x86/include/asm/setup.h +12
-0+#endif +apbt_setup_secondary_clock (); + } +} + +static void __init mrst_check_timer (void ) +{ +if (timer_irq_works ()) +printk (KERN_INFO "APB timer works\n" ); +else +panic ("Check APB timer failed\n" ); +}
Errm. You add a new platform function just to add printk debug noise ?
arch/x86/include/asm/setup.h line 79
Quoted 12 lines
arch/x86/include/asm/setup.h +12
-0+static unsigned long __init mrst_calibrate_tsc (void ) +{ +unsigned long flags, fast_calibrate; + +local_irq_save (flags); + fast_calibrate =apbt_quick_calibrate (); +local_irq_restore (flags); + +if (fast_calibrate) +return fast_calibrate; + +return 0 ;
return fast_calibrate;
might do the same with less obfuscation.
arch/x86/include/asm/setup.h
Quoted 9 lines
arch/x86/include/asm/setup.h +8
-0+} +inline void setup_mrst_default_feature (void ) +{ +/* +* x86pc default platform setup ops are setup prior to start_kernel +* we override default platform_setup calls for Moorestown +*/ + platform_setup.resources.reserve_ebda_region = platform_setup_noop;
See below.
arch/x86/include/asm/setup.h
Quoted 5 lines
arch/x86/include/asm/setup.h +5
-0+void __init mrst_early_detect (void ) +{ +int subarch_id = boot_params.hdr.hardware_subarch; + +if ((subarch_id >=0 ) && (subarch_id <N_X86_SUBARCHS )) {
What's the purpose of this check ? Either it's X86_SUBARCH_MRST or not.
arch/x86/include/asm/setup.h void __init setup_arch(char **cmdline_p) · line 695
Quoted 7 lines
arch/x86/include/asm/setup.h +3
-0+if (subarch_id ==X86_SUBARCH_MRST ) { +setup_mrst_default_feature ();@@ -692,6 +692,7 @@ void __init setup_arch(char **cmdline_p)#ifdef CONFIG_X86_32 memcpy (&boot_cpu_data, &new_cpu_data,sizeof (new_cpu_data));visws_early_detect (); +mrst_early_detect ();
That call is too late.
You override platform_setup.resources.reserve_ebda_region _AFTER_ it has been called.
Thanks,
tglx
RFC PATCH 4/7 x86/apbt: Moorestown APB system timer driver
In reply to Thomas GleixnerQuoted 1 line
From
c6e346613ce50ab24b0d23ab6ff780790080a195Mon Sep 17 00:00:00 2001
From: Jacob Pan <[email protected]>
Date: Wed, 15 Jul 2009 14:12:55 -0700
Subject: [PATCH] x86/apbt: Moorestown APB system timer driver
Moorestown platform has introduced legacy replacement system timers, called APB timers. There are four timers available to the kernel via SFI MTMR table. APB timers are always running and have a known frequency. Two timers used for per CPU clockevent deivces, one for clocksource, one by the watchdog driver.
This driver serve similar functionality found in i8254 and HPET, APB timers are given higher rating than local APIC timer so that they are used for per CPU timer in SMP/HT. Broadcast timer is avoided. If cmdline option no_percpu_apbt is given, the kernel will pick local APIC timers and one APB timer as broadcast clockevent device.
--- Documentation/kernel-parameters.txt | 4 + arch/x86/Kconfig | 11 + arch/x86/include/asm/apb_timer.h | 67 +++ arch/x86/kernel/Makefile | 2 +- arch/x86/kernel/apb_timer.c | 762 +++++++++++++++++++++++++++++++++++ arch/x86/kernel/apic/apic.c | 3 + 6 files changed, 848 insertions(+), 1 deletions(-) create mode 100644 arch/x86/include/asm/apb_timer.h create mode 100644 arch/x86/kernel/apb_timer.c
Documentation/kernel-parameters.txt +4 -0
@@ -1654,6 +1654,10 @@ and is between 256 and 4096 characters. It is defined in the file nomfgpt [X86-32] Disable Multi-Function General Purpose Timer usage (for AMD Geode machines). + no_percpu_apbt [X86-32,APBT] + Disable per CPU APB timer as clockevent devices. this + will make the local APIC timer used as per CPU timer. + norandmaps Don't use address space randomization. Equivalent to echo 0 > /proc/sys/kernel/randomize_va_space
arch/x86/Kconfig +11 -0
@@ -571,6 +571,16 @@ config HPET_EMULATE_RTC def_bool y depends on HPET_TIMER && (RTC=y || RTC=m || RTC_DRV_CMOS=m || RTC_DRV_CMOS=y) +config APB_TIMER + def_bool y if MRST + prompt "Langwell APB Timer Support" if MRST + help + APB timer is the replacement for 8254, HPET on X86 MID platforms. + The APBT provides a stable time base on SMP + systems, unlike the TSC, but it is more expensive to access, + as it is off-chip. APB timers are always running regardless of CPU + C states, they are used as per CPU clockevent device when possible. + # Mark as embedded because too many people got it wrong. # The code disables itself when not needed. config DMI
@@ -1663,6 +1673,7 @@ config MRST default n depends on X86_32 select SFI + select APB_TIMER help Moorestown is Intel's Low Power Intel Architecture (LPIA) based Moblin Internet Device(MID) platform. Moorestown consists of two chips:
arch/x86/include/asm/apb_timer.h new file +67 -0
67 lines not on this page · raw message
arch/x86/kernel/Makefile +1 -1
@@ -87,7 +87,7 @@ obj-$(CONFIG_VM86) += vm86_32.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o obj-$(CONFIG_HPET_TIMER) += hpet.o - +obj-$(CONFIG_APB_TIMER) += apb_timer.o obj-$(CONFIG_K8_NB) += k8.o obj-$(CONFIG_MGEODE_LX) += geode_32.o mfgpt_32.o obj-$(CONFIG_DEBUG_RODATA_TEST) += test_rodata.o
arch/x86/kernel/apb_timer.c new file +762 -0
762 lines not on this page · raw message
arch/x86/kernel/apic/apic.c +3 -0
@@ -738,6 +738,9 @@ static int __init calibrate_APIC_clock(void)*/ void __init setup_boot_APIC_clock (void ) { +/* we rely on global clockevent for calibration */ +if (global_clock_event ==NULL ) +return ;/* * The local apic timer can be disabled via the kernel * commandline or from the CPU detection code. Register the lapic
--
1.5.6.5
RFC PATCH 5/7 x86/apic: decouple legacy irq handling in ioapic
In reply to Thomas GleixnerQuoted 1 line
From
b37e4a846402d0ef7b1c19ea17d2d3aee22e81c2Mon Sep 17 00:00:00 2001
From: Jacob Pan <[email protected]>
Date: Wed, 15 Jul 2009 11:29:42 -0700
Subject: [PATCH] x86/apic: RFC decouple legacy irq handling in ioapic
This patch uses platform feature flags to separate i8259/PIC from ioapic. A cleaner solution might be adding abstraction for device interrupt controller and moving apic initialization earlier so that platforms with legacy replace devices can boot without the constriant of PIC, PIT, etc. Such change obviously introduces risk.
The intention of this patch is also to show what kind of changes are needed for non-pc x86 platform such as Moorestown MID. perhpas we can take a phased approach.
--- arch/x86/kernel/apic/io_apic.c | 31 ++++++++++++++++++++++++------- 1 files changed, 24 insertions(+), 7 deletions(-)
arch/x86/kernel/apic/io_apic.c +24 -7
@@ -62,7 +62,7 @@#include <asm/hw_irq.h> #include <asm/uv/uv_hub.h> #include <asm/uv/uv_irq.h> - +#include <asm/platform_feature.h> #include <asm/apic.h> #define __apicdebuginit (type) static type __init
@@ -1447,6 +1447,12 @@ int setup_ioapic_entry(int apic_id, int irq,return 0 ; } +static inline int is_i8259_legacy_irq (int irq) +{ +return ((irq <NR_IRQS_LEGACY ) + &&platform_has (X86_PLATFORM_FEATURE_8259 )); +} +static void setup_IO_APIC_irq (int apic_id,int pin,unsigned int irq,struct irq_desc *desc,int trigger,int polarity) {
@@ -1480,7 +1486,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 (is_i8259_legacy_irq (irq))disable_8259A_irq (irq);ioapic_write_entry (apic_id, pin, entry);
@@ -1851,6 +1857,9 @@ __apicdebuginit(void) print_PIC(void)unsigned int v;unsigned long flags; +if (!platform_has (X86_PLATFORM_FEATURE_8259 )) +return ; +if (apic_verbosity ==APIC_QUIET )return ;
@@ -1914,6 +1923,8 @@ void __init enable_IO_APIC(void)spin_unlock_irqrestore (&ioapic_lock, flags); nr_ioapic_registers[apic] = reg_01.bits.entries+1 ; } +if (!platform_has (X86_PLATFORM_FEATURE_8259 )) +return ;for (apic =0 ; apic < nr_ioapics; apic++) {int pin;/* See if any of the pins is in ExtINT mode */
@@ -1968,6 +1979,8 @@ void disable_IO_APIC(void)*/ clear_IO_APIC (); +if (!platform_has (X86_PLATFORM_FEATURE_8259 )) +return ;/* * If the i8259 is routed through an IOAPIC * Put that IOAPIC in virtual wire mode
@@ -2198,7 +2211,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 (is_i8259_legacy_irq (irq)) {disable_8259A_irq (irq);if (i8259A_irq_pending (irq)) was_pending =1 ;
@@ -2709,7 +2722,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 (is_i8259_legacy_irq (irq))make_8259A_irq (irq);else /* Strange. Oh, well.. */
@@ -3052,9 +3065,13 @@ void __init setup_IO_APIC(void)/* * calling enable_IO_APIC() is moved to setup_local_APIC for BP +* For platforms that do not have legacy IRQs, IOAPIC IRQ can be any +* number. */ - - io_apic_irqs = ~PIC_IRQS ; +if (!platform_has (X86_PLATFORM_FEATURE_8259 )) + io_apic_irqs = ~0 ; +else + io_apic_irqs = ~PIC_IRQS ;apic_printk (APIC_VERBOSE ,"ENABLING IO-APIC IRQs\n" );/*
@@ -3907,7 +3924,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 (!is_i8259_legacy_irq (irq)) { cfg = desc->chip_data;add_pin_to_irq_node (cfg, node, ioapic, pin); }
Signature · 1 line
1.5.6.5
RFC PATCH 6/7 x86/apic: Early setup IOAPIC for APB timer
In reply to Thomas GleixnerQuoted 1 line
From
9438ac713c0175e975ef3d0013e6bf2b46883dd0Mon Sep 17 00:00:00 2001
From: Jacob Pan <[email protected]>
Date: Wed, 15 Jul 2009 11:30:40 -0700
Subject: [PATCH] x86/apic: Early setup IOAPIC for APB timer
Intel Moorestown platform uses APB system timers which rely on IOAPIC to deliver its interrupts. Early setup the APIC system is necessary to allow timer interrupts.
--- arch/x86/include/asm/apic.h | 1 + arch/x86/kernel/apic/io_apic.c | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 0 deletions(-)
arch/x86/include/asm/apic.h +1 -0
@@ -84,6 +84,7 @@ extern void xapic_wait_icr_idle(void);extern u32 safe_xapic_wait_icr_idle (void );extern void xapic_icr_write (u32 ,u32 );extern int setup_profiling_timer (unsigned int ); +extern void pre_init_apic_IRQ (void );static inline void native_apic_mem_write (u32 reg,u32 v) {
arch/x86/kernel/apic/io_apic.c +17 -0
@@ -36,6 +36,7 @@#include <linux/freezer.h> #include <linux/kthread.h> #include <linux/jiffies.h> /* time_after() */ +#include <linux/sfi.h> #ifdef CONFIG_ACPI #include <acpi/acpi_bus.h> #endif
@@ -63,6 +64,7 @@#include <asm/uv/uv_hub.h> #include <asm/uv/uv_irq.h> #include <asm/platform_feature.h> +#include <asm/apb_timer.h> #include <asm/apic.h> #define __apicdebuginit (type) static type __init
@@ -4211,3 +4213,18 @@ void __init ioapic_insert_resources(void) r++; } } + +/* Enable IOAPIC early just for system timer */ +void __init pre_init_apic_IRQ (void ) +{ +struct irq_cfg *cfg; + +printk (KERN_INFO "Early APIC setup for system timer\n" ); +#ifndef CONFIG_SMP + phys_cpu_present_map =physid_mask_of_physid (boot_cpu_physical_apicid); +#endif +setup_local_APIC (); + cfg =irq_cfg (0 ); +add_pin_to_irq_node (cfg,0 ,0 ,0 ); +setup_timer_IRQ0_pin (0 ,0 , cfg->vector); +}
Signature · 1 line
1.5.6.5
RFC PATCH 7/7 x86: add more platform_setup functions
In reply to Thomas GleixnerQuoted 1 line
From
fbfe65d64e4dbb31940d31a59e080bfa15d121bbMon Sep 17 00:00:00 2001
From: Jacob Pan <[email protected]>
Date: Wed, 8 Jul 2009 16:51:42 -0700
Subject: [PATCH] x86: RFC add more platform_setup functions
check_timer can be abstracted so that we don't have to do the complicated checks for platform timer for all platforms. pci irq enable/disable can also benefit from the platform setup layer, but this part is not complete in this patch, should be able to include visws. e.g.
pcibios_enable_irq = &pci_visws_enable_irq;pcibios_disable_irq = &pci_visws_disable_irq;
--- arch/x86/include/asm/apic.h | 2 ++ arch/x86/include/asm/pci_x86.h | 2 ++ arch/x86/include/asm/platform.h | 11 +++++++++++ arch/x86/kernel/apic/io_apic.c | 6 +++--- arch/x86/kernel/platform_setup.c | 4 ++++ arch/x86/pci/irq.c | 11 +++++++---- 6 files changed, 29 insertions(+), 7 deletions(-)
arch/x86/include/asm/apic.h +2 -0
@@ -85,6 +85,8 @@ extern u32 safe_xapic_wait_icr_idle(void);extern void xapic_icr_write (u32 ,u32 );extern int setup_profiling_timer (unsigned int );extern void pre_init_apic_IRQ (void ); +extern void default_check_timer (void ); +extern int timer_irq_works (void );static inline void native_apic_mem_write (u32 reg,u32 v) {
arch/x86/include/asm/pci_x86.h +2 -0
@@ -116,6 +116,8 @@ extern int __init pci_visws_init(void);extern int __init pci_numaq_init (void );extern int __init pcibios_init (void ); +extern int pirq_enable_irq (struct pci_dev *dev); +/* pci-mmconfig.c */ extern int __init pci_mmcfg_arch_init (void );
arch/x86/include/asm/platform.h +11 -0
@@ -6,6 +6,7 @@struct mpc_bus ;struct mpc_cpu ;struct mpc_table ; +struct pci_dev ;/** * struct platform_setup_quirks - platform specific quirks
@@ -62,6 +63,11 @@ struct platform_setup_irqs {void (*pre_vector_init)(void );void (*intr_init)(void );void (*trap_init)(void ); + +#ifdef CONFIG_PCI +int (*pci_enable_irq)(struct pci_dev *dev); +void (*pci_disable_irq)(struct pci_dev *dev); +#endif };/**
@@ -97,6 +103,7 @@ struct platform_setup_timers {void (*tsc_pre_init)(void );void (*timer_init)(void );unsigned long (*calibrate_tsc)(void ); +void (*check_timers)(void ); };/**
@@ -127,4 +134,8 @@ extern struct platform_setup_cpuhotplug platform_cpuhotplug_setup;extern void platform_setup_noop (void );extern void platform_setup_uint_noop (unsigned int unused); +#ifdef CONFIG_PCI +extern int pirq_enable_irq (struct pci_dev *dev); +#endif +#endif
arch/x86/kernel/apic/io_apic.c +3 -3
@@ -2155,7 +2155,7 @@ __setup("no_timer_check", notimercheck);* - if this function detects that timer IRQs are defunct, then we fall * back to ISA timer IRQs */ -static int __init timer_irq_works (void ) +int __init timer_irq_works (void ) {unsigned long t1 = jiffies;unsigned long flags;
@@ -2868,7 +2868,7 @@ int timer_through_8259 __initdata;* * FIXME: really need to revamp this for all platforms. */ -static inline void __init check_timer (void ) +inline void __init default_check_timer (void ) {struct irq_desc *desc =irq_to_desc (0 );struct irq_cfg *cfg = desc->chip_data;
@@ -3084,7 +3084,7 @@ void __init setup_IO_APIC(void)sync_Arb_IDs ();setup_IO_APIC_irqs ();init_IO_APIC_traps (); -check_timer (); + platform_setup.timers.check_timers (); }/*
arch/x86/kernel/platform_setup.c +4 -0
@@ -44,6 +44,9 @@ struct __initdata platform_setup_ops platform_setup = { .pre_vector_init = init_ISA_irqs, .intr_init = native_init_IRQ, .trap_init = platform_setup_noop, +#ifdef CONFIG_PCI + .pci_enable_irq = pirq_enable_irq, +#endif }, .oem = {
@@ -61,6 +64,7 @@ struct __initdata platform_setup_ops platform_setup = { .tsc_pre_init = platform_setup_noop, .timer_init = hpet_time_init, .calibrate_tsc = native_calibrate_tsc, + .check_timers = default_check_timer, }, .quirks = {
arch/x86/pci/irq.c +7 -4
@@ -14,6 +14,7 @@#include <linux/io.h> #include <linux/smp.h> #include <asm/io_apic.h> +#include <asm/platform_feature.h> #include <linux/irq.h> #include <linux/acpi.h> #include <asm/pci_x86.h>
@@ -26,8 +27,6 @@ static int acer_tm360_irqrouting;static struct irq_routing_table *pirq_table; -static int pirq_enable_irq (struct pci_dev *dev); -/* * Never use: 0, 1, 2 (timer, keyboard, and cascade) * Avoid using: 13, 14 and 15 (FP error and IDE).
@@ -1022,6 +1021,10 @@ static void __init pcibios_fixup_irqs(void)u8 pin;DBG (KERN_DEBUG "PCI: IRQ fixup\n" ); +if (!platform_has (X86_PLATFORM_FEATURE_BIOS )) { +DBG (KERN_DEBUG "PCI: No BIOS, skip IRQ fixup\n" ); +return ; + }while ((dev =pci_get_device (PCI_ANY_ID ,PCI_ANY_ID , dev)) !=NULL ) {/* * If the BIOS has set an out of range IRQ number, just
@@ -1142,7 +1145,7 @@ int __init pcibios_irq_init(void) pirq_table =NULL ; } - pcibios_enable_irq = pirq_enable_irq; + pcibios_enable_irq = platform_setup.irqs.pci_enable_irq;pcibios_fixup_irqs ();
@@ -1185,7 +1188,7 @@ void pcibios_penalize_isa_irq(int irq, int active)pirq_penalize_isa_irq (irq, active); } -static int pirq_enable_irq (struct pci_dev *dev) +int pirq_enable_irq (struct pci_dev *dev) {u8 pin;
Signature · 1 line
1.5.6.5
Re: [RFC PATCH 7/7] x86: add more platform_setup functions
Quoted 7 lines · Jacob jun
Quoted 1 line
From
fbfe65d64e4dbb31940d31a59e080bfa15d121bbMon Sep 17 00:00:00 2001From: Jacob Pan <[email protected]>
Date: Wed, 8 Jul 2009 16:51:42 -0700
Subject: [PATCH] x86: RFC add moreplatform_setupfunctions
check_timercan be abstracted so that we don't have to do the complicated checks for platform timer for all platforms.
Well, if it's necessary then we replace it, but the code you showed in an earlier patch is just adding debug cruft. So what's the point ?
Quoted 3 lines
pci irq enable/disable can also
benefit from the platform setup layer, but this part is not complete in this patch, should be able to include visws. e.g.
Please provide one patch per feature / change.
Quoted 2 lines
pcibios_enable_irq=&pci_visws_enable_irq;pcibios_disable_irq=&pci_visws_disable_irq;
No, this is patently wrong. You abstract at the wrong point. If abstraction of the pci init is necessary then the various #ifdeffed function calls in legacy.c:pci_subsys_init() have to be platformized.
Quoted 14 lines
extern int
__initpci_mmcfg_arch_init(void);arch/x86/include/asm/platform.h +1
-0@@ -6,6 +6,7 @@struct mpc_bus ;struct mpc_cpu ;struct mpc_table ; +struct pci_dev ;/** * struct platform_setup_quirks - platform specific quirks
arch/x86/include/asm/platform.h struct platform_setup_irqs { · line 70
Quoted 8 lines
arch/x86/include/asm/platform.h +5
-0@@ -62,6 +63,11 @@ struct platform_setup_irqs {void (*pre_vector_init)(void );void (*intr_init)(void );void (*trap_init)(void ); + +#ifdef CONFIG_PCI +int (*pci_enable_irq)(struct pci_dev *dev); +void (*pci_disable_irq)(struct pci_dev *dev); +#endif
PCI stuff does not belong to irq. It needs a separate data structure. Also using the function pointers just to assign them later to some other function pointer is pointless. The code can be restructured so you can just tweak the existing function pointer. Also I avoided #ifdefs in the platform code on purpose. The few bytes you spare in the init structure are not worth the #ifdef mess which is needed all over the place.
Thanks,
tglx
RFC PATCH 3/32 x86: Add request_standard_resources to platform_setup
In reply to Thomas GleixnerThe 32bit and the 64bit code are slighty different in the reservation of standard resources. Also the upcoming Moorestown support needs its own version of that.
Add it to the platform_setup and initialize it with the 64bit default. 32bit overrides it in early boot. Now moorestown can add it's own override w/o sprinkling the code with more #ifdefs
--- arch/x86/include/asm/platform.h | 3 +++ arch/x86/include/asm/setup.h | 3 +++ arch/x86/kernel/head32.c | 1 + arch/x86/kernel/platform_setup.c | 3 ++- arch/x86/kernel/setup.c | 28 ++++++++++++++++------------ 5 files changed, 25 insertions(+), 13 deletions(-)
arch/x86/include/asm/platform.h +3 -0
@@ -11,10 +11,13 @@ struct platform_setup_quirks {/** * struct platform_setup_resources - platform specific resource related ops * @probe_roms: probe BIOS roms +* @reserve_resources: reserve the standard resources for the +* platform * */ struct platform_setup_resources {void (*probe_roms)(void ); +void (*reserve_resources)(void ); };/**
arch/x86/include/asm/setup.h +3 -0
@@ -88,6 +88,9 @@ extern unsigned long saved_video_mode;#define paravirt_post_allocator_init () do {} while (0)#endif +extern void reserve_standard_io_resources (void ); +extern void i386_reserve_resources (void ); +#ifndef _SETUP/*
arch/x86/kernel/head32.c +1 -0
@@ -31,6 +31,7 @@ void __init i386_start_kernel(void)#endif /* Initilize 32bit specific setup functions */ platform_setup.resources.probe_roms = probe_roms; + platform_setup.resources.reserve_resources = i386_reserve_resources;reserve_ebda_region ();
arch/x86/kernel/platform_setup.c +2 -1
@@ -5,7 +5,7 @@*/ #include <linux/init.h> -#include <asm/platform.h> +#include <asm/setup.h> void __cpuinit platform_setup_noop (void ) { }
@@ -17,5 +17,6 @@ struct __initdata platform_setup_ops pla .resources = { .probe_roms = platform_setup_noop, + .reserve_resources = reserve_standard_io_resources, }, };
arch/x86/kernel/setup.c +16 -12
@@ -171,13 +171,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 */
@@ -605,7 +598,7 @@ static struct resource standard_io_resou .flags = IORESOURCE_BUSY | IORESOURCE_IO } }; -static void __init reserve_standard_io_resources (void ) +void __init reserve_standard_io_resources (void ) {int i;
@@ -1013,10 +1006,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 (); + platform_setup.resources.reserve_resources ();e820_setup_gap ();
@@ -1102,4 +1092,18 @@ void __init x86_quirk_time_init(void) irq0.mask =cpumask_of_cpu (0 ); setup_irq(0, &irq0); } + +static struct resource video_ram_resource = { + .name ="Video RAM area" , + .start =0xa0000 , + .end =0xbffff , + .flags =IORESOURCE_BUSY |IORESOURCE_MEM +}; + +void __init i386_reserve_resources (void ) +{ +request_resource (&iomem_resource, &video_ram_resource); +reserve_standard_io_resources (); +} +#endif /* CONFIG_X86_32 */
RFC PATCH 4/32 x86: Add reserve_ebda_region to platform_setup
In reply to Thomas Gleixnerreserve_ebda_region needs to be called befor start_kernel. Moorestown needs to override it. Make it a platform_setup function and initialize it with the default reserve_ebda_region.
--- arch/x86/include/asm/platform.h | 2 ++ arch/x86/kernel/head32.c | 4 ++-- arch/x86/kernel/head64.c | 3 +-- arch/x86/kernel/platform_setup.c | 2 ++ 4 files changed, 7 insertions(+), 4 deletions(-)
arch/x86/include/asm/platform.h +2 -0
@@ -13,11 +13,13 @@ struct platform_setup_quirks {* @probe_roms: probe BIOS roms * @reserve_resources: reserve the standard resources for the * platform +* @reserve_ebda_region: reserve the extended bios data area * */ struct platform_setup_resources {void (*probe_roms)(void );void (*reserve_resources)(void ); +void (*reserve_ebda_region)(void ); };/**
arch/x86/kernel/head32.c +2 -2
@@ -11,7 +11,7 @@#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> void __init i386_start_kernel (void )
@@ -33,7 +33,7 @@ void __init i386_start_kernel(void) platform_setup.resources.probe_roms = probe_roms; platform_setup.resources.reserve_resources = i386_reserve_resources; -reserve_ebda_region (); + platform_setup.resources.reserve_ebda_region ();/* * At this point everything still needed from the boot loader
arch/x86/kernel/head64.c +1 -2
@@ -23,7 +23,6 @@#include <asm/sections.h> #include <asm/kdebug.h> #include <asm/e820.h> -#include <asm/bios_ebda.h> #include <asm/trampoline.h> static void __init zap_identity_mappings (void )
@@ -112,7 +111,7 @@ void __init x86_64_start_reservations(ch }#endif -reserve_ebda_region (); + platform_setup.resources.reserve_ebda_region ();/* * At this point everything still needed from the boot loader
arch/x86/kernel/platform_setup.c +2 -0
@@ -5,6 +5,7 @@*/ #include <linux/init.h> +#include <asm/bios_ebda.h> #include <asm/setup.h> void __cpuinit platform_setup_noop (void ) { }
@@ -18,5 +19,6 @@ struct __initdata platform_setup_ops pla .resources = { .probe_roms = platform_setup_noop, .reserve_resources = reserve_standard_io_resources, + .reserve_ebda_region = reserve_ebda_region, }, };
RFC PATCH 5/32 x86: Move memory_setup to platform
In reply to Thomas Gleixnermemory_setup is overridden by x86_quirks and by paravirts with weak functions and quirks. Unify the whole mess and make it an unconditional platform setup function which defaults to the standard function and can be overridden by the early platform code.
--- arch/x86/include/asm/e820.h | 2 -- arch/x86/include/asm/paravirt.h | 1 - arch/x86/include/asm/platform.h | 2 ++ arch/x86/include/asm/setup.h | 1 - arch/x86/kernel/apic/numaq_32.c | 1 - arch/x86/kernel/e820.c | 19 +------------------ arch/x86/kernel/paravirt.c | 6 ------ arch/x86/kernel/platform_setup.c | 2 ++ arch/x86/kernel/visws_quirks.c | 3 ++- arch/x86/lguest/boot.c | 3 ++- arch/x86/xen/enlighten.c | 3 ++- 11 files changed, 11 insertions(+), 32 deletions(-)
arch/x86/include/asm/e820.h +0 -2
@@ -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__ */
arch/x86/include/asm/paravirt.h +0 -1
@@ -88,7 +88,6 @@ struct pv_init_ops {/* Basic arch-specific setup */ void (*arch_setup)(void ); -char *(*memory_setup)(void );void (*post_allocator_init)(void );/* Print a banner to identify the environment */
arch/x86/include/asm/platform.h +2 -0
@@ -14,12 +14,14 @@ struct platform_setup_quirks {* @reserve_resources: reserve the standard resources for the * platform * @reserve_ebda_region: reserve the extended bios data area +* @memory_setup: platform specific memory setup * */ struct platform_setup_resources {void (*probe_roms)(void );void (*reserve_resources)(void );void (*reserve_ebda_region)(void ); +char *(*memory_setup)(void ); };/**
arch/x86/include/asm/setup.h +0 -1
@@ -22,7 +22,6 @@ struct x86_quirks {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);
arch/x86/kernel/apic/numaq_32.c +0 -1
@@ -260,7 +260,6 @@ static struct x86_quirks numaq_x86_quirk .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,
arch/x86/kernel/e820.c +1 -18
@@ -1455,28 +1455,11 @@ char *__init default_machine_specific_mereturn 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 = platform_setup.resources.memory_setup ();memcpy (&e820_saved, &e820,sizeof (struct e820map ));printk (KERN_INFO "BIOS-provided physical RAM map:\n" );e820_print_map (who);
arch/x86/kernel/paravirt.c +0 -6
@@ -60,11 +60,6 @@ static void __init default_banner(void) 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[]; \
@@ -322,7 +317,6 @@ 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 = {
arch/x86/kernel/platform_setup.c +2 -0
@@ -7,6 +7,7 @@#include <asm/bios_ebda.h> #include <asm/setup.h> +#include <asm/e820.h> void __cpuinit platform_setup_noop (void ) { }
@@ -20,5 +21,6 @@ struct __initdata platform_setup_ops pla .probe_roms = platform_setup_noop, .reserve_resources = reserve_standard_io_resources, .reserve_ebda_region = reserve_ebda_region, + .memory_setup = default_machine_specific_memory_setup, }, };
arch/x86/kernel/visws_quirks.c +2 -1
@@ -239,7 +239,6 @@ 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,
@@ -263,6 +262,8 @@ void __init visws_early_detect(void)*/ x86_quirks = &visws_x86_quirks; + platform_setup.resources.memory_setup = visws_memory_setup; +/* * Install reboot quirks: */
arch/x86/lguest/boot.c +2 -1
@@ -1270,7 +1270,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 */
@@ -1325,6 +1324,8 @@ __init void lguest_init(void) pv_time_ops.time_init = lguest_time_init; pv_time_ops.get_tsc_khz = lguest_tsc_khz; + platform_setup.resources.memory_setup = lguest_memory_setup; +/* * Now is a good time to look at the implementations of these functions * before returning to the rest of lguest_init().
arch/x86/xen/enlighten.c +2 -1
@@ -841,7 +841,6 @@ static const struct pv_init_ops xen_init .patch = xen_patch, .banner = xen_banner, - .memory_setup = xen_memory_setup, .arch_setup = xen_arch_setup, .post_allocator_init = xen_post_allocator_init, };
@@ -986,6 +985,8 @@ asmlinkage void __init xen_start_kernel( pv_apic_ops = xen_apic_ops; pv_mmu_ops = xen_mmu_ops; + platform_setup.resources.memory_setup = xen_memory_setup; +xen_init_irq_ops ();xen_init_cpuid_mask ();
RFC PATCH 6/32 x86: Sanitize smp_record and move it to platform_setup
In reply to Thomas GleixnerThe x86 quirkification introduced an extra ugly hackery with a variable pointer in the mpparse code. If the pointer is initialized then it is dereferenced and the variable set to 0 or incremented.
Create a platform_setup quirk function and let the affected numaq code hold the function. Default init is a setup noop.
--- arch/x86/include/asm/platform.h | 3 +++ arch/x86/include/asm/setup.h | 1 - arch/x86/kernel/apic/numaq_32.c | 19 ++++++++++++++++--- arch/x86/kernel/mpparse.c | 6 ++---- arch/x86/kernel/platform_setup.c | 5 +++++ 5 files changed, 26 insertions(+), 8 deletions(-)
arch/x86/include/asm/platform.h +3 -0
@@ -3,9 +3,11 @@/** * struct platform_setup_quirks - platform specific quirks +* @mpc_record: platform specific mpc record accounting * */ struct platform_setup_quirks { +void (*mpc_record)(unsigned int mode); };/**
@@ -36,5 +38,6 @@ struct platform_setup_ops {extern struct platform_setup_ops platform_setup;extern void platform_setup_noop (void ); +extern void platform_setup_uint_noop (unsigned int unused);#endif
arch/x86/include/asm/setup.h +0 -1
@@ -25,7 +25,6 @@ struct x86_quirks {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);
arch/x86/kernel/apic/numaq_32.c +16 -3
@@ -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 ];
@@ -177,6 +176,19 @@ static void mpc_oem_pci_bus(struct mpc_b 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
@@ -264,7 +276,6 @@ static struct x86_quirks numaq_x86_quirk .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,
@@ -285,8 +296,10 @@ static __init void early_check_numaq(voiif (smp_found_config)early_get_smp_config (); -if (found_numaq) +if (found_numaq) { x86_quirks = &numaq_x86_quirks; + platform_setup.quirks.mpc_record = numaq_mpc_record; + } }int __init get_memcfg_numaq (void )
arch/x86/kernel/mpparse.c +2 -4
@@ -320,8 +320,7 @@ static int __init smp_read_mpc(struct mp/* * Now process the configuration blocks. */ -if (x86_quirks->mpc_record) - *x86_quirks->mpc_record =0 ; + platform_setup.quirks.mpc_record (0 );while (count < mpc->length) {switch (*mpt) {
@@ -353,8 +352,7 @@ static int __init smp_read_mpc(struct mp count = mpc->length;break ; } -if (x86_quirks->mpc_record) - (*x86_quirks->mpc_record)++; + platform_setup.quirks.mpc_record (1 ); }#ifdef CONFIG_X86_BIGSMP
arch/x86/kernel/platform_setup.c +5 -0
@@ -10,6 +10,7 @@#include <asm/e820.h> void __cpuinit platform_setup_noop (void ) { } +void __init platform_setup_uint_noop (unsigned int unused) { }/* * The platform setup functions are preset with the default functions
@@ -23,4 +24,8 @@ struct __initdata platform_setup_ops pla .reserve_ebda_region = reserve_ebda_region, .memory_setup = default_machine_specific_memory_setup, }, + + .quirks = { + .mpc_record = platform_setup_uint_noop, + }, };
RFC PATCH 7/32 x86: Move ioapic_ids_setup to platform_setup
In reply to Thomas Gleixner32bit and also the numaq code have special requirements on the ioapic_id setup. Convert it to a platform_setup function and get rid of the quirks and #ifdefs
--- arch/x86/include/asm/io_apic.h | 3 ++- arch/x86/include/asm/platform.h | 10 +++++++++- arch/x86/include/asm/setup.h | 1 - arch/x86/kernel/apic/io_apic.c | 11 ++++------- arch/x86/kernel/apic/numaq_32.c | 8 +------- arch/x86/kernel/head32.c | 3 +++ arch/x86/kernel/platform_setup.c | 4 ++++ 7 files changed, 23 insertions(+), 17 deletions(-)
arch/x86/include/asm/io_apic.h +2 -1
@@ -177,12 +177,13 @@ extern int setup_ioapic_entry(int apic, 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 );#else /* !CONFIG_X86_IO_APIC */ #define io_apic_assign_pci_irqs 0 +#define setup_ioapic_ids_from_mpc platform_setup_noopstatic 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
arch/x86/include/asm/platform.h +9 -1
@@ -4,13 +4,20 @@/** * struct platform_setup_quirks - platform specific quirks * @mpc_record: platform specific mpc record accounting -* */ struct platform_setup_quirks {void (*mpc_record)(unsigned int mode); };/** +* struct platform_setup_mpparse - platform specific mpparse ops +* @setup_ioapic_ids: platform specific ioapic id override +*/ +struct platform_setup_mpparse { +void (*setup_ioapic_ids)(void ); +}; + +/** * struct platform_setup_resources - platform specific resource related ops * @probe_roms: probe BIOS roms * @reserve_resources: reserve the standard resources for the
@@ -32,6 +39,7 @@ struct platform_setup_resources {*/ struct platform_setup_ops {struct platform_setup_resources resources; +struct platform_setup_mpparse mpparse;struct platform_setup_quirks quirks; };
arch/x86/include/asm/setup.h +0 -1
@@ -30,7 +30,6 @@ struct x86_quirks {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 );
arch/x86/kernel/apic/io_apic.c +4 -7
@@ -2014,7 +2014,7 @@ void disable_IO_APIC(void)* by Matt Domsch <[email protected]> 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;
@@ -2023,9 +2023,8 @@ static void __init setup_ioapic_ids_fromunsigned 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.
@@ -3061,10 +3060,8 @@ void __init setup_IO_APIC(void)/* * Set up IO-APIC IRQ routing. */ -#ifdef CONFIG_X86_32 -if (!acpi_ioapic) -setup_ioapic_ids_from_mpc (); -#endif + platform_setup.mpparse.setup_ioapic_ids (); +sync_Arb_IDs ();setup_IO_APIC_irqs ();init_IO_APIC_traps ();
arch/x86/kernel/apic/numaq_32.c +1 -7
@@ -262,12 +262,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 ,
@@ -280,7 +274,6 @@ static struct x86_quirks numaq_x86_quirk .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 )
@@ -299,6 +292,7 @@ static __init void early_check_numaq(voiif (found_numaq) { x86_quirks = &numaq_x86_quirks; platform_setup.quirks.mpc_record = numaq_mpc_record; + platform_setup.mpparse.setup_ioapic_ids = platform_setup_noop; } }
arch/x86/kernel/head32.c +3 -0
@@ -13,6 +13,8 @@#include <asm/e820.h> #include <asm/page.h> #include <asm/trampoline.h> +#include <asm/apic.h> +#include <asm/io_apic.h> void __init i386_start_kernel (void ) {
@@ -32,6 +34,7 @@ void __init i386_start_kernel(void)/* Initilize 32bit specific setup functions */ platform_setup.resources.probe_roms = probe_roms; platform_setup.resources.reserve_resources = i386_reserve_resources; + platform_setup.mpparse.setup_ioapic_ids = setup_ioapic_ids_from_mpc; platform_setup.resources.reserve_ebda_region ();
arch/x86/kernel/platform_setup.c +4 -0
@@ -25,6 +25,10 @@ struct __initdata platform_setup_ops pla .memory_setup = default_machine_specific_memory_setup, }, + .mpparse = { + .setup_ioapic_ids = platform_setup_noop, + }, + .quirks = { .mpc_record = platform_setup_uint_noop, },
RFC PATCH 8/32 x86: Move mpc_apic_id to platform_setup
In reply to Thomas GleixnerThe mpc_apic_id setup is handled by a x86_quirk. Make it a platform_setup function with a default implementation.
--- arch/x86/include/asm/mpspec.h | 2 ++ arch/x86/include/asm/platform.h | 4 ++++ arch/x86/include/asm/setup.h | 2 -- arch/x86/kernel/apic/numaq_32.c | 2 +- arch/x86/kernel/mpparse.c | 10 ++++++---- arch/x86/kernel/platform_setup.c | 2 ++ 6 files changed, 15 insertions(+), 7 deletions(-)
arch/x86/include/asm/mpspec.h +2 -0
@@ -62,10 +62,12 @@ extern void get_smp_config(void);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);#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#endif void __cpuinit generic_processor_info (int apicid,int version);
arch/x86/include/asm/platform.h +4 -0
@@ -1,6 +1,8 @@#ifndef _ASM_X86_PLATFORM_H#define _ASM_X86_PLATFORM_H +struct mpc_cpu ; +/** * struct platform_setup_quirks - platform specific quirks * @mpc_record: platform specific mpc record accounting
@@ -12,9 +14,11 @@ struct platform_setup_quirks {/** * struct platform_setup_mpparse - platform specific mpparse ops * @setup_ioapic_ids: platform specific ioapic id override +* @mpc_apic_id: platform specific mpc apic id assignment */ struct platform_setup_mpparse {void (*setup_ioapic_ids)(void ); +int (*mpc_apic_id)(struct mpc_cpu *m); };/**
arch/x86/include/asm/setup.h +0 -2
@@ -12,7 +12,6 @@/* * Any setup quirks to be performed? */ -struct mpc_cpu ;struct mpc_bus ;struct mpc_oemtable ;
@@ -25,7 +24,6 @@ struct x86_quirks {int (*mach_get_smp_config)(unsigned int early);int (*mach_find_smp_config)(unsigned int reserve); -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,
arch/x86/kernel/apic/numaq_32.c +1 -1
@@ -270,7 +270,6 @@ static struct x86_quirks numaq_x86_quirk .arch_trap_init = NULL, .mach_get_smp_config = NULL, .mach_find_smp_config = NULL, - .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,
@@ -293,6 +292,7 @@ static __init void early_check_numaq(voi x86_quirks = &numaq_x86_quirks; platform_setup.quirks.mpc_record = numaq_mpc_record; platform_setup.mpparse.setup_ioapic_ids = platform_setup_noop; + platform_setup.mpparse.mpc_apic_id = mpc_apic_id; } }
arch/x86/kernel/mpparse.c +6 -4
@@ -45,6 +45,11 @@ static int __init mpf_checksum(unsignedreturn 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(strreturn ; } -if (x86_quirks->mpc_apic_id) - apicid = x86_quirks->mpc_apic_id (m); -else - apicid = m->apicid; + apicid = platform_setup.mpparse.mpc_apic_id (m);if (m->cpuflag &CPU_BOOTPROCESSOR ) { bootup_cpu =" (Bootup-CPU)" ;
arch/x86/kernel/platform_setup.c +2 -0
@@ -6,6 +6,7 @@#include <linux/init.h> #include <asm/bios_ebda.h> +#include <asm/mpspec.h> #include <asm/setup.h> #include <asm/e820.h>
@@ -27,6 +28,7 @@ struct __initdata platform_setup_ops pla .mpparse = { .setup_ioapic_ids = platform_setup_noop, + .mpc_apic_id = default_mpc_apic_id, }, .quirks = {
RFC PATCH 9/32 x86: Move smp_read_mpc_oem to platform_setup
In reply to Thomas GleixnerMove smp_read_mpc_oem from quirks to platform_setup.
--- arch/x86/include/asm/mpspec.h | 2 ++ arch/x86/include/asm/platform.h | 3 +++ arch/x86/include/asm/setup.h | 3 --- arch/x86/kernel/apic/numaq_32.c | 6 +++--- arch/x86/kernel/mpparse.c | 8 ++++---- arch/x86/kernel/platform_setup.c | 1 + 6 files changed, 13 insertions(+), 10 deletions(-)
arch/x86/include/asm/mpspec.h +2 -0
@@ -63,11 +63,13 @@ 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);#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#endif void __cpuinit generic_processor_info (int apicid,int version);
arch/x86/include/asm/platform.h +3 -0
@@ -2,6 +2,7 @@#define _ASM_X86_PLATFORM_Hstruct mpc_cpu ; +struct mpc_table ;/** * struct platform_setup_quirks - platform specific quirks
@@ -15,10 +16,12 @@ struct platform_setup_quirks {* struct platform_setup_mpparse - platform specific mpparse ops * @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 */ struct platform_setup_mpparse {void (*setup_ioapic_ids)(void );int (*mpc_apic_id)(struct mpc_cpu *m); +void (*smp_read_mpc_oem)(struct mpc_table *mpc); };/**
arch/x86/include/asm/setup.h +0 -3
@@ -13,7 +13,6 @@* Any setup quirks to be performed? */ struct mpc_bus ; -struct mpc_oemtable ;struct x86_quirks {int (*arch_pre_time_init)(void );
@@ -26,8 +25,6 @@ struct x86_quirks {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); };extern void x86_quirk_intr_init (void );
arch/x86/kernel/apic/numaq_32.c +3 -3
@@ -218,9 +218,9 @@ static int __init mpf_checksum(unsigned/* * 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 *oem_table = (void *)(long )mpc->oemptr;int count =sizeof (*oemtable);/* the header size */ unsigned char *oemptr = ((unsigned char *)oemtable) + count;
@@ -272,7 +272,6 @@ static struct x86_quirks numaq_x86_quirk .mach_find_smp_config = NULL, .mpc_oem_bus_info = mpc_oem_bus_info, .mpc_oem_pci_bus = mpc_oem_pci_bus, - .smp_read_mpc_oem = smp_read_mpc_oem, };static __init void early_check_numaq (void )
@@ -293,6 +292,7 @@ static __init void early_check_numaq(voi platform_setup.quirks.mpc_record = numaq_mpc_record; platform_setup.mpparse.setup_ioapic_ids = platform_setup_noop; platform_setup.mpparse.mpc_apic_id = mpc_apic_id; + platform_setup.mpparse.smp_read_mpc_oem = smp_read_mpc_oem; } }
arch/x86/kernel/mpparse.c +4 -4
@@ -293,6 +293,8 @@ static void __init smp_dump_mptable(stru 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 ];
@@ -314,10 +316,8 @@ static int __init smp_read_mpc(struct mpif (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) + platform_setup.mpparse.smp_read_mpc_oem (mpc);/* * Now process the configuration blocks.
arch/x86/kernel/platform_setup.c +1 -0
@@ -29,6 +29,7 @@ struct __initdata platform_setup_ops pla .mpparse = { .setup_ioapic_ids = platform_setup_noop, .mpc_apic_id = default_mpc_apic_id, + .smp_read_mpc_oem = default_smp_read_mpc_oem, }, .quirks = {
RFC PATCH 10/32 x86: Move mpc_oem_pci_bus to platform_setup
In reply to Thomas Gleixner--- arch/x86/include/asm/platform.h | 3 +++ arch/x86/include/asm/setup.h | 1 - arch/x86/kernel/apic/numaq_32.c | 2 +- arch/x86/kernel/mpparse.c | 4 ++-- 4 files changed, 6 insertions(+), 4 deletions(-)
arch/x86/include/asm/platform.h +3 -0
@@ -1,6 +1,7 @@#ifndef _ASM_X86_PLATFORM_H#define _ASM_X86_PLATFORM_H +struct mpc_bus ;struct mpc_cpu ;struct mpc_table ;
@@ -17,11 +18,13 @@ struct platform_setup_quirks {* @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) */ struct platform_setup_mpparse {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); };/**
arch/x86/include/asm/setup.h +0 -1
@@ -24,7 +24,6 @@ struct x86_quirks {int (*mach_find_smp_config)(unsigned int reserve);void (*mpc_oem_bus_info)(struct mpc_bus *m,char *name); -void (*mpc_oem_pci_bus)(struct mpc_bus *m); };extern void x86_quirk_intr_init (void );
arch/x86/kernel/apic/numaq_32.c +1 -1
@@ -271,7 +271,6 @@ static struct x86_quirks numaq_x86_quirk .mach_get_smp_config = NULL, .mach_find_smp_config = NULL, .mpc_oem_bus_info = mpc_oem_bus_info, - .mpc_oem_pci_bus = mpc_oem_pci_bus, };static __init void early_check_numaq (void )
@@ -293,6 +292,7 @@ static __init void early_check_numaq(voi platform_setup.mpparse.setup_ioapic_ids = platform_setup_noop; platform_setup.mpparse.mpc_apic_id = mpc_apic_id; platform_setup.mpparse.smp_read_mpc_oem = smp_read_mpc_oem; + platform_setup.mpparse.mpc_oem_pci_bus = mpc_oem_pci_bus; } }
arch/x86/kernel/mpparse.c +2 -2
@@ -98,8 +98,8 @@ static void __init MP_bus_info(struct mp 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 (platform_setup.mpparse.mpc_oem_pci_bus) + platform_setup.mpparse.mpc_oem_pci_bus (m);clear_bit (m->busid, mp_bus_not_pci);#if defined(CONFIG_EISA ) || defined(CONFIG_MCA )
RFC PATCH 11/32 x86: Move oem_bus_info to platform_setup
In reply to Thomas Gleixner--- arch/x86/include/asm/mpspec.h | 6 ++++++ arch/x86/include/asm/platform.h | 2 ++ arch/x86/include/asm/setup.h | 3 --- arch/x86/kernel/apic/numaq_32.c | 2 +- arch/x86/kernel/mpparse.c | 14 ++++++++------ arch/x86/kernel/platform_setup.c | 1 + 6 files changed, 18 insertions(+), 10 deletions(-)
arch/x86/include/asm/mpspec.h +6 -0
@@ -64,12 +64,18 @@ extern void early_reserve_e820_mpc_new(vextern 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 #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#endif void __cpuinit generic_processor_info (int apicid,int version);
arch/x86/include/asm/platform.h +2 -0
@@ -19,12 +19,14 @@ struct platform_setup_quirks {* @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 */ struct platform_setup_mpparse {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); };/**
arch/x86/include/asm/setup.h +0 -3
@@ -12,7 +12,6 @@/* * Any setup quirks to be performed? */ -struct mpc_bus ;struct x86_quirks {int (*arch_pre_time_init)(void );
@@ -22,8 +21,6 @@ struct x86_quirks {int (*arch_trap_init)(void );int (*mach_get_smp_config)(unsigned int early);int (*mach_find_smp_config)(unsigned int reserve); - -void (*mpc_oem_bus_info)(struct mpc_bus *m,char *name); };extern void x86_quirk_intr_init (void );
arch/x86/kernel/apic/numaq_32.c +1 -1
@@ -270,7 +270,6 @@ static struct x86_quirks numaq_x86_quirk .arch_trap_init = NULL, .mach_get_smp_config = NULL, .mach_find_smp_config = NULL, - .mpc_oem_bus_info = mpc_oem_bus_info, };static __init void early_check_numaq (void )
@@ -293,6 +292,7 @@ static __init void early_check_numaq(voi platform_setup.mpparse.mpc_apic_id = mpc_apic_id; platform_setup.mpparse.smp_read_mpc_oem = smp_read_mpc_oem; platform_setup.mpparse.mpc_oem_pci_bus = mpc_oem_pci_bus; + platform_setup.mpparse.mpc_oem_bus_info = mpc_oem_bus_info; } }
arch/x86/kernel/mpparse.c +8 -6
@@ -72,16 +72,18 @@ static void __init MP_processor_info(str }#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); +} + +static void __init MP_bus_info (struct mpc_bus *m) +{ +char str[7 ]; -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); + platform_setup.mpparse.mpc_oem_bus_info (m, str);#if MAX_MP_BUSSES <256 if (m->busid >=MAX_MP_BUSSES ) {
arch/x86/kernel/platform_setup.c +1 -0
@@ -30,6 +30,7 @@ struct __initdata platform_setup_ops pla .setup_ioapic_ids = platform_setup_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, }, .quirks = {
RFC PATCH 12/32 x86: Move get/find_smp_config to platform_setup
In reply to Thomas GleixnerReplace the quirk machinery by a platform setup function which defaults to the standard implementation.
--- arch/x86/include/asm/mpspec.h | 30 ++++++++++++++++++++++++------ arch/x86/include/asm/platform.h | 4 ++++ arch/x86/include/asm/setup.h | 2 -- arch/x86/kernel/apic/numaq_32.c | 2 -- arch/x86/kernel/mpparse.c | 33 ++------------------------------- arch/x86/kernel/platform_setup.c | 2 ++ arch/x86/kernel/setup.c | 2 -- arch/x86/kernel/visws_quirks.c | 14 ++++---------- 8 files changed, 36 insertions(+), 53 deletions(-)
arch/x86/include/asm/mpspec.h +24 -6
@@ -4,6 +4,7 @@#include <linux/init.h> #include <asm/mpspec_def.h> +#include <asm/platform.h> extern int apic_version[MAX_APICS ];extern int pic_mode;
@@ -41,9 +42,6 @@ extern int quad_local_to_mp_bus_id [NR_C#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
@@ -56,10 +54,27 @@ extern int smp_found_config;extern int mpc_default_type;extern unsigned long mp_lapic_addr; -extern void get_smp_config (void ); +static inline void get_smp_config (void ) +{ + platform_setup.mpparse.get_smp_config (0 ); +} + +static inline void early_get_smp_config (void ) +{ + platform_setup.mpparse.get_smp_config (1 ); +} + +static inline void find_smp_config (void ) +{ + platform_setup.mpparse.find_smp_config (1 ); +} + +static inline void early_find_smp_config (void ) +{ + platform_setup.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);
@@ -69,13 +84,16 @@ extern void default_mpc_oem_bus_info(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 platform_setup_uint_noop +#define default_get_smp_config platform_setup_uint_noop#endif void __cpuinit generic_processor_info (int apicid,int version);
arch/x86/include/asm/platform.h +4 -0
@@ -20,6 +20,8 @@ struct platform_setup_quirks {* @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 platform_setup_mpparse {void (*setup_ioapic_ids)(void );
@@ -27,6 +29,8 @@ struct platform_setup_mpparse {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); };/**
arch/x86/include/asm/setup.h +0 -2
@@ -19,8 +19,6 @@ struct x86_quirks {int (*arch_pre_intr_init)(void );int (*arch_intr_init)(void );int (*arch_trap_init)(void ); -int (*mach_get_smp_config)(unsigned int early); -int (*mach_find_smp_config)(unsigned int reserve); };extern void x86_quirk_intr_init (void );
arch/x86/kernel/apic/numaq_32.c +0 -2
@@ -268,8 +268,6 @@ static struct x86_quirks numaq_x86_quirk .arch_pre_intr_init = NULL, .arch_intr_init = NULL, .arch_trap_init = NULL, - .mach_get_smp_config = NULL, - .mach_find_smp_config = NULL, };static __init void early_check_numaq (void )
arch/x86/kernel/mpparse.c +2 -31
@@ -610,7 +610,7 @@ static int __init check_physptr(struct m/* * 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;
@@ -627,11 +627,6 @@ static void __init __get_smp_config(unsiif (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 )
@@ -672,16 +667,6 @@ static void __init __get_smp_config(unsi*/ } -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);
@@ -747,14 +732,10 @@ static int __init smp_scan_config(unsignreturn 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...
@@ -789,16 +770,6 @@ static void __init __find_smp_config(unssmp_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 ];
arch/x86/kernel/platform_setup.c +2 -0
@@ -31,6 +31,8 @@ struct __initdata platform_setup_ops pla .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, }, .quirks = {
arch/x86/kernel/setup.c +0 -2
@@ -981,13 +981,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 ();
arch/x86/kernel/visws_quirks.c +4 -10
@@ -156,12 +156,8 @@ static void visws_machine_power_off(voidoutl (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 +204,7 @@ static void __init MP_processor_info(str 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,8 +226,6 @@ static int __init visws_find_smp_config(MP_processor_info (mp++); mp_lapic_addr =APIC_DEFAULT_PHYS_BASE ; - -return 1 ; }static int visws_trap_init (void );
@@ -241,8 +235,6 @@ static struct x86_quirks visws_x86_quirk .arch_pre_intr_init = visws_pre_intr_init, .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, };void __init visws_early_detect (void )
@@ -263,6 +255,8 @@ void __init visws_early_detect(void) x86_quirks = &visws_x86_quirks; platform_setup.resources.memory_setup = visws_memory_setup; + platform_setup.mpparse.get_smp_config = visws_get_smp_config; + platform_setup.mpparse.find_smp_config = visws_find_smp_config;/* * Install reboot quirks:
RFC PATCH 13/32 x86: Move pre_intr_init to platform_setup
In reply to Thomas GleixnerReplace the quirk machinery by a platform setup function which defaults to the standard implementation. This is also a preparatory patch for Moorestown support which needs to replace the default init_ISA_irqs as well.
--- arch/x86/include/asm/irq.h | 2 ++ arch/x86/include/asm/platform.h | 10 ++++++++++ arch/x86/include/asm/setup.h | 1 - arch/x86/kernel/apic/numaq_32.c | 1 - arch/x86/kernel/irqinit.c | 24 ++---------------------- arch/x86/kernel/platform_setup.c | 5 +++++ arch/x86/kernel/visws_quirks.c | 10 +++------- 7 files changed, 22 insertions(+), 31 deletions(-)
arch/x86/include/asm/irq.h +2 -0
@@ -47,4 +47,6 @@ extern unsigned int do_IRQ(struct pt_reg 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 */
arch/x86/include/asm/platform.h +10 -0
@@ -50,12 +50,22 @@ struct platform_setup_resources { };/** +* struct platform_setup_irqs - platform specific interrupt setup +* @pre_vector_init: init code to run before interrupt vectors +* are set up. +*/ +struct platform_setup_irqs { +void (*pre_vector_init)(void ); +}; + +/** * struct platform_setup_ops - functions for platform specific setup * */ struct platform_setup_ops {struct platform_setup_resources resources;struct platform_setup_mpparse mpparse; +struct platform_setup_irqs irqs;struct platform_setup_quirks quirks; };
arch/x86/include/asm/setup.h +0 -1
@@ -16,7 +16,6 @@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 ); };
arch/x86/kernel/apic/numaq_32.c +0 -1
@@ -265,7 +265,6 @@ static void __init smp_read_mpc_oem(strustatic 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_intr_init =NULL , .arch_trap_init =NULL , };
arch/x86/kernel/irqinit.c +2 -22
@@ -116,7 +116,7 @@ int vector_used_by_percpu_irq(unsigned ireturn 0 ; } -static void __init init_ISA_irqs (void ) +void __init init_ISA_irqs (void ) {int i;
@@ -213,32 +213,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 (); + platform_setup.irqs.pre_vector_init ();apic_intr_init ();
arch/x86/kernel/platform_setup.c +5 -0
@@ -9,6 +9,7 @@#include <asm/mpspec.h> #include <asm/setup.h> #include <asm/e820.h> +#include <asm/irq.h> void __cpuinit platform_setup_noop (void ) { }void __init platform_setup_uint_noop (unsigned int unused) { }
@@ -35,6 +36,10 @@ struct __initdata platform_setup_ops pla .get_smp_config = default_get_smp_config, }, + .irqs = { + .pre_vector_init = init_ISA_irqs, + }, + .quirks = { .mpc_record = platform_setup_uint_noop, },
arch/x86/kernel/visws_quirks.c +3 -7
@@ -73,14 +73,10 @@ static int __init visws_time_init(void)return 0 ; } -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. */
@@ -232,7 +228,6 @@ 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_intr_init =NULL , .arch_trap_init = visws_trap_init, };
@@ -257,6 +252,7 @@ void __init visws_early_detect(void) platform_setup.resources.memory_setup = visws_memory_setup; platform_setup.mpparse.get_smp_config = visws_get_smp_config; platform_setup.mpparse.find_smp_config = visws_find_smp_config; + platform_setup.irqs.pre_vector_init = visws_pre_intr_init;/* * Install reboot quirks:
RFC PATCH 14/32 x86: Move irq_init to platform_setup
In reply to Thomas Gleixnerirq_init is overridden by x86_quirks and by paravirts. Unify the whole mess and make it an unconditional platform setup function which defaults to the standard function and can be overridden by the early platform code.
--- arch/x86/include/asm/irq.h | 1 - arch/x86/include/asm/paravirt.h | 2 -- arch/x86/include/asm/platform.h | 2 ++ arch/x86/include/asm/setup.h | 3 --- arch/x86/kernel/apic/numaq_32.c | 1 - arch/x86/kernel/irqinit.c | 12 ++++-------- arch/x86/kernel/paravirt.c | 6 ------ arch/x86/kernel/platform_setup.c | 1 + arch/x86/kernel/setup.c | 17 ----------------- arch/x86/kernel/visws_quirks.c | 1 - arch/x86/lguest/boot.c | 2 +- arch/x86/xen/irq.c | 5 +++-- 12 files changed, 11 insertions(+), 42 deletions(-)
arch/x86/include/asm/irq.h +0 -1
@@ -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);
arch/x86/include/asm/paravirt.h +0 -2
@@ -208,8 +208,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
arch/x86/include/asm/platform.h +2 -0
@@ -53,9 +53,11 @@ struct platform_setup_resources {* struct platform_setup_irqs - platform specific interrupt setup * @pre_vector_init: init code to run before interrupt vectors * are set up. +* @intr_init: interrupt init code */ struct platform_setup_irqs {void (*pre_vector_init)(void ); +void (*intr_init)(void ); };/**
arch/x86/include/asm/setup.h +0 -3
@@ -16,12 +16,9 @@struct x86_quirks {int (*arch_pre_time_init)(void );int (*arch_time_init)(void ); -int (*arch_intr_init)(void );int (*arch_trap_init)(void ); }; -extern void x86_quirk_intr_init (void ); -extern void x86_quirk_trap_init (void );extern void x86_quirk_pre_time_init (void );
arch/x86/kernel/apic/numaq_32.c +0 -1
@@ -265,7 +265,6 @@ static void __init smp_read_mpc_oem(strustatic struct x86_quirks numaq_x86_quirks__initdata = { .arch_pre_time_init = numaq_pre_time_init, .arch_time_init =NULL , - .arch_intr_init =NULL , .arch_trap_init =NULL , };
arch/x86/kernel/irqinit.c +4 -8
@@ -140,8 +140,10 @@ void __init init_ISA_irqs(void) } } -/* Overridden in paravirt.c */ -void init_IRQ (void ) __attribute__((weak,alias ("native_init_IRQ" ))); +void init_IRQ (void ) +{ + platform_setup.irqs.intr_init (); +}static void __init smp_intr_init (void ) {
@@ -238,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. */
arch/x86/kernel/paravirt.c +0 -6
@@ -183,11 +183,6 @@ unsigned paravirt_patch_insns(void *insnreturn insn_len; } -void init_IRQ (void ) -{ - pv_irq_ops.init_IRQ (); -} -static void native_flush_tlb (void ) {__native_flush_tlb ();
@@ -328,7 +323,6 @@ struct pv_time_ops pv_time_ops = { };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),
arch/x86/kernel/platform_setup.c +1 -0
@@ -38,6 +38,7 @@ struct __initdata platform_setup_ops pla .irqs = { .pre_vector_init = init_ISA_irqs, + .intr_init = native_init_IRQ, }, .quirks = {
arch/x86/kernel/setup.c +0 -17
@@ -1021,23 +1021,6 @@ void __init setup_arch(char **cmdline_p)#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:
arch/x86/kernel/visws_quirks.c +0 -1
@@ -228,7 +228,6 @@ static int visws_trap_init(void);static struct x86_quirks visws_x86_quirks__initdata = { .arch_time_init = visws_time_init, - .arch_intr_init =NULL , .arch_trap_init = visws_trap_init, };
arch/x86/lguest/boot.c +1 -1
@@ -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);
@@ -1325,6 +1324,7 @@ __init void lguest_init(void) pv_time_ops.get_tsc_khz = lguest_tsc_khz; platform_setup.resources.memory_setup = lguest_memory_setup; + platform_setup.irqs.intr_init = lguest_init_IRQ;/* * Now is a good time to look at the implementations of these functions
arch/x86/xen/irq.c +3 -2
@@ -1,5 +1,7 @@#include <linux/hardirq.h> +#include <asm/platform.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_ovoid __init xen_init_irq_ops () { pv_irq_ops = xen_irq_ops; + platform_setup.irqs.intr_init = xen_init_IRQ; }
RFC PATCH 15/32 x86: Move traps_init to platform_setup
In reply to Thomas GleixnerReplace the quirks by a simple platform_setup function.
--- arch/x86/include/asm/platform.h | 2 ++ arch/x86/include/asm/setup.h | 3 --- arch/x86/kernel/apic/numaq_32.c | 1 - arch/x86/kernel/platform_setup.c | 1 + arch/x86/kernel/setup.c | 15 --------------- arch/x86/kernel/traps.c | 5 ++--- arch/x86/kernel/visws_quirks.c | 8 +++----- 7 files changed, 8 insertions(+), 27 deletions(-)
arch/x86/include/asm/platform.h +2 -0
@@ -54,10 +54,12 @@ struct platform_setup_resources {* @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 platform_setup_irqs {void (*pre_vector_init)(void );void (*intr_init)(void ); +void (*trap_init)(void ); };/**
arch/x86/include/asm/setup.h +0 -3
@@ -16,11 +16,8 @@struct x86_quirks {int (*arch_pre_time_init)(void );int (*arch_time_init)(void ); -int (*arch_trap_init)(void ); }; -extern void x86_quirk_trap_init (void ); -extern void x86_quirk_pre_time_init (void );extern void x86_quirk_time_init (void );
arch/x86/kernel/apic/numaq_32.c +0 -1
@@ -265,7 +265,6 @@ static void __init smp_read_mpc_oem(strustatic struct x86_quirks numaq_x86_quirks__initdata = { .arch_pre_time_init = numaq_pre_time_init, .arch_time_init =NULL , - .arch_trap_init =NULL , };static __init void early_check_numaq (void )
arch/x86/kernel/platform_setup.c +1 -0
@@ -39,6 +39,7 @@ struct __initdata platform_setup_ops pla .irqs = { .pre_vector_init = init_ISA_irqs, .intr_init = native_init_IRQ, + .trap_init = platform_setup_noop, }, .quirks = {
arch/x86/kernel/setup.c +0 -15
@@ -1020,21 +1020,6 @@ void __init setup_arch(char **cmdline_p)#ifdef CONFIG_X86_32 -/** -* 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,
arch/x86/kernel/traps.c +2 -3
@@ -59,6 +59,7 @@#include <asm/mach_traps.h> #ifdef CONFIG_X86_64 +#include <asm/platform.h> #include <asm/pgalloc.h> #include <asm/proto.h> #else
@@ -980,7 +981,5 @@ void __init trap_init(void)*/ cpu_init (); -#ifdef CONFIG_X86_32 -x86_quirk_trap_init (); -#endif + platform_setup.irqs.trap_init (); }
arch/x86/kernel/visws_quirks.c +3 -5
@@ -224,11 +224,10 @@ static void __init visws_find_smp_config mp_lapic_addr =APIC_DEFAULT_PHYS_BASE ; } -static int visws_trap_init (void ); +static void visws_trap_init (void );static struct x86_quirks visws_x86_quirks__initdata = { .arch_time_init = visws_time_init, - .arch_trap_init = visws_trap_init, };void __init visws_early_detect (void )
@@ -252,6 +251,7 @@ void __init visws_early_detect(void) platform_setup.mpparse.get_smp_config = visws_get_smp_config; platform_setup.mpparse.find_smp_config = visws_find_smp_config; platform_setup.irqs.pre_vector_init = visws_pre_intr_init; + platform_setup.irqs.trap_init = visws_trap_init;/* * Install reboot quirks:
@@ -390,12 +390,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 ; }/*
RFC PATCH 16/32 x86: Replace ARCH_SETUP by a proper platform function
In reply to Thomas GleixnerARCH_SETUP is a horrible hack of paravirt/xen which is way nicer to read as a platform setup function.
--- arch/x86/include/asm/paravirt.h | 2 -- arch/x86/include/asm/platform.h | 9 +++++++++ arch/x86/kernel/paravirt.c | 1 - arch/x86/kernel/platform_setup.c | 4 ++++ arch/x86/kernel/setup.c | 6 +----- arch/x86/xen/enlighten.c | 2 +- 6 files changed, 15 insertions(+), 9 deletions(-)
arch/x86/include/asm/paravirt.h +0 -2
@@ -87,7 +87,6 @@ struct pv_init_ops { unsigned long addr, unsigned len);/* Basic arch-specific setup */ -void (*arch_setup)(void );void (*post_allocator_init)(void );/* Print a banner to identify the environment */
@@ -699,7 +698,6 @@ static inline void load_sp0(struct tss_sPVOP_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);
arch/x86/include/asm/platform.h +9 -0
@@ -63,6 +63,14 @@ struct platform_setup_irqs { };/** +* struct platform_setup_oem - oem platform specific customizing functions +* @arch_setup: platform specific architecure setup +*/ +struct platform_setup_oem { +void (*arch_setup)(void ); +}; + +/** * struct platform_setup_ops - functions for platform specific setup * */
@@ -70,6 +78,7 @@ struct platform_setup_ops {struct platform_setup_resources resources;struct platform_setup_mpparse mpparse;struct platform_setup_irqs irqs; +struct platform_setup_oem oem;struct platform_setup_quirks quirks; };
arch/x86/kernel/paravirt.c +0 -1
@@ -311,7 +311,6 @@ struct pv_info pv_info = {struct pv_init_ops pv_init_ops = { .patch = native_patch, .banner = default_banner, - .arch_setup = paravirt_nop, };struct pv_time_ops pv_time_ops = {
arch/x86/kernel/platform_setup.c +4 -0
@@ -42,6 +42,10 @@ struct __initdata platform_setup_ops pla .trap_init = platform_setup_noop, }, + .oem = { + .arch_setup = platform_setup_noop, + }, + .quirks = { .mpc_record = platform_setup_uint_noop, },
arch/x86/kernel/setup.c +1 -5
@@ -108,10 +108,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
@@ -750,7 +746,7 @@ void __init setup_arch(char **cmdline_p) }#endif -ARCH_SETUP + platform_setup.oem.arch_setup ();setup_memory_map ();parse_setup_data ();
arch/x86/xen/enlighten.c +1 -1
@@ -841,7 +841,6 @@ static const struct pv_init_ops xen_init .patch = xen_patch, .banner = xen_banner, - .arch_setup = xen_arch_setup, .post_allocator_init = xen_post_allocator_init, };
@@ -986,6 +985,7 @@ asmlinkage void __init xen_start_kernel( pv_mmu_ops = xen_mmu_ops; platform_setup.resources.memory_setup = xen_memory_setup; + platform_setup.oem.arch_setup = xen_arch_setup;xen_init_irq_ops ();
Re: [RFC patch 16/32] x86: Replace ARCH_SETUP by a proper platform function
Quoted 3 lines · Thomas Gleixner
ARCH_SETUPis a horrible hack of paravirt/xen which is way nicer to read as a platform setup function.
Not really correct; its a left-over from the old subarch stuff. But it was certainly never very pretty.
J
Re: [RFC patch 16/32] x86: Replace ARCH_SETUP by a proper platform function
Quoted 7 lines · Jeremy Fitzhardinge
Quoted 3 lines · Thomas Gleixner
ARCH_SETUPis a horrible hack of paravirt/xen which is way nicer to read as a platform setup function.Not really correct; its a left-over from the old subarch stuff. But it was certainly never very pretty.
Oops. Sorry, I squeezed the history out of my brain and my subconscious mind attributed it to paravirt/xen :)
Will fix the comment.
Thanks,
tglx
PATCH 1/7 x86/boot: adding hw subarch ID for Moorestown
Quoted 1 line
From
2de4f68e7b0403bb39954d7c2e3d5097d0e6e3acMon Sep 17 00:00:00 2001
From: Jacob Pan <[email protected]>
Date: Thu, 11 Jun 2009 20:34:47 -0700
Subject: [PATCH] x86/boot: adding hw subarch ID for Moorestown
x86 bootprotocol 2.07 has introduced hardware_subarch ID in the boot parameters provided by FW. We use it to identify Moorestown platforms.
The subarchitecture ID will help select a set of platform features and x86_quirks.
--- Documentation/x86/boot.txt | 1 + arch/x86/include/asm/bootparam.h | 11 +++++++++++ 2 files changed, 12 insertions(+), 0 deletions(-)
Documentation/x86/boot.txt +1 -0
@@ -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)
arch/x86/include/asm/bootparam.h +11 -0
@@ -109,4 +109,15 @@ struct boot_params {__u8 _pad9[276 ];/* 0xeec */ } __attribute__((packed)); +#define N_X86_SUBARCHS 4 + +enum { +X86_SUBARCH_PC =0 , +X86_SUBARCH_LGUEST , +X86_SUBARCH_XEN , +X86_SUBARCH_MRST , +}; + + +#endif /* _ASM_X86_BOOTPARAM_H */
Signature · 1 line
1.5.6.5
Re: [PATCH 1/7] x86/boot: adding hw subarch ID for Moorestown
Quoted 34 lines · Jacob jun
Quoted 1 line
From
2de4f68e7b0403bb39954d7c2e3d5097d0e6e3acMon Sep 17 00:00:00 2001From: Jacob Pan <[email protected]>
Date: Thu, 11 Jun 2009 20:34:47 -0700
Subject: [PATCH] x86/boot: adding hw subarch ID for Moorestownx86 bootprotocol 2.07 has introduced
hardware_subarchID in the boot parameters provided by FW. We use it to identify Moorestown platforms.The subarchitecture ID will help select a set of platform features and
x86_quirks.Signed-off-by Jacob Pan <[email protected]>--- Documentation/x86/boot.txt | 1 + arch/x86/include/asm/bootparam.h | 11 +++++++++++ 2 files changed, 12 insertions(+), 0 deletions(-)Documentation/x86/boot.txt +1
-0@@ -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)arch/x86/include/asm/bootparam.h +0
-0
arch/x86/include/asm/bootparam.h struct boot_params { · line 112
Quoted 4 lines
arch/x86/include/asm/bootparam.h +1
-0@@ -109,4 +109,15 @@ struct boot_params {__u8 _pad9[276 ];/* 0xeec */ } __attribute__((packed)); +#define N_X86_SUBARCHS 4
Grr.
arch/x86/include/asm/bootparam.h struct boot_params { · line 118
Quoted 5 lines
arch/x86/include/asm/bootparam.h +5
-0+enum { +X86_SUBARCH_PC =0 , +X86_SUBARCH_LGUEST , +X86_SUBARCH_XEN , +X86_SUBARCH_MRST ,
X86_NR_SUBARCHS,
perhaps ?
Also this patch will result in boot failure when paravirt is enabled. head_32.S wants to be tweaked as well.
Thanks,
tglx
RFC PATCH 17/32 x86: Move paravirt banner printout to platform
In reply to Thomas GleixnerReplace another obscure paravirt magic and move it to platform setup. Such a hook is also useful for embedded and special hardware.
--- arch/x86/include/asm/paravirt.h | 6 +++++- arch/x86/include/asm/platform.h | 2 ++ arch/x86/kernel/paravirt.c | 10 +--------- arch/x86/kernel/platform_setup.c | 1 + arch/x86/kernel/setup.c | 1 + arch/x86/xen/enlighten.c | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-)
arch/x86/include/asm/paravirt.h +5 -1
@@ -1623,6 +1623,8 @@ static inline unsigned long __raw_local_#undef PVOP_VCALL4#undef PVOP_CALL4 +extern void default_banner (void ); +#else /* __ASSEMBLY__ */ #define _PVSITE (ptype, clobbers, ops, word, algn) \
@@ -1763,5 +1765,7 @@ static inline unsigned long __raw_local_#endif /* CONFIG_X86_32 */ #endif /* __ASSEMBLY__ */ -#endif /* CONFIG_PARAVIRT */ +#else /* CONFIG_PARAVIRT */ +# define default_banner platform_setup_noop +#endif /* !CONFIG_PARAVIRT */ #endif /* _ASM_X86_PARAVIRT_H */
arch/x86/include/asm/platform.h +2 -0
@@ -65,9 +65,11 @@ struct platform_setup_irqs {/** * struct platform_setup_oem - oem platform specific customizing functions * @arch_setup: platform specific architecure setup +* @banner: print a platform specific banner */ struct platform_setup_oem {void (*arch_setup)(void ); +void (*banner)(void ); };/**
arch/x86/kernel/paravirt.c +1 -9
@@ -54,7 +54,7 @@ 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);
@@ -208,13 +208,6 @@ extern void native_irq_enable_sysexit(voextern 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 ,
@@ -310,7 +303,6 @@ struct pv_info pv_info = {struct pv_init_ops pv_init_ops = { .patch = native_patch, - .banner = default_banner, };struct pv_time_ops pv_time_ops = {
arch/x86/kernel/platform_setup.c +1 -0
@@ -44,6 +44,7 @@ struct __initdata platform_setup_ops pla .oem = { .arch_setup = platform_setup_noop, + .banner = default_banner, }, .quirks = {
arch/x86/kernel/setup.c +1 -0
@@ -1012,6 +1012,7 @@ void __init setup_arch(char **cmdline_p) conswitchp = &dummy_con;#endif #endif + platform_setup.oem.banner (); }#ifdef CONFIG_X86_32
arch/x86/xen/enlighten.c +1 -1
@@ -840,7 +840,6 @@ static const struct pv_info xen_info __istatic const struct pv_init_ops xen_init_ops__initdata = { .patch = xen_patch, - .banner = xen_banner, .post_allocator_init = xen_post_allocator_init, };
@@ -986,6 +985,7 @@ asmlinkage void __init xen_start_kernel( platform_setup.resources.memory_setup = xen_memory_setup; platform_setup.oem.arch_setup = xen_arch_setup; + platform_setup.oem.banner = xen_banner;xen_init_irq_ops ();
RFC PATCH 18/32 x86: Move paravirt pagetable_setup to platform
In reply to Thomas GleixnerReplace more paravirt hackery by proper platform setup.
--- arch/x86/include/asm/paravirt.h | 19 ------------------- arch/x86/include/asm/pgtable.h | 10 ---------- arch/x86/include/asm/pgtable_types.h | 4 ++-- arch/x86/include/asm/platform.h | 13 +++++++++++++ arch/x86/kernel/paravirt.c | 7 ------- arch/x86/kernel/platform_setup.c | 6 ++++++ arch/x86/kernel/setup.c | 4 ++-- arch/x86/xen/enlighten.c | 2 +- arch/x86/xen/mmu.c | 11 +++++++---- arch/x86/xen/mmu.h | 2 +- 10 files changed, 32 insertions(+), 46 deletions(-)
arch/x86/include/asm/paravirt.h +0 -19
@@ -241,15 +241,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 );
@@ -1025,16 +1016,6 @@ static inline void paravirt_post_allocat (*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)
arch/x86/include/asm/pgtable.h +0 -10
@@ -55,16 +55,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)
arch/x86/include/asm/pgtable_types.h +2 -2
@@ -299,8 +299,8 @@ void set_pte_vaddr(unsigned long vaddr,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 platform_setup_pgd_noop +#define native_pagetable_setup_done platform_setup_pgd_noop#endif struct seq_file ;
arch/x86/include/asm/platform.h +13 -0
@@ -1,6 +1,8 @@#ifndef _ASM_X86_PLATFORM_H#define _ASM_X86_PLATFORM_H +#include <asm/pgtable_types.h> +struct mpc_bus ;struct mpc_cpu ;struct mpc_table ;
@@ -73,6 +75,16 @@ struct platform_setup_oem { };/** +* struct platform_setup_paging - platform specific paging functions +* @pagetable_setup_start: platform specific pre paging_init() call +* @pagetable_setup_done: platform specific post paging_init() call +*/ +struct platform_setup_paging { +void (*pagetable_setup_start)(pgd_t *base); +void (*pagetable_setup_done)(pgd_t *base); +}; + +/** * struct platform_setup_ops - functions for platform specific setup * */
@@ -81,6 +93,7 @@ struct platform_setup_ops {struct platform_setup_mpparse mpparse;struct platform_setup_irqs irqs;struct platform_setup_oem oem; +struct platform_setup_paging paging;struct platform_setup_quirks quirks; };
arch/x86/kernel/paravirt.c +0 -7
@@ -402,13 +402,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,
arch/x86/kernel/platform_setup.c +6 -0
@@ -13,6 +13,7 @@void __cpuinit platform_setup_noop (void ) { }void __init platform_setup_uint_noop (unsigned int unused) { } +void __init platform_setup_pgd_noop (pgd_t *unused) { }/* * The platform setup functions are preset with the default functions
@@ -47,6 +48,11 @@ struct __initdata platform_setup_ops pla .banner = default_banner, }, + .paging = { + .pagetable_setup_start = native_pagetable_setup_start, + .pagetable_setup_done = native_pagetable_setup_done, + }, + .quirks = { .mpc_record = platform_setup_uint_noop, },
arch/x86/kernel/setup.c +2 -2
@@ -959,9 +959,9 @@ void __init setup_arch(char **cmdline_p)kvmclock_init ();#endif -paravirt_pagetable_setup_start (swapper_pg_dir); + platform_setup.paging.pagetable_setup_start (swapper_pg_dir);paging_init (); -paravirt_pagetable_setup_done (swapper_pg_dir); + platform_setup.paging.pagetable_setup_done (swapper_pg_dir);paravirt_post_allocator_init ();#ifdef CONFIG_X86_64
arch/x86/xen/enlighten.c +1 -1
@@ -981,12 +981,12 @@ asmlinkage void __init xen_start_kernel( pv_time_ops = xen_time_ops; pv_cpu_ops = xen_cpu_ops; pv_apic_ops = xen_apic_ops; - pv_mmu_ops = xen_mmu_ops; platform_setup.resources.memory_setup = xen_memory_setup; platform_setup.oem.arch_setup = xen_arch_setup; platform_setup.oem.banner = xen_banner; +xen_init_mmu_ops ();xen_init_irq_ops ();xen_init_cpuid_mask ();
arch/x86/xen/mmu.c +7 -4
@@ -1875,10 +1875,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 +1951,12 @@ const struct pv_mmu_ops xen_mmu_ops __in .set_fixmap = xen_set_fixmap, }; +void __init xen_init_mmu_ops (void ) +{ + platform_setup.paging.pagetable_setup_start = xen_pagetable_setup_start; + platform_setup.paging.pagetable_setup_done = xen_pagetable_setup_done; + pv_mmu_ops = xen_mmu_ops; +}#ifdef CONFIG_XEN_DEBUG_FS
arch/x86/xen/mmu.h +1 -1
@@ -59,5 +59,5 @@ void xen_ptep_modify_prot_commit(structunsigned 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 */
RFC PATCH 19/32 x86: Move xen_post_allocator_init into xen_pagetable_setup_done
In reply to Thomas GleixnerWe really do not need two paravirt/platform setup functions which are called in two consecutive source lines. Move the only user of post_allocator_init into the already existing pagetable_setup_done function.
--- arch/x86/include/asm/paravirt.h | 9 --------- arch/x86/include/asm/setup.h | 4 ---- arch/x86/kernel/setup.c | 1 - arch/x86/xen/enlighten.c | 2 -- arch/x86/xen/mmu.c | 5 ++++- arch/x86/xen/xen-ops.h | 2 -- 6 files changed, 4 insertions(+), 19 deletions(-)
arch/x86/include/asm/paravirt.h +0 -9
@@ -86,9 +86,6 @@ struct pv_init_ops {unsigned (*patch)(u8 type,u16 clobber,void *insnbuf,unsigned long addr,unsigned len); -/* Basic arch-specific setup */ -void (*post_allocator_init)(void ); -/* Print a banner to identify the environment */ void (*banner)(void ); };
@@ -1010,12 +1007,6 @@ static inline void 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)(); -} -#ifdef CONFIG_SMP static inline void startup_ipi_hook (int phys_apicid,unsigned long start_eip,unsigned long start_esp)
arch/x86/include/asm/setup.h +0 -4
@@ -63,10 +63,6 @@ static inline int is_visws_box(void) { rextern struct x86_quirks *x86_quirks;extern unsigned long saved_video_mode; -#ifndef CONFIG_PARAVIRT -#define paravirt_post_allocator_init () do {} while (0) -#endif -extern void reserve_standard_io_resources (void );extern void i386_reserve_resources (void );
arch/x86/kernel/setup.c +0 -1
@@ -962,7 +962,6 @@ void __init setup_arch(char **cmdline_p) platform_setup.paging.pagetable_setup_start (swapper_pg_dir);paging_init (); platform_setup.paging.pagetable_setup_done (swapper_pg_dir); -paravirt_post_allocator_init ();#ifdef CONFIG_X86_64 map_vsyscall ();
arch/x86/xen/enlighten.c +0 -2
@@ -839,8 +839,6 @@ static const struct pv_info xen_info __istatic const struct pv_init_ops xen_init_ops__initdata = { .patch = xen_patch, - - .post_allocator_init = xen_post_allocator_init, };static const struct pv_time_ops xen_time_ops__initdata = {
arch/x86/xen/mmu.c +4 -1
@@ -1229,9 +1229,12 @@ static __init void xen_pagetable_setup_s { } +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,#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;
arch/x86/xen/xen-ops.h +0 -2
@@ -30,8 +30,6 @@ pgd_t *xen_setup_kernel_pagetable(pgd_tvoid 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 );
RFC PATCH 20/32 x86: Move percpu clockevents setup to platform
In reply to Thomas Gleixnerparavirt overrides the setup of the default apic timers as per cpu timers. Moorestown needs to override that as well.
Move it to platform setup and create a separate platform_cpuhotplug_setup struct which holds the function for the secondary evtl. hotplugabble CPUs.
--- arch/x86/include/asm/apic.h | 3 --- arch/x86/include/asm/paravirt.h | 15 --------------- arch/x86/include/asm/platform.h | 19 +++++++++++++++++++ arch/x86/kernel/apic/apic.c | 3 ++- arch/x86/kernel/kvmclock.c | 5 ++++- arch/x86/kernel/paravirt.c | 2 -- arch/x86/kernel/platform_setup.c | 9 +++++++++ arch/x86/kernel/smpboot.c | 4 ++-- arch/x86/kernel/vmi_32.c | 5 +++-- arch/x86/xen/enlighten.c | 6 ++++-- 10 files changed, 43 insertions(+), 28 deletions(-)
arch/x86/include/asm/apic.h +0 -3
@@ -70,9 +70,6 @@ static inline void default_inquire_remot*/ #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
arch/x86/include/asm/paravirt.h +0 -15
@@ -228,9 +228,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);
@@ -995,18 +992,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 -#ifdef CONFIG_SMP static inline void startup_ipi_hook (int phys_apicid,unsigned long start_eip,unsigned long start_esp)
arch/x86/include/asm/platform.h +19 -0
@@ -85,6 +85,15 @@ struct platform_setup_paging { };/** +* struct platform_setup_timers - platform specific timer setup +* @setup_perpcu_clockev: set up the per cpu clock event device for the +* boot cpu +*/ +struct platform_setup_timers { +void (*setup_percpu_clockev)(void ); +}; + +/** * struct platform_setup_ops - functions for platform specific setup * */
@@ -94,10 +103,20 @@ struct platform_setup_ops {struct platform_setup_irqs irqs;struct platform_setup_oem oem;struct platform_setup_paging paging; +struct platform_setup_timers timers;struct platform_setup_quirks quirks; }; +/** +* struct platform_setup_cpuhotplug - platform specific cpu hotplug setups +* @setup_percpu_clockev: set up the per cpu clock event device +*/ +struct platform_setup_cpuhotplug { +void (*setup_percpu_clockev)(void ); +}; +extern struct platform_setup_ops platform_setup; +extern struct platform_setup_cpuhotplug platform_cpuhotplug_setup;extern void platform_setup_noop (void );extern void platform_setup_uint_noop (unsigned int unused);
arch/x86/kernel/apic/apic.c +2 -1
@@ -36,6 +36,7 @@#include <linux/mm.h> #include <asm/perf_counter.h> +#include <asm/platform.h> #include <asm/pgalloc.h> #include <asm/atomic.h> #include <asm/mpspec.h>
@@ -1701,7 +1702,7 @@ int __init APIC_init_uniprocessor(void)localise_nmi_watchdog ();#endif -setup_boot_clock (); + platform_setup.timers.setup_percpu_clockev ();#ifdef CONFIG_X86_64 check_nmi_watchdog ();#endif
arch/x86/kernel/kvmclock.c +4 -1
@@ -22,6 +22,8 @@#include <asm/msr.h> #include <asm/apic.h> #include <linux/percpu.h> + +#include <asm/platform.h> #include <asm/reboot.h> #define KVM_SCALE 22
@@ -187,7 +189,8 @@ void __init kvmclock_init(void) pv_time_ops.sched_clock = kvm_clock_read; pv_time_ops.get_tsc_khz = kvm_get_tsc_khz;#ifdef CONFIG_X86_LOCAL_APIC - pv_apic_ops.setup_secondary_clock = kvm_setup_secondary_clock; + platform_cpuhotplug_setup.setup_percpu_clockev = + kvm_setup_secondary_clock;#endif #ifdef CONFIG_SMP smp_ops.smp_prepare_boot_cpu = kvm_smp_prepare_boot_cpu;
arch/x86/kernel/paravirt.c +0 -2
@@ -387,8 +387,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 };
arch/x86/kernel/platform_setup.c +9 -0
@@ -8,6 +8,7 @@#include <asm/bios_ebda.h> #include <asm/mpspec.h> #include <asm/setup.h> +#include <asm/apic.h> #include <asm/e820.h> #include <asm/irq.h>
@@ -53,7 +54,15 @@ struct __initdata platform_setup_ops pla .pagetable_setup_done = native_pagetable_setup_done, }, + .timers = { + .setup_percpu_clockev = setup_boot_APIC_clock, + }, + .quirks = { .mpc_record = platform_setup_uint_noop, }, }; + +__cpuinitdata struct platform_setup_cpuhotplug platform_cpuhotplug_setup = { + .setup_percpu_clockev = setup_secondary_APIC_clock, +};
arch/x86/kernel/smpboot.c +2 -2
@@ -323,7 +323,7 @@ notrace static void __cpuinit start_seco/* enable local interrupts */ local_irq_enable (); -setup_secondary_clock (); + platform_cpuhotplug_setup.setup_percpu_clockev ();wmb ();cpu_idle ();
@@ -1112,7 +1112,7 @@ void __init native_smp_prepare_cpus(unsiprintk (KERN_INFO "CPU%d: " ,0 );print_cpu_info (&cpu_data (0 )); -setup_boot_clock (); + platform_setup.timers.setup_percpu_clockev ();if (is_uv_system ())uv_system_init ();
arch/x86/kernel/vmi_32.c +3 -2
@@ -821,8 +821,9 @@ static inline int __init activate_vmi(vo pv_time_ops.get_wallclock = vmi_get_wallclock; pv_time_ops.set_wallclock = vmi_set_wallclock;#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; + platform_setup.timers.setup_percpu_clockev = vmi_time_bsp_init; + platform_cpuhotplug_setup.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;
arch/x86/xen/enlighten.c +4 -2
@@ -912,8 +912,6 @@ static const struct pv_cpu_ops xen_cpu_ostatic 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 };
@@ -984,6 +982,10 @@ asmlinkage void __init xen_start_kernel( platform_setup.oem.arch_setup = xen_arch_setup; platform_setup.oem.banner = xen_banner; +/* Override the default per cpu clockevents setup functions */ + platform_setup.timers.setup_percpu_clockev = platform_setup_noop; + platform_cpuhotplug_setup.setup_percpu_clockev = platform_setup_noop; +xen_init_mmu_ops ();xen_init_irq_ops ();
RFC PATCH 21/32 x86: Add timer_init to platform
In reply to Thomas GleixnerThe timer init code is convoluted with several quirks and the paravirt timer chooser. Figuring out which code path is actually taken is not for the faint hearted.
Move the numaq TSC quirk to tsc_pre_init platform function and replace the paravirt time chooser and the remaining x86 quirk with a simple platform setup function.
--- arch/x86/include/asm/paravirt.h | 7 ------ arch/x86/include/asm/platform.h | 4 +++ arch/x86/include/asm/setup.h | 21 +------------------ arch/x86/include/asm/time.h | 1 arch/x86/include/asm/timer.h | 3 -- arch/x86/kernel/apic/numaq_32.c | 10 +-------- arch/x86/kernel/paravirt.c | 1 arch/x86/kernel/platform_setup.c | 3 ++ arch/x86/kernel/setup.c | 43 --------------------------------------- arch/x86/kernel/time_32.c | 34 ++++++++++++++++++++---------- arch/x86/kernel/time_64.c | 9 ++++++-- arch/x86/kernel/tsc.c | 2 + arch/x86/kernel/visws_quirks.c | 22 +++++-------------- arch/x86/kernel/vmi_32.c | 2 - arch/x86/lguest/boot.c | 2 - arch/x86/xen/enlighten.c | 4 +-- 16 files changed, 54 insertions(+), 114 deletions(-)
arch/x86/include/asm/paravirt.h +0 -7
@@ -98,8 +98,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 );
@@ -693,11 +691,6 @@ static inline int set_wallclock(unsignedreturn 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)
arch/x86/include/asm/platform.h +4 -0
@@ -88,9 +88,13 @@ struct platform_setup_paging {* struct platform_setup_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 platform_setup_timers {void (*setup_percpu_clockev)(void ); +void (*tsc_pre_init)(void ); +void (*timer_init)(void ); };/**
arch/x86/include/asm/setup.h +2 -19
@@ -5,24 +5,6 @@#define COMMAND_LINE_SIZE 2048 -#ifndef __ASSEMBLY__ - -#include <asm/platform.h> - -/* -* Any setup quirks to be performed? -*/ - -struct x86_quirks { -int (*arch_pre_time_init)(void ); -int (*arch_time_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>
@@ -42,6 +24,7 @@ extern void x86_quirk_time_init(void);#ifndef __ASSEMBLY__#include <asm/bootparam.h> +#include <asm/platform.h> /* Interrupt control for vSMPowered x86_64 systems */ #ifdef CONFIG_X86_64
@@ -60,11 +43,11 @@ static inline void visws_early_detect(vostatic inline int is_visws_box (void ) {return 0 ; }#endif -extern struct x86_quirks *x86_quirks;extern unsigned long saved_video_mode;extern void reserve_standard_io_resources (void );extern void i386_reserve_resources (void ); +extern void setup_default_timer_irq (void );#ifndef _SETUP
arch/x86/include/asm/time.h +0 -1
@@ -54,7 +54,6 @@ extern void time_init(void);#define get_wallclock () native_get_wallclock()#define set_wallclock (x) native_set_wallclock(x) -#define choose_time_init () hpet_time_init#endif /* CONFIG_PARAVIRT */
arch/x86/include/asm/timer.h +1 -2
@@ -12,8 +12,7 @@ unsigned long native_calibrate_tsc(void)#ifdef CONFIG_X86_32 extern int timer_ack; -extern irqreturn_t timer_interrupt (int irq,void *dev_id); -#endif /* CONFIG_X86_32 */ +#endif extern int recalibrate_cpu_khz (void );extern int no_timer_check;
arch/x86/kernel/apic/numaq_32.c +2 -8
@@ -129,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)
@@ -262,11 +261,6 @@ static void __init smp_read_mpc_oem(stru } } -static struct x86_quirks numaq_x86_quirks__initdata = { - .arch_pre_time_init = numaq_pre_time_init, - .arch_time_init =NULL , -}; -static __init void early_check_numaq (void ) {/*
@@ -281,13 +275,13 @@ static __init void early_check_numaq(voiearly_get_smp_config ();if (found_numaq) { - x86_quirks = &numaq_x86_quirks; platform_setup.quirks.mpc_record = numaq_mpc_record; platform_setup.mpparse.setup_ioapic_ids = platform_setup_noop; platform_setup.mpparse.mpc_apic_id = mpc_apic_id; platform_setup.mpparse.smp_read_mpc_oem = smp_read_mpc_oem; platform_setup.mpparse.mpc_oem_pci_bus = mpc_oem_pci_bus; platform_setup.mpparse.mpc_oem_bus_info = mpc_oem_bus_info; + platform_setup.tsc_pre_init = numaq_tsc_init; } }
arch/x86/kernel/paravirt.c +0 -1
@@ -306,7 +306,6 @@ struct pv_init_ops pv_init_ops = { };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,
arch/x86/kernel/platform_setup.c +3 -0
@@ -10,6 +10,7 @@#include <asm/setup.h> #include <asm/apic.h> #include <asm/e820.h> +#include <asm/time.h> #include <asm/irq.h> void __cpuinit platform_setup_noop (void ) { }
@@ -56,6 +57,8 @@ struct __initdata platform_setup_ops pla .timers = { .setup_percpu_clockev = setup_boot_APIC_clock, + .tsc_pre_init = platform_setup_noop, + .timer_init = hpet_time_init, }, .quirks = {
arch/x86/kernel/setup.c +0 -43
55 lines not on this page · raw message
arch/x86/kernel/time_32.c +23 -11
@@ -72,7 +72,7 @@ EXPORT_SYMBOL(profile_pc);* 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) +static irqreturn_t timer_interrupt (int irq,void *dev_id) {/* Keep nmi watchdog up to date */ inc_irq_stat (irq0_irqs);
@@ -113,25 +113,37 @@ irqreturn_t timer_interrupt(int irq, voireturn IRQ_HANDLED ; } -/* Duplicate of time_init() below, with hpet_enable part added */ +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 (); -x86_quirk_time_init (); +setup_default_timer_irq (); +} + +static void x86_late_time_init (void ) +{ + platform_setup.timers.timer_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. +* Initialize TSC and delay the periodic timer init to +* late x86_late_time_init() so ioremap works. */ void __init time_init (void ) { -x86_quirk_pre_time_init ();tsc_init (); - late_time_init =choose_time_init (); + late_time_init = x86_late_time_init; }
arch/x86/kernel/time_64.c +7 -2
@@ -19,6 +19,7 @@#include <linux/mca.h> #include <linux/nmi.h> +#include <asm/platform.h> #include <asm/i8253.h> #include <asm/hpet.h> #include <asm/vgtod.h>
@@ -127,9 +128,13 @@ void __init hpet_time_init(void)setup_irq (0 , &irq0); } +static void x86_late_time_init (void ) +{ + platform_setup.timers.timer_init (); +} +void __init time_init (void ) {tsc_init (); - - late_time_init =choose_time_init (); + late_time_init = x86_late_time_init; }
arch/x86/kernel/tsc.c +2 -0
@@ -857,6 +857,8 @@ void __init tsc_init(void)u64 lpj;int cpu; + platform_setup.timers.tsc_pre_init (); +if (!cpu_has_tsc)return ;
arch/x86/kernel/visws_quirks.c +6 -16
@@ -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,8 +54,10 @@ int is_visws_box(void)return visws_board_type >=0 ; } -static int __init visws_time_init (void ) +static void __init visws_time_init (void ) { +hpet_time_init (); +printk (KERN_INFO "Starting Cobalt Timer system clock\n" );/* Set the countdown value */
@@ -65,12 +68,6 @@ 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 ; }/* Replaces the default init_ISA_irqs in the generic setup */
@@ -226,10 +223,6 @@ static void __init visws_find_smp_configstatic void visws_trap_init (void ); -static struct x86_quirks visws_x86_quirks__initdata = { - .arch_time_init = visws_time_init, -}; -void __init visws_early_detect (void ) {int raw;
@@ -241,17 +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; - platform_setup.resources.memory_setup = visws_memory_setup; platform_setup.mpparse.get_smp_config = visws_get_smp_config; platform_setup.mpparse.find_smp_config = visws_find_smp_config; platform_setup.irqs.pre_vector_init = visws_pre_intr_init; platform_setup.irqs.trap_init = visws_trap_init; + platform_setup.timers.timer_init = visws_time_init;/* * Install reboot quirks:
arch/x86/kernel/vmi_32.c +1 -1
@@ -817,7 +817,7 @@ static inline int __init activate_vmi(vo 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; + platform_setup.timers.timer_init = vmi_time_init; pv_time_ops.get_wallclock = vmi_get_wallclock; pv_time_ops.set_wallclock = vmi_set_wallclock;#ifdef CONFIG_X86_LOCAL_APIC
arch/x86/lguest/boot.c +1 -1
@@ -1320,11 +1320,11 @@ __init void lguest_init(void)/* 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; platform_setup.resources.memory_setup = lguest_memory_setup; platform_setup.irqs.intr_init = lguest_init_IRQ; + platform_setup.timers.timer_init = lguest_time_init;/* * Now is a good time to look at the implementations of these functions
arch/x86/xen/enlighten.c +2 -2
@@ -842,8 +842,6 @@ static const struct pv_init_ops xen_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,
@@ -982,6 +980,8 @@ asmlinkage void __init xen_start_kernel( platform_setup.oem.arch_setup = xen_arch_setup; platform_setup.oem.banner = xen_banner; + platform_setup.timers.timer_init = xen_time_init; +/* Override the default per cpu clockevents setup functions */ platform_setup.timers.setup_percpu_clockev = platform_setup_noop; platform_cpuhotplug_setup.setup_percpu_clockev = platform_setup_noop;
Re: [RFC patch 21/32] x86: Add timer_init to platform
Quoted 21 lines · Thomas Gleixner
The timer init code is convoluted with several quirks and the paravirt timer chooser. Figuring out which code path is actually taken is not for the faint hearted.
Move the numaq TSC quirk to
tsc_pre_initplatform function and replace the paravirt time chooser and the remaining x86 quirk with a simple platform setup function.Index:
linux-2.6/arch/x86/kernel/visws_quirks.c
===================================================================arch/x86/kernel/visws_quirks.c +1
-0@@ -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>
arch/x86/kernel/visws_quirks.c int is_visws_box(void) · line 59
Quoted 7 lines
arch/x86/kernel/visws_quirks.c +2
-1@@ -53,8 +54,10 @@ int is_visws_box(void)return visws_board_type >=0 ; } -static int __init visws_time_init (void ) +static void __init visws_time_init (void ) { +hpet_time_init ();
What's the purpose of this line ? It's highly unlikely that there is HPET hidden somewhere inside VisWs :)
Quoted 15 lines
arch/x86/kernel/visws_quirks.c +0
-6printk (KERN_INFO "Starting Cobalt Timer system clock\n" );/* Set the countdown value */ @@ -65,12 +68,6 @@ 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 ; }
RFC PATCH 22/32 x86: Remove do_timer hook
In reply to Thomas GleixnerThis is a left over of the old x86 sub arch support. Remove it and open code it like we do in time_64.c
--- arch/x86/include/asm/do_timer.h | 16 ---------------- arch/x86/kernel/time_32.c | 7 ++++--- 2 files changed, 4 insertions(+), 19 deletions(-)
arch/x86/include/asm/do_timer.h deleted +0 -16
@@ -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); -}
arch/x86/kernel/time_32.c +4 -3
@@ -28,6 +28,7 @@* serialize accesses to xtime/lost_ticks). */ +#include <linux/clockchips.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/time.h>
@@ -37,8 +38,8 @@#include <asm/hpet.h> #include <asm/time.h> #include <asm/timer.h> - -#include <asm/do_timer.h> +#include <asm/i8259.h> +#include <asm/i8253.h> int timer_ack;
@@ -92,7 +93,7 @@ static irqreturn_t timer_interrupt(int i }#endif -do_timer_interrupt_hook (); + global_clock_event->event_handler (global_clock_event);#ifdef CONFIG_MCA if (MCA_bus) {
RFC PATCH 23/32 x86: Prepare unification of time_32/64.c
In reply to Thomas GleixnerUnify the top comment and the includes.
--- arch/x86/kernel/time_32.c | 43 ++++++++++++------------------------------- arch/x86/kernel/time_64.c | 12 ++++-------- 2 files changed, 16 insertions(+), 39 deletions(-)
arch/x86/kernel/time_32.c +12 -31
@@ -1,45 +1,26 @@/* -* Copyright (C) 1991, 1992, 1995 Linus Torvalds +* 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 * -* 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 <[email protected]>, Andrew D. -* Balsa <[email protected]>, Philip Gladstone <[email protected]>; -* ported from 2.0.35 Jumbo-9 by Michael Krause <[email protected]>). -* 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/clockchips.h> -#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/platform.h> #include <asm/i8259.h> #include <asm/i8253.h> +#include <asm/timer.h> +#include <asm/hpet.h> +#include <asm/time.h> +#include <asm/nmi.h> int timer_ack;
arch/x86/kernel/time_64.c +4 -8
@@ -1,6 +1,4 @@/* -* "High Precision Event Timer" based timekeeping. -* * Copyright (c) 1991,1992,1995 Linus Torvalds * Copyright (c) 1994 Alan Modra * Copyright (c) 1995 Markus Kuhn
@@ -8,23 +6,21 @@* 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/platform.h> +#include <asm/i8259.h> #include <asm/i8253.h> +#include <asm/timer.h> #include <asm/hpet.h> -#include <asm/vgtod.h> #include <asm/time.h> -#include <asm/timer.h> +#include <asm/nmi.h> volatile unsigned long __jiffies __section_jiffies =INITIAL_JIFFIES ;
RFC PATCH 24/32 x86: Simplify timer_ack magic in time_32.c
In reply to Thomas GleixnerLet the compiler optimize the timer_ack magic away in the 32bit timer interrupt and put the same code into time_64.c. It's optimized out for CONFIG_X86_IO_APIC on 32bit and for 64bit because timer_ack is const 0 in both cases.
--- arch/x86/include/asm/timer.h | 6 ++++-- arch/x86/kernel/time_32.c | 5 +++-- arch/x86/kernel/time_64.c | 14 ++++++++++++++ 3 files changed, 21 insertions(+), 4 deletions(-)
arch/x86/include/asm/timer.h +4 -2
@@ -9,11 +9,13 @@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; +#else +# define timer_ack (0)#endif -extern int recalibrate_cpu_khz (void );extern int no_timer_check;
arch/x86/kernel/time_32.c +3 -2
@@ -22,7 +22,9 @@#include <asm/time.h> #include <asm/nmi.h> +#if defined(CONFIG_X86_32 ) && defined(CONFIG_X86_IO_APIC )int timer_ack; +#endif unsigned long profile_pc (struct pt_regs *regs) {
@@ -59,7 +61,7 @@ static irqreturn_t timer_interrupt(int i/* Keep nmi watchdog up to date */ inc_irq_stat (irq0_irqs); -#ifdef CONFIG_X86_IO_APIC +/* Optimized out for !IO_APIC and x86_64 */ if (timer_ack) {/* * Subtle, when I/O APICs are used we have to ack timer IRQ
@@ -72,7 +74,6 @@ static irqreturn_t timer_interrupt(int iinb (PIC_MASTER_POLL );spin_unlock (&i8259A_lock); } -#endif global_clock_event->event_handler (global_clock_event);
arch/x86/kernel/time_64.c +14 -0
@@ -50,6 +50,20 @@ static irqreturn_t timer_interrupt(int i {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);#ifdef CONFIG_MCA
RFC PATCH 25/32 x86: Remove mca bus ifdef from timer interrupt
In reply to Thomas GleixnerMCA_bus is constant 0 when CONFIG_MCA=n. So the compiler removes that code w/o needing an extra #ifdef
--- arch/x86/kernel/time_32.c | 18 +++--------------- arch/x86/kernel/time_64.c | 9 +++------ 2 files changed, 6 insertions(+), 21 deletions(-)
arch/x86/kernel/time_32.c +3 -15
@@ -77,21 +77,9 @@ static irqreturn_t timer_interrupt(int i global_clock_event->event_handler (global_clock_event); -#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 +/* 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 ; }
arch/x86/kernel/time_64.c +3 -6
@@ -66,12 +66,9 @@ static irqreturn_t timer_interrupt(int i 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 +/* 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 ; }
RFC PATCH 26/32 x86: Make timer setup and global variables the same in time_32/64.c
In reply to Thomas GleixnerThe timer and timer irq setup code is identical in 32 and 64 bit. Make it the same formatting as well. Also add the global variables under the necessary ifdefs to both files.
--- arch/x86/kernel/time_32.c | 8 +++++--- arch/x86/kernel/time_64.c | 38 ++++++++++++++++++++++++++++++-------- 2 files changed, 35 insertions(+), 11 deletions(-)
arch/x86/kernel/time_32.c +5 -3
@@ -26,6 +26,10 @@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);
@@ -52,9 +56,7 @@ unsigned long profile_pc(struct pt_regsEXPORT_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. +* Default timer interrupt handler for PIT/HPET */ static irqreturn_t timer_interrupt (int irq,void *dev_id) {
arch/x86/kernel/time_64.c +30 -8
@@ -22,7 +22,13 @@#include <asm/time.h> #include <asm/nmi.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) {
@@ -46,8 +52,12 @@ unsigned long profile_pc(struct pt_regs }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 */
@@ -73,8 +83,10 @@ static irqreturn_t timer_interrupt(int ireturn IRQ_HANDLED ; } -/* calibrate_cpu is used on systems with fixed rate TSCs to determine -* processor frequency */ +/* +* calibrate_cpu is used on systems with fixed rate TSCs to determine +* processor frequency +*/ #define TICK_COUNT 100000000unsigned long __init calibrate_cpu (void ) {
@@ -121,18 +133,24 @@ unsigned long __init calibrate_cpu(void)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" +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_irq (0 , &irq0); +setup_default_timer_irq (); }static void x86_late_time_init (void )
@@ -140,6 +158,10 @@ static void x86_late_time_init(void) platform_setup.timers.timer_init (); } +/* +* Initialize TSC and delay the periodic timer init to +* late x86_late_time_init() so ioremap works. +*/ void __init time_init (void ) {tsc_init ();
RFC PATCH 27/32 x86: Move calibrate_cpu to tsc.c
In reply to Thomas GleixnerMove the code where it's only user is. Also we need to look whether this hardwired hackery might interfere with perfcounters.
--- arch/x86/include/asm/time.h | 2 - arch/x86/kernel/time_32.c | 1 arch/x86/kernel/time_64.c | 51 --------------------------------------- arch/x86/kernel/tsc.c | 57 ++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 55 insertions(+), 56 deletions(-)
arch/x86/include/asm/time.h +0 -2
@@ -57,6 +57,4 @@ extern void time_init(void);#endif /* CONFIG_PARAVIRT */ -extern unsigned long __init calibrate_cpu (void ); -#endif /* _ASM_X86_TIME_H */
arch/x86/kernel/time_32.c +0 -1
@@ -20,7 +20,6 @@#include <asm/timer.h> #include <asm/hpet.h> #include <asm/time.h> -#include <asm/nmi.h> #if defined(CONFIG_X86_32 ) && defined(CONFIG_X86_IO_APIC )int timer_ack;
arch/x86/kernel/time_64.c +0 -51
63 lines not on this page · raw message
arch/x86/kernel/tsc.c +55 -2
78 lines not on this page · raw message
RFC PATCH 28/32 x86: time_32/64.c unify profile_pc
In reply to Thomas GleixnerThe code is identical except for the formatting and a useless #ifdef. Make it the same.
--- arch/x86/kernel/time_32.c | 13 ++++++------- arch/x86/kernel/time_64.c | 8 +++++--- 2 files changed, 11 insertions(+), 10 deletions(-)
arch/x86/kernel/time_32.c +6 -7
@@ -33,23 +33,22 @@ unsigned long profile_pc(struct pt_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. */ +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 } -#endif return pc; }EXPORT_SYMBOL (profile_pc);
arch/x86/kernel/time_64.c +5 -3
@@ -33,14 +33,16 @@ unsigned long profile_pc(struct pt_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; +/* +* 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 )
RFC PATCH 29/32 x86: Replace the now identical time_32/64.c by time.c
In reply to Thomas GleixnerRemove the redundant copy.
--- arch/x86/kernel/Makefile | 2 arch/x86/kernel/time.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++ arch/x86/kernel/time_32.c | 120 ---------------------------------------------- arch/x86/kernel/time_64.c | 120 ---------------------------------------------- 4 files changed, 121 insertions(+), 241 deletions(-)
arch/x86/kernel/Makefile +1 -1
@@ -31,7 +31,7 @@ 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 += time.o ioport.o ldt.o dumpstack.o obj-y += setup.o platform_setup.o i8259.o irqinit.o obj-$(CONFIG_X86_VISWS) += visws_quirks.o obj-$(CONFIG_X86_32) += probe_roms_32.o
arch/x86/kernel/time.c new file +120 -0
120 lines not on this page · raw message
arch/x86/kernel/time_32.c deleted +0 -120
120 lines not on this page · raw message
arch/x86/kernel/time_64.c deleted +0 -120
120 lines not on this page · raw message
RFC PATCH 30/32 x86: Move tsc_calibration to platform
In reply to Thomas GleixnerTSC calibration is modified by the vmware hypervisor and paravirt by separate means. Moorestown wants to add its own calibration routine as well. So make calibrate_tsc a proper platform function and override it by paravirt or by the early setup of the vmware hypervisor.
--- arch/x86/include/asm/hypervisor.h | 2 +- arch/x86/include/asm/paravirt.h | 2 -- arch/x86/include/asm/platform.h | 2 ++ arch/x86/include/asm/timer.h | 5 ----- arch/x86/include/asm/tsc.h | 3 ++- arch/x86/include/asm/vmware.h | 2 +- arch/x86/kernel/cpu/hypervisor.c | 14 +++++++------- arch/x86/kernel/cpu/vmware.c | 35 +++++++++++++++++++---------------- arch/x86/kernel/kvmclock.c | 2 +- arch/x86/kernel/paravirt.c | 1 - arch/x86/kernel/platform_setup.c | 2 ++ arch/x86/kernel/setup.c | 2 +- arch/x86/kernel/tsc.c | 10 ++-------- arch/x86/kernel/vmi_32.c | 2 +- arch/x86/kernel/vmiclock_32.c | 2 +- arch/x86/lguest/boot.c | 2 +- arch/x86/xen/enlighten.c | 2 +- 17 files changed, 42 insertions(+), 48 deletions(-)
arch/x86/include/asm/hypervisor.h +1 -1
@@ -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
arch/x86/include/asm/paravirt.h +0 -2
@@ -103,7 +103,6 @@ struct pv_time_ops {int (*set_wallclock)(unsigned long );unsigned long long (*sched_clock)(void ); -unsigned long (*get_tsc_khz)(void ); };struct pv_cpu_ops {
@@ -867,7 +866,6 @@ static inline unsigned long long paravir { 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) {
arch/x86/include/asm/platform.h +2 -0
@@ -90,11 +90,13 @@ struct platform_setup_paging {* boot cpu * @tsc_pre_init: platform function called before TSC init * @timer_init: initialize the platform timer (default PIT/HPET) +* @calibrate_tsc: calibrate TSC */ struct platform_setup_timers {void (*setup_percpu_clockev)(void );void (*tsc_pre_init)(void );void (*timer_init)(void ); +unsigned long (*calibrate_tsc)(void ); };/**
arch/x86/include/asm/timer.h +0 -5
@@ -8,7 +8,6 @@#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 );#if defined(CONFIG_X86_32 ) && defined(CONFIG_X86_IO_APIC )
@@ -19,10 +18,6 @@ extern int timer_ack;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:
arch/x86/include/asm/tsc.h +2 -1
@@ -48,7 +48,8 @@ static __always_inline cycles_t vget_cycextern 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
arch/x86/include/asm/vmware.h +1 -1
@@ -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);
arch/x86/kernel/cpu/hypervisor.c +7 -7
@@ -35,13 +35,6 @@ detect_hypervisor_vendor(struct cpuinfo_ } } -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) {
@@ -56,3 +49,10 @@ void __cpuinit init_hypervisor(struct cpdetect_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 (); +}
arch/x86/kernel/cpu/vmware.c +19 -16
@@ -24,6 +24,7 @@#include <linux/dmi.h> #include <asm/div64.h> #include <asm/vmware.h> +#include <asm/platform.h> #define CPUID_VMWARE_INFO_LEAF 0x40000000#define VMWARE_HYPERVISOR_MAGIC 0x564D5868
@@ -47,19 +48,27 @@ static inline int __vmware_platform(voidreturn 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; +uint64_t tsc_hz; +uint32_t eax, ebx, ecx, edx; + +VMWARE_PORT (GETHZ , eax, ebx, ecx, edx); + + 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); +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; +if (ebx !=UINT_MAX ) + platform_setup.timers.calibrate_tsc = vmware_get_tsc_khz; }/*
@@ -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
arch/x86/kernel/kvmclock.c +1 -1
@@ -187,7 +187,7 @@ void __init kvmclock_init(void) 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; + platform_setup.timers.calibrate_tsc = kvm_get_tsc_khz;#ifdef CONFIG_X86_LOCAL_APIC platform_cpuhotplug_setup.setup_percpu_clockev = kvm_setup_secondary_clock;
arch/x86/kernel/paravirt.c +0 -1
@@ -309,7 +309,6 @@ struct pv_time_ops pv_time_ops = { .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 = {
arch/x86/kernel/platform_setup.c +2 -0
@@ -12,6 +12,7 @@#include <asm/e820.h> #include <asm/time.h> #include <asm/irq.h> +#include <asm/tsc.h> void __cpuinit platform_setup_noop (void ) { }void __init platform_setup_uint_noop (unsigned int unused) { }
@@ -59,6 +60,7 @@ struct __initdata platform_setup_ops pla .setup_percpu_clockev = setup_boot_APIC_clock, .tsc_pre_init = platform_setup_noop, .timer_init = hpet_time_init, + .calibrate_tsc = native_calibrate_tsc, }, .quirks = {
arch/x86/kernel/setup.c +1 -1
@@ -818,7 +818,7 @@ 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 (); platform_setup.resources.probe_roms ();
arch/x86/kernel/tsc.c +2 -8
@@ -401,15 +401,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);
@@ -917,7 +911,7 @@ void __init tsc_init(void)if (!cpu_has_tsc)return ; - tsc_khz =calibrate_tsc (); + tsc_khz = platform_setup.timers.calibrate_tsc (); cpu_khz = tsc_khz;if (!tsc_khz) {
arch/x86/kernel/vmi_32.c +1 -1
@@ -826,7 +826,7 @@ static inline int __init activate_vmi(vo vmi_time_ap_init;#endif pv_time_ops.sched_clock = vmi_sched_clock; - pv_time_ops.get_tsc_khz = vmi_tsc_khz; + platform_setup.timers.calibrate_tsc = vmi_tsc_khz;/* We have true wallclock functions; disable CMOS clock sync */ no_sync_cmos_clock =1 ;
arch/x86/kernel/vmiclock_32.c +1 -1
@@ -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 */ +/* platform_setup.calibrate_tsc = vmi_tsc_khz */ unsigned long vmi_tsc_khz (void ) {unsigned long long khz;
arch/x86/lguest/boot.c +1 -1
@@ -1320,11 +1320,11 @@ __init void lguest_init(void)/* Time operations */ pv_time_ops.get_wallclock = lguest_get_wallclock; - pv_time_ops.get_tsc_khz = lguest_tsc_khz; platform_setup.resources.memory_setup = lguest_memory_setup; platform_setup.irqs.intr_init = lguest_init_IRQ; platform_setup.timers.timer_init = lguest_time_init; + platform_setup.timers.calibrate_tsc = lguest_tsc_khz;/* * Now is a good time to look at the implementations of these functions
arch/x86/xen/enlighten.c +1 -1
@@ -844,7 +844,6 @@ static const struct pv_init_ops xen_initstatic const struct pv_time_ops xen_time_ops__initdata = { .set_wallclock = xen_set_wallclock, .get_wallclock = xen_get_wallclock, - .get_tsc_khz = xen_tsc_khz, .sched_clock = xen_sched_clock, };
@@ -981,6 +980,7 @@ asmlinkage void __init xen_start_kernel( platform_setup.oem.banner = xen_banner; platform_setup.timers.timer_init = xen_time_init; + platform_setup.timers.calibrate_tsc = xen_tsc_khz;/* Override the default per cpu clockevents setup functions */ platform_setup.timers.setup_percpu_clockev = platform_setup_noop;
RFC PATCH 31/32 init: Move sched_clock_init after late_time_init
In reply to Thomas GleixnerSome architectures initialize clocks and timers in late_time_init and x86 wants to do the same to avoid FIXMAP hackery for calibrating the TSC. That would result in undefined sched_clock readout and wreckaged printk timestamps again. We probably have those already on archs which do all their time/clock setup in late_time_init.
There is no harm to move that after late_time_init except that a few more boot timestamps are stale. The scheduler is not active at that point so no real wreckage is expected.
--- init/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
init/main.c +1 -1
@@ -631,7 +631,6 @@ asmlinkage void __init start_kernel(voidsoftirq_init ();timekeeping_init ();time_init (); -sched_clock_init ();profile_init ();if (!irqs_disabled ()) printk(KERN_CRIT "start_kernel(): bug: interrupts were "
@@ -682,6 +681,7 @@ asmlinkage void __init start_kernel(voidnuma_policy_init ();if (late_time_init)late_time_init (); +sched_clock_init ();calibrate_delay ();pidmap_init ();anon_vma_init ();
RFC PATCH 32/32 x86: Move tsc_init to late_time_init
In reply to Thomas GleixnerWe do not need the TSC before late_time_init. Move the tsc_init to the late time init code so we can also utilize HPET for calibration (which we claimed to do but never did except in some older kernel version). This also helps Moorestown to calibrate the TSC with the AHBT timer which needs to be initialized in late_time_init like HPET.
--- arch/x86/kernel/time.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/kernel/time.c +1 -1
@@ -107,6 +107,7 @@ void __init hpet_time_init(void)static void x86_late_time_init (void ) { platform_setup.timers.timer_init (); +tsc_init (); }/*
@@ -115,6 +116,5 @@ static void x86_late_time_init(void)*/ void __init time_init (void ) { -tsc_init (); late_time_init = x86_late_time_init; }
Quoted 6 lines · Thomas Gleixner
The following patch series refactors the setup related
x86_quirksand the setup related paravirt hooks and puts them into an extensibleplatform_setupinfrastructure to provide a proper base for adding the Moorestown modifications. As a side effect it also unifies time_32/64.c and removes some leftovers of the prearch/x86era.
I haven't gone through the patches at all yet, but I definitely like this direction. I've got some local patches to generalize x86_quirks a bit, and I'm hoping that you've already subsumed them; if not, it should be easy to extend on top of your patches.
J
* Thomas Gleixner <[email protected]> wrote:
[...]
Quoted 7 lines
The following patch series refactors the setup related
x86_quirksand the setup related paravirt hooks and puts them into an extensibleplatform_setupinfrastructure to provide a proper base for adding the Moorestown modifications. As a side effect it also unifies time_32/64.c and removes some leftovers of the prearch/x86era.
Quoted 6 lines
Note, this is not a replacement for
paravirt_ops. It is just replacing the setup related paravirt stuff so it can be reused for other platforms though I have to say that it removes a fair amount of obscurity which was introduced by paravirt & Co.47 files changed, 622 insertions(+), 808 deletions(-)
Very nice!
One small detail, before we spread out these patches. While looking at the patches i noticed that at places our new x86 init namespace is very long:
Review
Quoted 3 lines
(quoted diff) +3
-0+ platform_setup.timers.setup_percpu_clockev = platform_setup_noop; + platform_cpuhotplug_setup.setup_percpu_clockev = platform_setup_noop; +
I think we should shorten the name-space a bit - we'll use it in a _lot_ of places, so the shorter, the better and the easier to use.
I'd suggest something like:
x86_init.timers.init_percpu_clockev = x86_init_noop;
x86_cpuhotplug_init.init_percpu_clockev = x86_init_noop;( This also has the advantage that 'init' is the general term we use
for kernel structure initialization - 'setup' is a more restrictive term we use related to bootloading, most of the time. )
An even shorter form would be to use 'x86' as a general template for platform details:
x86.timers.init_percpu_ce = x86_init_noop;
x86_cpuhotplug.init_percpu_ce = x86_init_noop;this is even shorter, plus it allows us to put runtime details into this structure as well. Note that the fields themselves (init_percpu_clockev) already signal the 'init' property sufficiently. Plus 'ce' is an existing, well-known abbreviation for clockevents. (but 'clockev' would be good too - i might be pushing it)
What do you think?
Ingo
Quoted 16 lines · Ingo Molnar
Quoted 1 line · Thomas Gleixner
47 files changed, 622 insertions(+), 808 deletions(-)Very nice!
One small detail, before we spread out these patches. While looking at the patches i noticed that at places our new x86 init namespace is very long:
Review
Quoted 3 lines
(quoted diff) +3
-0+ platform_setup.timers.setup_percpu_clockev = platform_setup_noop; + platform_cpuhotplug_setup.setup_percpu_clockev = platform_setup_noop; +I think we should shorten the name-space a bit - we'll use it in a _lot_ of places, so the shorter, the better and the easier to use.
Quoted 8 lines
I'd suggest something like:
x86_init.timers.init_percpu_clockev = x86_init_noop; x86_cpuhotplug_init.init_percpu_clockev = x86_init_noop;( This also has the advantage that 'init' is the general term we use
for kernel structure initialization - 'setup' is a more restrictive term we use related to bootloading, most of the time. )
Fair enough.
Quoted 8 lines
An even shorter form would be to use 'x86' as a general template for platform details:
x86.timers.init_percpu_ce = x86_init_noop; x86_cpuhotplug.init_percpu_ce = x86_init_noop;this is even shorter, plus it allows us to put runtime details into this structure as well. Note that the fields themselves
We should have a separate struct for runtime details otherwise we need to keep the full init stuff around forever instead of freeing it. That's why I already have that separate cpuhotplug struct.
Quoted 4 lines
(
init_percpu_clockev) already signal the 'init' property sufficiently. Plus 'ce' is an existing, well-known abbreviation for clockevents. (but 'clockev' would be good too - i might be pushing it)
Yes you do. Next you suggest to have x86_i.pcpu_ce :)
Thanks,
tglx