uart and gic from dtb

This commit is contained in:
quackerd 2024-10-22 02:47:21 -04:00
parent b5d93b9b73
commit 6b34443bee
11 changed files with 198 additions and 93 deletions

View File

@ -54,10 +54,10 @@ src_arm64 = [
"arm64/time.c",
"arm64/trap.c",
"arm64/trapentry.S",
"arm64/gic.c",
"arm64/pdcache.c",
# Devices
"dev/arm64/uart.c",
"dev/arm64/gic.c",
# Metal
"arm64/metal.c",
"arm64/paging.c",

View File

@ -0,0 +1,16 @@
#pragma once
#include <stdint.h>
#define MAX_BOOT_MEM_REGIONS 16
struct bootinfo {
const void * dtb_addr;
unsigned int dtb_len;
paddr_t mem_region_base[MAX_BOOT_MEM_REGIONS];
size_t mem_region_len[MAX_BOOT_MEM_REGIONS];
unsigned int mem_region_sz;
};
extern struct bootinfo kbootinfo;

View File

@ -107,4 +107,4 @@ vm_insert_pd(struct vmpt * pt, struct vmpd * pd, unsigned int pgshift, paddr_t p
}
void paging_init();
void vm_early_paging_init();

View File

@ -12,7 +12,6 @@
#include <machine/trap.h>
#include <machine/pmap.h>
#include <machine/mp.h>
#include <machine/gic.h>
#include <sys/thread.h>
#include <sys/disk.h>
@ -20,6 +19,7 @@
#include <sys/vfs.h>
#include <sys/elf64.h>
#include "../dev/arm64/gic.h"
#include "../dev/console.h"
#include <machine/cpuop.h>
#include <machine/metal.h>
@ -83,29 +83,6 @@ void Machine_Init()
{
Machine_EarlyInit();
kprintf("Initializing GIC ...\n");
if (gic_init() != 0) {
PANIC("gic initialization failed!\n");
}
kprintf("GIC initialized.\n");
// enable hardware timer
// __asm__ volatile (
// "mrs x1, CNTFRQ_EL0;"
// "msr CNTP_TVAL_EL0, x1;"
// "mov x0, #1;"
// "msr CNTP_CTL_EL0, x0;"
// "msr DAIFClr, #0b1111;"
// :
// :
// : "x0", "x1"
// );
// while(1){
// hlt();
// }
//Machine_SyscallInit();
/*
@ -117,6 +94,26 @@ void Machine_Init()
XMem_Init();
PAlloc_LateInit();
MachineBoot_AddMem();
// initialize GIC
kprintf("Initializing GIC ...\n");
if (gic_init() != 0) {
PANIC("GIC initialization failed!\n");
}
kprintf("GIC Initialized!\n");
//enable hardware timer
// __asm__ volatile (
// "mrs x1, CNTFRQ_EL0;"
// "msr CNTP_TVAL_EL0, x1;"
// "mov x0, #1;"
// "msr CNTP_CTL_EL0, x0;"
// "msr DAIFClr, #0b1111;"
// :
// :
// : "x0", "x1"
// );
while(1){
hlt();
}
@ -139,7 +136,7 @@ void Machine_Init()
/*
* Initialize Additional Processors
*/
MP_Init();
// MP_Init();
/*
* Initialize Basic Devices

View File

@ -13,6 +13,7 @@
#include <machine/mrt.h>
#include <machine/pmap.h>
#include <machine/paging.h>
#include <machine/bootinfo.h>
#include <sys/contrib/libfdt/libfdt.h>
@ -23,26 +24,55 @@ extern void Machine_EarlyInit();
extern void Machine_Init();
extern void PAlloc_AddRegion(uintptr_t start, uintptr_t len);
#define MAX_REGIONS 16
static uintptr_t memRegionStart[MAX_REGIONS];
static uintptr_t memRegionLen[MAX_REGIONS];
static int memRegionIdx;
struct bootinfo kbootinfo;
static void
machineboot_init_mem_regions()
//
// parse the total memory
//
static bool
machineboot_parse_dtb()
{
// kernel loaded at 4MB
// 2GB to 3GB
memRegionStart[0] = 0x80000000;
// 1GB
memRegionLen[0] = 0x40000000;
memRegionIdx = 1;
}
const void * dtb = kbootinfo.dtb_addr;
bool
machineboot_parse_dtb(const void * dtb, unsigned long len)
{
return fdt_check_full(dtb, len) == 0;
if (fdt_num_mem_rsv(kbootinfo.dtb_addr) > 0) {
/* XXX: don't support memory reservation for now */
return false;
}
int offset = -1;
kbootinfo.mem_region_sz = 0;
while(true) {
offset = fdt_node_offset_by_prop_value(dtb, offset, "device_type",
"memory", strlen("memory") + 1);
if (offset < 0) {
break;
}
if (kbootinfo.mem_region_sz >= MAX_BOOT_MEM_REGIONS) {
// max region reached
return false;
}
int lenp;
const struct fdt_property * prop = fdt_get_property(dtb, offset, "reg", &lenp);
if (prop == NULL || lenp != 4 * sizeof(uint32_t)) {
// invalid memory block spec
return false;
}
const uint32_t * ptr = (const uint32_t *)prop->data;
const uint64_t base = fdt32_to_cpu(ptr[1]) | ((uint64_t)fdt32_to_cpu(ptr[0]) << 32);
const uint64_t limit = fdt32_to_cpu(ptr[3]) | ((uint64_t)fdt32_to_cpu(ptr[2]) << 32);
kbootinfo.mem_region_base[kbootinfo.mem_region_sz] = base;
kbootinfo.mem_region_len[kbootinfo.mem_region_sz] = limit;
kbootinfo.mem_region_sz++;
}
return kbootinfo.mem_region_sz > 0;
}
void
@ -52,21 +82,23 @@ MachineBoot_Entry(unsigned long magic, paddr_t dtb_paddr, unsigned long dtb_len)
Halt();
}
const void * dtb = (const void *)DMPA2VA(dtb_paddr);
if (!machineboot_parse_dtb(dtb, dtb_len)){
Halt();
}
// initialize metal mode
mtl_init();
// early metal paging init
paging_init();
vm_early_paging_init();
// initialize memory regions
machineboot_init_mem_regions();
// parse dtb files
if (fdt_check_full((const void *)DMPA2VA(dtb_paddr), dtb_len) != 0) {
Halt();
}
kbootinfo.dtb_addr = (const void *)DMPA2VA(dtb_paddr);
kbootinfo.dtb_len = dtb_len;
if (!machineboot_parse_dtb()){
Halt();
}
// Main initialization
Machine_Init();
@ -77,24 +109,24 @@ MachineBoot_Entry(unsigned long magic, paddr_t dtb_paddr, unsigned long dtb_len)
void
MachineBoot_AddMem()
{
int i;
unsigned int i;
uintptr_t initRamEnd = 32*1024*1024;
for (i = 0; i < memRegionIdx; i++)
for (i = 0; i < kbootinfo.mem_region_sz; i++)
{
uintptr_t start = memRegionStart[i];
uintptr_t len = memRegionLen[i];
uintptr_t start = kbootinfo.mem_region_base[i];
uintptr_t len = kbootinfo.mem_region_len[i];
if (start + len < initRamEnd)
continue;
if (start + len < initRamEnd)
continue;
if (start < initRamEnd) {
len = initRamEnd - start;
start = initRamEnd;
}
kprintf("Adding Region: 0x%llx 0x%llx ... ", start, len);
PAlloc_AddRegion(start + MEM_DIRECTMAP_BASE, len);
kprintf("Done!\n");
if (start < initRamEnd) {
len = initRamEnd - start;
start = initRamEnd;
}
kprintf("Initializing physical memory region: base = 0x%llx, len = 0x%llx ... ", start, len);
PAlloc_AddRegion(start + MEM_DIRECTMAP_BASE, len);
kprintf("Done!\n");
}
}

