static void trap_init(void) { extern char except_vec3_generic; int i; unsigned long ebase; ebase = CKSEG1; /* * Copy the generic exception handlers to their final destination. * This will be overriden later as suitable for a particular * configuration. */ memcpy((void *)(ebase + 0x180), &except_vec3_generic, 0x80); /* * Setup default vectors */ for (i = 0; i <= 31; i++) { set_except_vector(i, &handle_reserved); } if (!cpu_has_4kex) memcpy((void *)(ebase + 0x080), &except_vec3_generic, 0x80); /* FIXME: handle tlb */ memcpy((void *)(ebase), &except_vec3_generic, 0x80); /* unset BOOT EXCEPTION VECTOR bit */ write_c0_status(read_c0_status() & ~ST0_BEV); }
static void tx4927_irq_cp0_modify(unsigned cp0_reg, unsigned clr_bits, unsigned set_bits) { unsigned long val = 0; switch (cp0_reg) { case CCP0_STATUS: val = read_c0_status(); break; case CCP0_CAUSE: val = read_c0_cause(); break; } val &= (~clr_bits); val |= (set_bits); switch (cp0_reg) { case CCP0_STATUS:{ write_c0_status(val); break; } case CCP0_CAUSE:{ write_c0_cause(val); break; } } return; }
void tlb_init(void) { unsigned int config = read_c0_config(); unsigned long status; probe_tlb(config); status = read_c0_status(); status &= ~(ST0_UPS | ST0_KPS); #ifdef CONFIG_PAGE_SIZE_4KB status |= (TFP_PAGESIZE_4K << 32) | (TFP_PAGESIZE_4K << 36); #elif defined(CONFIG_PAGE_SIZE_8KB) status |= (TFP_PAGESIZE_8K << 32) | (TFP_PAGESIZE_8K << 36); #elif defined(CONFIG_PAGE_SIZE_16KB) status |= (TFP_PAGESIZE_16K << 32) | (TFP_PAGESIZE_16K << 36); #elif defined(CONFIG_PAGE_SIZE_64KB) status |= (TFP_PAGESIZE_64K << 32) | (TFP_PAGESIZE_64K << 36); #endif write_c0_status(status); write_c0_wired(0); local_flush_tlb_all(); build_tlb_refill_handler(); }
void __init arch_init_irq(void) { unsigned int irq; /* */ mips_cpu_irq_init(); /* */ for (irq = PNX833X_PIC_IRQ_BASE; irq < (PNX833X_PIC_IRQ_BASE + PNX833X_PIC_NUM_IRQ); irq++) { pnx833x_hard_disable_pic_irq(irq); irq_set_chip_and_handler(irq, &pnx833x_pic_irq_type, handle_simple_irq); } for (irq = PNX833X_GPIO_IRQ_BASE; irq < (PNX833X_GPIO_IRQ_BASE + PNX833X_GPIO_NUM_IRQ); irq++) irq_set_chip_and_handler(irq, &pnx833x_gpio_irq_type, handle_simple_irq); /* */ PNX833X_PIC_INT_PRIORITY = 0; /* */ pnx833x_startup_pic_irq(PNX833X_PIC_GPIO_INT); /* */ if (cpu_has_vint) set_vi_handler(4, pic_dispatch); write_c0_status(read_c0_status() | IE_IRQ2); }
void __init tlb_init(void) { unsigned int config = read_c0_config(); unsigned long status; probe_tlb(config); status = read_c0_status(); status &= ~(ST0_UPS | ST0_KPS); #ifdef CONFIG_PAGE_SIZE_4KB status |= (TFP_PAGESIZE_4K << 32) | (TFP_PAGESIZE_4K << 36); #elif defined(CONFIG_PAGE_SIZE_8KB) status |= (TFP_PAGESIZE_8K << 32) | (TFP_PAGESIZE_8K << 36); #elif defined(CONFIG_PAGE_SIZE_16KB) status |= (TFP_PAGESIZE_16K << 32) | (TFP_PAGESIZE_16K << 36); #elif defined(CONFIG_PAGE_SIZE_64KB) status |= (TFP_PAGESIZE_64K << 32) | (TFP_PAGESIZE_64K << 36); #endif write_c0_status(status); write_c0_wired(0); local_flush_tlb_all(); memcpy((void *)(CKSEG0 + 0x00), &except_vec0_generic, 0x80); memcpy((void *)(CKSEG0 + 0x80), except_vec1_r8k, 0x80); flush_icache_range(CKSEG0 + 0x80, CKSEG0 + 0x100); }
void __init arch_init_irq(void) { unsigned int irq; /* setup standard internal cpu irqs */ mips_cpu_irq_init(); /* Set IRQ information in irq_desc */ for (irq = PNX833X_PIC_IRQ_BASE; irq < (PNX833X_PIC_IRQ_BASE + PNX833X_PIC_NUM_IRQ); irq++) { pnx833x_hard_disable_pic_irq(irq); irq_set_chip_and_handler(irq, &pnx833x_pic_irq_type, handle_simple_irq); } for (irq = PNX833X_GPIO_IRQ_BASE; irq < (PNX833X_GPIO_IRQ_BASE + PNX833X_GPIO_NUM_IRQ); irq++) irq_set_chip_and_handler(irq, &pnx833x_gpio_irq_type, handle_simple_irq); /* Set PIC priority limiter register to 0 */ PNX833X_PIC_INT_PRIORITY = 0; /* Setup GPIO IRQ dispatching */ pnx833x_startup_pic_irq(PNX833X_PIC_GPIO_INT); /* Enable PIC IRQs (HWIRQ2) */ if (cpu_has_vint) set_vi_handler(4, pic_dispatch); write_c0_status(read_c0_status() | IE_IRQ2); }
/* * hwint 1 deals with EISA and SCSI interrupts, * * The EISA_INT bit in CSITPEND is high active, all others are low active. */ static void pcimt_hwint1(void) { u8 pend = *(volatile char *)PCIMT_CSITPEND; unsigned long flags; if (pend & IT_EISA) { int irq; /* * Note: ASIC PCI's builtin interrupt acknowledge feature is * broken. Using it may result in loss of some or all i8259 * interrupts, so don't use PCIMT_INT_ACKNOWLEDGE ... */ irq = i8259_irq(); if (unlikely(irq < 0)) return; do_IRQ(irq); } if (!(pend & IT_SCSI)) { flags = read_c0_status(); clear_c0_status(ST0_IM); do_IRQ(PCIMT_IRQ_SCSI); write_c0_status(flags); } }
void __init arch_init_irq(void) { unsigned int i; set_irq_priority(); /* clear interrupt counter for VPE0 and VPE1 */ if (isRT6855A) tc_outl(CR_INTC_ITR, (1 << 18) | (1 << 10)); /* Disable all hardware interrupts */ clear_c0_status(ST0_IM); clear_c0_cause(CAUSEF_IP); /* Initialize IRQ action handlers */ for (i = 0; i < NR_IRQS; i++) { #ifdef CONFIG_MIPS_TC3262 /* * Only MT is using the software interrupts currently, so we just * leave them uninitialized for other processors. */ if (cpu_has_mipsmt) { if ((i == SI_SWINT1_INT0) || (i == SI_SWINT1_INT1) || (i == SI_SWINT_INT0) || (i == SI_SWINT_INT1)) { set_irq_chip(i, &mips_mt_cpu_irq_controller); continue; } } if ((i == SI_TIMER_INT) || (i == SI_TIMER1_INT)) set_irq_chip_and_handler(i, &tc3162_irq_chip, handle_percpu_irq); else set_irq_chip_and_handler(i, &tc3162_irq_chip, handle_level_irq); #else set_irq_chip_and_handler(i, &tc3162_irq_chip, handle_level_irq); #endif } #ifdef CONFIG_MIPS_TC3262 if (cpu_has_veic || cpu_has_vint) { write_c0_status((read_c0_status() & ~ST0_IM ) | (STATUSF_IP0 | STATUSF_IP1)); /* register irq dispatch functions */ for (i = 0; i < NR_IRQS; i++) set_vi_handler(i, irq_dispatch_tab[i]); } else { change_c0_status(ST0_IM, ALLINTS); } #else /* Enable all interrupts */ change_c0_status(ST0_IM, ALLINTS); #endif #ifdef CONFIG_MIPS_MT_SMP vsmp_int_init(); #endif }
static inline void modify_cp0_intmask(unsigned clr_mask, unsigned set_mask) { unsigned long status = read_c0_status(); status &= ~((clr_mask & 0xFF) << 8); status |= (set_mask & 0xFF) << 8; write_c0_status(status); }
void restore_processor_state(void) { write_c0_status(saved_status); if (is_fpu_owner()) restore_fp(current); if (cpu_has_dsp) restore_dsp(current); }
/* * Get the FPU Implementation/Revision. */ static inline unsigned long cpu_get_fpu_id(void) { unsigned long tmp, fpu_id; tmp = read_c0_status(); __enable_fpu(); fpu_id = read_32bit_cp1_register(CP1_REVISION); write_c0_status(tmp); return fpu_id; }
void __init plat_time_init(void) { /* JU: TBD: there was some special SMP handling added here in original kernel */ mips_hpt_frequency = calculateCpuSpeed() / 2; #if defined(CONFIG_BCM_PWRMNGT) || defined(CONFIG_BCM_PWRMNGT_MODULE) BcmPwrMngtInitC0Speed(); #else // Enable cp0 counter/compare interrupt only when not using power management write_c0_status(IE_IRQ5 | read_c0_status()); #endif }
void mips_cpu_timer_enable(void) { uint32_t sr = read_c0_status(); sr |= ((0x1UL << 7) << 8); write_c0_status(sr); uint32_t cause = read_c0_cause(); cause &= ~(0x1UL << 27); write_c0_cause(cause); write_c0_compare(read_c0_count() + COUNTER_TICK_COUNT); }
void exception_init(void) { write_c0_status(0x10000400); memcpy((void *)(A_K0BASE ), except_common_entry, 0x20); memcpy((void *)(A_K0BASE + 0x180), except_common_entry, 0x20); memcpy((void *)(A_K0BASE + 0x200), except_common_entry, 0x20); __dcache_writeback_all(); __icache_invalidate_all(); }
static void paravirt_init_secondary(void) { unsigned int sr; sr = set_c0_status(ST0_BEV); write_c0_ebase((u32)ebase); sr |= STATUSF_IP2; /* Interrupt controller on IP2 */ write_c0_status(sr); irq_cpu_online(); }
/** * Disable access to Octeon's COP2 crypto hardware in the kernel. * This must be called after an octeon_crypto_enable() before any * context switch or return to userspace. * * @param state COP2 state to restore * @param flags Return value from octeon_crypto_enable() */ void octeon_crypto_disable(struct octeon_cop2_state *state, unsigned long crypto_flags) { unsigned long flags; local_irq_save(flags); if (crypto_flags & ST0_CU2) octeon_cop2_restore(state); else write_c0_status(read_c0_status() & ~ST0_CU2); local_irq_restore(flags); }
static int cnmips_cu2_call(struct notifier_block *nfb, unsigned long action, void *data) { unsigned long flags; unsigned int status; switch (action) { case CU2_EXCEPTION: prefetch(¤t->thread.cp2); local_irq_save(flags); KSTK_STATUS(current) |= ST0_CU2; status = read_c0_status(); write_c0_status(status | ST0_CU2); octeon_cop2_restore(&(current->thread.cp2)); write_c0_status(status & ~ST0_CU2); local_irq_restore(flags); return NOTIFY_BAD; /* Don't call default notifier */ } return NOTIFY_OK; /* Let default notifier send signals */ }
/** * After we've done initial boot, this function is called to allow the * board code to clean up state, if needed */ static void octeon_init_secondary(void) { unsigned int sr; sr = set_c0_status(ST0_BEV); write_c0_ebase((u32)ebase); write_c0_status(sr); octeon_check_cpu_bist(); octeon_init_cvmcount(); octeon_irq_setup_secondary(); }
void __init arch_init_irq(void) { int i; //extern irq_desc_t irq_desc[]; /* init CPU irqs */ mips_cpu_irq_init(); /* init sys irqs */ sys_irq_base = M36_SYS_IRQ_BASE; for (i=sys_irq_base; i < sys_irq_base + M36_NUM_SYS_IRQ; i++) irq_set_chip_and_handler(i, &sys_irq_controller,handle_percpu_irq); /* Default all ICU IRQs to off and enable IM bit(IP3) of CP0 status for sys IRQ */ #if 1 *((unsigned long *)(0xB8000038)) = 0; *((unsigned long *)(0xB800003C)) = 0; *((unsigned long *)(0xB80000EC)) = 0; write_c0_status(read_c0_status() | STATUSF_IP3); #else *M6303_MSYSINT1REG = 0; *M6303_MSYSINT2REG = 0; #endif #ifdef CONFIG_REMOTE_DEBUG printk("Setting debug traps - please connect the remote debugger.\n"); set_debug_traps(); // you may move this line to whereever you want breakpoint(); #endif if((*(unsigned short *)0xB8000002 == 0x3901) \ || (*(unsigned short *)0xB8000002 == 0x3701) \ || (*(unsigned short *)0xB8000002 == 0x3503)) { sys_rpc_addr = 0xB8040037; sys_rpc_mask = 0x0C; sys_rpc_irq1_mask = 0x08; sys_rpc_irq2_mask = 0x04; } else { sys_rpc_addr = 0xB8040036; sys_rpc_mask = 0xC0; sys_rpc_irq1_mask = 0x80; sys_rpc_irq2_mask = 0x40; } }
void trap_init(){ volatile uint32_t status; volatile uint8_t *p1,*p2,*p3; p1 = (uint8_t*)0x80000000; p2 = (uint8_t*)_TRAP_HANDLER; p3 = p2+sizeof(_TRAP_HANDLER); for(;p2<p3;++p2){ *p1=*p2; ++p1; } status = read_c0_status(); status |= ST_BEV; status ^= ST_BEV; write_c0_status(status); }
void set_trap_handler() { uint32_t cp0_status=read_c0_status(); cp0_status |=ST_EXL |ST_BEV |ST_ERL |ST_IE |ST_IMx(INT_CLOCK) |ST_IMx(INT_CLOCK); cp0_status ^=ST_EXL |ST_BEV |ST_ERL; write_c0_status(cp0_status); memcpy((void*)TLB_REFILL_ENTRY, tlb_refill, INT_ENTRY_SIZE); memcpy((void*)GENERIC_EXC_ENTRY, generic_exception,INT_ENTRY_SIZE); }
/** * Enable access to Octeon's COP2 crypto hardware for kernel use. * Wrap any crypto operations in calls to * octeon_crypto_enable/disable in order to make sure the state of * COP2 isn't corrupted if userspace is also performing hardware * crypto operations. Allocate the state parameter on the stack. * * @param state State structure to store current COP2 state in * * @return Flags to be passed to octeon_crypto_disable() */ unsigned long octeon_crypto_enable(struct octeon_cop2_state *state) { int status; unsigned long flags; local_irq_save(flags); status = read_c0_status(); write_c0_status(status | ST0_CU2); if (KSTK_STATUS(current) & ST0_CU2) { octeon_cop2_save(&(current->thread.cp2)); KSTK_STATUS(current) &= ~ST0_CU2; status &= ~ST0_CU2; } else if (status & ST0_CU2) octeon_cop2_save(state); local_irq_restore(flags); return status & ST0_CU2; }
void handle_mips_systick(void) { /* clear EXL from status */ uint32_t sr = read_c0_status(); sr &= ~0x00000002; write_c0_status(sr); /* Call the interrupt entry routine */ atomIntEnter(); /* Call the OS system tick handler */ atomTimerTick(); write_c0_compare(read_c0_count() + COUNTER_TICK_COUNT); /* Call the interrupt exit routine */ atomIntExit(TRUE); }
void handle_tlb_refill(struct trapframe *tf) { unsigned long entryhi=read_c0_entryhi(); unsigned long vpn=TLB_VPN(entryhi); unsigned long pfn=pt[ENTRYHI_ASID(entryhi)][vpn]; if(pfn) { unsigned long entrylo=( TLB_PFN(pfn, entryhi) | TLB_COHERENT | TLB_VALID | TLB_DIRTY | TLB_GLOBAL)^TLB_GLOBAL; write_c0_entrylo0(entrylo); write_c0_entrylo1(TLB_ELO0TO1(entrylo)); tlbwr(); } else { kprintf("Fatal error, invalied page: %x with ASID= %d, rebooting...\n",vpn, ENTRYHI_ASID(entryhi)); unsigned long* reg=(unsigned long*)tf; write_c0_status((read_c0_status()|ST_KSU)^ST_KSU); reg[ORD_STATUS]=(read_c0_status()|ST_KSU)^ST_KSU; reg[ORD_EPC]=__reset; } return; }
/** * init hardware FPU */ void rt_hw_fpu_init(void) { rt_uint32_t c0_status = 0; rt_uint32_t c1_status = 0; // 使能协处理器1--FPU c0_status = read_c0_status(); c0_status |= (ST0_CU1 | ST0_FR); write_c0_status(c0_status); // 配置FPU c1_status = read_c1_status(); c1_status |= (FPU_CSR_FS | FPU_CSR_FO | FPU_CSR_FN); // set FS, FO, FN c1_status &= ~(FPU_CSR_ALL_E); // disable exception c1_status = (c1_status & (~FPU_CSR_RM)) | FPU_CSR_RN; // set RN write_c1_status(c1_status); return ; }
void ds2_init(void) { pfunc *p; write_c0_status(0x10000400); memcpy((void *)A_K0BASE, except_common_entry, 0x20); memcpy((void *)(A_K0BASE + 0x180), except_common_entry, 0x20); memcpy((void *)(A_K0BASE + 0x200), except_common_entry, 0x20); __dcache_writeback_all(); __icache_invalidate_all(); init_perihery(); InitExcept(); _intc_init(); detect_clock(); // gpio_init(); // serial_init(); pm_init(); //dgprintf("\n\nOS initial!\n"); // OSInit(); /* Invoke constroctor functions when needed. */ #if 1 for (p=&__CTOR_END__[-1]; p >= __CTOR_LIST__; p--) { printf("create class %08x\n",p); (*p)(); } //dgprintf("Before main function\n"); #endif //Start system ticker _StartSysTimer(); //enable global interrupt sti(); }
void __init init_IRQ(void) { int flags; // printk("\nfile %s cp0 status %x\n",__FILE__,read_c0_status()); flags = read_c0_status(); flags |= CAUSEF_IP4|CAUSEF_IP3|CAUSEF_IP5|0xfc00; write_c0_status(flags); //printk("\nfile %s cp0 status %x\n",__FILE__,read_c0_status()); #ifdef CONFIG_REMOTE_DEBUG extern void breakpoint(void); extern void set_debug_traps(void); printk("Wait for gdb client connection ...\n"); set_debug_traps(); breakpoint(); #endif /* Invoke board-specific irq setup */ irq_setup(); }
void __init asic_irq_init(void) { int i; /* set priority to 0 */ write_c0_status(read_c0_status() & ~(0x0000fc00)); asic_write(0, ien_int_0); asic_write(0, ien_int_1); asic_write(0, ien_int_2); asic_write(0, ien_int_3); asic_write(0x0fffffff, int_level_3_3); asic_write(0xffffffff, int_level_3_2); asic_write(0xffffffff, int_level_3_1); asic_write(0xffffffff, int_level_3_0); asic_write(0xffffffff, int_level_2_3); asic_write(0xffffffff, int_level_2_2); asic_write(0xffffffff, int_level_2_1); asic_write(0xffffffff, int_level_2_0); asic_write(0xffffffff, int_level_1_3); asic_write(0xffffffff, int_level_1_2); asic_write(0xffffffff, int_level_1_1); asic_write(0xffffffff, int_level_1_0); asic_write(0xffffffff, int_level_0_3); asic_write(0xffffffff, int_level_0_2); asic_write(0xffffffff, int_level_0_1); asic_write(0xffffffff, int_level_0_0); asic_write(0xf, int_int_scan); /* * Initialize interrupt handlers. */ for (i = 0; i < NR_IRQS; i++) set_irq_chip_and_handler(i, &asic_irq_chip, handle_level_irq); }
void __init plat_timer_setup(struct irqaction *irq) { unsigned int est_freq; printk("calculating r4koff... "); r4k_offset = cal_r4koff(); printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset); //est_freq = 2*r4k_offset*HZ; est_freq = r4k_offset*HZ; est_freq += 5000; /* round */ est_freq -= est_freq%10000; printk("CPU frequency %d.%02d MHz\n", est_freq/1000000, (est_freq%1000000)*100/1000000); set_au1x00_speed(est_freq); set_au1x00_lcd_clock(); // program the LCD clock r4k_cur = (read_c0_count() + r4k_offset); write_c0_compare(r4k_cur); #ifdef CONFIG_PM /* * setup counter 0, since it keeps ticking after a * 'wait' instruction has been executed. The CP0 timer and * counter 1 do NOT continue running after 'wait' * * It's too early to call request_irq() here, so we handle * counter 0 interrupt as a special irq and it doesn't show * up under /proc/interrupts. * * Check to ensure we really have a 32KHz oscillator before * we do this. */ if (no_au1xxx_32khz) { unsigned int c0_status; printk("WARNING: no 32KHz clock found.\n"); /* Ensure we get CPO_COUNTER interrupts. */ c0_status = read_c0_status(); c0_status |= IE_IRQ5; write_c0_status(c0_status); } else { while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S); au_writel(0, SYS_TOYWRITE); while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S); au_writel(au_readl(SYS_WAKEMSK) | (1<<8), SYS_WAKEMSK); au_writel(~0, SYS_WAKESRC); au_sync(); while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20); /* setup match20 to interrupt once every HZ */ last_pc0 = last_match20 = au_readl(SYS_TOYREAD); au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2); au_sync(); while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20); startup_match20_interrupt(counter0_irq); /* We can use the real 'wait' instruction. */ allow_au1k_wait = 1; } #endif }
void handle_exception(struct trapframe *tf) { uint32_t cause=read_c0_cause(); unsigned long* reg=(unsigned long*)tf; if(EXCCODE(cause)==EC_int) { if(cause&CR_IPx(INT_CLOCK)) { if(sc_num!=SYS_NONE) { write_c0_compare(NULL); return; } //kprintf("--DEBUG-- CPU%d time out: %d\n",cpuid(),cur_pid); pcb[cur_pid].status=ST_READY; unsigned long i; pcb_save(cur_pid,i); next_process; pcb_restore(cur_pid,i); reg[ORD_ENTRYHI]=cur_pid; RESET_CLOCK; } } else if(EXCCODE(cause)==EC_sys) { reg[ORD_EPC]+=INST_SIZE; unsigned long i; switch(reg[ORD_V0]) { case SYS_PID: reg[ORD_V0]=cur_pid; break; case SYS_PPID: reg[ORD_V0]=pcb[cur_pid].ppid; break; case SYS_FORK: { sc_pid=cur_pid; sc_num=SYS_FORK; reg[ORD_STATUS]=(read_c0_status()|ST_KSU)^ST_KSU; pcb_save(cur_pid, i); pcb[cur_pid].status=ST_READY; pcb_restore(0, i); cur_pid=0; break; } case SYS_EXEC: sc_pid=cur_pid; sc_num=SYS_EXEC; sc_args[0]=reg[ORD_A0]; reg[ORD_STATUS]=(read_c0_status()|ST_KSU)^ST_KSU; pcb_save(cur_pid, i); pcb[cur_pid].status=ST_READY; pcb_restore(0, i); cur_pid=0; break; case SYS_SLEEP: if(reg[ORD_A0]==0)break; pcb[cur_pid].compare=read_c0_count()+reg[ORD_A0]*MS_PER_SEC*COUNT_PER_MS; pcb[cur_pid].status=ST_BLOCK; pcb_save(cur_pid,i); next_process; pcb_restore(cur_pid,i); reg[ORD_ENTRYHI]=cur_pid; RESET_CLOCK; break; case SYS_WAITPID: pcb[cur_pid].wait=reg[ORD_A0]; pcb[cur_pid].status=ST_BLOCK; pcb_save(cur_pid,i); next_process; pcb_restore(cur_pid,i); reg[ORD_ENTRYHI]=cur_pid; RESET_CLOCK; break; case SYS_MLC: reg[ORD_V0]=kmalloc(reg[ORD_A0]); break; case SYS_PUTS: sc_pid=cur_pid; sc_num=SYS_PUTS; sc_args[0]=reg[ORD_A0]; reg[ORD_STATUS]=(read_c0_status()|ST_KSU)^ST_KSU; pcb_save(cur_pid, i); pcb[cur_pid].status=ST_READY; pcb_restore(0, i); cur_pid=0; break; case SYS_KNL: reg[ORD_STATUS]=(read_c0_status()|ST_KSU)^ST_KSU; reg[ORD_V0]=0; break; case SYS_USR: pcb_save(0, i); pcb[cur_pid].status=ST_RUNNING; pcb_restore(cur_pid, i); reg[ORD_ENTRYHI]=cur_pid; reg[ORD_STATUS]=(read_c0_status()|ST_KSU)^KSU_SUPERVISOR; write_c0_compare(read_c0_count()+TIME_SLICE*COUNT_PER_MS); break; case SYS_EXIT: { kprintf("--DEBUG-- pid %d exited with %d!\n",cur_pid,reg[ORD_A0]); pcb[cur_pid].status=ST_STOPED; unsigned long max_page=TLB_VPN(pcb[cur_pid].max_addr); for(i=0;i<max_page;i++) { ppage_free(pt[cur_pid][i]); pt[cur_pid][i]=0; } next_process; reg[ORD_ENTRYHI]=cur_pid; pcb_restore(cur_pid,i); break; } case SYS_GETS: { sc_pid=cur_pid; sc_num=SYS_GETS; sc_args[0]=reg[ORD_A0]; sc_args[1]=reg[ORD_A1]; reg[ORD_STATUS]=(read_c0_status()|ST_KSU)^ST_KSU; pcb_save(cur_pid, i); pcb[cur_pid].status=ST_READY; pcb_restore(0, i); cur_pid=0; break; } } } else { kputs("Fatal error, unkown exception, rebooting...\n"); write_c0_status((read_c0_status()|ST_KSU)^ST_KSU); reg[ORD_STATUS]=(read_c0_status()|ST_KSU)^ST_KSU; reg[ORD_EPC]=__reset; } return; }