mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2026-07-27 08:50:58 +00:00
Maps entire physical memory range. Tracked-On: #8841 Signed-off-by: Yifan Liu <yifan1.liu@intel.com> Acked-by: Wang Yu1 <yu1.wang@intel.com>
207 lines
5.5 KiB
C
207 lines
5.5 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>
|
|
#include <reloc.h>
|
|
#include <fdt_api.h>
|
|
#include <acrn_hv_defs.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;
|
|
|
|
static uint64_t phys_mem_start;
|
|
static uint64_t phys_mem_size;
|
|
static struct mem_region rsvd_regions[MAX_FDT_RSVD_REGIONS];
|
|
static int nr_rsvd_regions;
|
|
|
|
void init_phys_mem_range(void)
|
|
{
|
|
int i;
|
|
#ifdef CONFIG_FDT_PARSE_ENABLED
|
|
int ret;
|
|
|
|
ret = fdt_get_phys_mem_region(get_host_fdt(), &phys_mem_start, &phys_mem_size);
|
|
if (ret < 0) {
|
|
panic("Failed to find memory information from FDT");
|
|
}
|
|
|
|
fdt_get_rsvd_mem_regions(get_host_fdt(), rsvd_regions, &nr_rsvd_regions);
|
|
#else
|
|
/* TODO: Replace with macros generated from config tool */
|
|
phys_mem_start = PHYS_MEM_START;
|
|
phys_mem_size = PHYS_MEM_SIZE;
|
|
#endif
|
|
|
|
pr_info("Physical Memory: [0x%lx-0x%lx]", phys_mem_start, phys_mem_start + phys_mem_size);
|
|
for (i = 0; i < nr_rsvd_regions; i++) {
|
|
pr_info("Reserved memory: [0x%lx-0x%lx]",
|
|
rsvd_regions[i].addr,
|
|
rsvd_regions[i].addr + rsvd_regions[i].size);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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(CSR_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)
|
|
{
|
|
uint64_t hva_base;
|
|
int i;
|
|
|
|
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);
|
|
|
|
/* Maps all physical memory */
|
|
pgtable_add_map((uint64_t *)ppt_mmu_top_addr, phys_mem_start,
|
|
phys_mem_start, phys_mem_size,
|
|
PAGE_V | PAGE_R | PAGE_W,
|
|
&ppt_pgtable);
|
|
|
|
/* Remove reserved region */
|
|
for (i = 0; i < nr_rsvd_regions; i++) {
|
|
pgtable_modify_or_del_map((uint64_t *)ppt_mmu_top_addr, rsvd_regions[i].addr,
|
|
rsvd_regions[i].size, 0UL, 0UL, &ppt_pgtable, MR_DEL);
|
|
}
|
|
|
|
/*TODO: Only map PAGE_X for text section*/
|
|
hva_base = get_hv_image_base();
|
|
pgtable_modify_or_del_map((uint64_t *)ppt_mmu_top_addr, hva_base,
|
|
get_hv_image_size(), PAGE_X, 0UL, &ppt_pgtable, MR_MODIFY);
|
|
|
|
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_phys_mem_range();
|
|
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);
|
|
}
|
|
|
|
|
|
|
|
|
|
/* FIXME: Remove it when public API that maps host memory range is available */
|
|
void dummy_pgtable_add_map(uint64_t paddr_base, uint64_t vaddr_base, uint64_t size, uint64_t prot)
|
|
{
|
|
pgtable_add_map((uint64_t *)ppt_mmu_top_addr, paddr_base, vaddr_base, size, prot, &ppt_pgtable);
|
|
}
|