View File

@ -1,4 +1,5 @@
#include "machine/cpu.h"
#include <machine/cpu.h>
#include <sys/kassert.h>
#include <machine/metalp.h>
#include <machine/paging.h>
#include <machine/pmap.h>
@ -14,8 +15,7 @@ static struct vmpt boot_pt;
static struct vmpd boot_pd[BOOT_PD_NUM];
static struct vmpd boot_dev_pd[BOOT_PD_NUM];
void paging_init()
void vm_early_paging_init()
{
int ret;
memset(&boot_pd, 0, sizeof(boot_pd));
@ -51,7 +51,7 @@ void paging_init()
METAL_MENTER(MRT_SET_MPTB_IDX);
METAL_MROUTINE_GETRET(MRT_SET_MPTB_RET_STATUS, ret);
if (ret != 0) {
hlt();
Halt();
}
// set page table attribute override bits

View File

@ -79,7 +79,7 @@ pdcache_grow()
pdc.first = first;
pdc.total += free;
kprintf("Growing pdcache: +%d nodes, free: %d nodes, total: %d nodes.\n", free, pdc.free, pdc.total);
//kprintf("Growing pdcache: +%d nodes, free: %d nodes, total: %d nodes.\n", free, pdc.free, pdc.total);
return 0;
}

View File

