Received: by 2002:a05:6a10:8c0a:0:0:0:0 with SMTP id go10csp5027722pxb; Mon, 15 Feb 2021 07:42:27 -0800 (PST) X-Google-Smtp-Source: ABdhPJw6RtA3gnLcdfISxeLP9Wi2Kf1E/+7MUEHvD8QpGWJNbr1BaMj3FTiCd5nzOqlj8jlJjTr2 X-Received: by 2002:a17:907:778e:: with SMTP id ky14mr16162770ejc.154.1613403747441; Mon, 15 Feb 2021 07:42:27 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1613403747; cv=none; d=google.com; s=arc-20160816; b=gw2dDTcBRlGexgMb4DMcC5BvJ0eDEyGYeL8PhBwJw/P5W7TqdWtW1nFtPKSuWDaRtX ZIarptEAbqDOXpUWEJ30pslfmld0VcIb5rUtycGPPdeE9AKbj5fxbl0s5jTughKjt3J4 5jhDWhVcV69rFcUHCKNcuY3S+OG0mVVezgMGHRPtIG4yRmFBhuje9mFaGNDm+F2WhATt pqBsLyjvfQk+7dJl6eMzv56bJYv/uXFtuKWg5hxxP5i7AjZC2TvIaLzHkIvF/BwfW1nm zsryIlEpkkDFO61vHZEzMrfLoNI3QjFRtuQBPFn5ce+a4QZf6CwKOo24P4HIIe6/dOMI 0fig== 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=ZImYEWP/a33LCZwBk6Wg8UeCzoqFvRhSey7yZRUllXI=; b=yT1nYnAIdrHQvPSxqGS31cI+fpZ/Wp4m/ie0XHGuXOFTvqyq9eLudG0UIK5fEt8yNp sGhAmgCUKrlvougCEdTsiogN0doaJrO4VI77Rg5uRXQQilMEqoGZak4RFUaayldtncPz VKCroeosiqnIDrC+M/rKdVvl4fmY23PUpMjnz1bnxSFgjJzhS/xmrWT46zss94jNYa2L xZefiFRDU5U34tD8yGXNFKwknk1g2qp8lutgK0et87o/DyUWJpJj9GMIQeADbDn0yZ5D VkSdDvtU7Eu2EPvqcxz+XRTX4AN3CbvQLGOgwYCh81JtB5DM5OS6SCdI3QcYAg+G/sr4 p5QQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=TgGM9Ebc; 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 ck13si12145683edb.505.2021.02.15.07.42.04; Mon, 15 Feb 2021 07:42:27 -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=TgGM9Ebc; 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 S231588AbhBOPlZ (ORCPT + 99 others); Mon, 15 Feb 2021 10:41:25 -0500 Received: from mail.kernel.org ([198.145.29.99]:45592 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231152AbhBOP3u (ORCPT ); Mon, 15 Feb 2021 10:29:50 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 8E55C64E68; Mon, 15 Feb 2021 15:28:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1613402928; bh=4GnNk/KKLHNVQ7NshEI7wG2P8MTjPMl/1tv4gl/MEbY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=TgGM9EbcQsMS/Z650omAeiRuRGufYcze8ytPbfLetVVC9LPpGYcf6Qs4Y/n3e7uqC VsdkOAj0bivKmADSxsa3TLKinO/s97h/RFE6wr6knBCd9bnADhfiGSv2zjj631rImO u1fcbWFK8P/hoghMWxdLEPRyvUhyx3joYgp6p1uw= 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.4 23/60] ARM: kexec: fix oops after TLB are invalidated Date: Mon, 15 Feb 2021 16:27:11 +0100 Message-Id: <20210215152716.099434750@linuxfoundation.org> X-Mailer: git-send-email 2.30.1 In-Reply-To: <20210215152715.401453874@linuxfoundation.org> References: <20210215152715.401453874@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 --- /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 --- a/arch/arm/kernel/asm-offsets.c +++ b/arch/arm/kernel/asm-offsets.c @@ -15,6 +15,7 @@ #include #endif #include +#include #include #include #include @@ -190,5 +191,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; } --- a/arch/arm/kernel/machine_kexec.c +++ b/arch/arm/kernel/machine_kexec.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -24,11 +25,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; /* @@ -161,6 +157,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; @@ -176,18 +173,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); --- 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