From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gate.crashing.org (gate.crashing.org [63.228.1.57]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 1C12A2C0095 for ; Wed, 5 Sep 2012 11:08:47 +1000 (EST) Message-ID: <1346807308.2257.14.camel@pasglop> Subject: Re: 3.5+: yaboot, Invalid memory access From: Benjamin Herrenschmidt To: Christian Kujau Date: Wed, 05 Sep 2012 11:08:28 +1000 In-Reply-To: References: <1346741491.7619.12.camel@concordia> Content-Type: text/plain; charset="UTF-8" Mime-Version: 1.0 Cc: linuxppc-dev@ozlabs.org, Steven Rostedt List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , On Tue, 2012-09-04 at 02:32 -0700, Christian Kujau wrote: > On Tue, 4 Sep 2012 at 16:51, Michael Ellerman wrote: > > My guess would be we're calling that quite early and the __put_user() > > check is getting confused and failing. That means we'll have left some > > code unpatched, which then fails. > > > > Can you try with the patch applied, but instead of returning if the > > __put_user() fails, just continue on anyway. > > You mean, like this? Try this: powerpc: Don't use __put_user() in patch_instruction patch_instruction() can be called very early on ppc32, when the kernel isn't yet running at it's linked address. That can cause the ! is_kernel_addr() test in __put_user() to trip and call might_sleep() which is very bad at that point during boot. Use a lower level function instead for now, at least until we get to rework ppc32 boot process to do the code patching later, like ppc64 does. Signed-off-by: Benjamin Herrenschmidt --- diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c index dd223b3..17e5b23 100644 --- a/arch/powerpc/lib/code-patching.c +++ b/arch/powerpc/lib/code-patching.c @@ -20,7 +20,7 @@ int patch_instruction(unsigned int *addr, unsigned int instr) { int err; - err = __put_user(instr, addr); + __put_user_size(instr, addr, 4, err); if (err) return err; asm ("dcbst 0, %0; sync; icbi 0,%0; sync; isync" : : "r" (addr));