mm/kmap: Finalize kmap implementation for RISC-V

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.
This commit is contained in:
Ville Juven 2023-11-23 16:25:20 +02:00 committed by Xiang Xiao
parent 26e4dd5638
commit 8a2b83c482
3 changed files with 82 additions and 7 deletions

View File

@ -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
****************************************************************************/
@ -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
*
@ -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));
@ -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));

View File

@ -1377,6 +1377,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
*

View File

@ -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);
}