From 5989cd6a1cbf86587edcc856791f960978087311 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Wed, 4 Aug 2010 13:30:27 -0700 Subject: x86, apic: Map the local apic when parsing the MP table. This fixes a regression in 2.6.35 from 2.6.34, that is present for select models of Intel cpus when people are using an MP table. The commit cf7500c0ea133d66f8449d86392d83f840102632 "x86, ioapic: In mpparse use mp_register_ioapic" started calling mp_register_ioapic from MP_ioapic_info. An extremely simple change that was obviously correct. Unfortunately mp_register_ioapic did just a little more than the previous hand crafted code and so we gained this call path. The problem call path is: MP_ioapic_info() mp_register_ioapic() io_apic_unique_id() io_apic_get_unique_id() get_physical_broadcast() modern_apic() lapic_get_version() apic_read(APIC_LVR) Which turned out to be a problem because the local apic was not mapped, at that point, unlike the similar point in the ACPI parsing code. This problem is fixed by mapping the local apic when parsing the mptable as soon as we reasonably can. Looking at the number of places we setup the fixmap for the local apic, I see some serious simplification opportunities. For the moment except for not duplicating the setting up of the fixmap in init_apic_mappings, I have not acted on them. The regression from 2.6.34 is tracked in bug https://bugzilla.kernel.org/show_bug.cgi?id=16173 Cc: 2.6.35 Reported-by: David Hill Reported-by: Tvrtko Ursulin Tested-by: Tvrtko Ursulin Signed-off-by: Eric W. Biederman LKML-Reference: Signed-off-by: H. Peter Anvin --- arch/x86/kernel/apic/apic.c | 2 +- arch/x86/kernel/mpparse.c | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index a96489ee6ca..c07e51391a3 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1606,7 +1606,7 @@ void __init init_apic_mappings(void) * acpi lapic path already maps that address in * acpi_register_lapic_address() */ - if (!acpi_lapic) + if (!acpi_lapic && !smp_found_config) set_fixmap_nocache(FIX_APIC_BASE, apic_phys); apic_printk(APIC_VERBOSE, "mapped APIC to %08lx (%08lx)\n", diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index d86dbf7e54b..d7b6f7fb4fe 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c @@ -274,6 +274,18 @@ static void __init smp_dump_mptable(struct mpc_table *mpc, unsigned char *mpt) void __init default_smp_read_mpc_oem(struct mpc_table *mpc) { } +static void __init smp_register_lapic_address(unsigned long address) +{ + mp_lapic_addr = address; + + set_fixmap_nocache(FIX_APIC_BASE, address); + if (boot_cpu_physical_apicid == -1U) { + boot_cpu_physical_apicid = read_apic_id(); + apic_version[boot_cpu_physical_apicid] = + GET_APIC_VERSION(apic_read(APIC_LVR)); + } +} + static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early) { char str[16]; @@ -295,6 +307,10 @@ static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early) if (early) return 1; + /* Initialize the lapic mapping */ + if (!acpi_lapic) + smp_register_lapic_address(mpc->lapic); + if (mpc->oemptr) x86_init.mpparse.smp_read_mpc_oem(mpc); -- cgit v1.2.3-70-g09d2 From 8fd49936a8cac246fc9ed85508556c82cd44cf68 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 11 Aug 2010 15:37:41 +0900 Subject: x86: Document __phys_reloc_hide() usage in __pa_symbol() Until all supported versions of gcc recognize -fno-strict-overflow, we should keep the RELOC_HIDE() magic in __pa_symbol(). Comment it. Signed-off-by: Namhyung Kim LKML-Reference: <1281508661-29507-1-git-send-email-namhyung@gmail.com> Signed-off-by: Ingo Molnar --- arch/x86/include/asm/page.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'arch') diff --git a/arch/x86/include/asm/page.h b/arch/x86/include/asm/page.h index 625c3f0e741..8ca82839288 100644 --- a/arch/x86/include/asm/page.h +++ b/arch/x86/include/asm/page.h @@ -37,6 +37,13 @@ static inline void copy_user_page(void *to, void *from, unsigned long vaddr, #define __pa_nodebug(x) __phys_addr_nodebug((unsigned long)(x)) /* __pa_symbol should be used for C visible symbols. This seems to be the official gcc blessed way to do such arithmetic. */ +/* + * We need __phys_reloc_hide() here because gcc may assume that there is no + * overflow during __pa() calculation and can optimize it unexpectedly. + * Newer versions of gcc provide -fno-strict-overflow switch to handle this + * case properly. Once all supported versions of gcc understand it, we can + * remove this Voodoo magic stuff. (i.e. once gcc3.x is deprecated) + */ #define __pa_symbol(x) __pa(__phys_reloc_hide((unsigned long)(x))) #define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET)) -- cgit v1.2.3-70-g09d2 From 30246557a06bb20618bed906a06d1e1e0faa8bb4 Mon Sep 17 00:00:00 2001 From: Luca Barbieri Date: Fri, 6 Aug 2010 04:04:38 +0200 Subject: x86, asm: Refactor atomic64_386_32.S to support old binutils and be cleaner The old code didn't work on binutils 2.12 because setting a symbol to a register apparently requires a fairly recent version. This commit refactors the code to use the C preprocessor instead, and in the process makes the whole code a bit easier to understand. The object code produced is unchanged as expected. This fixes kernel bugzilla 16506. Reported-by: Dieter Stussy Signed-off-by: Luca Barbieri Signed-off-by: H. Peter Anvin Cc: 2.6.35 LKML-Reference: --- arch/x86/lib/atomic64_386_32.S | 236 ++++++++++++++++++++++------------------- 1 file changed, 128 insertions(+), 108 deletions(-) (limited to 'arch') diff --git a/arch/x86/lib/atomic64_386_32.S b/arch/x86/lib/atomic64_386_32.S index 4a5979aa688..78ee8e0fa27 100644 --- a/arch/x86/lib/atomic64_386_32.S +++ b/arch/x86/lib/atomic64_386_32.S @@ -25,150 +25,170 @@ CFI_ADJUST_CFA_OFFSET -4 .endm -.macro BEGIN func reg -$v = \reg - -ENTRY(atomic64_\func\()_386) - CFI_STARTPROC - LOCK $v - -.macro RETURN - UNLOCK $v +#define BEGIN(op) \ +.macro END; \ + CFI_ENDPROC; \ +ENDPROC(atomic64_##op##_386); \ +.purgem END; \ +.endm; \ +ENTRY(atomic64_##op##_386); \ + CFI_STARTPROC; \ + LOCK v; + +#define RET \ + UNLOCK v; \ ret -.endm - -.macro END_ - CFI_ENDPROC -ENDPROC(atomic64_\func\()_386) -.purgem RETURN -.purgem END_ -.purgem END -.endm - -.macro END -RETURN -END_ -.endm -.endm - -BEGIN read %ecx - movl ($v), %eax - movl 4($v), %edx -END - -BEGIN set %esi - movl %ebx, ($v) - movl %ecx, 4($v) -END - -BEGIN xchg %esi - movl ($v), %eax - movl 4($v), %edx - movl %ebx, ($v) - movl %ecx, 4($v) -END - -BEGIN add %ecx - addl %eax, ($v) - adcl %edx, 4($v) -END -BEGIN add_return %ecx - addl ($v), %eax - adcl 4($v), %edx - movl %eax, ($v) - movl %edx, 4($v) -END - -BEGIN sub %ecx - subl %eax, ($v) - sbbl %edx, 4($v) -END - -BEGIN sub_return %ecx +#define RET_END \ + RET; \ + END + +#define v %ecx +BEGIN(read) + movl (v), %eax + movl 4(v), %edx +RET_END +#undef v + +#define v %esi +BEGIN(set) + movl %ebx, (v) + movl %ecx, 4(v) +RET_END +#undef v + +#define v %esi +BEGIN(xchg) + movl (v), %eax + movl 4(v), %edx + movl %ebx, (v) + movl %ecx, 4(v) +RET_END +#undef v + +#define v %ecx +BEGIN(add) + addl %eax, (v) + adcl %edx, 4(v) +RET_END +#undef v + +#define v %ecx +BEGIN(add_return) + addl (v), %eax + adcl 4(v), %edx + movl %eax, (v) + movl %edx, 4(v) +RET_END +#undef v + +#define v %ecx +BEGIN(sub) + subl %eax, (v) + sbbl %edx, 4(v) +RET_END +#undef v + +#define v %ecx +BEGIN(sub_return) negl %edx negl %eax sbbl $0, %edx - addl ($v), %eax - adcl 4($v), %edx - movl %eax, ($v) - movl %edx, 4($v) -END - -BEGIN inc %esi - addl $1, ($v) - adcl $0, 4($v) -END - -BEGIN inc_return %esi - movl ($v), %eax - movl 4($v), %edx + addl (v), %eax + adcl 4(v), %edx + movl %eax, (v) + movl %edx, 4(v) +RET_END +#undef v + +#define v %esi +BEGIN(inc) + addl $1, (v) + adcl $0, 4(v) +RET_END +#undef v + +#define v %esi +BEGIN(inc_return) + movl (v), %eax + movl 4(v), %edx addl $1, %eax adcl $0, %edx - movl %eax, ($v) - movl %edx, 4($v) -END - -BEGIN dec %esi - subl $1, ($v) - sbbl $0, 4($v) -END - -BEGIN dec_return %esi - movl ($v), %eax - movl 4($v), %edx + movl %eax, (v) + movl %edx, 4(v) +RET_END +#undef v + +#define v %esi +BEGIN(dec) + subl $1, (v) + sbbl $0, 4(v) +RET_END +#undef v + +#define v %esi +BEGIN(dec_return) + movl (v), %eax + movl 4(v), %edx subl $1, %eax sbbl $0, %edx - movl %eax, ($v) - movl %edx, 4($v) -END + movl %eax, (v) + movl %edx, 4(v) +RET_END +#undef v -BEGIN add_unless %ecx +#define v %ecx +BEGIN(add_unless) addl %eax, %esi adcl %edx, %edi - addl ($v), %eax - adcl 4($v), %edx + addl (v), %eax + adcl 4(v), %edx cmpl %eax, %esi je 3f 1: - movl %eax, ($v) - movl %edx, 4($v) + movl %eax, (v) + movl %edx, 4(v) movl $1, %eax 2: -RETURN + RET 3: cmpl %edx, %edi jne 1b xorl %eax, %eax jmp 2b -END_ +END +#undef v -BEGIN inc_not_zero %esi - movl ($v), %eax - movl 4($v), %edx +#define v %esi +BEGIN(inc_not_zero) + movl (v), %eax + movl 4(v), %edx testl %eax, %eax je 3f 1: addl $1, %eax adcl $0, %edx - movl %eax, ($v) - movl %edx, 4($v) + movl %eax, (v) + movl %edx, 4(v) movl $1, %eax 2: -RETURN + RET 3: testl %edx, %edx jne 1b jmp 2b -END_ +END +#undef v -BEGIN dec_if_positive %esi - movl ($v), %eax - movl 4($v), %edx +#define v %esi +BEGIN(dec_if_positive) + movl (v), %eax + movl 4(v), %edx subl $1, %eax sbbl $0, %edx js 1f - movl %eax, ($v) - movl %edx, 4($v) + movl %eax, (v) + movl %edx, 4(v) 1: -END +RET_END +#undef v -- cgit v1.2.3-70-g09d2 From 417484d47e115774745ef025bce712a102b6f86f Mon Sep 17 00:00:00 2001 From: Luca Barbieri Date: Thu, 12 Aug 2010 07:00:35 -0700 Subject: x86, asm: Use a lower case name for the end macro in atomic64_386_32.S Use a lowercase name for the end macro, which somehow fixes a binutils 2.16 problem. Signed-off-by: Luca Barbieri LKML-Reference: Signed-off-by: H. Peter Anvin --- arch/x86/lib/atomic64_386_32.S | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) (limited to 'arch') diff --git a/arch/x86/lib/atomic64_386_32.S b/arch/x86/lib/atomic64_386_32.S index 78ee8e0fa27..2cda60a06e6 100644 --- a/arch/x86/lib/atomic64_386_32.S +++ b/arch/x86/lib/atomic64_386_32.S @@ -26,35 +26,37 @@ .endm #define BEGIN(op) \ -.macro END; \ +.macro endp; \ CFI_ENDPROC; \ ENDPROC(atomic64_##op##_386); \ -.purgem END; \ +.purgem endp; \ .endm; \ ENTRY(atomic64_##op##_386); \ CFI_STARTPROC; \ LOCK v; +#define ENDP endp + #define RET \ UNLOCK v; \ ret -#define RET_END \ +#define RET_ENDP \ RET; \ - END + ENDP #define v %ecx BEGIN(read) movl (v), %eax movl 4(v), %edx -RET_END +RET_ENDP #undef v #define v %esi BEGIN(set) movl %ebx, (v) movl %ecx, 4(v) -RET_END +RET_ENDP #undef v #define v %esi @@ -63,14 +65,14 @@ BEGIN(xchg) movl 4(v), %edx movl %ebx, (v) movl %ecx, 4(v) -RET_END +RET_ENDP #undef v #define v %ecx BEGIN(add) addl %eax, (v) adcl %edx, 4(v) -RET_END +RET_ENDP #undef v #define v %ecx @@ -79,14 +81,14 @@ BEGIN(add_return) adcl 4(v), %edx movl %eax, (v) movl %edx, 4(v) -RET_END +RET_ENDP #undef v #define v %ecx BEGIN(sub) subl %eax, (v) sbbl %edx, 4(v) -RET_END +RET_ENDP #undef v #define v %ecx @@ -98,14 +100,14 @@ BEGIN(sub_return) adcl 4(v), %edx movl %eax, (v) movl %edx, 4(v) -RET_END +RET_ENDP #undef v #define v %esi BEGIN(inc) addl $1, (v) adcl $0, 4(v) -RET_END +RET_ENDP #undef v #define v %esi @@ -116,14 +118,14 @@ BEGIN(inc_return) adcl $0, %edx movl %eax, (v) movl %edx, 4(v) -RET_END +RET_ENDP #undef v #define v %esi BEGIN(dec) subl $1, (v) sbbl $0, 4(v) -RET_END +RET_ENDP #undef v #define v %esi @@ -134,7 +136,7 @@ BEGIN(dec_return) sbbl $0, %edx movl %eax, (v) movl %edx, 4(v) -RET_END +RET_ENDP #undef v #define v %ecx @@ -156,7 +158,7 @@ BEGIN(add_unless) jne 1b xorl %eax, %eax jmp 2b -END +ENDP #undef v #define v %esi @@ -177,7 +179,7 @@ BEGIN(inc_not_zero) testl %edx, %edx jne 1b jmp 2b -END +ENDP #undef v #define v %esi @@ -190,5 +192,5 @@ BEGIN(dec_if_positive) movl %eax, (v) movl %edx, 4(v) 1: -RET_END +RET_ENDP #undef v -- cgit v1.2.3-70-g09d2