<p>Xiang Wang has uploaded this change for <strong>review</strong>.</p><p><a href="https://review.coreboot.org/28569">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">riscv: add physical memory protection(PMP) support<br><br>Change-Id: I2e9e0c94e6518f63ade7680a3ce68bacfae219d4<br>Signed-off-by: Xiang Wang <wxjstz@126.com><br>---<br>A src/arch/riscv/include/arch/pmp.h<br>A src/arch/riscv/pmp.c<br>2 files changed, 342 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://review.coreboot.org:29418/coreboot refs/changes/69/28569/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/arch/riscv/include/arch/pmp.h b/src/arch/riscv/include/arch/pmp.h</span><br><span>new file mode 100644</span><br><span>index 0000000..bac8e9d</span><br><span>--- /dev/null</span><br><span>+++ b/src/arch/riscv/include/arch/pmp.h</span><br><span>@@ -0,0 +1,30 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * This file is part of the coreboot project.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (C) 2018 HardenedLinux</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; version 2 of the License.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef __RISCV_PMP_H__</span><br><span style="color: hsl(120, 100%, 40%);">+#define __RISCV_PMP_H__</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* this function needs to be implemented by a specific SoC.</span><br><span style="color: hsl(120, 100%, 40%);">+ * return number of pmp entries for current hart */</span><br><span style="color: hsl(120, 100%, 40%);">+extern int pmp_entries_num(void);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* reset PMP setting */</span><br><span style="color: hsl(120, 100%, 40%);">+void reset_pmp(void);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* this function used to setup pmp record */</span><br><span style="color: hsl(120, 100%, 40%);">+void setup_pmp(uintptr_t base, uintptr_t size, uintptr_t flags);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#endif /* __RISCV_PMP_H__ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>diff --git a/src/arch/riscv/pmp.c b/src/arch/riscv/pmp.c</span><br><span>new file mode 100644</span><br><span>index 0000000..c4ee8d3</span><br><span>--- /dev/null</span><br><span>+++ b/src/arch/riscv/pmp.c</span><br><span>@@ -0,0 +1,312 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * This file is part of the coreboot project.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (C) 2018 HardenedLinux</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; version 2 of the License.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <arch/encoding.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdint.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <arch/pmp.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <console/console.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define GRANULE               (1 << PMP_SHIFT)</span><br><span style="color: hsl(120, 100%, 40%);">+#define IS2POW(n)       ((n != 0) && ((n & (n - 1)) == 0))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* This structure is used to temporarily record PMP</span><br><span style="color: hsl(120, 100%, 40%);">+ * configuration information. */</span><br><span style="color: hsl(120, 100%, 40%);">+typedef struct {</span><br><span style="color: hsl(120, 100%, 40%);">+     /* used to record the value of pmpcfg[i] */</span><br><span style="color: hsl(120, 100%, 40%);">+   uintptr_t cfg;</span><br><span style="color: hsl(120, 100%, 40%);">+        /* When generating a TOR type configuration,</span><br><span style="color: hsl(120, 100%, 40%);">+   * the previous entry needs to record the starting address.</span><br><span style="color: hsl(120, 100%, 40%);">+    * used to record the value of pmpaddr[i - 1] */</span><br><span style="color: hsl(120, 100%, 40%);">+      uintptr_t before_address;</span><br><span style="color: hsl(120, 100%, 40%);">+     /* used to record the value of pmpaddr[i] */</span><br><span style="color: hsl(120, 100%, 40%);">+  uintptr_t address;</span><br><span style="color: hsl(120, 100%, 40%);">+} pmpcfg_t;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* This variable is used to record which entries have been used. */</span><br><span style="color: hsl(120, 100%, 40%);">+static uintptr_t pmp_entry_used_mask;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* helper function used to read pmpcfg[idx] */</span><br><span style="color: hsl(120, 100%, 40%);">+static uintptr_t read_pmpcfg(int idx)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+#if __riscv_xlen == 32</span><br><span style="color: hsl(120, 100%, 40%);">+     int shift = 8 * (idx & 3);</span><br><span style="color: hsl(120, 100%, 40%);">+        switch (idx >> 2) {</span><br><span style="color: hsl(120, 100%, 40%);">+     case 0:</span><br><span style="color: hsl(120, 100%, 40%);">+               return (read_csr(pmpcfg0) >> shift) & 0xff;</span><br><span style="color: hsl(120, 100%, 40%);">+ case 1:</span><br><span style="color: hsl(120, 100%, 40%);">+               return (read_csr(pmpcfg1) >> shift) & 0xff;</span><br><span style="color: hsl(120, 100%, 40%);">+ case 2:</span><br><span style="color: hsl(120, 100%, 40%);">+               return (read_csr(pmpcfg2) >> shift) & 0xff;</span><br><span style="color: hsl(120, 100%, 40%);">+ case 3:</span><br><span style="color: hsl(120, 100%, 40%);">+               return (read_csr(pmpcfg3) >> shift) & 0xff;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+#elif __riscv_xlen == 64</span><br><span style="color: hsl(120, 100%, 40%);">+   int shift = 8 * (idx & 7);</span><br><span style="color: hsl(120, 100%, 40%);">+        switch (idx >> 3) {</span><br><span style="color: hsl(120, 100%, 40%);">+     case 0:</span><br><span style="color: hsl(120, 100%, 40%);">+               return (read_csr(pmpcfg0) >> shift) & 0xff;</span><br><span style="color: hsl(120, 100%, 40%);">+ case 1:</span><br><span style="color: hsl(120, 100%, 40%);">+               return (read_csr(pmpcfg2) >> shift) & 0xff;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+     return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* helper function used to write pmpcfg[idx] */</span><br><span style="color: hsl(120, 100%, 40%);">+static void write_pmpcfg(int idx, uintptr_t cfg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       uintptr_t old;</span><br><span style="color: hsl(120, 100%, 40%);">+        uintptr_t new;</span><br><span style="color: hsl(120, 100%, 40%);">+#if __riscv_xlen == 32</span><br><span style="color: hsl(120, 100%, 40%);">+        int shift = 8 * (idx & 3);</span><br><span style="color: hsl(120, 100%, 40%);">+        switch (idx >> 2) {</span><br><span style="color: hsl(120, 100%, 40%);">+     case 0:</span><br><span style="color: hsl(120, 100%, 40%);">+               old = read_csr(pmpcfg0);</span><br><span style="color: hsl(120, 100%, 40%);">+              new = (old & ~(0xff << shift)) | ((cfg & 0xff) << shift);</span><br><span style="color: hsl(120, 100%, 40%);">+         write_csr(pmpcfg0, new);</span><br><span style="color: hsl(120, 100%, 40%);">+              break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case 1:</span><br><span style="color: hsl(120, 100%, 40%);">+               old = read_csr(pmpcfg1);</span><br><span style="color: hsl(120, 100%, 40%);">+              new = (old & ~(0xff << shift)) | ((cfg & 0xff) << shift);</span><br><span style="color: hsl(120, 100%, 40%);">+         write_csr(pmpcfg1, new);</span><br><span style="color: hsl(120, 100%, 40%);">+              break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case 2:</span><br><span style="color: hsl(120, 100%, 40%);">+               old = read_csr(pmpcfg2);</span><br><span style="color: hsl(120, 100%, 40%);">+              new = (old & ~(0xff << shift)) | ((cfg & 0xff) << shift);</span><br><span style="color: hsl(120, 100%, 40%);">+         write_csr(pmpcfg2, new);</span><br><span style="color: hsl(120, 100%, 40%);">+              break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case 3:</span><br><span style="color: hsl(120, 100%, 40%);">+               old = read_csr(pmpcfg3);</span><br><span style="color: hsl(120, 100%, 40%);">+              new = (old & ~(0xff << shift)) | ((cfg & 0xff) << shift);</span><br><span style="color: hsl(120, 100%, 40%);">+         write_csr(pmpcfg3, new);</span><br><span style="color: hsl(120, 100%, 40%);">+              break;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+#elif __riscv_xlen == 64</span><br><span style="color: hsl(120, 100%, 40%);">+   int shift = 8 * (idx & 7);</span><br><span style="color: hsl(120, 100%, 40%);">+        switch (idx >> 3) {</span><br><span style="color: hsl(120, 100%, 40%);">+     case 0:</span><br><span style="color: hsl(120, 100%, 40%);">+               old = read_csr(pmpcfg0);</span><br><span style="color: hsl(120, 100%, 40%);">+              new = (old & ~(0xff << shift)) | ((cfg & 0xff) << shift);</span><br><span style="color: hsl(120, 100%, 40%);">+         write_csr(pmpcfg0, new);</span><br><span style="color: hsl(120, 100%, 40%);">+              break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case 1:</span><br><span style="color: hsl(120, 100%, 40%);">+               old = read_csr(pmpcfg2);</span><br><span style="color: hsl(120, 100%, 40%);">+              new = (old & ~(0xff << shift)) | ((cfg & 0xff) << shift);</span><br><span style="color: hsl(120, 100%, 40%);">+         write_csr(pmpcfg2, new);</span><br><span style="color: hsl(120, 100%, 40%);">+              break;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* helper function used to read pmpaddr[idx] */</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+static uintptr_t read_pmpaddr(int idx)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        switch(idx) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case 0:</span><br><span style="color: hsl(120, 100%, 40%);">+               return read_csr(pmpaddr0);</span><br><span style="color: hsl(120, 100%, 40%);">+    case 1:</span><br><span style="color: hsl(120, 100%, 40%);">+               return read_csr(pmpaddr1);</span><br><span style="color: hsl(120, 100%, 40%);">+    case 2:</span><br><span style="color: hsl(120, 100%, 40%);">+               return read_csr(pmpaddr2);</span><br><span style="color: hsl(120, 100%, 40%);">+    case 3:</span><br><span style="color: hsl(120, 100%, 40%);">+               return read_csr(pmpaddr3);</span><br><span style="color: hsl(120, 100%, 40%);">+    case 4:</span><br><span style="color: hsl(120, 100%, 40%);">+               return read_csr(pmpaddr4);</span><br><span style="color: hsl(120, 100%, 40%);">+    case 5:</span><br><span style="color: hsl(120, 100%, 40%);">+               return read_csr(pmpaddr5);</span><br><span style="color: hsl(120, 100%, 40%);">+    case 6:</span><br><span style="color: hsl(120, 100%, 40%);">+               return read_csr(pmpaddr6);</span><br><span style="color: hsl(120, 100%, 40%);">+    case 7:</span><br><span style="color: hsl(120, 100%, 40%);">+               return read_csr(pmpaddr7);</span><br><span style="color: hsl(120, 100%, 40%);">+    case 8:</span><br><span style="color: hsl(120, 100%, 40%);">+               return read_csr(pmpaddr8);</span><br><span style="color: hsl(120, 100%, 40%);">+    case 9:</span><br><span style="color: hsl(120, 100%, 40%);">+               return read_csr(pmpaddr9);</span><br><span style="color: hsl(120, 100%, 40%);">+    case 10:</span><br><span style="color: hsl(120, 100%, 40%);">+              return read_csr(pmpaddr10);</span><br><span style="color: hsl(120, 100%, 40%);">+   case 11:</span><br><span style="color: hsl(120, 100%, 40%);">+              return read_csr(pmpaddr11);</span><br><span style="color: hsl(120, 100%, 40%);">+   case 12:</span><br><span style="color: hsl(120, 100%, 40%);">+              return read_csr(pmpaddr12);</span><br><span style="color: hsl(120, 100%, 40%);">+   case 13:</span><br><span style="color: hsl(120, 100%, 40%);">+              return read_csr(pmpaddr13);</span><br><span style="color: hsl(120, 100%, 40%);">+   case 14:</span><br><span style="color: hsl(120, 100%, 40%);">+              return read_csr(pmpaddr14);</span><br><span style="color: hsl(120, 100%, 40%);">+   case 15:</span><br><span style="color: hsl(120, 100%, 40%);">+              return read_csr(pmpaddr15);</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+*/</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* helper function used to write pmpaddr[idx] */</span><br><span style="color: hsl(120, 100%, 40%);">+static void write_pmpaddr(int idx, uintptr_t val)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    switch (idx) {</span><br><span style="color: hsl(120, 100%, 40%);">+        case 0:</span><br><span style="color: hsl(120, 100%, 40%);">+               write_csr(pmpaddr0, val);</span><br><span style="color: hsl(120, 100%, 40%);">+             break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case 1:</span><br><span style="color: hsl(120, 100%, 40%);">+               write_csr(pmpaddr1, val);</span><br><span style="color: hsl(120, 100%, 40%);">+             break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case 2:</span><br><span style="color: hsl(120, 100%, 40%);">+               write_csr(pmpaddr2, val);</span><br><span style="color: hsl(120, 100%, 40%);">+             break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case 3:</span><br><span style="color: hsl(120, 100%, 40%);">+               write_csr(pmpaddr3, val);</span><br><span style="color: hsl(120, 100%, 40%);">+             break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case 4:</span><br><span style="color: hsl(120, 100%, 40%);">+               write_csr(pmpaddr4, val);</span><br><span style="color: hsl(120, 100%, 40%);">+             break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case 5:</span><br><span style="color: hsl(120, 100%, 40%);">+               write_csr(pmpaddr5, val);</span><br><span style="color: hsl(120, 100%, 40%);">+             break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case 6:</span><br><span style="color: hsl(120, 100%, 40%);">+               write_csr(pmpaddr6, val);</span><br><span style="color: hsl(120, 100%, 40%);">+             break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case 7:</span><br><span style="color: hsl(120, 100%, 40%);">+               write_csr(pmpaddr7, val);</span><br><span style="color: hsl(120, 100%, 40%);">+             break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case 8:</span><br><span style="color: hsl(120, 100%, 40%);">+               write_csr(pmpaddr8, val);</span><br><span style="color: hsl(120, 100%, 40%);">+             break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case 9:</span><br><span style="color: hsl(120, 100%, 40%);">+               write_csr(pmpaddr9, val);</span><br><span style="color: hsl(120, 100%, 40%);">+             break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case 10:</span><br><span style="color: hsl(120, 100%, 40%);">+              write_csr(pmpaddr10, val);</span><br><span style="color: hsl(120, 100%, 40%);">+            break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case 11:</span><br><span style="color: hsl(120, 100%, 40%);">+              write_csr(pmpaddr11, val);</span><br><span style="color: hsl(120, 100%, 40%);">+            break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case 12:</span><br><span style="color: hsl(120, 100%, 40%);">+              write_csr(pmpaddr12, val);</span><br><span style="color: hsl(120, 100%, 40%);">+            break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case 13:</span><br><span style="color: hsl(120, 100%, 40%);">+              write_csr(pmpaddr13, val);</span><br><span style="color: hsl(120, 100%, 40%);">+            break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case 14:</span><br><span style="color: hsl(120, 100%, 40%);">+              write_csr(pmpaddr14, val);</span><br><span style="color: hsl(120, 100%, 40%);">+            break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case 15:</span><br><span style="color: hsl(120, 100%, 40%);">+              write_csr(pmpaddr15, val);</span><br><span style="color: hsl(120, 100%, 40%);">+            break;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Generate a pmp configuration of type NA4/NAPOT */</span><br><span style="color: hsl(120, 100%, 40%);">+static pmpcfg_t generate_pmp_napot(</span><br><span style="color: hsl(120, 100%, 40%);">+           uintptr_t base, uintptr_t size, uintptr_t flags)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   pmpcfg_t p;</span><br><span style="color: hsl(120, 100%, 40%);">+   flags = flags & (PMP_R | PMP_W | PMP_X | PMP_L);</span><br><span style="color: hsl(120, 100%, 40%);">+  p.cfg = flags | (size > GRANULE ? PMP_NAPOT : PMP_NA4);</span><br><span style="color: hsl(120, 100%, 40%);">+    p.before_address = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ p.address = (base + (size / 2 - 1)) >> PMP_SHIFT;</span><br><span style="color: hsl(120, 100%, 40%);">+       return p;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Generate a pmp configuration of type TOR */</span><br><span style="color: hsl(120, 100%, 40%);">+static pmpcfg_t generate_pmp_range(</span><br><span style="color: hsl(120, 100%, 40%);">+         uintptr_t base, uintptr_t size, uintptr_t flags)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   pmpcfg_t p;</span><br><span style="color: hsl(120, 100%, 40%);">+   flags = flags & (PMP_R | PMP_W | PMP_X | PMP_L);</span><br><span style="color: hsl(120, 100%, 40%);">+  p.cfg = flags | PMP_TOR;</span><br><span style="color: hsl(120, 100%, 40%);">+      p.before_address = base >> PMP_SHIFT;</span><br><span style="color: hsl(120, 100%, 40%);">+   p.address = (base + size) >> PMP_SHIFT;</span><br><span style="color: hsl(120, 100%, 40%);">+ return p;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Generate a pmp configuration */</span><br><span style="color: hsl(120, 100%, 40%);">+static pmpcfg_t generate_pmp(uintptr_t base, uintptr_t size, uintptr_t flags)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        if (IS2POW(size) && (size >= 4) && ((base & (size - 1)) == 0))</span><br><span style="color: hsl(120, 100%, 40%);">+         return generate_pmp_napot(base, size, flags);</span><br><span style="color: hsl(120, 100%, 40%);">+ else</span><br><span style="color: hsl(120, 100%, 40%);">+          return generate_pmp_range(base, size, flags);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* find empty pmp entry by type</span><br><span style="color: hsl(120, 100%, 40%);">+ * TOR type configuration requires two consecutive PMP entries,</span><br><span style="color: hsl(120, 100%, 40%);">+ * others requires one. */</span><br><span style="color: hsl(120, 100%, 40%);">+static int find_empty_pmp_entry(int is_range)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        int status = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+       for (int i = 0; i < pmp_entries_num(); i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+              if (pmp_entry_used_mask & (1 << i))</span><br><span style="color: hsl(120, 100%, 40%);">+                 status = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+           else</span><br><span style="color: hsl(120, 100%, 40%);">+                  status++;</span><br><span style="color: hsl(120, 100%, 40%);">+             if (is_range && (status == 2))</span><br><span style="color: hsl(120, 100%, 40%);">+                        return i;</span><br><span style="color: hsl(120, 100%, 40%);">+             if (!is_range && (status == 1))</span><br><span style="color: hsl(120, 100%, 40%);">+                       return i;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+     die("Too many pmp configurations, no free entries can be used!");</span><br><span style="color: hsl(120, 100%, 40%);">+   return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* mark pmp entry has be used</span><br><span style="color: hsl(120, 100%, 40%);">+ * this function need be used with find_entry_pmp_entry</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *   n = find_empty_pmp_entry(is_range)</span><br><span style="color: hsl(120, 100%, 40%);">+ *   ... // pmp set operate</span><br><span style="color: hsl(120, 100%, 40%);">+ *   mask_pmp_entry_used(n, is_range);</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static void mask_pmp_entry_used(int idx, int is_range)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     pmp_entry_used_mask |= 1 << idx;</span><br><span style="color: hsl(120, 100%, 40%);">+        if (is_range)</span><br><span style="color: hsl(120, 100%, 40%);">+         pmp_entry_used_mask |= 1 << (idx - 1);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* reset PMP setting */</span><br><span style="color: hsl(120, 100%, 40%);">+void reset_pmp(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   for (int i = 0; i < pmp_entries_num(); i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+              if (read_pmpcfg(i) & PMP_L)</span><br><span style="color: hsl(120, 100%, 40%);">+                       die("Some PMP configurations are locked "</span><br><span style="color: hsl(120, 100%, 40%);">+                                   "and cannot be reset!");</span><br><span style="color: hsl(120, 100%, 40%);">+            write_pmpcfg(i, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+           write_pmpaddr(i, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* this function used to setup pmp record */</span><br><span style="color: hsl(120, 100%, 40%);">+void setup_pmp(uintptr_t base, uintptr_t size, uintptr_t flags)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      pmpcfg_t p;</span><br><span style="color: hsl(120, 100%, 40%);">+   int is_range, n;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    p = generate_pmp(base, size, flags);</span><br><span style="color: hsl(120, 100%, 40%);">+  is_range = ((p.cfg & PMP_A) == PMP_TOR);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        n = find_empty_pmp_entry(is_range);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ write_pmpaddr(n, p.address);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (is_range)</span><br><span style="color: hsl(120, 100%, 40%);">+         write_pmpaddr(n - 1, p.before_address);</span><br><span style="color: hsl(120, 100%, 40%);">+       write_pmpcfg(n, p.cfg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     mask_pmp_entry_used(n, is_range);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span></span><br></pre><p>To view, visit <a href="https://review.coreboot.org/28569">change 28569</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://review.coreboot.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://review.coreboot.org/28569"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: coreboot </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I2e9e0c94e6518f63ade7680a3ce68bacfae219d4 </div>
<div style="display:none"> Gerrit-Change-Number: 28569 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Xiang Wang <wxjstz@126.com> </div>