From 3cc620e986a09a433d6913f88ea2e89b23f27fb9 Mon Sep 17 00:00:00 2001 From: Gregor Haas Date: Mon, 10 Jun 2024 11:31:13 -0700 Subject: [PATCH 1/3] Remove old smm/osm management functions --- sm/src/sm.c | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/sm/src/sm.c b/sm/src/sm.c index fd7b11742..0b2a25c15 100644 --- a/sm/src/sm.c +++ b/sm/src/sm.c @@ -31,32 +31,6 @@ byte sm_public_key[PUBLIC_KEY_SIZE] = { 0, }; byte sm_private_key[PRIVATE_KEY_SIZE] = { 0, }; byte dev_public_key[PUBLIC_KEY_SIZE] = { 0, }; -int osm_pmp_set(uint8_t perm) -{ - /* in case of OSM, PMP cfg is exactly the opposite.*/ - return pmp_set_keystone(os_region_id, perm); -} - -static int smm_init(void) -{ - int region = -1; - int ret = pmp_region_init_atomic(SMM_BASE, SMM_SIZE, PMP_PRI_TOP, ®ion, 0); - if(ret) - return -1; - - return region; -} - -static int osm_init(void) -{ - int region = -1; - int ret = pmp_region_init_atomic(0, -1UL, PMP_PRI_BOTTOM, ®ion, 1); - if(ret) - return -1; - - return region; -} - void sm_sign(void* signature, const void* data, size_t len) { sign(signature, data, len, sm_public_key, sm_private_key); From 56524c0eb4aa740a4e9d9c439ad6f2466b2941aa Mon Sep 17 00:00:00 2001 From: Gregor Haas Date: Mon, 10 Jun 2024 12:53:12 -0700 Subject: [PATCH 2/3] Move sbi-lpmp.c -> lpmp.c and fix 32 bit build --- .../patches/opensbi/opensbi-lpmp.patch | 121 +------------ sm/src/lpmp.c | 166 +++++++++++++++--- sm/src/lpmp.h | 52 +----- 3 files changed, 149 insertions(+), 190 deletions(-) diff --git a/overlays/keystone/patches/opensbi/opensbi-lpmp.patch b/overlays/keystone/patches/opensbi/opensbi-lpmp.patch index aee2bdd58..41a401344 100644 --- a/overlays/keystone/patches/opensbi/opensbi-lpmp.patch +++ b/overlays/keystone/patches/opensbi/opensbi-lpmp.patch @@ -1,129 +1,12 @@ -diff --git a/include/sbi/sbi_lpmp.h b/include/sbi/sbi_lpmp.h -new file mode 100644 -index 0000000..d56ad96 ---- /dev/null -+++ b/include/sbi/sbi_lpmp.h -@@ -0,0 +1,21 @@ -+#ifndef __SBI_LPMP_H__ -+#define __SBI_LPMP_H__ -+ -+#define PTE_V (1L << 0) -+#define PTE_R (1L << 1) -+#define PTE_W (1L << 2) -+#define PTE_X (1L << 3) -+ -+#define PPNSHIFT 9 -+#define PGSHIFT 12 -+#define PTE2PA(pte) (((pte) >> 10) << 12) -+#define PXMASK 0x1FF // 9 bits -+#define PXSHIFT(level) (PGSHIFT + (9 * (level))) -+#define PX(level, va) ((((uint64_t)(va)) >> PXSHIFT(level)) & PXMASK) -+ -+typedef uint64_t *pagetable_t; -+typedef uint64_t pte_t; -+ -+int pmp_fault_handler(ulong mtval); -+ -+#endif -diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk -index 1ed1983..9bdc555 100644 ---- a/lib/sbi/objects.mk -+++ b/lib/sbi/objects.mk -@@ -44,3 +44,4 @@ libsbi-objs-y += sbi_tlb.o - libsbi-objs-y += sbi_trap.o - libsbi-objs-y += sbi_unpriv.o - libsbi-objs-y += sbi_expected_trap.o -+libsbi-objs-y += sbi_lpmp.o -diff --git a/lib/sbi/sbi_lpmp.c b/lib/sbi/sbi_lpmp.c -new file mode 100644 -index 0000000..35837e3 ---- /dev/null -+++ b/lib/sbi/sbi_lpmp.c -@@ -0,0 +1,75 @@ -+#include "lpmp.h" -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static uint64_t get_pt_root(void) { -+ return ((csr_read(satp) & 0xFFFFFFFFFFF) << 12); -+} -+ -+static uint64_t walkaddr(pagetable_t pagetable, uint64_t va) { -+ if (pagetable == 0) -+ return 0; -+ pte_t *pte; -+ uint64_t level; -+ uint64_t pa; -+ -+ // make sure page tables in PMP. -+ host_hit_region((uint64_t)pagetable); -+ for (level = 4; level > 0; level--) { -+ pte = &pagetable[PX(level, va)]; -+ if (*pte & (PTE_X | PTE_W | PTE_R)) { -+ goto found; // A leaf pte has been found. -+ } else if (*pte & PTE_V) { -+ pagetable = (pagetable_t)PTE2PA(*pte); -+ host_hit_region((uint64_t)pagetable); -+ } else { -+ sbi_panic("invalid va=0x%lx\n", va); -+ } -+ } -+ pte = &pagetable[PX(0, va)]; -+ -+found: -+ if (pte == 0) -+ return 0; -+ if ((*pte & PTE_V) == 0) -+ return 0; -+ uint64_t number_of_ones = PGSHIFT + level * PPNSHIFT; -+ uint64_t offset_mask = (1 << number_of_ones) - 1; -+ uint64_t offset = (va & offset_mask); -+ pa = PTE2PA(*pte) + offset; -+ -+ return pa; -+} -+ -+static inline void flush_tlb() -+{ -+ asm volatile("sfence.vma"); -+} -+ -+int pmp_fault_handler(ulong mtval) { -+ if (!mtval) { -+ sbi_printf("mepc = 0x%lx\n", csr_read(CSR_MEPC)); -+ sbi_printf("Null pointer!\n"); -+ return -1; -+ } -+ pagetable_t pt_root = (pagetable_t)get_pt_root(); -+ uintptr_t pa = pt_root ? walkaddr(pt_root, mtval) : mtval; -+ -+ if (pa && host_hit_region(pa)) { -+ activate_host_lpmp(); -+ // Option 1. enable TLB cached PMP. -+ asm volatile("sfence.vma %0, zero \n\t" : : "r"(mtval)); -+ -+ // Option 2. disable TLB cached PMP. -+ // flush_tlb(); -+ -+ return 0; -+ } else { -+ sbi_printf("Error: Host should not access this pa\n"); -+ return -1; -+ } -+} diff --git a/lib/sbi/sbi_trap.c b/lib/sbi/sbi_trap.c -index ee3e4e9..2a4fd44 100644 +index ee3e4e9..0ac34f9 100644 --- a/lib/sbi/sbi_trap.c +++ b/lib/sbi/sbi_trap.c @@ -21,6 +21,7 @@ #include #include #include -+#include ++#include "lpmp.h" static void __noreturn sbi_trap_error(const char *msg, int rc, ulong mcause, ulong mtval, ulong mtval2, diff --git a/sm/src/lpmp.c b/sm/src/lpmp.c index f835a4964..4f6f938c3 100644 --- a/sm/src/lpmp.c +++ b/sm/src/lpmp.c @@ -9,28 +9,82 @@ #include #include #include +#include #include "sm-sbi-opensbi.h" #include "lpmp.h" #include "cpu.h" #include "page.h" #include "ipi.h" +#include "sm.h" -static spinlock_t region_lock = SPIN_LOCK_INITIALIZER; -static lpmp_region_t host_regions[MAX_HOST_REGION_N]; +/* PMP defines */ + +#define IDX_TO_ADDR_CSR(n) (CSR_PMPADDR0 + (n)) + +#if __riscv_xlen == 64 +#define IDX_TO_CFG_CSR(n) ((CSR_PMPCFG0 + ((n) >> 2)) & ~1) +#define IDX_TO_CFG_SHIFT(n) (((n)&7) << 3) +#elif __riscv_xlen == 32 +#define IDX_TO_CFG_CSR(n) (CSR_PMPCFG0 + ((n) >> 2)) +#define IDX_TO_CFG_SHIFT(n) (((n)&3) << 3) +#else +#error "Unexpected __riscv_xlen" +#endif + +#define PMP_A_OFF 0 +#define PMP_ALL_PERM (PMP_W | PMP_X | PMP_R) +#define PMP_NO_PERM 0 +#define PMP_SET_IDX(idx, addr, perm, TYPE) \ + do { \ + int pmpaddr_csr = IDX_TO_ADDR_CSR(idx); \ + int pmpcfg_csr = IDX_TO_CFG_CSR(idx); \ + int pmpcfg_shift = IDX_TO_CFG_SHIFT(idx); \ + u64 cfg_mask = ~(0xFFUL << pmpcfg_shift); \ + u64 pmpcfg = csr_read_num(pmpcfg_csr) & cfg_mask; \ + pmpcfg |= ((perm | PMP_A_##TYPE) << pmpcfg_shift) & ~cfg_mask; \ + csr_write_num(pmpaddr_csr, ((addr) >> PMP_SHIFT) & PMP_ADDR_MASK); \ + csr_write_num(pmpcfg_csr, pmpcfg); \ + } while (0) + +#define MAX_HOST_REGION_N 128 // can be larger static struct { struct sbi_dlist head; - uint64_t count; + size_t count; } host_reg; +typedef struct { + uintptr_t pa; + size_t size; + int is_inst; + size_t count; + struct sbi_dlist entry; +} lpmp_region_t; + +static spinlock_t region_lock = SPIN_LOCK_INITIALIZER; +static lpmp_region_t host_regions[MAX_HOST_REGION_N]; +typedef int region_id; + +/* Paging defines */ + +#define PPNSHIFT 9 +#define PGSHIFT 12 +#define PTE2PA(pte) (((pte) >> 10) << 12) +#define PXMASK 0x1FF // 9 bits +#define PXSHIFT(level) (PGSHIFT + (9 * (level))) +#define PX(level, va) ((((uintptr_t)(va)) >> PXSHIFT(level)) & PXMASK) + +typedef uintptr_t *pagetable_t; +typedef uintptr_t pte_t; + static void __dump_host_region_list(void) { lpmp_region_t *cur; int i = 0; - uint64_t size = 0; + size_t size = 0; sbi_printf("Dump region list of Host, count = %lu:\n", host_reg.count); - + if (!host_reg.count) { return; } @@ -58,7 +112,7 @@ void dump_host_region_list(void) spin_unlock(®ion_lock); } -static inline void set_region(lpmp_region_t *reg, uintptr_t pa, uint64_t size) +static inline void set_region(lpmp_region_t *reg, uintptr_t pa, size_t size) { reg->pa = pa; reg->size = size; @@ -78,7 +132,7 @@ static lpmp_region_t * __host_alloc_new_region(void) return NULL; } -static int __host_add_new_region(uintptr_t pa, uint64_t size, int is_inst) +static int __host_add_new_region(uintptr_t pa, size_t size, int is_inst) { lpmp_region_t *reg = __host_alloc_new_region(); reg->pa = pa; @@ -89,7 +143,7 @@ static int __host_add_new_region(uintptr_t pa, uint64_t size, int is_inst) return 1; } -static int __host_expand_region(uintptr_t pa, uint64_t size) +static int __host_expand_region(uintptr_t pa, size_t size) { lpmp_region_t *cur; sbi_list_for_each_entry(cur, &host_reg.head, entry) { @@ -121,7 +175,7 @@ static void __host_remove_region(uintptr_t pa) } } -static int __host_add_region(uintptr_t pa, uint64_t size, int is_inst) +static int __host_add_region(uintptr_t pa, size_t size, int is_inst) { int ret = __host_expand_region(pa, size); // -1 (not expand), 0 (expand) if (ret) @@ -129,7 +183,7 @@ static int __host_add_region(uintptr_t pa, uint64_t size, int is_inst) return ret; } -int host_add_region(uintptr_t pa, uint64_t size, int is_inst) +int host_add_region(uintptr_t pa, size_t size, int is_inst) { spin_lock(®ion_lock); int ret = __host_add_region(pa, size, is_inst); @@ -137,13 +191,13 @@ int host_add_region(uintptr_t pa, uint64_t size, int is_inst) return ret; // return 0 or 1 (#added_region) } -static void __host_split_region(uint64_t pa, uint64_t size, int is_inst) +static void __host_split_region(uintptr_t pa, size_t size, int is_inst) { lpmp_region_t *cur; sbi_list_for_each_entry(cur, &host_reg.head, entry) { if (cur->pa <= pa && pa < cur->pa + cur->size) { - uint64_t start_addr = cur->pa; - uint64_t end_addr = start_addr + cur->size; + uintptr_t start_addr = cur->pa; + uintptr_t end_addr = start_addr + cur->size; __host_remove_region(cur->pa); if (pa > start_addr) __host_add_region(start_addr, pa - start_addr, 0); @@ -155,7 +209,7 @@ static void __host_split_region(uint64_t pa, uint64_t size, int is_inst) return; } -void host_split_region(uint64_t pa, uint64_t size, int is_inst) +void host_split_region(uintptr_t pa, size_t size, int is_inst) { spin_lock(®ion_lock); __host_split_region(pa, size, is_inst); @@ -198,7 +252,7 @@ void host_free_regions(void) } void host_regions_init(void) -{ +{ sbi_memset(host_regions, 0, sizeof(host_regions)); // clear out SPIN_LOCK_INIT(region_lock); SBI_INIT_LIST_HEAD(&host_reg.head); @@ -213,7 +267,7 @@ void pmp_clear(void) PMP_SET_IDX(i, 0, PMP_NO_PERM, OFF); } -static bool is_power_of_two(uint64_t num) +static bool is_power_of_two(uintptr_t num) { if (!num) return 0; @@ -221,14 +275,14 @@ static bool is_power_of_two(uint64_t num) return (num & (num - 1)) == 0; } -static int napot_power(uintptr_t pa, uint64_t size) +static int napot_power(uintptr_t pa, size_t size) { if (is_power_of_two(size) && (pa % size == 0)) return sbi_ffs(size); return -1; } -static int set_pmp(int index, uintptr_t pa, uint64_t size) +static int set_pmp(int index, uintptr_t pa, size_t size) { int ret = 0; if (index < 0) @@ -257,7 +311,7 @@ static void __activate_host_pmp(int pmp_count) lpmp_region_t *cur; sbi_list_for_each_entry(cur, &host_reg.head, entry) { uintptr_t pa = cur->pa; - uint64_t size = cur->size; + size_t size = cur->size; int consumed = set_pmp(index, pa, size); if (!consumed) break; @@ -267,7 +321,7 @@ static void __activate_host_pmp(int pmp_count) } void activate_host_lpmp(void) -{ +{ spin_lock(®ion_lock); pmp_clear(); smp_mb(); @@ -281,7 +335,7 @@ void pmp_dump(void) spin_lock(®ion_lock); unsigned int i; int rc; - uint64_t prot, addr, log2len; + unsigned long prot, addr, log2len; smp_mb(); @@ -290,7 +344,7 @@ void pmp_dump(void) if (rc) { sbi_panic("PMP info read error!\n"); } - char *pmpmode = ((prot & PMP_A) == 0) ? "Off" : + char *pmpmode = ((prot & PMP_A) == 0) ? "Off" : ((prot & PMP_A) == PMP_A_NA4) ? "NA4" : ((prot & PMP_A) == PMP_A_NAPOT) ? "NAPOT" : ((prot & PMP_A) == PMP_A_TOR) ? "TOR" : @@ -307,3 +361,71 @@ void pmp_dump(void) smp_mb(); spin_unlock(®ion_lock); } + +static uintptr_t walkaddr(pagetable_t pagetable, uintptr_t va) { + if (pagetable == 0) + return 0; + pte_t *pte; + int level; + uintptr_t pa; + + // make sure page tables in PMP. + host_hit_region((uintptr_t)pagetable); + for (level = 4; level > 0; level--) { + pte = &pagetable[PX(level, va)]; + if (*pte & (PTE_X | PTE_W | PTE_R)) { + goto found; // A leaf pte has been found. + } else if (*pte & PTE_V) { + pagetable = (pagetable_t)PTE2PA(*pte); + host_hit_region((uintptr_t)pagetable); + } else { + sbi_panic("invalid va=0x%lx\n", va); + } + } + pte = &pagetable[PX(0, va)]; + +found: + if (pte == 0) + return 0; + if ((*pte & PTE_V) == 0) + return 0; + uintptr_t number_of_ones = PGSHIFT + level * PPNSHIFT; + uintptr_t offset_mask = (1 << number_of_ones) - 1; + uintptr_t offset = (va & offset_mask); + pa = PTE2PA(*pte) + offset; + + return pa; +} + +static inline void flush_tlb() +{ + asm volatile("sfence.vma"); +} + +static uintptr_t get_pt_root(void) { + return ((csr_read(satp) & 0xFFFFFFFFFFF) << 12); +} + +int pmp_fault_handler(ulong mtval) { + if (!mtval) { + sbi_printf("mepc = 0x%lx\n", csr_read(CSR_MEPC)); + sbi_printf("Null pointer!\n"); + return -1; + } + pagetable_t pt_root = (pagetable_t)get_pt_root(); + uintptr_t pa = pt_root ? walkaddr(pt_root, mtval) : mtval; + + if (pa && host_hit_region(pa)) { + activate_host_lpmp(); + // Option 1. enable TLB cached PMP. + asm volatile("sfence.vma %0, zero \n\t" : : "r"(mtval)); + + // Option 2. disable TLB cached PMP. + // flush_tlb(); + + return 0; + } else { + sbi_printf("Error: Host should not access this pa\n"); + return -1; + } +} diff --git a/sm/src/lpmp.h b/sm/src/lpmp.h index 31d09b439..e103ad4df 100644 --- a/sm/src/lpmp.h +++ b/sm/src/lpmp.h @@ -1,62 +1,16 @@ #ifndef _LPMP_H_ #define _LPMP_H_ -#include "sm.h" -#include -#include - -#define IDX_TO_ADDR_CSR(n) (CSR_PMPADDR0 + (n)) - -#if __riscv_xlen == 64 -#define IDX_TO_CFG_CSR(n) ((CSR_PMPCFG0 + ((n) >> 2)) & ~1) -#define IDX_TO_CFG_SHIFT(n) (((n)&7) << 3) -#elif __riscv_xlen == 32 -#define IDX_TO_CFG_CSR(n) (CSR_PMPCFG0 + ((n) >> 2)) -#define IDX_TO_CFG_SHIFT(n) (((n)&3) << 3) -#else -#error "Unexpected __riscv_xlen" -#endif - -#define PMP_A_OFF 0 -#define PMP_ALL_PERM (PMP_W | PMP_X | PMP_R) -#define PMP_NO_PERM 0 -#define PMP_SET_IDX(idx, addr, perm, TYPE) \ - do { \ - int pmpaddr_csr = IDX_TO_ADDR_CSR(idx); \ - int pmpcfg_csr = IDX_TO_CFG_CSR(idx); \ - int pmpcfg_shift = IDX_TO_CFG_SHIFT(idx); \ - u64 cfg_mask = ~(0xFFUL << pmpcfg_shift); \ - u64 pmpcfg = csr_read_num(pmpcfg_csr) & cfg_mask; \ - pmpcfg |= ((perm | PMP_A_##TYPE) << pmpcfg_shift) & ~cfg_mask; \ - csr_write_num(pmpaddr_csr, ((addr) >> PMP_SHIFT) & PMP_ADDR_MASK); \ - csr_write_num(pmpcfg_csr, pmpcfg); \ - } while (0) - -#define MAX_HOST_REGION_N 128 // can be larger - -typedef struct { - uintptr_t pa; - uint64_t size; - int is_inst; - uint64_t count; - struct sbi_dlist entry; -} lpmp_region_t; - -typedef int region_id; void host_regions_init(void); -int host_add_region(uintptr_t pa, uint64_t size, int is_inst); +int host_add_region(uintptr_t pa, size_t size, int is_inst); -void host_split_region(uint64_t pa, uint64_t size, int is_inst); - -int host_hit_region(uintptr_t pa); +void host_split_region(uintptr_t pa, size_t size, int is_inst); void activate_host_lpmp(void); -void dump_host_region_list(void); - void pmp_clear(void); -void pmp_dump(void); +int pmp_fault_handler(ulong mtval); #endif From 156f1d7d10ab0ca0f8293b85b66bcbabbbdc4d1b Mon Sep 17 00:00:00 2001 From: Gregor Haas Date: Mon, 10 Jun 2024 14:04:22 -0700 Subject: [PATCH 3/3] Cleanup warnings for mpfs build --- sm/src/ipi.c | 2 +- sm/src/ipi.h | 2 +- sm/src/lpmp.c | 16 +++++++++------- sm/src/lpmp.h | 4 ++++ sm/src/pmp.c | 2 +- 5 files changed, 16 insertions(+), 10 deletions(-) diff --git a/sm/src/ipi.c b/sm/src/ipi.c index 0adf83481..4f5881835 100644 --- a/sm/src/ipi.c +++ b/sm/src/ipi.c @@ -35,7 +35,7 @@ void sbi_flush_tlb_local(struct sbi_tlb_info *__info) asm volatile("sfence.vma"); } -void send_flush_tlb_ipi() +void send_flush_tlb_ipi(void) { ulong mask = 0; ulong source_hart = current_hartid(); diff --git a/sm/src/ipi.h b/sm/src/ipi.h index a16c22910..26b526c9b 100644 --- a/sm/src/ipi.h +++ b/sm/src/ipi.h @@ -27,6 +27,6 @@ void send_and_sync_pmp_ipi(int region_idx, int type, uint8_t perm); void sbi_flush_tlb_local(struct sbi_tlb_info *__info); -void send_flush_tlb_ipi(); +void send_flush_tlb_ipi(void); #endif diff --git a/sm/src/lpmp.c b/sm/src/lpmp.c index 4f6f938c3..9654cc245 100644 --- a/sm/src/lpmp.c +++ b/sm/src/lpmp.c @@ -231,7 +231,7 @@ static int __host_hit_region(uintptr_t pa) return 0; } -int host_hit_region(uintptr_t pa) +static int host_hit_region(uintptr_t pa) { spin_lock(®ion_lock); int ret = __host_hit_region(pa); @@ -239,7 +239,9 @@ int host_hit_region(uintptr_t pa) return ret; // ret: 1 (hit), 0 (miss) } -void host_free_regions(void) + +__attribute__((unused)) +static void host_free_regions(void) { spin_lock(®ion_lock); lpmp_region_t *cur; @@ -344,14 +346,14 @@ void pmp_dump(void) if (rc) { sbi_panic("PMP info read error!\n"); } - char *pmpmode = ((prot & PMP_A) == 0) ? "Off" : + const char *pmpmode = ((prot & PMP_A) == 0) ? "Off" : ((prot & PMP_A) == PMP_A_NA4) ? "NA4" : ((prot & PMP_A) == PMP_A_NAPOT) ? "NAPOT" : ((prot & PMP_A) == PMP_A_TOR) ? "TOR" : "Error"; - char *perm_r = (prot & PMP_R) ? "R" : "-"; - char *perm_w = (prot & PMP_W) ? "W" : "-"; - char *perm_x = (prot & PMP_X) ? "X" : "-"; + const char *perm_r = (prot & PMP_R) ? "R" : "-"; + const char *perm_w = (prot & PMP_W) ? "W" : "-"; + const char *perm_x = (prot & PMP_X) ? "X" : "-"; sbi_printf("PMP %u: Mode: %s, Permission: %s%s%s, " "addr: 0x%lx, len: 0x%lx\n", i, pmpmode, perm_r, perm_w, perm_x, @@ -397,7 +399,7 @@ static uintptr_t walkaddr(pagetable_t pagetable, uintptr_t va) { return pa; } -static inline void flush_tlb() +static inline void flush_tlb(void) { asm volatile("sfence.vma"); } diff --git a/sm/src/lpmp.h b/sm/src/lpmp.h index e103ad4df..0549b9dc3 100644 --- a/sm/src/lpmp.h +++ b/sm/src/lpmp.h @@ -9,8 +9,12 @@ void host_split_region(uintptr_t pa, size_t size, int is_inst); void activate_host_lpmp(void); +void dump_host_region_list(void); + void pmp_clear(void); +void pmp_dump(void); + int pmp_fault_handler(ulong mtval); #endif diff --git a/sm/src/pmp.c b/sm/src/pmp.c index 36e155ce6..581a9f93c 100644 --- a/sm/src/pmp.c +++ b/sm/src/pmp.c @@ -132,7 +132,7 @@ static int search_rightmost_unset(uint64_t bitmap, int max, uint64_t mask) return -1; } -static region_id get_free_region_idx() +static region_id get_free_region_idx(void) { return search_rightmost_unset(region_def_bitmap, PMP_MAX_N_REGION, 0x1); }