Received: by 2002:a05:6a10:8c0a:0:0:0:0 with SMTP id go10csp5070620pxb; Mon, 15 Feb 2021 08:44:29 -0800 (PST) X-Google-Smtp-Source: ABdhPJx00QL3ESQL+shkIrmYdhy7cwXM0rOLgWUw/eblghbI7ZLNtKfVpYR0wjQYE0OhhyYt9wIO X-Received: by 2002:a17:907:d21:: with SMTP id gn33mr5284041ejc.242.1613407466979; Mon, 15 Feb 2021 08:44:26 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1613407466; cv=none; d=google.com; s=arc-20160816; b=PHOwu8aBpOKUWiKT2XajnxFQo9XdUBVY2x/FPz+6/X20bJ370Y3rUri/n0nG1TsmA3 2RB4fpYBQgwYtWcmNuCnnBRDxXRv4Z3lt420oNGwozaJBj7GsuclB3zpMYG4brb0dpfb oAcH0rJ/DrRIDcjmNBVWV3LtW/m/ZT0ZNtB5gmOwwQ/TlJwdY849LwP5AUQvrcmIyjMw njPlr5/6VaejoUS3vB0zezq2F3l2Ze9FiDTu0NVS79UTbzniW20u5K8wQ1s7UuiM5e57 wC0Jv1zpfJsQKDPEnsuN63tKDOQBiUALaElE+yyDWfns67EyfXfMvSCqrbX3f9/8qa4f TUTA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=xAUfJ5P43L74CNfOG2FPyf79XDdyMoeemSWzQCtYJrI=; b=E4ulrywRZskIuRV/F7AuiIIQh6mcUT+XabQBN2s94C2UzqSScDKLf7ZHTEuRGHfjv6 elclM7wRbQ2VXttIm4u/3Udc1K9oPr3aIfrbqixu1Zt2bF/cMZ9FLCroERqfEUP/lNEQ sALzgMn5u8t70nvRH7JCyAFHSRIOBrqNthtaT3S7R6PdpRHe5gITOn1MwkWRy4L0cuJ1 mCX7nvmLuuGPLwv1FfhO5kp6p9u6r32S+99tZ9vOs25VvqK/lZl+wdmQxUnGc+z0fVeB 4Wsf7D53Icq/Etay+4rt/dp/8Bb3IM7Q1tGVXpUbsDwm4N2Ml8HJzB7kTXKwoVqiJyn/ BuyA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b="A/jR1HQn"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id jz3si12087494ejc.700.2021.02.15.08.44.02; Mon, 15 Feb 2021 08:44:26 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b="A/jR1HQn"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231982AbhBOQnA (ORCPT + 99 others); Mon, 15 Feb 2021 11:43:00 -0500 Received: from mail.kernel.org ([198.145.29.99]:49202 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231592AbhBOPiE (ORCPT ); Mon, 15 Feb 2021 10:38:04 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id C751864EA6; Mon, 15 Feb 2021 15:33:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1613403233; bh=KqdBtz4ottQ7UIvyckd2fMKx7JZ7EDOeuUQjGaqDG/A=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=A/jR1HQnmxFPBRbofUWEGsb4Z86VOJspGo0niGdkK3GO+2xZCUUueuCrtIJfLqm/D hVSc36XvxCdKX5Xj0Y0zwZGcKgP9pL/2ltM8WClrSKAJojQvBkAeJkai5h9Guhtep+ TnNCEMKzs4v7oIivwffD6IjN1jDJnv8YXszS4w1M= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Giancarlo Ferrari , Russell King , Sasha Levin Subject: [PATCH 5.10 042/104] ARM: kexec: fix oops after TLB are invalidated Date: Mon, 15 Feb 2021 16:26:55 +0100 Message-Id: <20210215152720.831687013@linuxfoundation.org> X-Mailer: git-send-email 2.30.1 In-Reply-To: <20210215152719.459796636@linuxfoundation.org> References: <20210215152719.459796636@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Russell King [ Upstream commit 4d62e81b60d4025e2dfcd5ea531cc1394ce9226f ] Giancarlo Ferrari reports the following oops while trying to use kexec: Unable to handle kernel paging request at virtual address 80112f38 pgd = fd7ef03e [80112f38] *pgd=0001141e(bad) Internal error: Oops: 80d [#1] PREEMPT SMP ARM ... This is caused by machine_kexec() trying to set the kernel text to be read/write, so it can poke values into the relocation code before copying it - and an interrupt occuring which changes the page tables. The subsequent writes then hit read-only sections that trigger a data abort resulting in the above oops. Fix this by copying the relocation code, and then writing the variables into the destination, thereby avoiding the need to make the kernel text read/write. Reported-by: Giancarlo Ferrari Tested-by: Giancarlo Ferrari Signed-off-by: Russell King Signed-off-by: Sasha Levin --- arch/arm/include/asm/kexec-internal.h | 12 +++++++++ arch/arm/kernel/asm-offsets.c | 5 ++++ arch/arm/kernel/machine_kexec.c | 20 ++++++-------- arch/arm/kernel/relocate_kernel.S | 38 ++++++++------------------- 4 files changed, 36 insertions(+), 39 deletions(-) create mode 100644 arch/arm/include/asm/kexec-internal.h diff --git a/arch/arm/include/asm/kexec-internal.h b/arch/arm/include/asm/kexec-internal.h new file mode 100644 index 0000000000000..ecc2322db7aa1 --- /dev/null +++ b/arch/arm/include/asm/kexec-internal.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ARM_KEXEC_INTERNAL_H +#define _ARM_KEXEC_INTERNAL_H + +struct kexec_relocate_data { + unsigned long kexec_start_address; + unsigned long kexec_indirection_page; + unsigned long kexec_mach_type; + unsigned long kexec_r2; +}; + +#endif diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c index a1570c8bab25a..be8050b0c3dfb 100644 --- a/arch/arm/kernel/asm-offsets.c +++ b/arch/arm/kernel/asm-offsets.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -170,5 +171,9 @@ int main(void) DEFINE(MPU_RGN_PRBAR, offsetof(struct mpu_rgn, prbar)); DEFINE(MPU_RGN_PRLAR, offsetof(struct mpu_rgn, prlar)); #endif + DEFINE(KEXEC_START_ADDR, offsetof(struct kexec_relocate_data, kexec_start_address)); + DEFINE(KEXEC_INDIR_PAGE, offsetof(struct kexec_relocate_data, kexec_indirection_page)); + DEFINE(KEXEC_MACH_TYPE, offsetof(struct kexec_relocate_data, kexec_mach_type)); + DEFINE(KEXEC_R2, offsetof(struct kexec_relocate_data, kexec_r2)); return 0; } diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c index 5d84ad333f050..2b09dad7935eb 100644 --- a/arch/arm/kernel/machine_kexec.c +++ b/arch/arm/kernel/machine_kexec.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -22,11 +23,6 @@ extern void relocate_new_kernel(void); extern const unsigned int relocate_new_kernel_size; -extern unsigned long kexec_start_address; -extern unsigned long kexec_indirection_page; -extern unsigned long kexec_mach_type; -extern unsigned long kexec_boot_atags; - static atomic_t waiting_for_crash_ipi; /* @@ -159,6 +155,7 @@ void (*kexec_reinit)(void); void machine_kexec(struct kimage *image) { unsigned long page_list, reboot_entry_phys; + struct kexec_relocate_data *data; void (*reboot_entry)(void); void *reboot_code_buffer; @@ -174,18 +171,17 @@ void machine_kexec(struct kimage *image) reboot_code_buffer = page_address(image->control_code_page); - /* Prepare parameters for reboot_code_buffer*/ - set_kernel_text_rw(); - kexec_start_address = image->start; - kexec_indirection_page = page_list; - kexec_mach_type = machine_arch_type; - kexec_boot_atags = image->arch.kernel_r2; - /* copy our kernel relocation code to the control code page */ reboot_entry = fncpy(reboot_code_buffer, &relocate_new_kernel, relocate_new_kernel_size); + data = reboot_code_buffer + relocate_new_kernel_size; + data->kexec_start_address = image->start; + data->kexec_indirection_page = page_list; + data->kexec_mach_type = machine_arch_type; + data->kexec_r2 = image->arch.kernel_r2; + /* get the identity mapping physical address for the reboot code */ reboot_entry_phys = virt_to_idmap(reboot_entry); diff --git a/arch/arm/kernel/relocate_kernel.S b/arch/arm/kernel/relocate_kernel.S index 72a08786e16eb..218d524360fcd 100644 --- a/arch/arm/kernel/relocate_kernel.S +++ b/arch/arm/kernel/relocate_kernel.S @@ -5,14 +5,16 @@ #include #include +#include #include .align 3 /* not needed for this code, but keeps fncpy() happy */ ENTRY(relocate_new_kernel) - ldr r0,kexec_indirection_page - ldr r1,kexec_start_address + adr r7, relocate_new_kernel_end + ldr r0, [r7, #KEXEC_INDIR_PAGE] + ldr r1, [r7, #KEXEC_START_ADDR] /* * If there is no indirection page (we are doing crashdumps) @@ -57,34 +59,16 @@ ENTRY(relocate_new_kernel) 2: /* Jump to relocated kernel */ - mov lr,r1 - mov r0,#0 - ldr r1,kexec_mach_type - ldr r2,kexec_boot_atags - ARM( ret lr ) - THUMB( bx lr ) - - .align - - .globl kexec_start_address -kexec_start_address: - .long 0x0 - - .globl kexec_indirection_page -kexec_indirection_page: - .long 0x0 - - .globl kexec_mach_type -kexec_mach_type: - .long 0x0 - - /* phy addr of the atags for the new kernel */ - .globl kexec_boot_atags -kexec_boot_atags: - .long 0x0 + mov lr, r1 + mov r0, #0 + ldr r1, [r7, #KEXEC_MACH_TYPE] + ldr r2, [r7, #KEXEC_R2] + ARM( ret lr ) + THUMB( bx lr ) ENDPROC(relocate_new_kernel) + .align 3 relocate_new_kernel_end: .globl relocate_new_kernel_size -- 2.27.0