Skip to content

Commit

Permalink
mm/kmap: Finalize kmap implementation for RISC-V
Browse files Browse the repository at this point in the history
After this, RISC-V fully supports the kmap interface.

Due to the current design limitations of having only a single L2 table
per process, the kernel kmap area cannot be mapped via any user page
directory, as they do not contain the page tables to address that range.

So a "kernel address environment" is added, which can do the mapping. The
mapping is reflected to every process as only the root page directory (L1)
is copied to users, which means every change to L2 / L3 tables will be
seen by every user.
  • Loading branch information
pussuw committed Dec 8, 2023
1 parent b1d7e41 commit 8e170d2
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 7 deletions.
61 changes: 55 additions & 6 deletions arch/risc-v/src/common/riscv_addrenv_pgmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@

#ifdef CONFIG_BUILD_KERNEL

/****************************************************************************
* Private Data
****************************************************************************/

#ifdef CONFIG_MM_KMAP
static struct arch_addrenv_s g_kernel_addrenv;
#endif

/****************************************************************************
* Public Functions
****************************************************************************/
Expand Down Expand Up @@ -141,6 +149,51 @@ bool up_addrenv_user_vaddr(uintptr_t vaddr)

#ifdef CONFIG_MM_KMAP

/****************************************************************************
* Name: up_addrenv_kmap_init
*
* Description:
* Initialize the architecture specific part of the kernel mapping
* interface.
*
* Input Parameters:
* None.
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned
* on failure.
*
****************************************************************************/

int up_addrenv_kmap_init(void)
{
struct arch_addrenv_s *addrenv;
uintptr_t next;
uintptr_t vaddr;
int i;

/* Populate the static page tables one by one */

addrenv = &g_kernel_addrenv;
next = g_kernel_pgt_pbase;
vaddr = CONFIG_ARCH_KMAP_VBASE;

for (i = 0; i < (ARCH_SPGTS - 1); i++)
{
/* Connect the static page tables */

uintptr_t lnvaddr = riscv_pgvaddr(next);
addrenv->spgtables[i] = next;
next = mmu_pte_to_paddr(mmu_ln_getentry(i + 1, lnvaddr, vaddr));
}

/* Set the page directory root */

addrenv->satp = mmu_satp_reg(g_kernel_pgt_pbase, 0);

return OK;
}

/****************************************************************************
* Name: up_addrenv_kmap_pages
*
Expand All @@ -164,13 +217,11 @@ bool up_addrenv_user_vaddr(uintptr_t vaddr)
int up_addrenv_kmap_pages(void **pages, unsigned int npages, uintptr_t vaddr,
int prot)
{
struct tcb_s *tcb = nxsched_self();
struct arch_addrenv_s *addrenv = &tcb->addrenv_own->addrenv;
struct arch_addrenv_s *addrenv = &g_kernel_addrenv;
int mask = 0;

/* Sanity checks */

DEBUGASSERT(tcb && tcb->addrenv_own);
DEBUGASSERT(pages != NULL && npages > 0);
DEBUGASSERT(vaddr >= CONFIG_ARCH_KMAP_VBASE && vaddr < ARCH_KMAP_VEND);
DEBUGASSERT(MM_ISALIGNED(vaddr));
Expand Down Expand Up @@ -220,12 +271,10 @@ int up_addrenv_kmap_pages(void **pages, unsigned int npages, uintptr_t vaddr,

int up_addrenv_kunmap_pages(uintptr_t vaddr, unsigned int npages)
{
struct tcb_s *tcb = nxsched_self();
struct arch_addrenv_s *addrenv = &tcb->addrenv_own->addrenv;
struct arch_addrenv_s *addrenv = &g_kernel_addrenv;

/* Sanity checks */

DEBUGASSERT(tcb && tcb->addrenv_own);
DEBUGASSERT(npages > 0);
DEBUGASSERT(vaddr >= CONFIG_ARCH_KMAP_VBASE && vaddr < ARCH_KMAP_VEND);
DEBUGASSERT(MM_ISALIGNED(vaddr));
Expand Down
20 changes: 20 additions & 0 deletions include/nuttx/arch.h
Original file line number Diff line number Diff line change
Expand Up @@ -1326,6 +1326,26 @@ uintptr_t up_addrenv_page_vaddr(uintptr_t page);
bool up_addrenv_user_vaddr(uintptr_t vaddr);
#endif

/****************************************************************************
* Name: up_addrenv_kmap_init
*
* Description:
* Initialize the architecture specific part of the kernel mapping
* interface.
*
* Input Parameters:
* None.
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned
* on failure.
*
****************************************************************************/

#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_MM_KMAP)
int up_addrenv_kmap_init(void);
#endif

/****************************************************************************
* Name: up_addrenv_kmap_pages
*
Expand Down
8 changes: 7 additions & 1 deletion mm/kmap/kmm_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -279,10 +279,16 @@ static void kmm_map_unlock(void)

void kmm_map_initialize(void)
{
/* Initialize the architecture specific part */

DEBUGVERIFY(up_addrenv_kmap_init());

/* Then, the local vmap */

g_kmm_map_vpages = gran_initialize((FAR void *)CONFIG_ARCH_KMAP_VBASE,
CONFIG_ARCH_KMAP_NPAGES << MM_PGSHIFT,
MM_PGSHIFT, MM_PGSHIFT);
DEBUGVERIFY(g_kmm_map_vpages);
DEBUGASSERT(g_kmm_map_vpages != NULL);
mm_map_initialize(&g_kmm_map, true);
}

Expand Down

0 comments on commit 8e170d2

Please sign in to comment.