From e0037df3852b4b60edbe01f70f4968e4a9fdb272 Mon Sep 17 00:00:00 2001 From: Andrea Shepard Date: Sun, 19 Oct 2008 23:33:03 -0700 Subject: sparc64: Fix race in arch/sparc64/kernel/trampoline.S Make arch/sparc64/kernel/trampoline.S in 2.6.27.1 lock prom_entry_lock when calling the PROM. This prevents a race condition that I observed causing a hang on startup on a 12-CPU E4500. I am not subscribed to this list, so please CC me on replies. Signed-off-by: Andrea Shepard Signed-off-by: David S. Miller diff --git a/arch/sparc64/kernel/trampoline.S b/arch/sparc64/kernel/trampoline.S index 704a3af..83abd5a 100644 --- a/arch/sparc64/kernel/trampoline.S +++ b/arch/sparc64/kernel/trampoline.S @@ -328,6 +328,12 @@ after_lock_tlb: wrpr %g0, 0, %wstate + sethi %hi(prom_entry_lock), %g2 +1: ldstub [%g2 + %lo(prom_entry_lock)], %g1 + membar #StoreLoad | #StoreStore + brnz,pn %g1, 1b + nop + /* As a hack, put &init_thread_union into %g6. * prom_world() loads from here to restore the %asi * register. @@ -337,7 +343,7 @@ after_lock_tlb: sethi %hi(is_sun4v), %o0 lduw [%o0 + %lo(is_sun4v)], %o0 - brz,pt %o0, 1f + brz,pt %o0, 2f nop TRAP_LOAD_TRAP_BLOCK(%g2, %g3) @@ -369,10 +375,10 @@ after_lock_tlb: call %o1 add %sp, (2047 + 128), %o0 - ba,pt %xcc, 2f + ba,pt %xcc, 3f nop -1: sethi %hi(sparc64_ttable_tl0), %o0 +2: sethi %hi(sparc64_ttable_tl0), %o0 set prom_set_trap_table_name, %g2 stx %g2, [%sp + 2047 + 128 + 0x00] mov 1, %g2 @@ -386,7 +392,11 @@ after_lock_tlb: call %o1 add %sp, (2047 + 128), %o0 -2: ldx [%l0], %g6 +3: sethi %hi(prom_entry_lock), %g2 + stb %g0, [%g2 + %lo(prom_entry_lock)] + membar #StoreStore | #StoreLoad + + ldx [%l0], %g6 ldx [%g6 + TI_TASK], %g4 mov 1, %g5 -- cgit v0.10.2 From a1731e5b9aa236dfa51a82799dc91c56611ddaab Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Tue, 21 Oct 2008 21:55:33 -0700 Subject: sparc: correct section of apc_no_idle The latest mainline gives this section mismatch on sparc: The function __devinit apc_probe() references a variable __initdata apc_no_idle. If apc_no_idle is only used by apc_probe then annotate apc_no_idle with a matching annotation. Since the commit 7e7e2f035663c5ceb029bfb9d91e75099b0a5625, apc_probe() is on __devinit so we have to correct apc_no_idle which is referenced by this function. Signed-off-by: Frederic Weisbecker Signed-off-by: David S. Miller diff --git a/arch/sparc/kernel/apc.c b/arch/sparc/kernel/apc.c index 4dd1ba7..9c11582 100644 --- a/arch/sparc/kernel/apc.c +++ b/arch/sparc/kernel/apc.c @@ -31,7 +31,7 @@ #define APC_DEVNAME "apc" static u8 __iomem *regs; -static int apc_no_idle __initdata = 0; +static int apc_no_idle __devinitdata = 0; #define apc_readb(offs) (sbus_readb(regs+offs)) #define apc_writeb(val, offs) (sbus_writeb(val, regs+offs)) -- cgit v0.10.2 From 8dd9453737822469837d48d5da3785ce70fb2118 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Tue, 21 Oct 2008 21:56:42 -0700 Subject: sparc: correct section of current_pc() Latest mainline gives this section mismatch on sparc: The function current_pc() references the variable __init no_sun4u_here. This is often because current_pc lacks a __init annotation or the annotation of no_sun4u_here is wrong. Since current_pc() is used only in early time, it is correct to put it in .init section. Signed-off-by: Frederic Weisbecker Signed-off-by: David S. Miller diff --git a/arch/sparc/kernel/head.S b/arch/sparc/kernel/head.S index 2d325fd..2fe2c11 100644 --- a/arch/sparc/kernel/head.S +++ b/arch/sparc/kernel/head.S @@ -465,6 +465,7 @@ gokernel: mov %o7, %g4 ! Save %o7 /* Jump to it, and pray... */ + __INIT current_pc: call 1f nop -- cgit v0.10.2 From d41e2d7317cd55cc5135356a05c289537b0f6d70 Mon Sep 17 00:00:00 2001 From: Martin Habets Date: Tue, 21 Oct 2008 21:58:29 -0700 Subject: sparc: Add checkstack support Add sparc support to checkstack. Signed-off-by: Martin Habets Signed-off-by: David S. Miller diff --git a/scripts/checkstack.pl b/scripts/checkstack.pl index f7e8e93..14ee68e 100755 --- a/scripts/checkstack.pl +++ b/scripts/checkstack.pl @@ -14,6 +14,7 @@ # M68k port by Geert Uytterhoeven and Andreas Schwab # AVR32 port by Haavard Skinnemoen # PARISC port by Kyle McMartin +# sparc port by Martin Habets # # Usage: # objdump -d vmlinux | scripts/checkstack.pl [arch] @@ -94,6 +95,9 @@ my (@stack, $re, $dre, $x, $xs); } elsif ($arch =~ /^blackfin$/) { # 0: 00 e8 38 01 LINK 0x4e0; $re = qr/.*[[:space:]]LINK[[:space:]]*(0x$x{1,8})/o; + } elsif ($arch eq 'sparc' || $arch eq 'sparc64') { + # f0019d10: 9d e3 bf 90 save %sp, -112, %sp + $re = qr/.*save.*%sp, -(([0-9]{2}|[3-9])[0-9]{2}), %sp/o; } else { print("wrong or unknown architecture \"$arch\"\n"); exit -- cgit v0.10.2 From 930cc144a043ff95e56b6888fa51c618b33f89e7 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Tue, 21 Oct 2008 22:19:00 -0700 Subject: math-emu: Fix signalling of underflow and inexact while packing result. I'm trying to move the powerpc math-emu code to use the include/math-emu bits. In doing so I've been using TestFloat to see how good or bad we are doing. For the most part the current math-emu code that PPC uses has a number of issues that the code in include/math-emu seems to solve (plus bugs we've had for ever that no one every realized). Anyways, I've come across a case that we are flagging underflow and inexact because we think we have a denormalized result from a double precision divide: 000.FFFFFFFFFFFFF / 3FE.FFFFFFFFFFFFE soft: 001.0000000000000 ..... syst: 001.0000000000000 ...ux What it looks like is the results out of FP_DIV_D are: D: sign: 0 mantissa: 01000000 00000000 exp: -1023 (0) The problem seems like we aren't normalizing the result and bumping the exp. Now that I'm digging into this a bit I'm thinking my issue has to do with the fix DaveM put in place from back in Aug 2007 (commit 405849610fd96b4f34cd1875c4c033228fea6c0f): [MATH-EMU]: Fix underflow exception reporting. 2) we ended up rounding back up to normal (this is the case where we set the exponent to 1 and set the fraction to zero), this should set inexact too ... Another example, "0x0.0000000000001p-1022 / 16.0", should signal both inexact and underflow. The cpu implementations and ieee1754 literature is very clear about this. This is case #2 above. Here is the distilled glibc test case from Jakub Jelinek which prompted that commit: -------------------- #include #include #include volatile double d = DBL_MIN; volatile double e = 0x0.0000000000001p-1022; volatile double f = 16.0; int main (void) { printf ("%x\n", fetestexcept (FE_UNDERFLOW)); d /= f; printf ("%x\n", fetestexcept (FE_UNDERFLOW)); e /= f; printf ("%x\n", fetestexcept (FE_UNDERFLOW)); return 0; } -------------------- It looks like the case I have we are exact before rounding, but think it looks like the rounding case since it appears as if "overflow is set". 000.FFFFFFFFFFFFF / 3FE.FFFFFFFFFFFFE = 001.0000000000000 I think the following adds the check for my case and still works for the issue your commit was trying to resolve. Signed-off-by: David S. Miller diff --git a/include/math-emu/op-common.h b/include/math-emu/op-common.h index cc1ec39..bc50aa0 100644 --- a/include/math-emu/op-common.h +++ b/include/math-emu/op-common.h @@ -139,18 +139,27 @@ do { \ if (X##_e <= _FP_WFRACBITS_##fs) \ { \ _FP_FRAC_SRS_##wc(X, X##_e, _FP_WFRACBITS_##fs); \ - _FP_ROUND(wc, X); \ if (_FP_FRAC_HIGH_##fs(X) \ & (_FP_OVERFLOW_##fs >> 1)) \ { \ X##_e = 1; \ _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ - FP_SET_EXCEPTION(FP_EX_INEXACT); \ } \ else \ { \ - X##_e = 0; \ - _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \ + _FP_ROUND(wc, X); \ + if (_FP_FRAC_HIGH_##fs(X) \ + & (_FP_OVERFLOW_##fs >> 1)) \ + { \ + X##_e = 1; \ + _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ + FP_SET_EXCEPTION(FP_EX_INEXACT); \ + } \ + else \ + { \ + X##_e = 0; \ + _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \ + } \ } \ if ((FP_CUR_EXCEPTIONS & FP_EX_INEXACT) || \ (FP_TRAPPING_EXCEPTIONS & FP_EX_UNDERFLOW)) \ -- cgit v0.10.2 From 60b8267338aafde5315fc65ff385f3d4d75eccfe Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 22 Oct 2008 22:09:59 -0700 Subject: math-emu: Fix thinko in _FP_DIV In commit 48d6c64311ddb6417b901639530ccbc47bdc7635 ("math-emu: Add support for reporting exact invalid exception") code was added to set the new FP_EX_INVALID_{IDI,ZDZ} exception flag bits. However there is a missing break statement for the _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF) switch case, the code just falls into _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO) which then proceeds to overwrite all of the settings. Fix by adding the missing break. Signed-off-by: David S. Miller diff --git a/include/math-emu/op-common.h b/include/math-emu/op-common.h index bc50aa0..f456534 100644 --- a/include/math-emu/op-common.h +++ b/include/math-emu/op-common.h @@ -503,6 +503,8 @@ do { \ R##_c = FP_CLS_NAN; \ _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \ FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_IDI);\ + break; \ + \ case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \ R##_s = _FP_NANSIGN_##fs; \ R##_c = FP_CLS_NAN; \ -- cgit v0.10.2