Received: by 2002:a05:6a10:8c0a:0:0:0:0 with SMTP id go10csp318301pxb; Sat, 6 Mar 2021 00:35:31 -0800 (PST) X-Google-Smtp-Source: ABdhPJxnOdWOUWtQHFeb9QLdaoCx2YJOWJlNcga/jBba7JE0XlS/1Xm74UqAnEJ58bppoDCEv3Ce X-Received: by 2002:a50:f9c8:: with SMTP id a8mr12981737edq.270.1615019731665; Sat, 06 Mar 2021 00:35:31 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1615019731; cv=none; d=google.com; s=arc-20160816; b=rVmAttZaG0RLm9z5b/PiXflC+WADeVQ6L5txlu5oD/z6kEVV/nSjEvddXZRLR97FXd 3XTy7baWcVlPCRNAGg0N0VuUxb8QU9cnsLFmDb7PFJvkvMtTXk5tekdjBVns4fZW4gAJ OqEFVVdpCbXY5JLo0wAKaaSvyx+iJ4Bn3YtjjZE6T8UstJXFxq2/Nk7pId8BlJepfCmb 8RhkEOh3xCi54fFdxJScwSrGPkgL1hNnokJLB+MYmGASNTu7oROwIM4cUncCJ46Zl4g1 /mJR3qCZdqMCxzopsLkfl64H+gaNDxDCHP8gyH2Zis/vo40y8BtjeWo6sQav1tkhdJBZ 9NUA== 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 :message-id:date:subject:cc:to:from; bh=Qe13m8nMImYaIQN0xzryiWUz50N/gqF2z7u2armTAGk=; b=GDv9Bkn3VrALu6if1LCJ4s2jK4lse1vJTX3rseLldNfGmLqtJGAdsxF9VaaAbhkZUM Ulag/qDR2wZzQt+FRQXgtxH6yDoUNLouUMzMNkk2FjT4J8bEGfOk9QucpvPOV4RZ8hGh DQKD3dKq0nFF10V/32XXVFiVoUF8KnfH+fIY2SqMkQ/ZGGgjHUk3PflDQOOqE6s83bXY 8Fb2UfH7zbI887ItT0sZeq9PzPgjVdkKQ8eeqdCkgBIOy90JcaUzidkEuoDVUTHB+Bki dVJl+s7OxRMBbkgL2DO518mHnbUoM9Izs194jBoUR8nKtgvVoncPRoj/UG95YvQZkUDX 1dMg== ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id e6si3093869edv.313.2021.03.06.00.35.06; Sat, 06 Mar 2021 00:35:31 -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; 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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229881AbhCFI3e (ORCPT + 99 others); Sat, 6 Mar 2021 03:29:34 -0500 Received: from mx2.suse.de ([195.135.220.15]:49074 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229626AbhCFI3R (ORCPT ); Sat, 6 Mar 2021 03:29:17 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id A7D57AC54; Sat, 6 Mar 2021 08:29:15 +0000 (UTC) From: Thomas Bogendoerfer To: Mike Rapoport , Andrew Morton , Roman Gushchin , linux-mips@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Kamal Dasu , Serge Semin Subject: [PATCH v2] MIPS: kernel: Reserve exception base early to prevent corruption Date: Sat, 6 Mar 2021 09:29:09 +0100 Message-Id: <20210306082910.3472-1-tsbogend@alpha.franken.de> X-Mailer: git-send-email 2.29.2 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org BMIPS is one of the few platforms that do change the exception base. After commit 2dcb39645441 ("memblock: do not start bottom-up allocations with kernel_end") we started seeing BMIPS boards fail to boot with the built-in FDT being corrupted. Before the cited commit, early allocations would be in the [kernel_end, RAM_END] range, but after commit they would be within [RAM_START + PAGE_SIZE, RAM_END]. The custom exception base handler that is installed by bmips_ebase_setup() done for BMIPS5000 CPUs ends-up trampling on the memory region allocated by unflatten_and_copy_device_tree() thus corrupting the FDT used by the kernel. To fix this, we need to perform an early reservation of the custom exception space. So we reserve it already in cpu_probe() for the CPUs where this is fixed. For CPU with an ebase config register allocation of exception space will be done in trap_init(). Huge thanks to Serget for analysing and proposing a solution to this issue. Fixes: 2dcb39645441 ("memblock: do not start bottom-up allocations with kernel_end") Reported-by: Kamal Dasu Debugged-by: Serge Semin Signed-off-by: Thomas Bogendoerfer --- Changes in v2: - do only memblock reservation in reserve_exception_space() - reserve 0..0x400 for all CPUs without ebase register and to addtional reserve_exception_space for BMIPS CPUs arch/mips/include/asm/traps.h | 3 +++ arch/mips/kernel/cpu-probe.c | 7 +++++++ arch/mips/kernel/cpu-r3k-probe.c | 3 +++ arch/mips/kernel/traps.c | 10 +++++----- 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/arch/mips/include/asm/traps.h b/arch/mips/include/asm/traps.h index 6aa8f126a43d..b710e76c9c65 100644 --- a/arch/mips/include/asm/traps.h +++ b/arch/mips/include/asm/traps.h @@ -24,8 +24,11 @@ extern void (*board_ebase_setup)(void); extern void (*board_cache_error_setup)(void); extern int register_nmi_notifier(struct notifier_block *nb); +extern void reserve_exception_space(phys_addr_t addr, unsigned long size); extern char except_vec_nmi[]; +#define VECTORSPACING 0x100 /* for EI/VI mode */ + #define nmi_notifier(fn, pri) \ ({ \ static struct notifier_block fn##_nb = { \ diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 9a89637b4ecf..b565bc4b900d 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include "fpu-probe.h" @@ -1628,6 +1629,7 @@ static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu) c->cputype = CPU_BMIPS3300; __cpu_name[cpu] = "Broadcom BMIPS3300"; set_elf_platform(cpu, "bmips3300"); + reserve_exception_space(0x400, VECTORSPACING * 64); break; case PRID_IMP_BMIPS43XX: { int rev = c->processor_id & PRID_REV_MASK; @@ -1638,6 +1640,7 @@ static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu) __cpu_name[cpu] = "Broadcom BMIPS4380"; set_elf_platform(cpu, "bmips4380"); c->options |= MIPS_CPU_RIXI; + reserve_exception_space(0x400, VECTORSPACING * 64); } else { c->cputype = CPU_BMIPS4350; __cpu_name[cpu] = "Broadcom BMIPS4350"; @@ -1654,6 +1657,7 @@ static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu) __cpu_name[cpu] = "Broadcom BMIPS5000"; set_elf_platform(cpu, "bmips5000"); c->options |= MIPS_CPU_ULRI | MIPS_CPU_RIXI; + reserve_exception_space(0x1000, VECTORSPACING * 64); break; } } @@ -2133,6 +2137,9 @@ void cpu_probe(void) if (cpu == 0) __ua_limit = ~((1ull << cpu_vmbits) - 1); #endif + + if (cpu_has_mips_r2_r6) + reserve_exception_space(0, 0x400); } void cpu_report(void) diff --git a/arch/mips/kernel/cpu-r3k-probe.c b/arch/mips/kernel/cpu-r3k-probe.c index abdbbe8c5a43..af654771918c 100644 --- a/arch/mips/kernel/cpu-r3k-probe.c +++ b/arch/mips/kernel/cpu-r3k-probe.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "fpu-probe.h" @@ -158,6 +159,8 @@ void cpu_probe(void) cpu_set_fpu_opts(c); else cpu_set_nofpu_opts(c); + + reserve_exception_space(0, 0x400); } void cpu_report(void) diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index e0352958e2f7..808b8b61ded1 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -2009,13 +2009,16 @@ void __noreturn nmi_exception_handler(struct pt_regs *regs) nmi_exit(); } -#define VECTORSPACING 0x100 /* for EI/VI mode */ - unsigned long ebase; EXPORT_SYMBOL_GPL(ebase); unsigned long exception_handlers[32]; unsigned long vi_handlers[64]; +void reserve_exception_space(phys_addr_t addr, unsigned long size) +{ + memblock_reserve(addr, size); +} + void __init *set_except_vector(int n, void *addr) { unsigned long handler = (unsigned long) addr; @@ -2367,10 +2370,7 @@ void __init trap_init(void) if (!cpu_has_mips_r2_r6) { ebase = CAC_BASE; - ebase_pa = virt_to_phys((void *)ebase); vec_size = 0x400; - - memblock_reserve(ebase_pa, vec_size); } else { if (cpu_has_veic || cpu_has_vint) vec_size = 0x200 + VECTORSPACING*64; -- 2.29.2