@ -63,7 +63,7 @@ PMapAllocPageTable()
void
PMap_Init()
{
kprintf("Initializing PMAP ...\n");
kprintf("Initializing PMAP ... ");
// Setup global state
for (int i = 0; i < MAX_CPUS; i++) {
@ -93,7 +93,7 @@ PMap_Init()
PMap_LoadAS(&systemAS);
kprintf("PMAP initialized.\n");
kprintf("Done!\n");
}
void

View File

@ -1,11 +1,14 @@
#include <machine/gic.h>
#include "include/pmap.h"
#include "sys/cdefs.h"
#include "errno.h"
#include <machine/pmap.h>
#include <machine/bootinfo.h>
#include <sys/cdefs.h>
#include <errno.h>
#include <sys/kassert.h>
#include "gic.h"
#define DIST_BASE_ADDR (0x2c000000)
#define REDIST_BASE_ADDR (0x2c010000)
#include <sys/contrib/libfdt/libfdt.h>
// #define DIST_BASE_ADDR (0x2c000000)
// #define REDIST_BASE_ADDR (0x2c010000)
struct GICv3_dist_if
{
@ -202,8 +205,6 @@ struct GICv3_its_sgi_if
volatile uint64_t GITS_SGIR; // +0x0020 - RW - Written by peripherals to generate vSGI (GICv4.1)
};
struct gic {
struct GICv3_dist_if* gic_dist;
struct GICv3_rdist_if* gic_rdist;
@ -216,13 +217,33 @@ static struct gic gic = {
.max_rd = 0
};
static void
gic_addr_init(void)
static bool
gic_discover(void)
{
const void * dtb = kbootinfo.dtb_addr;
const int offset = fdt_node_offset_by_compatible(dtb, -1, "arm,gic-v3");
if (offset < 0) {
return false;
}
int lenp;
const struct fdt_property * prop = fdt_get_property(dtb, offset, "reg", &lenp);
if (prop == NULL || lenp != 8 * sizeof(uint32_t)) {
// invalid gicv3 dtb spec
return false;
}
const uint32_t * ptr = (const uint32_t *)prop->data;
const uint64_t dist_base = fdt32_to_cpu(ptr[1]) | ((uint64_t)fdt32_to_cpu(ptr[0]) << 32);
const uint64_t redist_base = fdt32_to_cpu(ptr[5]) | ((uint64_t)fdt32_to_cpu(ptr[4]) << 32);
uint32_t index = 0;
gic.gic_dist = (void*)DEVPA2VA(DIST_BASE_ADDR);
gic.gic_rdist = (void*)DEVPA2VA(REDIST_BASE_ADDR);
gic.gic_dist = (void*)DEVPA2VA(dist_base);
gic.gic_rdist = (void*)DEVPA2VA(redist_base);
kprintf("GIC v3 dist base = 0x%llx, redist base = 0x%llx.\n", gic.gic_dist, gic.gic_rdist);
while((gic.gic_rdist[index].lpis.GICR_TYPER & (1<<4)) == 0) // Keep incrementing until GICR_TYPER.Last reports no more RDs in block
{
@ -230,6 +251,8 @@ gic_addr_init(void)
}
gic.max_rd = index;
return true;
}
static void
@ -639,7 +662,10 @@ gic_init(void)
{
int ret;
gic_addr_init();
if (!gic_discover()) {
return ENOENT;
}
gic_enable();
unsigned int rd;

View File

@ -1,7 +1,12 @@
#include "uart.h"
#include "sys/kassert.h"
#include <stdint.h>
#include "machine/pmap.h"
#include <sys/kassert.h>
#include <machine/bootinfo.h>
#include <machine/pmap.h>
#include <sys/contrib/libfdt/libfdt.h>
#include "uart.h"
#define UART_DR_OFFSET (0x000)
#define UART_FR_OFFSET (0x018)
@ -27,7 +32,7 @@ struct uart {
};
static struct uart g_uart0 = {
.base = DEVPA2VA(0x1c090000),
.base = 0,
.baud = 115200,
.clock = 24000000,
.dbits = 8,
@ -54,9 +59,40 @@ uart_tx_wait(const struct uart *dev)
}
}
static bool
uart_discover(struct uart * dev)
{
const void * dtb = kbootinfo.dtb_addr;
const int offset = fdt_node_offset_by_compatible(dtb, -1, "arm,pl011");
if (offset < 0) {
return false;
}
int lenp;
const struct fdt_property * prop = fdt_get_property(dtb, offset, "reg", &lenp);
if (prop == NULL || lenp != 4 * sizeof(uint32_t)) {
// invalid pl011 uart spec
return false;
}
const uint32_t * ptr = (const uint32_t *)prop->data;
const uint64_t base = fdt32_to_cpu(ptr[1]) | ((uint64_t)fdt32_to_cpu(ptr[0]) << 32);
dev->base = DEVPA2VA(base);
return true;
}
static void
uart_init(struct uart *dev)
{
if (!uart_discover(dev)) {
PANIC("Failed to discover uart");
}
uint32_t cr = uart_readreg(dev, UART_CR_OFFSET);
uint32_t lcr = uart_readreg(dev, UART_LCR_OFFSET);
@ -114,8 +150,6 @@ Serial_Send(const char *data, size_t size)
{
if (g_uart0.initialized) {
uart_send(&g_uart0, data, size);
} else {
Halt();
}
}