{"id":818140,"url":"http://patchwork.ozlabs.org/api/patches/818140/?format=json","web_url":"http://patchwork.ozlabs.org/project/linux-imx/patch/1506330344-31556-4-git-send-email-vladimir.murzin@arm.com/","project":{"id":19,"url":"http://patchwork.ozlabs.org/api/projects/19/?format=json","name":"Linux IMX development","link_name":"linux-imx","list_id":"linux-imx-kernel.lists.patchwork.ozlabs.org","list_email":"linux-imx-kernel@lists.patchwork.ozlabs.org","web_url":null,"scm_url":null,"webscm_url":null,"list_archive_url":"","list_archive_url_format":"","commit_url_format":""},"msgid":"<1506330344-31556-4-git-send-email-vladimir.murzin@arm.com>","list_archive_url":null,"date":"2017-09-25T09:05:39","name":"[v3,3/8] ARM: NOMMU: Rework MPU to be mostly done in C","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"5d9d60f1749c940eb14975c8133fe97a31c07e31","submitter":{"id":65248,"url":"http://patchwork.ozlabs.org/api/people/65248/?format=json","name":"Vladimir Murzin","email":"vladimir.murzin@arm.com"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/linux-imx/patch/1506330344-31556-4-git-send-email-vladimir.murzin@arm.com/mbox/","series":[{"id":4911,"url":"http://patchwork.ozlabs.org/api/series/4911/?format=json","web_url":"http://patchwork.ozlabs.org/project/linux-imx/list/?series=4911","date":"2017-09-25T09:05:36","name":"ARM: NOMMU: MPU updates","version":3,"mbox":"http://patchwork.ozlabs.org/series/4911/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/818140/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/818140/checks/","tags":{},"related":[],"headers":{"Return-Path":"<linux-arm-kernel-bounces+incoming-imx=patchwork.ozlabs.org@lists.infradead.org>","X-Original-To":"incoming-imx@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming-imx@bilbo.ozlabs.org","Authentication-Results":["ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=lists.infradead.org\n\t(client-ip=65.50.211.133; helo=bombadil.infradead.org;\n\tenvelope-from=linux-arm-kernel-bounces+incoming-imx=patchwork.ozlabs.org@lists.infradead.org;\n\treceiver=<UNKNOWN>)","ozlabs.org; dkim=pass (2048-bit key;\n\tunprotected) header.d=lists.infradead.org\n\theader.i=@lists.infradead.org\n\theader.b=\"QloFmwN9\"; dkim-atps=neutral"],"Received":["from bombadil.infradead.org (bombadil.infradead.org\n\t[65.50.211.133])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3y0yvy3BYBz9tXD\n\tfor <incoming-imx@patchwork.ozlabs.org>;\n\tMon, 25 Sep 2017 19:09:50 +1000 (AEST)","from localhost ([127.0.0.1] helo=bombadil.infradead.org)\n\tby bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux))\n\tid 1dwPOY-0004S5-TI; Mon, 25 Sep 2017 09:09:42 +0000","from usa-sjc-mx-foss1.foss.arm.com ([217.140.101.70]\n\thelo=foss.arm.com)\n\tby bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux))\n\tid 1dwPLP-0001MA-2f for linux-arm-kernel@lists.infradead.org;\n\tMon, 25 Sep 2017 09:06:32 +0000","from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249])\n\tby usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 3EA0F1688;\n\tMon, 25 Sep 2017 02:06:10 -0700 (PDT)","from bc-c11-3-12.euhpc.arm.com. (bc-c11-3-12.euhpc.arm.com\n\t[10.6.2.250])\n\tby usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id\n\tB0DB83F3E1; Mon, 25 Sep 2017 02:06:08 -0700 (PDT)"],"DKIM-Signature":"v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;\n\td=lists.infradead.org; s=bombadil.20170209; h=Sender:\n\tContent-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post:\n\tList-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:\n\tMessage-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description:\n\tResent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:\n\tList-Owner; bh=JWFLZALTXxFFFcNjnOzgBdLebCVjwvq4fX+x9QnKhkw=;\n\tb=QloFmwN9pQUQY+\n\t5JLLPsBU+H1Nop7bYc/XbuMsRGugP5FmkEUC8MSthJ8Mcmkxb7roUh04Ib/adkIFRLaXHPoGlcMf/\n\tMjq9rNsn7QjrPh8uryfaG5EX3qhoLvLqfRr2SO1ZNSDKpTYbZywdENGS9cLLLAo54HsJ+2IP9E/I1\n\tlFxLjkPmosib05INB6l2AsftUu+VU7bQfI+X9EwrJ9tuD0LyYFYFjIv43sU1PZkXsP2dKEBaCQfBf\n\t3B4dtwbJU0wduwzt+OUj1QftCvLAbnQM8bWg9SFTurrt0RM2N8dOMnVvlxXAPP+dYVjhTHoMZPWY6\n\tQ9aYVk/wlGPUN4H+afew==;","From":"Vladimir Murzin <vladimir.murzin@arm.com>","To":"linux-arm-kernel@lists.infradead.org","Subject":"[PATCH v3 3/8] ARM: NOMMU: Rework MPU to be mostly done in C","Date":"Mon, 25 Sep 2017 10:05:39 +0100","Message-Id":"<1506330344-31556-4-git-send-email-vladimir.murzin@arm.com>","X-Mailer":"git-send-email 2.0.0","In-Reply-To":"<1506330344-31556-1-git-send-email-vladimir.murzin@arm.com>","References":"<1506330344-31556-1-git-send-email-vladimir.murzin@arm.com>","MIME-Version":"1.0","X-CRM114-Version":"20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 ","X-CRM114-CacheID":"sfid-20170925_020627_225497_0730EC11 ","X-CRM114-Status":"GOOD (  23.40  )","X-Spam-Score":"-6.9 (------)","X-Spam-Report":"SpamAssassin version 3.4.1 on bombadil.infradead.org summary:\n\tContent analysis details:   (-6.9 points)\n\tpts rule name              description\n\t---- ----------------------\n\t--------------------------------------------------\n\t-5.0 RCVD_IN_DNSWL_HI RBL: Sender listed at http://www.dnswl.org/,\n\thigh trust [217.140.101.70 listed in list.dnswl.org]\n\t-0.0 SPF_PASS               SPF: sender matches SPF record\n\t-0.0 RP_MATCHES_RCVD Envelope sender domain matches handover relay\n\tdomain\n\t-1.9 BAYES_00               BODY: Bayes spam probability is 0 to 1%\n\t[score: 0.0000]","X-BeenThere":"linux-arm-kernel@lists.infradead.org","X-Mailman-Version":"2.1.21","Precedence":"list","List-Unsubscribe":"<http://lists.infradead.org/mailman/options/linux-arm-kernel>,\n\t<mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>","List-Archive":"<http://lists.infradead.org/pipermail/linux-arm-kernel/>","List-Post":"<mailto:linux-arm-kernel@lists.infradead.org>","List-Help":"<mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>","List-Subscribe":"<http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,\n\t<mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>","Cc":"alexandre.torgue@st.com, manabian@gmail.com, linux@armlinux.org.uk,\n\tstefan@agner.ch, kbuild-all@01.org, u.kleine-koenig@pengutronix.de,\n\tsza@esh.hu","Content-Type":"text/plain; charset=\"utf-8\"","Content-Transfer-Encoding":"base64","Sender":"\"linux-arm-kernel\" <linux-arm-kernel-bounces@lists.infradead.org>","Errors-To":"linux-arm-kernel-bounces+incoming-imx=patchwork.ozlabs.org@lists.infradead.org","List-Id":"linux-imx-kernel.lists.patchwork.ozlabs.org"},"content":"Currently, there are several issues with how MPU is setup:\n\n 1. We won't boot if MPU is missing\n 2. We won't boot if use XIP\n 3. Further extension of MPU setup requires asm skills\n\nThe 1st point can be relaxed, so we can continue with boot CPU even if\nMPU is missed and fail boot for secondaries only. To address the 2nd\npoint we could create region covering CONFIG_XIP_PHYS_ADDR - _end and\nthat might work for the first stage of MPU enable, but due to MPU's\nalignment requirement we could cover too much, IOW we need more\nflexibility in how we're partitioning memory regions... and it'd be\nhardly possible to archive because of the 3rd point.\n\nThis patch is trying to address 1st and 3rd issues and paves the path\nfor 2nd and further improvements.\n\nThe most visible change introduced with this patch is that we start\nusing mpu_rgn_info array (as it was supposed?), so change in MPU setup\ndone by boot CPU is recorded there and feed to secondaries. It\nallows us to keep minimal region setup for boot CPU and do the rest in\nC. Since we start programming MPU regions in C evaluation of MPU\nconstrains (number of regions supported and minimal region order) can\nbe done once, which in turn open possibility to free-up \"probe\"\nregion early.\n\nTested-by: Szemző András <sza@esh.hu>\nTested-by: Alexandre TORGUE <alexandre.torgue@st.com>\nSigned-off-by: Vladimir Murzin <vladimir.murzin@arm.com>\n---\n arch/arm/include/asm/mpu.h    |  2 +-\n arch/arm/include/asm/smp.h    |  2 +-\n arch/arm/kernel/asm-offsets.c | 11 ++++++\n arch/arm/kernel/head-nommu.S  | 80 +++++++++++++++++++++++++++++++++----------\n arch/arm/kernel/smp.c         |  2 +-\n arch/arm/mm/pmsa-v7.c         | 70 +++++++++++++++++++++++++++----------\n 6 files changed, 127 insertions(+), 40 deletions(-)","diff":"diff --git a/arch/arm/include/asm/mpu.h b/arch/arm/include/asm/mpu.h\nindex edec5cf..403462e 100644\n--- a/arch/arm/include/asm/mpu.h\n+++ b/arch/arm/include/asm/mpu.h\n@@ -62,7 +62,7 @@ struct mpu_rgn {\n };\n \n struct mpu_rgn_info {\n-\tu32 mpuir;\n+\tunsigned int used;\n \tstruct mpu_rgn rgns[MPU_MAX_REGIONS];\n };\n extern struct mpu_rgn_info mpu_rgn_info;\ndiff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h\nindex 3d6dc8b..709a559 100644\n--- a/arch/arm/include/asm/smp.h\n+++ b/arch/arm/include/asm/smp.h\n@@ -60,7 +60,7 @@\n  */\n struct secondary_data {\n \tunion {\n-\t\tunsigned long mpu_rgn_szr;\n+\t\tstruct mpu_rgn_info *mpu_rgn_info;\n \t\tu64 pgdir;\n \t};\n \tunsigned long swapper_pg_dir;\ndiff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c\nindex 6080082..0098d3c4 100644\n--- a/arch/arm/kernel/asm-offsets.c\n+++ b/arch/arm/kernel/asm-offsets.c\n@@ -23,6 +23,7 @@\n #include <asm/mach/arch.h>\n #include <asm/thread_info.h>\n #include <asm/memory.h>\n+#include <asm/mpu.h>\n #include <asm/procinfo.h>\n #include <asm/suspend.h>\n #include <asm/vdso_datapage.h>\n@@ -183,5 +184,15 @@ int main(void)\n #ifdef CONFIG_VDSO\n   DEFINE(VDSO_DATA_SIZE,\tsizeof(union vdso_data_store));\n #endif\n+  BLANK();\n+#ifdef CONFIG_ARM_MPU\n+  DEFINE(MPU_RNG_INFO_RNGS,\toffsetof(struct mpu_rgn_info, rgns));\n+  DEFINE(MPU_RNG_INFO_USED,\toffsetof(struct mpu_rgn_info, used));\n+\n+  DEFINE(MPU_RNG_SIZE,\t\tsizeof(struct mpu_rgn));\n+  DEFINE(MPU_RGN_DRBAR,\t\toffsetof(struct mpu_rgn, drbar));\n+  DEFINE(MPU_RGN_DRSR,\t\toffsetof(struct mpu_rgn, drsr));\n+  DEFINE(MPU_RGN_DRACR,\t\toffsetof(struct mpu_rgn, dracr));\n+#endif\n   return 0; \n }\ndiff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S\nindex 4b9e8da..f242ae5 100644\n--- a/arch/arm/kernel/head-nommu.S\n+++ b/arch/arm/kernel/head-nommu.S\n@@ -13,6 +13,7 @@\n  */\n #include <linux/linkage.h>\n #include <linux/init.h>\n+#include <linux/errno.h>\n \n #include <asm/assembler.h>\n #include <asm/ptrace.h>\n@@ -131,8 +132,8 @@ ENTRY(secondary_startup)\n \n #ifdef CONFIG_ARM_MPU\n \t/* Use MPU region info supplied by __cpu_up */\n-\tldr\tr6, [r7]\t\t\t@ get secondary_data.mpu_szr\n-\tbl      __setup_mpu\t\t\t@ Initialize the MPU\n+\tldr\tr6, [r7]\t\t\t@ get secondary_data.mpu_rgn_info\n+\tbl      __secondary_setup_mpu\t\t@ Initialize the MPU\n #endif\n \n \tbadr\tlr, 1f\t\t\t\t@ return (PIC) address\n@@ -225,13 +226,13 @@ ENTRY(__setup_mpu)\n \tmrc\tp15, 0, r0, c0, c1, 4\t\t@ Read ID_MMFR0\n \tand\tr0, r0, #(MMFR0_PMSA)\t\t@ PMSA field\n \tteq\tr0, #(MMFR0_PMSAv7)\t\t@ PMSA v7\n-\tbne\t__error_p\t\t\t@ Fail: ARM_MPU on NOT v7 PMSA\n+\tbxne\tlr\n \n \t/* Determine whether the D/I-side memory map is unified. We set the\n \t * flags here and continue to use them for the rest of this function */\n \tmrc\tp15, 0, r0, c0, c0, 4\t\t@ MPUIR\n \tands\tr5, r0, #MPUIR_DREGION_SZMASK\t@ 0 size d region => No MPU\n-\tbeq\t__error_p\t\t\t@ Fail: ARM_MPU and no MPU\n+\tbxeq\tlr\n \ttst\tr0, #MPUIR_nU\t\t\t@ MPUIR_nU = 0 for unified\n \n \t/* Setup second region first to free up r6 */\n@@ -259,27 +260,70 @@ ENTRY(__setup_mpu)\n \tsetup_region r0, r5, r6, MPU_INSTR_SIDE @ 0x0, BG region, enabled\n 2:\tisb\n \n-\t/* Vectors region */\n-\tset_region_nr r0, #MPU_VECTORS_REGION\n+\t/* Enable the MPU */\n+\tmrc\tp15, 0, r0, c1, c0, 0\t\t@ Read SCTLR\n+\tbic\tr0, r0, #CR_BR\t\t\t@ Disable the 'default mem-map'\n+\torr\tr0, r0, #CR_M\t\t\t@ Set SCTRL.M (MPU on)\n+\tmcr\tp15, 0, r0, c1, c0, 0\t\t@ Enable MPU\n+\tisb\n+\n+\tret\tlr\n+ENDPROC(__setup_mpu)\n+\n+#ifdef CONFIG_SMP\n+/*\n+ * r6: pointer at mpu_rgn_info\n+ */\n+\n+ENTRY(__secondary_setup_mpu)\n+\t/* Probe for v7 PMSA compliance */\n+\tmrc\tp15, 0, r0, c0, c1, 4\t\t@ Read ID_MMFR0\n+\tand\tr0, r0, #(MMFR0_PMSA)\t\t@ PMSA field\n+\tteq\tr0, #(MMFR0_PMSAv7)\t\t@ PMSA v7\n+\tbne\t__error_p\n+\n+\t/* Determine whether the D/I-side memory map is unified. We set the\n+\t * flags here and continue to use them for the rest of this function */\n+\tmrc\tp15, 0, r0, c0, c0, 4\t\t@ MPUIR\n+\tands\tr5, r0, #MPUIR_DREGION_SZMASK\t@ 0 size d region => No MPU\n+\tbeq\t__error_p\n+\n+\tldr\tr4, [r6, #MPU_RNG_INFO_USED]\n+\tmov\tr5, #MPU_RNG_SIZE\n+\tadd\tr3, r6, #MPU_RNG_INFO_RNGS\n+\tmla\tr3, r4, r5, r3\n+\n+1:\n+\ttst\tr0, #MPUIR_nU\t\t\t@ MPUIR_nU = 0 for unified\n+\tsub\tr3, r3, #MPU_RNG_SIZE\n+\tsub\tr4, r4, #1\n+\n+\tset_region_nr r0, r4\n \tisb\n-\t/* Shared, inaccessible to PL0, rw PL1 */\n-\tmov\tr0, #CONFIG_VECTORS_BASE\t@ Cover from VECTORS_BASE\n-\tldr\tr5,=(MPU_AP_PL1RW_PL0NA | MPU_RGN_NORMAL)\n-\t/* Writing N to bits 5:1 (RSR_SZ) --> region size 2^N+1 */\n-\tmov\tr6, #(((2 * PAGE_SHIFT - 1) << MPU_RSR_SZ) | 1 << MPU_RSR_EN)\n \n-\tsetup_region r0, r5, r6, MPU_DATA_SIDE\t@ VECTORS_BASE, PL0 NA, enabled\n-\tbeq\t3f\t\t\t\t@ Memory-map not unified\n-\tsetup_region r0, r5, r6, MPU_INSTR_SIDE\t@ VECTORS_BASE, PL0 NA, enabled\n-3:\tisb\n+\tldr\tr0, [r3, #MPU_RGN_DRBAR]\n+\tldr\tr6, [r3, #MPU_RGN_DRSR]\n+\tldr\tr5, [r3, #MPU_RGN_DRACR]\n+\n+\tsetup_region r0, r5, r6, MPU_DATA_SIDE\n+\tbeq\t2f\n+\tsetup_region r0, r5, r6, MPU_INSTR_SIDE\n+2:\tisb\n+\n+\tmrc\tp15, 0, r0, c0, c0, 4\t\t@ Reevaluate the MPUIR\n+\tcmp\tr4, #0\n+\tbgt\t1b\n \n \t/* Enable the MPU */\n \tmrc\tp15, 0, r0, c1, c0, 0\t\t@ Read SCTLR\n-\tbic     r0, r0, #CR_BR\t\t\t@ Disable the 'default mem-map'\n+\tbic\tr0, r0, #CR_BR\t\t\t@ Disable the 'default mem-map'\n \torr\tr0, r0, #CR_M\t\t\t@ Set SCTRL.M (MPU on)\n \tmcr\tp15, 0, r0, c1, c0, 0\t\t@ Enable MPU\n \tisb\n+\n \tret\tlr\n-ENDPROC(__setup_mpu)\n-#endif\n+ENDPROC(__secondary_setup_mpu)\n+\n+#endif /* CONFIG_SMP */\n+#endif /* CONFIG_ARM_MPU */\n #include \"head-common.S\"\ndiff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c\nindex c9a0a52..b4fbf00 100644\n--- a/arch/arm/kernel/smp.c\n+++ b/arch/arm/kernel/smp.c\n@@ -114,7 +114,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)\n \t */\n \tsecondary_data.stack = task_stack_page(idle) + THREAD_START_SP;\n #ifdef CONFIG_ARM_MPU\n-\tsecondary_data.mpu_rgn_szr = mpu_rgn_info.rgns[MPU_RAM_REGION].drsr;\n+\tsecondary_data.mpu_rgn_info = &mpu_rgn_info;\n #endif\n \n #ifdef CONFIG_MMU\ndiff --git a/arch/arm/mm/pmsa-v7.c b/arch/arm/mm/pmsa-v7.c\nindex 5b55f8f..029d204 100644\n--- a/arch/arm/mm/pmsa-v7.c\n+++ b/arch/arm/mm/pmsa-v7.c\n@@ -12,6 +12,9 @@\n \n #include \"mm.h\"\n \n+static unsigned int __initdata mpu_min_region_order;\n+static unsigned int __initdata mpu_max_regions;\n+\n #define DRBAR\t__ACCESS_CP15(c6, 0, c1, 0)\n #define IRBAR\t__ACCESS_CP15(c6, 0, c1, 1)\n #define DRSR\t__ACCESS_CP15(c6, 0, c1, 2)\n@@ -75,6 +78,11 @@ static inline u32 irbar_read(void)\n \treturn read_sysreg(IRBAR);\n }\n \n+static int __init mpu_present(void)\n+{\n+\treturn ((read_cpuid_ext(CPUID_EXT_MMFR0) & MMFR0_PMSA) == MMFR0_PMSAv7);\n+}\n+\n /* MPU initialisation functions */\n void __init adjust_lowmem_bounds_mpu(void)\n {\n@@ -85,6 +93,9 @@ void __init adjust_lowmem_bounds_mpu(void)\n \tphys_addr_t mem_start;\n \tphys_addr_t mem_end;\n \n+\tif (!mpu_present())\n+\t\treturn;\n+\n \tfor_each_memblock(memory, reg) {\n \t\tif (first) {\n \t\t\t/*\n@@ -146,12 +157,7 @@ void __init adjust_lowmem_bounds_mpu(void)\n \n }\n \n-static int mpu_present(void)\n-{\n-\treturn ((read_cpuid_ext(CPUID_EXT_MMFR0) & MMFR0_PMSA) == MMFR0_PMSAv7);\n-}\n-\n-static int mpu_max_regions(void)\n+static int __init __mpu_max_regions(void)\n {\n \t/*\n \t * We don't support a different number of I/D side regions so if we\n@@ -159,6 +165,7 @@ static int mpu_max_regions(void)\n \t * whichever side has a smaller number of supported regions.\n \t */\n \tu32 dregions, iregions, mpuir;\n+\n \tmpuir = read_cpuid(CPUID_MPUIR);\n \n \tdregions = iregions = (mpuir & MPUIR_DREGION_SZMASK) >> MPUIR_DREGION;\n@@ -171,15 +178,16 @@ static int mpu_max_regions(void)\n \treturn min(dregions, iregions);\n }\n \n-static int mpu_iside_independent(void)\n+static int __init mpu_iside_independent(void)\n {\n \t/* MPUIR.nU specifies whether there is *not* a unified memory map */\n \treturn read_cpuid(CPUID_MPUIR) & MPUIR_nU;\n }\n \n-static int mpu_min_region_order(void)\n+static int __init __mpu_min_region_order(void)\n {\n \tu32 drbar_result, irbar_result;\n+\n \t/* We've kept a region free for this probing */\n \trgnr_write(MPU_PROBE_REGION);\n \tisb();\n@@ -198,22 +206,24 @@ static int mpu_min_region_order(void)\n \t}\n \tisb(); /* Ensure that MPU region operations have completed */\n \t/* Return whichever result is larger */\n+\n \treturn __ffs(max(drbar_result, irbar_result));\n }\n \n-static int mpu_setup_region(unsigned int number, phys_addr_t start,\n+static int __init mpu_setup_region(unsigned int number, phys_addr_t start,\n \t\t\tunsigned int size_order, unsigned int properties)\n {\n \tu32 size_data;\n \n \t/* We kept a region free for probing resolution of MPU regions*/\n-\tif (number > mpu_max_regions() || number == MPU_PROBE_REGION)\n+\tif (number > mpu_max_regions\n+\t    || number >= MPU_MAX_REGIONS)\n \t\treturn -ENOENT;\n \n \tif (size_order > 32)\n \t\treturn -ENOMEM;\n \n-\tif (size_order < mpu_min_region_order())\n+\tif (size_order < mpu_min_region_order)\n \t\treturn -ENOMEM;\n \n \t/* Writing N to bits 5:1 (RSR_SZ)  specifies region size 2^N+1 */\n@@ -240,6 +250,9 @@ static int mpu_setup_region(unsigned int number, phys_addr_t start,\n \tmpu_rgn_info.rgns[number].dracr = properties;\n \tmpu_rgn_info.rgns[number].drbar = start;\n \tmpu_rgn_info.rgns[number].drsr = size_data;\n+\n+\tmpu_rgn_info.used++;\n+\n \treturn 0;\n }\n \n@@ -248,19 +261,38 @@ static int mpu_setup_region(unsigned int number, phys_addr_t start,\n */\n void __init mpu_setup(void)\n {\n-\tint region_err;\n+\tint region = 0, err = 0;\n+\n \tif (!mpu_present())\n \t\treturn;\n \n-\tregion_err = mpu_setup_region(MPU_RAM_REGION, PHYS_OFFSET,\n-\t\t\t\t\tilog2(memblock.memory.regions[0].size),\n-\t\t\t\t\tMPU_AP_PL1RW_PL0RW | MPU_RGN_NORMAL);\n-\tif (region_err) {\n-\t\tpanic(\"MPU region initialization failure! %d\", region_err);\n+\t/* Free-up MPU_PROBE_REGION */\n+\tmpu_min_region_order = __mpu_min_region_order();\n+\n+\t/* How many regions are supported */\n+\tmpu_max_regions = __mpu_max_regions();\n+\n+\t/* Now setup MPU (order is important) */\n+\n+\t/* Background */\n+\terr |= mpu_setup_region(region++, 0, 32,\n+\t\t\t\tMPU_ACR_XN | MPU_RGN_STRONGLY_ORDERED | MPU_AP_PL1RW_PL0NA);\n+\n+\t/* RAM */\n+\terr |= mpu_setup_region(region++, PHYS_OFFSET,\n+\t\t\t\tilog2(memblock.memory.regions[0].size),\n+\t\t\t\tMPU_AP_PL1RW_PL0RW | MPU_RGN_NORMAL);\n+\n+\t/* Vectors */\n+\terr |= mpu_setup_region(region++, vectors_base,\n+\t\t\t\tilog2(2 * PAGE_SIZE),\n+\t\t\t\tMPU_AP_PL1RW_PL0NA | MPU_RGN_NORMAL);\n+\tif (err) {\n+\t\tpanic(\"MPU region initialization failure! %d\", err);\n \t} else {\n \t\tpr_info(\"Using ARMv7 PMSA Compliant MPU. \"\n-\t\t\t \"Region independence: %s, Max regions: %d\\n\",\n+\t\t\t \"Region independence: %s, Used %d of %d regions\\n\",\n \t\t\tmpu_iside_independent() ? \"Yes\" : \"No\",\n-\t\t\tmpu_max_regions());\n+\t\t\tmpu_rgn_info.used, mpu_max_regions);\n \t}\n }\n","prefixes":["v3","3/8"]}