Add kernel free map and linear map
This commit is contained in:
parent
a268135205
commit
d7c99b7f01
|
@ -42,6 +42,8 @@ clear_bss:
|
||||||
blt a3, a4, clear_bss
|
blt a3, a4, clear_bss
|
||||||
clear_bss_done:
|
clear_bss_done:
|
||||||
|
|
||||||
|
la sp, stacks_top
|
||||||
|
|
||||||
/* Initialize page tables and relocate to virtual addresses */
|
/* Initialize page tables and relocate to virtual addresses */
|
||||||
call setup_vm_early
|
call setup_vm_early
|
||||||
|
|
||||||
|
|
|
@ -88,7 +88,7 @@ SECTIONS
|
||||||
|
|
||||||
.text : {
|
.text : {
|
||||||
. = ALIGN(0x1000);
|
. = ALIGN(0x1000);
|
||||||
*(.text .text.* .gnu.linkonce.t.*)
|
*(.text .text.*)
|
||||||
}
|
}
|
||||||
|
|
||||||
. = ALIGN(0x1000);
|
. = ALIGN(0x1000);
|
||||||
|
@ -138,7 +138,7 @@ SECTIONS
|
||||||
__global_pointer$ = . + 0x800;
|
__global_pointer$ = . + 0x800;
|
||||||
*(.sdata*)
|
*(.sdata*)
|
||||||
}
|
}
|
||||||
|
. = ALIGN((1 << 21));
|
||||||
_edata = .;
|
_edata = .;
|
||||||
_end = .;
|
_end = .;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,14 +33,14 @@ Modification:
|
||||||
#include "pagetable.h"
|
#include "pagetable.h"
|
||||||
#include "registers.h"
|
#include "registers.h"
|
||||||
#include "ns16550.h"
|
#include "ns16550.h"
|
||||||
|
#include "printf.h"
|
||||||
#include <asm/csr.h>
|
#include <asm/csr.h>
|
||||||
#include <asm/pgtable-bits.h>
|
#include <asm/pgtable-bits.h>
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
//
|
||||||
// clang-format off
|
|
||||||
#define L2_PTE_VALID (1 << 0)
|
#define L2_PTE_VALID (1 << 0)
|
||||||
|
|
||||||
#define L3_PTE_VALID (1 << 0)
|
#define L3_PTE_VALID (1 << 0)
|
||||||
|
@ -62,7 +62,7 @@ Modification:
|
||||||
#define PAGE_KERNEL_READ (_PAGE_KERNEL & ~_PAGE_WRITE)
|
#define PAGE_KERNEL_READ (_PAGE_KERNEL & ~_PAGE_WRITE)
|
||||||
#define PAGE_KERNEL_EXEC (_PAGE_KERNEL | _PAGE_EXEC)
|
#define PAGE_KERNEL_EXEC (_PAGE_KERNEL | _PAGE_EXEC)
|
||||||
|
|
||||||
// clang-format on
|
//
|
||||||
uint64_t boot_l2pgdir[NUM_LEVEL2_PDE] __attribute__((aligned(0x1000))) = { 0 };
|
uint64_t boot_l2pgdir[NUM_LEVEL2_PDE] __attribute__((aligned(0x1000))) = { 0 };
|
||||||
|
|
||||||
uint64_t boot_dev_l3pgdir[NUM_LEVEL3_PDE] __attribute__((aligned(0x1000))) = { 0 };
|
uint64_t boot_dev_l3pgdir[NUM_LEVEL3_PDE] __attribute__((aligned(0x1000))) = { 0 };
|
||||||
|
@ -71,7 +71,7 @@ uint64_t boot_kern_l3pgdir[NUM_LEVEL3_PDE] __attribute__((aligned(0x1000))) = {
|
||||||
uint64_t boot_dev_l4pgdirs[NUM_LEVEL3_PDE][NUM_LEVEL4_PTE] __attribute__((aligned(0x1000))) = { 0 };
|
uint64_t boot_dev_l4pgdirs[NUM_LEVEL3_PDE][NUM_LEVEL4_PTE] __attribute__((aligned(0x1000))) = { 0 };
|
||||||
uint64_t boot_kern_l4pgdirs[NUM_LEVEL3_PDE][NUM_LEVEL4_PTE] __attribute__((aligned(0x1000))) = { 0 };
|
uint64_t boot_kern_l4pgdirs[NUM_LEVEL3_PDE][NUM_LEVEL4_PTE] __attribute__((aligned(0x1000))) = { 0 };
|
||||||
|
|
||||||
|
//
|
||||||
static void build_boot_pgdir()
|
static void build_boot_pgdir()
|
||||||
{
|
{
|
||||||
static bool built = false;
|
static bool built = false;
|
||||||
|
@ -118,16 +118,45 @@ static void load_boot_pgdir()
|
||||||
csr_write(CSR_SATP, satp_val);
|
csr_write(CSR_SATP, satp_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
static int test_access_map_address(void)
|
||||||
|
{
|
||||||
|
unsigned long address = KERN_MEM_BASE + (PHY_USER_FREEMEM_BASE - PHY_MEM_BASE) - 4096;
|
||||||
|
printf_early("to access 0x%lx\n", address);
|
||||||
|
*(unsigned long *)address = 0x55;
|
||||||
|
if(*(unsigned long *)address == 0x55) {
|
||||||
|
printf_early("access 0x%lx done\n", address);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_access_unmap_address(void)
|
||||||
|
{
|
||||||
|
unsigned long address = KERN_MEM_BASE + (PHY_USER_FREEMEM_BASE - PHY_MEM_BASE) + 4096;
|
||||||
|
*(unsigned long *)address = 0x55;
|
||||||
|
printf_early("access 0x%lx done\n", address);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_mmu(void)
|
||||||
|
{
|
||||||
|
test_access_map_address();
|
||||||
|
test_access_unmap_address();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
extern void main(void);
|
extern void main(void);
|
||||||
|
|
||||||
void bootmain(void)
|
void bootmain(void)
|
||||||
{
|
{
|
||||||
_debug_uart_printascii("bootmain start.\n");
|
_debug_uart_printascii("bootmain start\n");
|
||||||
|
#if 0
|
||||||
build_boot_pgdir();
|
test_mmu();
|
||||||
load_boot_pgdir();
|
#endif
|
||||||
_debug_uart_printascii("boot pgdir success\n");
|
|
||||||
|
|
||||||
main();
|
main();
|
||||||
|
|
||||||
|
_debug_uart_printascii("bootmain end\n");
|
||||||
|
while(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ Modification:
|
||||||
|
|
||||||
/* physical memory layout */
|
/* physical memory layout */
|
||||||
#define PHY_MEM_BASE (0x0000000040200000ULL)
|
#define PHY_MEM_BASE (0x0000000040200000ULL)
|
||||||
#define PHY_USER_FREEMEM_BASE (0x0000000080000000ULL)
|
#define PHY_USER_FREEMEM_BASE (0x0000000100000000ULL)
|
||||||
#define PHY_USER_FREEMEM_TOP (0x0000000200000000ULL)
|
#define PHY_USER_FREEMEM_TOP (0x0000000200000000ULL)
|
||||||
#define PHY_MEM_STOP (0x0000000200000000ULL)
|
#define PHY_MEM_STOP (0x0000000200000000ULL)
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,8 @@ pgd_t early_pg_dir[PTRS_PER_PGD] __initdata __attribute__((aligned(PAGE_SIZE)));
|
||||||
static pmd_t trampoline_pmd[PTRS_PER_PMD] __page_aligned_bss;
|
static pmd_t trampoline_pmd[PTRS_PER_PMD] __page_aligned_bss;
|
||||||
static pmd_t early_pmd[PTRS_PER_PMD] __initdata __attribute__((aligned(PAGE_SIZE)));
|
static pmd_t early_pmd[PTRS_PER_PMD] __initdata __attribute__((aligned(PAGE_SIZE)));
|
||||||
static pmd_t early_uart_pmd[PTRS_PER_PMD] __initdata __attribute__((aligned(PAGE_SIZE)));
|
static pmd_t early_uart_pmd[PTRS_PER_PMD] __initdata __attribute__((aligned(PAGE_SIZE)));
|
||||||
|
static pmd_t early_pmd_free[((PHY_USER_FREEMEM_BASE - PHY_MEM_BASE) >> PGDIR_SHIFT) + 1][PTRS_PER_PMD] __initdata __attribute__((aligned(PAGE_SIZE)));
|
||||||
|
static pmd_t early_pmd_inear_map[PTRS_PER_PMD] __initdata __attribute__((aligned(PAGE_SIZE)));
|
||||||
|
|
||||||
|
|
||||||
static pmd_t *__init get_pmd_virt_early(phys_addr_t pa)
|
static pmd_t *__init get_pmd_virt_early(phys_addr_t pa)
|
||||||
|
@ -86,7 +88,7 @@ static void __init create_pmd_mapping_early(pmd_t *pmdp,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init create_pgd_mapping_early(pgd_t *pgdp,
|
static void __init create_pgd_mapping_early(pgd_t *pgdp,
|
||||||
uintptr_t va, phys_addr_t pa,
|
uintptr_t va, phys_addr_t pa,
|
||||||
phys_addr_t sz, pgprot_t prot)
|
phys_addr_t sz, pgprot_t prot)
|
||||||
{
|
{
|
||||||
|
@ -116,7 +118,6 @@ void __init create_pgd_mapping_early(pgd_t *pgdp,
|
||||||
static void __init create_kernel_page_table_early(pgd_t *pgdir, bool early)
|
static void __init create_kernel_page_table_early(pgd_t *pgdir, bool early)
|
||||||
{
|
{
|
||||||
uintptr_t va, end_va;
|
uintptr_t va, end_va;
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
end_va = kernel_map.virt_addr + kernel_map.size;
|
end_va = kernel_map.virt_addr + kernel_map.size;
|
||||||
for (va = kernel_map.virt_addr; va < end_va; va += PMD_SIZE) {
|
for (va = kernel_map.virt_addr; va < end_va; va += PMD_SIZE) {
|
||||||
|
@ -124,7 +125,76 @@ static void __init create_kernel_page_table_early(pgd_t *pgdir, bool early)
|
||||||
kernel_map.phys_addr + (va - kernel_map.virt_addr),
|
kernel_map.phys_addr + (va - kernel_map.virt_addr),
|
||||||
PMD_SIZE,
|
PMD_SIZE,
|
||||||
PAGE_KERNEL_EXEC);
|
PAGE_KERNEL_EXEC);
|
||||||
i++;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void __init create_kernel_pgd_mapping_free_early(pgd_t *pgdp,
|
||||||
|
uintptr_t va, phys_addr_t pa,
|
||||||
|
phys_addr_t sz, pgprot_t prot)
|
||||||
|
{
|
||||||
|
pmd_t *nextp;
|
||||||
|
phys_addr_t next_phys;
|
||||||
|
uintptr_t pgd_idx = pgd_index(va);
|
||||||
|
uintptr_t start_pgd_idx = pgd_index(kernel_map.virt_addr);
|
||||||
|
|
||||||
|
if (pgd_val(pgdp[pgd_idx]) == 0) {
|
||||||
|
next_phys = early_pmd_free[pgd_idx - start_pgd_idx];
|
||||||
|
pgdp[pgd_idx] = pfn_pgd(PFN_DOWN(next_phys), PAGE_TABLE);
|
||||||
|
nextp = get_pmd_virt_early(next_phys);
|
||||||
|
memset(nextp, 0, PAGE_SIZE);
|
||||||
|
} else {
|
||||||
|
next_phys = PFN_PHYS(_pgd_pfn(pgdp[pgd_idx]));
|
||||||
|
nextp = get_pmd_virt_early(next_phys);
|
||||||
|
}
|
||||||
|
|
||||||
|
create_pmd_mapping_early(nextp, va, pa, sz, prot);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __init create_kernel_page_table_free_early(pgd_t *pgdir, bool early)
|
||||||
|
{
|
||||||
|
uintptr_t va, end_va;
|
||||||
|
|
||||||
|
end_va = kernel_map.virt_addr + (PHY_USER_FREEMEM_BASE - kernel_map.phys_addr);
|
||||||
|
for (va = kernel_map.virt_addr + kernel_map.size; va < end_va; va += PMD_SIZE) {
|
||||||
|
create_kernel_pgd_mapping_free_early(pgdir, va,
|
||||||
|
kernel_map.phys_addr + (va - kernel_map.virt_addr),
|
||||||
|
PMD_SIZE,
|
||||||
|
PAGE_KERNEL_EXEC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __init create_kernel_pgd_mapping_linear_map_early(pgd_t *pgdp,
|
||||||
|
uintptr_t va, phys_addr_t pa,
|
||||||
|
phys_addr_t sz, pgprot_t prot)
|
||||||
|
{
|
||||||
|
pmd_t *nextp;
|
||||||
|
phys_addr_t next_phys;
|
||||||
|
uintptr_t pgd_idx = pgd_index(va);
|
||||||
|
|
||||||
|
if (pgd_val(pgdp[pgd_idx]) == 0) {
|
||||||
|
next_phys = early_pmd_inear_map;
|
||||||
|
pgdp[pgd_idx] = pfn_pgd(PFN_DOWN(next_phys), PAGE_TABLE);
|
||||||
|
nextp = get_pmd_virt_early(next_phys);
|
||||||
|
memset(nextp, 0, PAGE_SIZE);
|
||||||
|
} else {
|
||||||
|
next_phys = PFN_PHYS(_pgd_pfn(pgdp[pgd_idx]));
|
||||||
|
nextp = get_pmd_virt_early(next_phys);
|
||||||
|
}
|
||||||
|
|
||||||
|
create_pmd_mapping_early(nextp, va, pa, sz, prot);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __init create_kernel_page_table_linear_map_early(pgd_t *pgdir, bool early)
|
||||||
|
{
|
||||||
|
uintptr_t va, end_va;
|
||||||
|
|
||||||
|
end_va = kernel_map.phys_addr + kernel_map.size;
|
||||||
|
for (va = kernel_map.phys_addr; va < end_va; va += PMD_SIZE) {
|
||||||
|
create_kernel_pgd_mapping_linear_map_early(pgdir, va,
|
||||||
|
kernel_map.phys_addr + (va - kernel_map.phys_addr),
|
||||||
|
PMD_SIZE,
|
||||||
|
PAGE_KERNEL_EXEC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,5 +236,11 @@ void __init setup_vm_early(void)
|
||||||
/* Setup uart PGD and PMD */
|
/* Setup uart PGD and PMD */
|
||||||
create_pgd_mapping_early(early_pg_dir, DEV_VRTMEM_BASE, (uintptr_t)early_uart_pmd, PGDIR_SIZE, PAGE_TABLE);
|
create_pgd_mapping_early(early_pg_dir, DEV_VRTMEM_BASE, (uintptr_t)early_uart_pmd, PGDIR_SIZE, PAGE_TABLE);
|
||||||
create_pmd_mapping_early(early_uart_pmd, DEV_VRTMEM_BASE, DEV_PHYMEM_BASE, PMD_SIZE, PAGE_KERNEL);
|
create_pmd_mapping_early(early_uart_pmd, DEV_VRTMEM_BASE, DEV_PHYMEM_BASE, PMD_SIZE, PAGE_KERNEL);
|
||||||
|
|
||||||
|
/* Setup kernel free PGD and PMD */
|
||||||
|
create_kernel_page_table_free_early(early_pg_dir, true);
|
||||||
|
|
||||||
|
/* Setup kernel linear map PGD and PMD */
|
||||||
|
create_kernel_page_table_linear_map_early(early_pg_dir, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -898,13 +898,24 @@ int fctprintf(void (*out)(char character, void* arg), void* arg, const char* for
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
__attribute__((weak)) void _debug_uart_putc(int ch);
|
__attribute__((weak)) void _debug_uart_putc(int ch) {}
|
||||||
|
|
||||||
|
static inline void _out_char_early(char character, void* buffer, size_t idx, size_t maxlen)
|
||||||
|
{
|
||||||
|
(void)buffer;
|
||||||
|
(void)idx;
|
||||||
|
(void)maxlen;
|
||||||
|
if (character) {
|
||||||
|
_debug_uart_putc(character);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int printf_early(const char* format, ...)
|
int printf_early(const char* format, ...)
|
||||||
{
|
{
|
||||||
va_list va;
|
va_list va;
|
||||||
va_start(va, format);
|
va_start(va, format);
|
||||||
char buffer[1];
|
char buffer[1];
|
||||||
const int ret = _vsnprintf(_debug_uart_putc, buffer, (size_t)-1, format, va);
|
const int ret = _vsnprintf(_out_char_early, buffer, (size_t)-1, format, va);
|
||||||
va_end(va);
|
va_end(va);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue