Squash commits for public release
This commit is contained in:
17
boot/arm32/vmm/consts.h
Normal file
17
boot/arm32/vmm/consts.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef _BOOT_VMM_CONSTS_H
|
||||
#define _BOOT_VMM_CONSTS_H
|
||||
|
||||
#define VMM_LV0_ENTITY_COUNT (256)
|
||||
#define VMM_LV1_ENTITY_COUNT (4096)
|
||||
#define VMM_PAGE_SIZE (4096)
|
||||
|
||||
#define VMM_OFFSET_IN_DIRECTORY(a) (((a) >> 20) & 0xfff)
|
||||
#define VMM_OFFSET_IN_TABLE(a) (((a) >> 12) & 0xff)
|
||||
#define VMM_OFFSET_IN_PAGE(a) ((a)&0xfff)
|
||||
#define TABLE_START(vaddr) ((vaddr >> 20) << 20)
|
||||
#define PAGE_START(vaddr) ((vaddr >> 12) << 12)
|
||||
#define FRAME(addr) (addr / VMM_PAGE_SIZE)
|
||||
|
||||
#define PTABLE_TOP_KERNEL_OFFSET 3072
|
||||
|
||||
#endif //_BOOT_VMM_CONSTS_H
|
||||
147
boot/arm32/vmm/vmm.c
Normal file
147
boot/arm32/vmm/vmm.c
Normal file
@@ -0,0 +1,147 @@
|
||||
#include "vmm.h"
|
||||
#include <libboot/log/log.h>
|
||||
#include <libboot/mem/alloc.h>
|
||||
#include <libboot/mem/mem.h>
|
||||
#include <libboot/types.h>
|
||||
|
||||
// #define DEBUG_VMM
|
||||
|
||||
#define VMM_OFFSET_IN_DIRECTORY(a) (((a) >> 20) & 0xfff)
|
||||
#define VMM_OFFSET_IN_TABLE(a) (((a) >> 12) & 0xff)
|
||||
#define VMM_OFFSET_IN_PAGE(a) ((a)&0xfff)
|
||||
#define ALIGN_TO_TABLE(a) ((a)&0xfff00000)
|
||||
|
||||
static pdirectory_t* pdir = NULL;
|
||||
|
||||
static ptable_t* map_table(size_t tphyz, size_t tvirt);
|
||||
static void mmu_enable();
|
||||
|
||||
static inline void write_ttbcr(uint32_t val)
|
||||
{
|
||||
asm volatile("mcr p15, 0, %0, c2, c0, 2"
|
||||
:
|
||||
: "r"(val)
|
||||
: "memory");
|
||||
asm volatile("dmb");
|
||||
}
|
||||
|
||||
static inline void write_ttbr0(uint32_t val)
|
||||
{
|
||||
asm volatile("mcr p15, 0, %0, c2, c0, 0"
|
||||
:
|
||||
: "r"(val)
|
||||
: "memory");
|
||||
asm volatile("dmb");
|
||||
}
|
||||
|
||||
static inline void write_dacr(uint32_t val)
|
||||
{
|
||||
asm volatile("mcr p15, 0, %0, c3, c0, 0"
|
||||
:
|
||||
: "r"(val));
|
||||
asm volatile("dmb");
|
||||
}
|
||||
|
||||
static void mmu_enable()
|
||||
{
|
||||
volatile uint32_t val;
|
||||
asm volatile("mrc p15, 0, %0, c1, c0, 0"
|
||||
: "=r"(val));
|
||||
asm volatile("orr %0, %1, #0x1"
|
||||
: "=r"(val)
|
||||
: "r"(val));
|
||||
asm volatile("mcr p15, 0, %0, c1, c0, 0" ::"r"(val)
|
||||
: "memory");
|
||||
asm volatile("isb");
|
||||
}
|
||||
|
||||
static pdirectory_t* vm_alloc_pdir()
|
||||
{
|
||||
return (pdirectory_t*)malloc_aligned(sizeof(pdirectory_t), sizeof(pdirectory_t));
|
||||
}
|
||||
|
||||
static ptable_t* vm_alloc_ptable()
|
||||
{
|
||||
return (ptable_t*)malloc_aligned(sizeof(ptable_t), sizeof(ptable_t));
|
||||
}
|
||||
|
||||
static ptable_t* map_table(size_t tphyz, size_t tvirt)
|
||||
{
|
||||
ptable_t* table = vm_alloc_ptable();
|
||||
for (size_t phyz = tphyz, virt = tvirt, i = 0; i < VMM_LV0_ENTITY_COUNT; phyz += VMM_PAGE_SIZE, virt += VMM_PAGE_SIZE, i++) {
|
||||
page_desc_t new_page;
|
||||
new_page.one = 1;
|
||||
new_page.baddr = (phyz / VMM_PAGE_SIZE);
|
||||
new_page.tex = 0b001;
|
||||
new_page.c = 1;
|
||||
new_page.b = 1;
|
||||
new_page.ap1 = 0b11;
|
||||
new_page.ap2 = 0b0;
|
||||
new_page.s = 1;
|
||||
table->entities[i] = new_page;
|
||||
}
|
||||
|
||||
uint32_t table_int = (uint32_t)table;
|
||||
pdir->entities[VMM_OFFSET_IN_DIRECTORY(tvirt)].valid = 1;
|
||||
pdir->entities[VMM_OFFSET_IN_DIRECTORY(tvirt)].zero1 = 0;
|
||||
pdir->entities[VMM_OFFSET_IN_DIRECTORY(tvirt)].zero2 = 0;
|
||||
pdir->entities[VMM_OFFSET_IN_DIRECTORY(tvirt)].ns = 0;
|
||||
pdir->entities[VMM_OFFSET_IN_DIRECTORY(tvirt)].zero3 = 0;
|
||||
pdir->entities[VMM_OFFSET_IN_DIRECTORY(tvirt)].domain = 0b0011;
|
||||
pdir->entities[VMM_OFFSET_IN_DIRECTORY(tvirt)].baddr = ((table_int / 1024));
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
static void vm_init()
|
||||
{
|
||||
pdir = vm_alloc_pdir();
|
||||
|
||||
for (int i = 0; i < VMM_LV1_ENTITY_COUNT; i++) {
|
||||
pdir->entities[i].valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void vm_map_devices()
|
||||
{
|
||||
map_table(0x1c000000, 0x1c000000); // mapping uart
|
||||
}
|
||||
|
||||
void vm_setup(size_t kernel_vaddr, size_t kernel_paddr, size_t kernel_size)
|
||||
{
|
||||
vm_init();
|
||||
vm_map_devices();
|
||||
|
||||
extern int bootloader_start[];
|
||||
size_t bootloader_start_aligned = ALIGN_TO_TABLE((size_t)bootloader_start);
|
||||
map_table(bootloader_start_aligned, bootloader_start_aligned);
|
||||
#ifdef DEBUG_VMM
|
||||
log("map %x to %x", bootloader_start_aligned, bootloader_start_aligned);
|
||||
#endif
|
||||
|
||||
size_t table_paddr = ALIGN_TO_TABLE(kernel_paddr);
|
||||
size_t table_vaddr = ALIGN_TO_TABLE(kernel_vaddr);
|
||||
const size_t bytes_per_table = VMM_LV0_ENTITY_COUNT * VMM_PAGE_SIZE;
|
||||
const size_t tables_per_kernel = align_size((kernel_size + bytes_per_table - 1) / bytes_per_table, 4);
|
||||
for (int i = 0; i < tables_per_kernel; i++) {
|
||||
map_table(table_paddr, table_paddr);
|
||||
map_table(table_paddr, table_vaddr);
|
||||
#ifdef DEBUG_VMM
|
||||
log("map %x to %x", table_paddr, table_paddr);
|
||||
log("map %x to %x", table_paddr, table_vaddr);
|
||||
#endif
|
||||
table_paddr += bytes_per_table;
|
||||
table_vaddr += bytes_per_table;
|
||||
}
|
||||
|
||||
write_ttbr0((size_t)(pdir));
|
||||
write_dacr(0x55555555);
|
||||
mmu_enable();
|
||||
}
|
||||
|
||||
void vm_setup_secondary_cpu()
|
||||
{
|
||||
write_ttbr0((uint32_t)(pdir));
|
||||
write_dacr(0x55555555);
|
||||
mmu_enable();
|
||||
}
|
||||
54
boot/arm32/vmm/vmm.h
Normal file
54
boot/arm32/vmm/vmm.h
Normal file
@@ -0,0 +1,54 @@
|
||||
#ifndef _BOOT_VMM_VMM_H
|
||||
#define _BOOT_VMM_VMM_H
|
||||
|
||||
#include "consts.h"
|
||||
#include <libboot/types.h>
|
||||
|
||||
struct PACKED page_desc {
|
||||
union {
|
||||
struct {
|
||||
unsigned int xn : 1; // Execute never. Stops execution of page.
|
||||
unsigned int one : 1; // Always one for tables
|
||||
unsigned int b : 1; // cacheable
|
||||
unsigned int c : 1; // Cacheable
|
||||
unsigned int ap1 : 2;
|
||||
unsigned int tex : 3;
|
||||
unsigned int ap2 : 1;
|
||||
unsigned int s : 1;
|
||||
unsigned int ng : 1;
|
||||
unsigned int baddr : 20;
|
||||
};
|
||||
uint32_t data;
|
||||
};
|
||||
};
|
||||
typedef struct page_desc page_desc_t;
|
||||
|
||||
struct PACKED table_desc {
|
||||
union {
|
||||
struct {
|
||||
int valid : 1; /* Valid mapping */
|
||||
int zero1 : 1;
|
||||
int zero2 : 1;
|
||||
int ns : 1;
|
||||
int zero3 : 1;
|
||||
int domain : 4;
|
||||
int imp : 1;
|
||||
int baddr : 22;
|
||||
};
|
||||
uint32_t data;
|
||||
};
|
||||
};
|
||||
typedef struct table_desc table_desc_t;
|
||||
|
||||
typedef struct {
|
||||
page_desc_t entities[VMM_LV0_ENTITY_COUNT];
|
||||
} ptable_t;
|
||||
|
||||
typedef struct pdirectory {
|
||||
table_desc_t entities[VMM_LV1_ENTITY_COUNT];
|
||||
} pdirectory_t;
|
||||
|
||||
void vm_setup(size_t kernel_vaddr, size_t kernel_paddr, size_t kernel_size);
|
||||
void vm_setup_secondary_cpu();
|
||||
|
||||
#endif // _BOOT_VMM_VMM_H
|
||||
Reference in New Issue
Block a user