123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 |
- /*****************************************************************
- * trap.c
- * by Zhiyi Huang, [email protected]
- * University of Otago
- *
- ********************************************************************/
- #include "types.h"
- #include "defs.h"
- #include "param.h"
- #include "memlayout.h"
- #include "mmu.h"
- #include "proc.h"
- #include "arm.h"
- #include "traps.h"
- #include "spinlock.h"
- extern u8 *vectors;
- void cprintf(char*, ...);
- void dsb_barrier(void);
- void flush_idcache(void);
- void *memmove(void *dst, const void *src, uint n);
- void set_mode_sp(char *, uint);
- struct spinlock tickslock;
- uint ticks;
- void enable_intrs(void)
- {
- intctrlregs *ip;
- ip = (intctrlregs *)INT_REGS_BASE;
- ip->gpuenable[0] |= 1 << 29; // enable the miniuart through Aux
- //ip->gpuenable[1] |= 1 << 25; // enable uart
- ip->armenable |= 1 << 0; // enable the system timer
- }
- void disable_intrs(void)
- {
- intctrlregs *ip;
- int disable;
- ip = (intctrlregs *)INT_REGS_BASE;
- disable = ~0;
- ip->gpudisable[0] = disable;
- ip->gpudisable[1] = disable;
- ip->armdisable = disable;
- ip->fiqctrl = 0;
- }
- void tvinit(void)
- {
- uint *d, *s;
- char *ptr;
- /* initialize the exception vectors */
- d = (uint *)HVECTORS;
- s = (uint *)&vectors;
- memmove(d, s, sizeof(Vpage0));
- /* cacheuwbinv(); drain write buffer and prefetch buffer
- * writeback and invalidate data cache
- * invalidate instruction cache
- */
- dsb_barrier();
- flush_idcache();
- ptr = kalloc();
- memset(ptr, 0, PGSIZE);
- set_mode_sp(ptr+4096, 0xD1);/* fiq mode, fiq and irq are disabled */
- ptr = kalloc();
- memset(ptr, 0, PGSIZE);
- set_mode_sp(ptr+4096, 0xD2);/* irq mode, fiq and irq are disabled */
- ptr = kalloc();
- memset(ptr, 0, PGSIZE);
- set_mode_sp(ptr+4096, 0xDB);/* undefined mode, fiq and irq are disabled */
- ptr = kalloc();
- memset(ptr, 0, PGSIZE);
- set_mode_sp(ptr+4096, 0xD7);/* abort mode, fiq and irq are disabled */
- ptr = kalloc();
- memset(ptr, 0, PGSIZE);
- set_mode_sp(ptr+4096, 0xD6);/* secure monitor mode, fiq and irq are disabled */
- ptr = kalloc();
- memset(ptr, 0, PGSIZE);
- set_mode_sp(ptr+4096, 0xDF);/* system mode, fiq and irq are disabled */
- dsb_barrier();
- }
- void trap_oops(struct trapframe *tf)
- {
- cprintf("trapno: %x, spsr: %x, sp: %x, pc: %x cpsr: %x ifar: %x\n", tf->trapno, tf->spsr, tf->sp, tf->pc, tf->cpsr, tf->ifar);
- cprintf("Saved registers: r0: %x, r1: %x, r2: %x, r3: %x, r4: %x, r5: %x\n", tf->r0, tf->r1, tf->r2, tf->r3, tf->r4, tf->r5);
- cprintf("More registers: r6: %x, r7: %x, r8: %x, r9: %x, r10: %x, r11: %x, r12: %x\n", tf->r6, tf->r7, tf->r8, tf->r9, tf->r10, tf->r11, tf->r12);
- //NotOkLoop();
- }
- void handle_irq(struct trapframe *tf)
- {
- intctrlregs *ip;
- /*cprintf("trapno: %x, spsr: %x, sp: %x, lr: %x cpsr: %x ifar: %x\n", tf->trapno, tf->spsr, tf->sp, tf->pc, tf->cpsr, tf->ifar);
- cprintf("Saved registers: r0: %x, r1: %x, r2: %x, r3: %x, r4: %x, r5: %x, r6: %x\n", tf->r0, tf->r1, tf->r2, tf->r3, tf->r4, tf->r5, tf->r6);
- cprintf("More registers: r6: %x, r7: %x, r8: %x, r9: %x, r10: %x, r11: %x, r12: %x, r13: %x, r14: %x\n", tf->r7, tf->r8, tf->r9, tf->r10, tf->r11, tf->r12, tf->r13, tf->r14);
- */
- ip = (intctrlregs *)INT_REGS_BASE;
- while(ip->gpupending[0] || ip->gpupending[1] || ip->armpending){
- if(ip->gpupending[0] & (1 << 3)) {
- timer3intr();
- }
- if(ip->gpupending[0] & (1 << 29)) {
- miniuartintr();
- }
- }
- }
- //PAGEBREAK: 41
- void
- trap(struct trapframe *tf)
- {
- intctrlregs *ip;
- uint istimer;
- //cprintf("Trap %d from cpu %d eip %x (cr2=0x%x)\n",
- // tf->trapno, curr_cpu->id, tf->eip, 0);
- //trap_oops(tf);
- if(tf->trapno == T_SYSCALL){
- if(curr_proc->killed)
- exit();
- curr_proc->tf = tf;
- syscall();
- if(curr_proc->killed)
- exit();
- return;
- }
- istimer = 0;
- switch(tf->trapno){
- case T_IRQ:
- ip = (intctrlregs *)INT_REGS_BASE;
- while(ip->gpupending[0] || ip->gpupending[1] || ip->armpending){
- if(ip->gpupending[0] & (1 << IRQ_TIMER3)) {
- istimer = 1;
- timer3intr();
- }
- if(ip->gpupending[0] & (1 << IRQ_MINIUART)) {
- miniuartintr();
- }
- }
- break;
- default:
- if(curr_proc == 0 || (tf->spsr & 0xF) != USER_MODE){
- // In kernel, it must be our mistake.
- cprintf("unexpected trap %d from cpu %d addr %x spsr %x cpsr %x ifar %x\n",
- tf->trapno, curr_cpu->id, tf->pc, tf->spsr, tf->cpsr, tf->ifar);
- panic("trap");
- }
- // In user space, assume process misbehaved.
- cprintf("pid %d %s: trap %d on cpu %d "
- "addr 0x%x spsr 0x%x cpsr 0x%x ifar 0x%x--kill proc\n",
- curr_proc->pid, curr_proc->name, tf->trapno, curr_cpu->id, tf->pc,
- tf->spsr, tf->cpsr, tf->ifar);
- curr_proc->killed = 1;
- }
- // Force process exit if it has been killed and is in user space.
- // (If it is still executing in the kernel, let it keep running
- // until it gets to the regular system call return.)
- //cprintf("Proc pointer: %d\n", curr_proc);
- if(curr_proc){
- if(curr_proc->killed && (tf->spsr&0xF) == USER_MODE)
- exit();
- // Force process to give up CPU on clock tick.
- // If interrupts were on while locks held, would need to check nlock.
- if(curr_proc->state == RUNNING && istimer)
- yield();
- // Check if the process has been killed since we yielded
- if(curr_proc->killed && (tf->spsr&0xF) == USER_MODE)
- exit();
- }
- //cprintf("Proc pointer: %d after\n", curr_proc);
- }
|