Files
acrn-hypervisor/hypervisor/arch/riscv/mmu.c
hangliu1 a436f72493 hv: riscv: add access usr memory interface
Add pre_user_access() and post_user_access() interfaces
to protect mmio from hypervisor accidental access,
SMAP extensiton need to be detected

Tracked-On: #8831
Signed-off-by: hangliu1 <hang1.liu@intel.com>
Reviewed-by: Liu, Yifan1 <yifan1.liu@intel.com>
Acked-by: Wang, Yu1 <yu1.wang@intel.com>
2025-10-21 14:14:55 +08:00

152 lines
3.9 KiB
C

/*
* Copyright (C) 2023-2025 Intel Corporation.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <types.h>
#include <rtl.h>
#include <mmu.h>
#include <asm/qemu.h>
#include <logmsg.h>
void set_paging_supervisor(__unused uint64_t base, __unused uint64_t size)
{
}
static struct page_pool ppt_page_pool;
static void *ppt_mmu_top_addr;
uint64_t init_satp;
extern uint8_t _code_start;
extern uint8_t _code_end;
/**
* Riscv mmio memory layout is continuous and it support 1G huge
* page by default, base on this, we assume it only consume one VPN3/2 page,
* and preserve 4 VPN1 page to deal with memory map without 1G alignment.
* for VPN0 page, we only preserve uart mmio related 2 pages.
*
* FIXME: The number need to be calculated according to the actual platform
* memory layout, which is to be generated by config tool.
*/
#define PPT_VPN3_PAGE_NUM 1UL
#define PPT_VPN2_PAGE_NUM 1UL
#define PPT_VPN1_PAGE_NUM 4UL
#define PPT_VPN0_PAGE_NUM 2UL
#define PPT_PAGE_NUM_SUM (PPT_VPN3_PAGE_NUM + PPT_VPN2_PAGE_NUM + PPT_VPN1_PAGE_NUM + PPT_VPN0_PAGE_NUM)
#define PPT_PAGE_NUM roundup(PPT_PAGE_NUM_SUM, 64U)
DEFINE_PAGE_TABLES(ppt_pages, PPT_PAGE_NUM);
DEFINE_PAGE_TABLE(ppt_pages_bitmap);
static bool large_page_support(enum _page_table_level level, uint64_t __unused prot)
{
if (level == PGT_LVL1|| level == PGT_LVL2)
return true;
else
return false;
}
static void ppt_flush_cache_pagewalk(const void* entry __attribute__((unused)))
{
}
static uint64_t ppt_pgentry_present(uint64_t pte)
{
return pte & PAGE_V;
}
static inline void ppt_set_pgentry(uint64_t *pte, uint64_t page, uint64_t prot, enum _page_table_level __unused level,
bool is_leaf, const struct pgtable *table)
{
uint64_t prot_tmp;
if (!is_leaf) {
prot_tmp = PAGE_V;
} else {
prot_tmp = prot;
}
make_pgentry(pte, page, prot_tmp, table);
}
static const struct pgtable ppt_pgtable = {
.pool = &ppt_page_pool,
.large_page_support = large_page_support,
.pgentry_present = ppt_pgentry_present,
.flush_cache_pagewalk = ppt_flush_cache_pagewalk,
.set_pgentry = ppt_set_pgentry,
};
/* TODO: need to formally get the value either from
* config tool or from DTS runtime parsing.
*/
static uint64_t get_board_hv_device_start(void)
{
return 0UL;
}
/* TODO: need to formally get the value either from
* config tool or from DTS runtime parsing.
*/
static uint64_t get_board_hv_device_size(void)
{
return 0x80000000UL;
}
static bool switch_satp(uint64_t satp_value)
{
/**
* Here is to detect whether SV48 is supported
* by the platform by writing the MODE in satp
* register, which is a WARL field. According to
* The RISC-V Instruction Set Manual volume II,
* if satp is written with an unsupported MODE,
* the entire write has no effect; no fields in
* satp are modified.
*/
set_satp(satp_value);
return (cpu_csr_read(satp) == satp_value);
}
/**
* TODO: need to detect existence of svpbmt extension to support PAGE_ATTR_IO
* and PAGE_ATTR_PMA for mapping.
*/
static void init_hv_mapping(void)
{
ppt_mmu_top_addr = (uint64_t *)alloc_page(&ppt_page_pool);
/*TODO: The SUM bit in sstatus is 0, meaning SMAP is enabled
* however, SMAP is provided by smepmp extension, we need to detect
* its existence from DTS.
*/
pgtable_add_map((uint64_t *)ppt_mmu_top_addr, get_board_hv_device_start(),
get_board_hv_device_start(), get_board_hv_device_size(),
PAGE_V | PAGE_R | PAGE_W,
&ppt_pgtable);
/*TODO: Only map PAGE_X for text section*/
pgtable_add_map((uint64_t *)ppt_mmu_top_addr, CONFIG_HV_RAM_START,
CONFIG_HV_RAM_START, (&_code_end - &_code_start),
PAGE_V | PAGE_X | PAGE_R | PAGE_W,
&ppt_pgtable);
init_satp = ((uint64_t)ppt_mmu_top_addr >> PAGE_SHIFT) | SATP_MODE_SV48;
if (!switch_satp(init_satp)) {
panic("Only support SV48 mode !");
}
}
void init_paging(void)
{
init_page_pool(&ppt_page_pool, (uint64_t *)ppt_pages,
(uint64_t *)ppt_pages_bitmap, PPT_PAGE_NUM);
init_hv_mapping();
}
void enable_paging(void)
{
set_satp(init_satp);
}