[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:
Travis Geiselbrecht
2019-10-21 02:52:38 -07:00
parent ac7683f84b
commit d06fbd35c8
11 changed files with 133 additions and 42 deletions

View File

@@ -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);

View File

@@ -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)

View File

@@ -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

View File

@@ -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__

View File

@@ -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__ */

View File

@@ -14,7 +14,7 @@
#include <kernel/thread.h>
#include <arch/vax.h>
#define LOCAL_TRACE 1
#define LOCAL_TRACE 0
struct thread *_current_thread;

View File

@@ -82,4 +82,6 @@ void platform_early_console_init(void) {
}
}
void platform_console_init(void) {
}

View File

@@ -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();
}

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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