[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.
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
#include <stdint.h>
|
||||
#include <arch/ops.h>
|
||||
#include <arch/vax.h>
|
||||
#include <kernel/thread.h>
|
||||
|
||||
#define LOCAL_TRACE 0
|
||||
|
||||
@@ -19,8 +20,8 @@
|
||||
extern uint8_t boot_stack[1024];
|
||||
static uint8_t irq_stack[512] __ALIGNED(4);
|
||||
|
||||
static uint32_t SCB[scb_max_index] __ALIGNED(512);
|
||||
static struct vax_pcb pcb;
|
||||
// defined in assembly
|
||||
extern uint32_t SCB[];
|
||||
|
||||
extern void vax_undefined_exception(void);
|
||||
extern void vax_exception_table(void);
|
||||
@@ -56,16 +57,19 @@ static void dump_regs(void) {
|
||||
|
||||
void arch_early_init(void) {
|
||||
|
||||
// initialize the SCB
|
||||
for (int i = 0; i < scb_max_index; i++) {
|
||||
SCB[i] = ((uint32_t)&vax_exception_table + (i * 16)) | SCB_FLAG_KERNEL_STACK;
|
||||
// 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 an initial, empty PCB.
|
||||
// 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)&pcb, PR_PCBB);
|
||||
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);
|
||||
|
||||
@@ -6,20 +6,24 @@
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
#include <lk/asm.h>
|
||||
#include <arch/vax.h>
|
||||
|
||||
// a global label, but not typed as a function
|
||||
#define GLABEL(x) .globl x; x:
|
||||
|
||||
.text
|
||||
|
||||
// first level exception vectors must be 4 byte aligned
|
||||
.balign 4
|
||||
.globl vax_undefined_exception
|
||||
vax_undefined_exception:
|
||||
GLABEL(vax_undefined_exception)
|
||||
halt
|
||||
|
||||
// for every possible exception handler, build a veneer routine that pushes
|
||||
// the exception number to the stack and branches to a common routine
|
||||
.balign 16
|
||||
.globl vax_exception_table
|
||||
vax_exception_table:
|
||||
GLABEL(vax_exception_table)
|
||||
.set i, 0
|
||||
.rept (0x600/4)
|
||||
.rept (SCB_MAX_OFFSET / 4)
|
||||
|
||||
pushl $i
|
||||
jbr interrupt_common
|
||||
@@ -27,7 +31,43 @@ jbr interrupt_common
|
||||
|
||||
.set i, i + 1
|
||||
.endr
|
||||
END_DATA(vax_exception_table)
|
||||
|
||||
FUNCTION(interrupt_common)
|
||||
.align 4
|
||||
GLABEL(interrupt_common)
|
||||
halt
|
||||
END_FUNCTION(interrupt_common)
|
||||
|
||||
.align 4
|
||||
GLABEL(_vax_mcheck)
|
||||
halt
|
||||
END_FUNCTION(_vax_mcheck)
|
||||
|
||||
.align 4
|
||||
GLABEL(_vax_invkstk)
|
||||
halt
|
||||
END_FUNCTION(_vax_invkstk)
|
||||
|
||||
.align 4
|
||||
GLABEL(_vax_interval_timer)
|
||||
pushr $0xfff
|
||||
|
||||
calls $0,vax_interval_timer
|
||||
|
||||
popr $0xfff
|
||||
rei
|
||||
END_FUNCTION(_vax_interval_timer)
|
||||
|
||||
// fill in a pre-computed SCB with a few vectors that we care about
|
||||
|
||||
#define SEEK(x) .org (x + SCB)
|
||||
#define SCB_VECTOR(offset, funct, stack) SEEK(offset); .long funct + stack
|
||||
.section .data
|
||||
.balign 4
|
||||
DATA(SCB)
|
||||
SCB_VECTOR(4, _vax_mcheck, SCB_FLAG_INT_STACK)
|
||||
SCB_VECTOR(8, _vax_invkstk, SCB_FLAG_INT_STACK)
|
||||
//SCB_VECTOR(40, _vax_syscall, SCB_FLAG_KERNEL_STACK)
|
||||
SCB_VECTOR(0xc0, _vax_interval_timer, SCB_FLAG_KERNEL_STACK)
|
||||
SEEK(SCB_MAX_OFFSET)
|
||||
END_DATA(SCB)
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#define PAGE_SIZE 512
|
||||
#define PAGE_SIZE_SHIFT 9
|
||||
|
||||
// XXX is this right?
|
||||
// is this right?
|
||||
#define CACHE_LINE 32
|
||||
|
||||
#define ARCH_DEFAULT_STACK_SIZE 1024
|
||||
#define ARCH_DEFAULT_STACK_SIZE 4096
|
||||
|
||||
@@ -7,22 +7,21 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <arch/vax/mtpr.h>
|
||||
|
||||
// Indexes (in units of a long word) into the SCB for various vectors
|
||||
// that we care about. Many are not used yet, so dont fill all of them.
|
||||
enum vax_scb_index {
|
||||
foo = 0,
|
||||
// Offsets into the SCB for various vectors that we care about.
|
||||
// Many are not used yet, so dont fill all of them.
|
||||
|
||||
scb_adaptor_base_index = 0x100/4,
|
||||
#define SCB_ADAPTER_BASE (0x100)
|
||||
#define SCB_DEVICE_BASE (0x200)
|
||||
#define SCB_MAX_OFFSET (0x600) // according to the 1987 vax arch manual
|
||||
|
||||
scb_device_base_index = 0x200/4,
|
||||
scb_max_index = 0x600/4
|
||||
};
|
||||
#define SCB_FLAG_KERNEL_STACK (0b00)
|
||||
#define SCB_FLAG_INT_STACK (0b01)
|
||||
|
||||
#define SCB_FLAG_KERNEL_STACK (0b00)
|
||||
#define SCB_FLAG_INT_STACK (0b01)
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
struct vax_pcb {
|
||||
uint32_t ksp;
|
||||
@@ -39,4 +38,5 @@ struct vax_pcb {
|
||||
};
|
||||
|
||||
static_assert(sizeof(struct vax_pcb) == 96);
|
||||
#endif // __ASSEMBLER__
|
||||
|
||||
|
||||
@@ -27,8 +27,7 @@
|
||||
|
||||
/* All bugs are subject to removal without further notice */
|
||||
|
||||
#ifndef _VAX_MTPR_H_
|
||||
#define _VAX_MTPR_H_
|
||||
#pragma once
|
||||
|
||||
/******************************************************************************
|
||||
|
||||
@@ -159,7 +158,7 @@
|
||||
#define AST_NO 4
|
||||
#define AST_OK 3
|
||||
|
||||
#ifndef _LOCORE
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
typedef unsigned int register_t;
|
||||
|
||||
@@ -183,6 +182,4 @@ mfpr(int reg)
|
||||
: "g" (reg));
|
||||
return __val;
|
||||
}
|
||||
#endif /* _LOCORE */
|
||||
|
||||
#endif /* _VAX_MTPR_H_ */
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#include <kernel/thread.h>
|
||||
#include <arch/vax.h>
|
||||
|
||||
#define LOCAL_TRACE 1
|
||||
#define LOCAL_TRACE 0
|
||||
|
||||
struct thread *_current_thread;
|
||||
|
||||
|
||||
@@ -82,4 +82,6 @@ void platform_early_console_init(void) {
|
||||
}
|
||||
}
|
||||
|
||||
void platform_console_init(void) {
|
||||
}
|
||||
|
||||
|
||||
@@ -40,14 +40,10 @@ void platform_early_init(void) {
|
||||
printf("VAX: sid %#x\n", sid);
|
||||
printf("VAX: cputype %#x\n", vax_cputype);
|
||||
printf("VAX: boardtype %#x\n", vax_boardtype);
|
||||
|
||||
platform_early_timer_init();
|
||||
}
|
||||
|
||||
// stubbed out time
|
||||
static lk_time_t t = 0;
|
||||
lk_time_t current_time() {
|
||||
return ++t;
|
||||
}
|
||||
|
||||
lk_bigtime_t current_time_hires() {
|
||||
return (++t) * 1000;
|
||||
void platform_init(void) {
|
||||
platform_console_init();
|
||||
}
|
||||
|
||||
@@ -15,3 +15,5 @@ extern uint32_t vax_cputype;
|
||||
extern uint32_t vax_boardtype;
|
||||
|
||||
void platform_early_console_init(void);
|
||||
void platform_console_init(void);
|
||||
void platform_early_timer_init(void);
|
||||
|
||||
@@ -7,12 +7,58 @@
|
||||
*/
|
||||
#include <lk/debug.h>
|
||||
#include <lk/err.h>
|
||||
#include <lk/trace.h>
|
||||
#include <kernel/thread.h>
|
||||
#include <platform.h>
|
||||
#include <platform/timer.h>
|
||||
#include <arch/vax.h>
|
||||
|
||||
static uint32_t ticks;
|
||||
static platform_timer_callback cb;
|
||||
static void *cb_arg;
|
||||
|
||||
// stubbed out timer
|
||||
status_t platform_set_periodic_timer(platform_timer_callback callback, void *arg, lk_time_t interval) {
|
||||
// for the moment, assume the kernel is asking for 10ms
|
||||
DEBUG_ASSERT(interval == 10);
|
||||
|
||||
cb = callback;
|
||||
cb_arg = arg;
|
||||
|
||||
return NO_ERROR;
|
||||
PANIC_UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
// fires once every 10ms
|
||||
void vax_interval_timer(void) {
|
||||
ticks++;
|
||||
|
||||
enum handler_return ret = cb(cb_arg, current_time());
|
||||
if (ret == INT_RESCHEDULE) {
|
||||
thread_preempt();
|
||||
}
|
||||
}
|
||||
|
||||
void platform_early_timer_init(void) {
|
||||
// we can only assume there is a single 10ms interval timer available,
|
||||
// but go ahead and configure it using the full register interface, since it
|
||||
// wont hurt.
|
||||
|
||||
// load the next count register with -10000 usecs
|
||||
mtpr(-10000, PR_NICR);
|
||||
|
||||
// start the timer and clear any old state
|
||||
// clear error, clear interrupt, enable interrupt, load count, run
|
||||
mtpr((1<<31) | (1<<7) | (1<<6) | (1<<4) | (1<<0), PR_ICCS);
|
||||
}
|
||||
|
||||
void platform_timer_init(void) {
|
||||
}
|
||||
|
||||
lk_time_t current_time() {
|
||||
return ticks * 10;
|
||||
}
|
||||
|
||||
lk_bigtime_t current_time_hires() {
|
||||
return ticks * 10000;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,3 +12,7 @@
|
||||
|
||||
#define LOCAL_FUNCTION(x) .type x,STT_FUNC; x:
|
||||
#define LOCAL_DATA(x) .type x,STT_OBJECT; x:
|
||||
|
||||
#define END_FUNCTION(x) .size x, . - x
|
||||
#define END_DATA(x) .size x, . - x
|
||||
|
||||
|
||||
Reference in New Issue
Block a user