Files
lk/arch/vax/arch.c
Travis Geiselbrecht d06fbd35c8 [arch][vax] redid the exception code, added timers
The port more or less fully works now, except for actual interrupt
driven io and proper atomics.

Also hit a floating point exception in the string benchmark.
2019-10-21 02:52:38 -07:00

116 lines
3.6 KiB
C

/*
* Copyright (c) 2019 Travis Geiselbrecht
*
* Use of this source code is governed by a MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT
*/
#include <assert.h>
#include <lk/compiler.h>
#include <lk/debug.h>
#include <lk/trace.h>
#include <stdint.h>
#include <arch/ops.h>
#include <arch/vax.h>
#include <kernel/thread.h>
#define LOCAL_TRACE 0
// initial boot stack that start.S leaves us on
extern uint8_t boot_stack[1024];
static uint8_t irq_stack[512] __ALIGNED(4);
// defined in assembly
extern uint32_t SCB[];
extern void vax_undefined_exception(void);
extern void vax_exception_table(void);
static void dump_pr(const char *name, int reg) {
printf("%s\t%#x\n", name, mfpr(reg));
}
#define dump_pr_byname(name) \
dump_pr(#name, PR_##name)
static void dump_regs(void) {
dump_pr_byname(SID);
dump_pr_byname(KSP); // Kernel Stack Pointer
dump_pr_byname(ESP); // Executive Stack Pointer
dump_pr_byname(SSP); // Supervisor Stack Pointer
dump_pr_byname(USP); // User Stack Pointer
dump_pr_byname(ISP); // Interrupt Stack Pointer
dump_pr_byname(P0BR); // P0 Base Register
dump_pr_byname(P0LR); // P0 Length Register
dump_pr_byname(P1BR); // P1 Base Register
dump_pr_byname(P1LR); // P1 Length Register
dump_pr_byname(SBR); // System Base Register
dump_pr_byname(SLR); // System Limit Register
dump_pr_byname(PCBB); // Process Control Block Base
dump_pr_byname(SCBB); // System Control Block Base
dump_pr_byname(IPL); // Interrupt Priority Level
dump_pr_byname(MAPEN); // Memory Management Enable
}
void arch_early_init(void) {
// initialize any empty slots in the SCB
for (int i = 0; i < SCB_MAX_OFFSET / 4; i++) {
if (SCB[i] == 0) {
SCB[i] = ((uint32_t)&vax_exception_table + (i * 16)) | SCB_FLAG_KERNEL_STACK;
}
}
mtpr((uint32_t)SCB, PR_SCBB);
// point the pcb base register at the bootstrap thread's empty pcb.
// we'll switch from it later when starting the threading system.
mtpr((uint32_t)&get_current_thread()->arch.pcb, PR_PCBB);
get_current_thread()->arch.pcb.p0lr = (4<<24); // set the AST level to 4
// set the interrupt stack. currently unused, but set it to something safe for now.
mtpr((uint32_t)irq_stack + sizeof(irq_stack), PR_ISP);
// null out the mmu registers
mtpr(0, PR_MAPEN);
mtpr(0, PR_SBR);
mtpr(0, PR_SLR);
mtpr(0, PR_P0BR);
mtpr(0, PR_P0LR);
mtpr(0, PR_P1BR);
mtpr(0, PR_P1LR);
dump_regs();
}
void arch_init(void) {
// print some arch info
//dprintf(INFO, "RISCV: mvendorid %#lx marchid %#lx mimpid %#lx mhartid %#lx\n",
// riscv_csr_read(mvendorid), riscv_csr_read(marchid),
// riscv_csr_read(mimpid), riscv_csr_read(mhartid));
//dprintf(INFO, "RISCV: misa %#lx\n", riscv_csr_read(misa));
// enable external interrupts
//riscv_csr_set(mie, RISCV_MIE_MEIE);
}
void arch_idle(void) {
// __asm__ volatile("wfi");
}
void arch_chain_load(void *entry, ulong arg0, ulong arg1, ulong arg2, ulong arg3) {
PANIC_UNIMPLEMENTED;
}
/* unimplemented cache operations */
void arch_disable_cache(uint flags) { PANIC_UNIMPLEMENTED; }
void arch_enable_cache(uint flags) { PANIC_UNIMPLEMENTED; }
void arch_clean_cache_range(addr_t start, size_t len) { PANIC_UNIMPLEMENTED; }
void arch_clean_invalidate_cache_range(addr_t start, size_t len) { PANIC_UNIMPLEMENTED; }
void arch_invalidate_cache_range(addr_t start, size_t len) { PANIC_UNIMPLEMENTED; }
void arch_sync_cache_range(addr_t start, size_t len) { PANIC_UNIMPLEMENTED; }