fix 10-SystemCall trap bug

This commit is contained in:
ccckmit
2021-11-15 19:08:55 +08:00
parent 303ca17a1d
commit 662b561d22
4 changed files with 13 additions and 45 deletions

View File

@@ -72,6 +72,7 @@
sw t3, 108(\base)
sw t4, 112(\base)
sw t5, 116(\base)
sw t6, 120(\base)
.endm
.macro reg_load base
@@ -142,12 +143,12 @@ trap_vector:
# save context(registers).
csrrw t6, mscratch, t6 # swap t6 and mscratch
reg_save t6
csrw mscratch, t6
# save mepc to context of current task
csrr a0, mepc
sw a0, 124(t6)
sw a0, 128(t6)
csrrw t6, mscratch, t6
# call the C trap handler in trap.c
csrr a0, mepc
csrr a1, mcause
@@ -158,28 +159,9 @@ trap_vector:
csrw mepc, a0
# load context(registers).
csrr t6, mscratch
csrrw t6, mscratch, t6
reg_load t6
mret
# void switch_to(struct context *next);
# a0: pointer to the context of the next task
.globl switch_to
.align 4
switch_to:
# switch mscratch to point to the context of the next task
csrw mscratch, a0
# set mepc to the pc of the next task
lw a1, 124(a0)
csrw mepc, a1
# Restore all GP registers
# Use t6 to point to the context of the new task
mv t6, a0
reg_load t6
# Do actual context switching.
# Notice this will enable global interrupt
csrrw t6, mscratch, t6
mret
.end

View File

@@ -12,7 +12,6 @@ int task_create(void (*task)(void))
{
int i = taskTop++;
ctx_tasks[i].ra = (reg_t)task;
// ctx_tasks[i].pc = (reg_t)task;
ctx_tasks[i].sp = (reg_t)&task_stack[i][STACK_SIZE - 1];
return i;
}
@@ -21,7 +20,6 @@ int task_create(void (*task)(void))
void task_go(int i)
{
ctx_now = &ctx_tasks[i];
// switch_to(ctx_now);
sys_switch(&ctx_os, &ctx_tasks[i]);
}
@@ -30,6 +28,5 @@ void task_os()
{
struct context *ctx = ctx_now;
ctx_now = &ctx_os;
// switch_to(&ctx_os);
sys_switch(ctx, &ctx_os);
}

View File

@@ -1,7 +1,6 @@
#include "timer.h"
// a scratch area per CPU for machine-mode timer interrupts.
reg_t timer_scratch[NCPU][5];
#define interval 20000000 // cycles; about 2 second in qemu.
@@ -9,23 +8,7 @@ void timer_init()
{
// each CPU has a separate source of timer interrupts.
int id = r_mhartid();
// ask the CLINT for a timer interrupt.
// int interval = 1000000; // cycles; about 1/10th second in qemu.
*(reg_t *)CLINT_MTIMECMP(id) = *(reg_t *)CLINT_MTIME + interval;
// prepare information in scratch[] for timervec.
// scratch[0..2] : space for timervec to save registers.
// scratch[3] : address of CLINT MTIMECMP register.
// scratch[4] : desired interval (in cycles) between timer interrupts.
reg_t *scratch = &timer_scratch[id][0];
scratch[3] = CLINT_MTIMECMP(id);
scratch[4] = interval;
w_mscratch((reg_t)scratch);
// enable machine-mode timer interrupts.
w_mie(r_mie() | MIE_MTIE);
}
static int timer_count = 0;

View File

@@ -4,10 +4,16 @@ extern void trap_vector();
extern void virtio_disk_isr();
extern void do_syscall(struct context *ctx);
// a scratch area per CPU for machine-mode interrupt.
reg_t trap_scratch[NCPU][32+1]; // R0-R31 + mepc
void trap_init()
{
// set the machine-mode trap handler.
w_mtvec((reg_t)trap_vector);
int id = r_mhartid();
reg_t *scratch = &trap_scratch[id][0];
w_mscratch((reg_t)scratch); // set scratch area for this core
w_mtvec((reg_t)trap_vector); // set the machine-mode trap handler.
w_mie(r_mie() | MIE_MTIE); // enable machine-mode timer interrupts.
}
void external_handler()