RISC-V: Add pgpool to vaddr utility function

The only mapping that is supported now is vaddr=paddr, but the function
DOES check that the address is within the page pool, so it is not
useless.
This commit is contained in:
Ville Juven 2022-02-15 15:48:38 +02:00 committed by Xiang Xiao
parent 1322f82802
commit 3d8ba496a2
3 changed files with 95 additions and 11 deletions

View File

@ -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 <nuttx/config.h>
#include <stdint.h>
#include <string.h>
/****************************************************************************
* 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 */

View File

@ -68,6 +68,7 @@
#include <arch/barriers.h>
#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 */

View File

@ -37,6 +37,7 @@
#include <arch/barriers.h>
#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;