diff --git a/arch/risc-v/src/common/pgalloc.h b/arch/risc-v/src/common/pgalloc.h new file mode 100644 index 00000000000..25d94af02d4 --- /dev/null +++ b/arch/risc-v/src/common/pgalloc.h @@ -0,0 +1,82 @@ +/**************************************************************************** + * arch/risc-v/src/common/pgalloc.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISC_V_SRC_COMMON_PGALLOC_H +#define __ARCH_RISC_V_SRC_COMMON_PGALLOC_H + +#ifdef CONFIG_MM_PGALLOC + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef CONFIG_ARCH_PGPOOL_MAPPING +# error "RISC-V needs CONFIG_ARCH_PGPOOL_MAPPING" +#endif + +/**************************************************************************** + * Public Functions Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: riscv_pgvaddr + * + * Description: + * Get virtual address for pgpool physical address. Note: this function + * is minimalistic and is only usable for kernel mappings and only tests + * if the paddr is in the pgpool. For user mapped addresses this does not + * work. + * + * Note: + * To get it to work with user addresses, a manual table walk needs to be + * implemented. Not too complex, but not needed for anything -> not + * implemented. + * + * Input Parameters: + * paddr - Physical pgpool address + * + * Return: + * vaddr - Virtual address for physical address + * + ****************************************************************************/ + +#ifdef CONFIG_ARCH_PGPOOL_MAPPING +static inline uintptr_t riscv_pgvaddr(uintptr_t paddr) +{ + if (paddr >= CONFIG_ARCH_PGPOOL_PBASE && paddr < CONFIG_ARCH_PGPOOL_PEND) + { + return paddr - CONFIG_ARCH_PGPOOL_PBASE + CONFIG_ARCH_PGPOOL_VBASE; + } + + return 0; +} +#endif /* CONFIG_ARCH_PGPOOL_MAPPING */ + +#endif /* CONFIG_MM_PGALLOC */ +#endif /* __ARCH_RISC_V_SRC_COMMON_PGALLOC_H */ diff --git a/arch/risc-v/src/common/riscv_addrenv.c b/arch/risc-v/src/common/riscv_addrenv.c index 539c179797f..3dacbfb2e7a 100644 --- a/arch/risc-v/src/common/riscv_addrenv.c +++ b/arch/risc-v/src/common/riscv_addrenv.c @@ -68,6 +68,7 @@ #include +#include "pgalloc.h" #include "riscv_mmu.h" /**************************************************************************** @@ -111,7 +112,7 @@ extern uintptr_t g_kernel_mappings; static inline void wipe_page(uintptr_t paddr) { - uintptr_t vaddr = paddr; + uintptr_t vaddr = riscv_pgvaddr(paddr); memset((void *)vaddr, 0, MM_PGSIZE); } @@ -133,7 +134,7 @@ static void map_spgtables(group_addrenv_t *addrenv, uintptr_t vaddr) /* Start from L1, and connect until max level - 1 */ - prev = addrenv->spgtables[0]; + prev = riscv_pgvaddr(addrenv->spgtables[0]); /* Check if the mapping already exists */ @@ -146,7 +147,7 @@ static void map_spgtables(group_addrenv_t *addrenv, uintptr_t vaddr) for (i = 0; i < (ARCH_SPGTS - 1); i++) { - uintptr_t next = addrenv->spgtables[i + 1]; + uintptr_t next = riscv_pgvaddr(addrenv->spgtables[i + 1]); mmu_ln_setentry(i + 1, prev, next, vaddr, MMU_UPGT_FLAGS); prev = next; } @@ -211,7 +212,7 @@ static int create_spgtables(group_addrenv_t *addrenv) static int copy_kernel_mappings(group_addrenv_t *addrenv) { - uintptr_t user_mappings = addrenv->spgtables[0]; + uintptr_t user_mappings = riscv_pgvaddr(addrenv->spgtables[0]); /* Copy the L1 references */ @@ -258,7 +259,7 @@ static int create_region(group_addrenv_t *addrenv, uintptr_t vaddr, nmapped = 0; npages = MM_NPAGES(size); - ptprev = addrenv->spgtables[ARCH_SPGTS - 1]; + ptprev = riscv_pgvaddr(addrenv->spgtables[ARCH_SPGTS - 1]); ptlevel = ARCH_SPGTS; /* Create mappings for the lower level tables */ @@ -292,7 +293,7 @@ static int create_region(group_addrenv_t *addrenv, uintptr_t vaddr, wipe_page(paddr); } - ptlast = paddr; + ptlast = riscv_pgvaddr(paddr); /* Then allocate memory for the region data */ @@ -505,12 +506,12 @@ int up_addrenv_destroy(group_addrenv_t *addrenv) /* First destroy the allocated memory and the final level page table */ - ptprev = (uintptr_t *)addrenv->spgtables[ARCH_SPGTS - 1]; + ptprev = (uintptr_t *)riscv_pgvaddr(addrenv->spgtables[ARCH_SPGTS - 1]); if (ptprev) { for (i = 0; i < ENTRIES_PER_PGT; i++) { - ptlast = (uintptr_t *)mmu_pte_to_paddr(ptprev[i]); + ptlast = (uintptr_t *)riscv_pgvaddr(mmu_pte_to_paddr(ptprev[i])); if (ptlast) { /* Page table allocated, free any allocated memory */ diff --git a/arch/risc-v/src/common/riscv_pgalloc.c b/arch/risc-v/src/common/riscv_pgalloc.c index 0542746530a..ae78eb5a75c 100644 --- a/arch/risc-v/src/common/riscv_pgalloc.c +++ b/arch/risc-v/src/common/riscv_pgalloc.c @@ -37,6 +37,7 @@ #include +#include "pgalloc.h" #include "riscv_mmu.h" #ifdef CONFIG_BUILD_KERNEL @@ -66,7 +67,7 @@ static inline void wipe_page(uintptr_t paddr) { - uintptr_t vaddr = paddr; + uintptr_t vaddr = riscv_pgvaddr(paddr); memset((void *)vaddr, 0, MM_PGSIZE); } @@ -88,7 +89,7 @@ static uintptr_t get_pgtable(group_addrenv_t *addrenv, uintptr_t vaddr) /* Get the current level MAX_LEVELS-1 entry corresponding to this vaddr */ ptlevel = ARCH_SPGTS; - ptprev = addrenv->spgtables[ARCH_SPGTS - 1]; + ptprev = riscv_pgvaddr(addrenv->spgtables[ARCH_SPGTS - 1]); paddr = mmu_pte_to_paddr(mmu_ln_getentry(ptlevel, ptprev, vaddr)); if (!paddr) @@ -188,7 +189,7 @@ uintptr_t pgalloc(uintptr_t brkaddr, unsigned int npages) { /* Get the address of the last level page table */ - ptlast = get_pgtable(&group->tg_addrenv, vaddr); + ptlast = riscv_pgvaddr(get_pgtable(&group->tg_addrenv, vaddr)); if (!ptlast) { return 0;