uart and gic from dtb
This commit is contained in:
parent
b5d93b9b73
commit
6b34443bee
@ -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",
|
||||
|
16
sys/arm64/include/bootinfo.h
Normal file
16
sys/arm64/include/bootinfo.h
Normal 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;
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
@ -51,22 +81,24 @@ MachineBoot_Entry(unsigned long magic, paddr_t dtb_paddr, unsigned long dtb_len)
|
||||
if (magic != 0x10CA5201) {
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user