asmlinkage void plat_irq_dispatch(void) { unsigned int pending; pending = read_c0_cause() & read_c0_status() & ST0_IM; /* machine-specific plat_irq_dispatch */ mach_irq_dispatch(pending); }
u32 do_general_exception(arch_regs_t *uregs) { u32 cp0_cause = read_c0_cause(); u32 cp0_status = read_c0_status(); mips32_entryhi_t ehi; u32 victim_asid; u32 victim_inst; struct vmm_vcpu *c_vcpu; u8 delay_slot_exception = IS_BD_SET(cp0_cause); ehi._entryhi = read_c0_entryhi(); victim_asid = ehi._s_entryhi.asid >> ASID_SHIFT; c_vcpu = vmm_scheduler_current_vcpu(); /* * When exception is happening in the delay slot. We need to emulate * the corresponding branch instruction first. If its one of the "likely" * instructions, we don't need to emulate the faulting instruction since * "likely" instructions don't allow slot to be executed if branch is not * taken. */ if (delay_slot_exception) { victim_inst = *((u32 *)(uregs->cp0_epc + 4)); /* * If this function returns zero, the branch instruction was a * "likely" instruction and the branch wasn't taken. So don't * execute the delay slot, just return. The correct EPC to return * to will be programmed under our feet. */ if (!cpu_vcpu_emulate_branch_and_jump_inst(c_vcpu, *((u32 *)uregs->cp0_epc), uregs)) { return VMM_OK; } } else { victim_inst = *((u32 *)uregs->cp0_epc); } switch (EXCEPTION_CAUSE(cp0_cause)) { case EXEC_CODE_COPU: cpu_vcpu_emulate_cop_inst(c_vcpu, victim_inst, uregs); if (!delay_slot_exception) uregs->cp0_epc += 4; break; case EXEC_CODE_TLBL: if (CPU_IN_USER_MODE(cp0_status) && is_vmm_asid(ehi._s_entryhi.asid)) { ehi._s_entryhi.asid = (0x1 << ASID_SHIFT); write_c0_entryhi(ehi._entryhi); vmm_panic("CPU is in user mode and ASID is pointing to VMM!!\n"); } break; } return VMM_OK; }
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; }
void arch_vcpu_regs_switch(struct vmm_vcpu *tvcpu, struct vmm_vcpu *vcpu, arch_regs_t *regs) { if (tvcpu) { vmm_memcpy(mips_uregs(tvcpu), regs, sizeof(arch_regs_t)); } if (vcpu) { if (!vcpu->is_normal) { mips_uregs(vcpu)->cp0_status = read_c0_status() & ~(0x01UL << CP0_STATUS_UM_SHIFT); } else { mips_uregs(vcpu)->cp0_status = read_c0_status() | (0x01UL << CP0_STATUS_UM_SHIFT); } vmm_memcpy(regs, mips_uregs(vcpu), sizeof(arch_regs_t)); } }
void save_processor_state(void) { saved_status = read_c0_status(); if (is_fpu_owner()) save_fp(current); if (cpu_has_dsp) save_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; }
asmlinkage void plat_irq_dispatch(void) { unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM; if (pending & STATUSF_IP7) /* cpu timer */ do_IRQ(7); else if (pending & STATUSF_IP2) /* int0 hardware line */ ar7_cascade(); else spurious_interrupt(); }
asmlinkage void plat_irq_dispatch(void) { unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM; if (pending & STATUSF_IP2) do_IRQ(2); else if (pending & STATUSF_IP3) do_IRQ(3); else spurious_interrupt(); }
asmlinkage void plat_irq_dispatch(void) { unsigned int pending; #if defined (CONFIG_RALINK_RT3883) || defined (CONFIG_RALINK_MT7620) || \ defined (CONFIG_RALINK_MT7628) unsigned int pci_status; #endif pending = read_c0_status() & read_c0_cause() & ST0_IM; if (!pending) { spurious_interrupt(); return; } if (pending & CAUSEF_IP7) { do_IRQ(SURFBOARDINT_MIPS_TIMER); // CPU Timer return; } if (pending & CAUSEF_IP5) do_IRQ(SURFBOARDINT_FE); // Frame Engine if (pending & CAUSEF_IP6) do_IRQ(SURFBOARDINT_WLAN); // Wireless if (pending & CAUSEF_IP4) { #if defined (CONFIG_RALINK_RT3883) pci_status = RALINK_PCI_PCIINT_ADDR; if (pci_status & 0x100000) do_IRQ(SURFBOARDINT_PCIE0); #if defined (CONFIG_PCI_ONLY) || defined (CONFIG_PCIE_PCI_CONCURRENT) else if (pci_status & 0x040000) do_IRQ(SURFBOARDINT_PCI0); else do_IRQ(SURFBOARDINT_PCI1); #endif #elif defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7628) pci_status = RALINK_PCI_PCIINT_ADDR; if (pci_status & 0x100000) do_IRQ(SURFBOARDINT_PCIE0); #endif } if (pending & CAUSEF_IP3) ralink_hw0_irqdispatch(1); else if (pending & CAUSEF_IP2) ralink_hw0_irqdispatch(0); #if 0 /* clear new potentially pending IP6..IP2 */ set_c0_status( STATUSF_IP6 | STATUSF_IP5 | STATUSF_IP4 | STATUSF_IP3 | STATUSF_IP2 ); #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); }
asmlinkage void plat_irq_dispatch(void) { unsigned int pending = read_c0_status() & read_c0_cause(); if (pending & STATUSF_IP4) pic_dispatch(); else if (pending & STATUSF_IP7) do_IRQ(PNX833X_TIMER_IRQ); else spurious_interrupt(); }
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 }
asmlinkage void plat_irq_dispatch(struct pt_regs *regs) { u32 pending; pending = read_c0_status() & read_c0_cause(); /* * jump to the correct interrupt routine * These are arranged in priority order and the timer * comes first! */ #ifdef CONFIG_IRQ_MSP_CIC /* break out the CIC stuff for now */ if (pending & C_IRQ4) /* do the peripherals first, that's the timer */ msp_cic_irq_dispatch(); else if (pending & C_IRQ0) do_IRQ(MSP_INT_MAC0); else if (pending & C_IRQ1) do_IRQ(MSP_INT_MAC1); else if (pending & C_IRQ2) do_IRQ(MSP_INT_USB); else if (pending & C_IRQ3) do_IRQ(MSP_INT_SAR); else if (pending & C_IRQ5) do_IRQ(MSP_INT_SEC); #else if (pending & C_IRQ5) do_IRQ(MSP_INT_TIMER); else if (pending & C_IRQ0) do_IRQ(MSP_INT_MAC0); else if (pending & C_IRQ1) do_IRQ(MSP_INT_MAC1); else if (pending & C_IRQ3) do_IRQ(MSP_INT_VE); else if (pending & C_IRQ4) msp_slp_irq_dispatch(); #endif else if (pending & C_SW0) /* do software after hardware */ do_IRQ(MSP_INT_SW0); else if (pending & C_SW1) do_IRQ(MSP_INT_SW1); }
asmlinkage void plat_irq_dispatch(struct pt_regs *regs) { unsigned int pending; #ifdef CONFIG_SIBYTE_BCM1480_PROF /* Set compare to count to silence count/compare timer interrupts */ write_c0_compare(read_c0_count()); #endif pending = read_c0_cause() & read_c0_status(); #ifdef CONFIG_SIBYTE_BCM1480_PROF if (pending & CAUSEF_IP7) /* Cpu performance counter interrupt */ sbprof_cpu_intr(exception_epc(regs)); else #endif if (pending & CAUSEF_IP4) bcm1480_timer_interrupt(regs); #ifdef CONFIG_SMP else if (pending & CAUSEF_IP3) bcm1480_mailbox_interrupt(regs); #endif #ifdef CONFIG_KGDB else if (pending & CAUSEF_IP6) bcm1480_kgdb_interrupt(regs); /* KGDB (uart 1) */ #endif else if (pending & CAUSEF_IP2) { unsigned long long mask_h, mask_l; unsigned long base; /* * Default...we've hit an IP[2] interrupt, which means we've * got to check the 1480 interrupt registers to figure out what * to do. Need to detect which CPU we're on, now that * smp_affinity is supported. */ base = A_BCM1480_IMR_MAPPER(smp_processor_id()); mask_h = __raw_readq( IOADDR(base + R_BCM1480_IMR_INTERRUPT_STATUS_BASE_H)); mask_l = __raw_readq( IOADDR(base + R_BCM1480_IMR_INTERRUPT_STATUS_BASE_L)); if (mask_h) { if (mask_h ^ 1) do_IRQ(fls64(mask_h) - 1, regs); else do_IRQ(63 + fls64(mask_l), regs); } } }
/* * IRQs on the SEAD board look basically are combined together on hardware * interrupt 0 (MIPS IRQ 2)) like: * * MIPS IRQ Source * -------- ------ * 0 Software (ignored) * 1 Software (ignored) * 2 UART0 (hw0) * 3 UART1 (hw1) * 4 Hardware (ignored) * 5 Hardware (ignored) * 6 Hardware (ignored) * 7 R4k timer (what we use) * * We handle the IRQ according to _our_ priority which is: * * Highest ---- R4k Timer * Lowest ---- Combined hardware interrupt * * then we just return, if multiple IRQs are pending then we will just take * another exception, big deal. */ asmlinkage void plat_irq_dispatch(void) { unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM; int irq; irq = irq_ffs(pending); if (irq >= 0) do_IRQ(MIPSCPU_INT_BASE + irq); else spurious_interrupt(regs); }
asmlinkage void plat_irq_dispatch(void) { unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM; unsigned int i; if (pending & CAUSEF_IP7) { do_IRQ(MIPS_CPU_TIMER_IRQ); goto out; } else { for (i = 0; i < 5; i++) { if (pending & (CAUSEF_IP2 << i)) { ltq_hw_irqdispatch(i); goto out; } } } pr_alert("Spurious IRQ: CAUSE=0x%08x\n", read_c0_status()); out: return; }
/** * 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); }
asmlinkage void plat_irq_dispatch(struct pt_regs *regs) { unsigned int pending = read_c0_cause() & read_c0_status(); if (pending & STATUSF_IP7) brcm_mips_int7_dispatch(regs); else if (pending & STATUSF_IP2) brcm_mips_int2_dispatch(regs); else spurious_interrupt(regs); }
asmlinkage void plat_irq_dispatch(void) { unsigned long pending; pending = read_c0_status() & read_c0_cause() & ST0_IM; if (pending & STATUSF_IP7) do_IRQ(ADM5120_IRQ_COUNTER); else if (pending & STATUSF_IP2) adm5120_intc_irq_dispatch(); else spurious_interrupt(); }
asmlinkage void plat_irq_dispatch(void) { unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM; if (pending & STATUSF_IP7) do_IRQ(WRPPMC_MIPS_TIMER_IRQ); /* CPU Compare/Count internal timer */ else if (pending & STATUSF_IP6) do_IRQ(WRPPMC_UART16550_IRQ); /* UART 16550 port */ else if (pending & STATUSF_IP3) do_IRQ(WRPPMC_PCI_INTA_IRQ); /* PCI INT_A */ else spurious_interrupt(); }
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 mips_spurious_interrupt(struct pt_regs *regs) { #if 1 return; #else unsigned long status, cause; printk("got spurious interrupt\n"); status = read_c0_status(); cause = read_c0_cause(); printk("status %x cause %x\n", status, cause); printk("epc %x badvaddr %x \n", regs->cp0_epc, regs->cp0_badvaddr); #endif }
/* * System irq dispatch */ void plat_irq_dispatch(void) { unsigned int pending; pending = read_c0_cause() & read_c0_status() & ST0_IM; /* timer interrupt, that we renumbered */ if (pending & STATUSF_IP7) do_IRQ(MIPS_CPU_IRQ_BASE + 7); else if (pending & STATUSF_IP2) adm8668_irq_cascade(); else spurious_interrupt(); }
static void jzsoc_smp_showregs(void) { int cpu = smp_processor_id(); unsigned int val; printk("CPU%d:\n",cpu); #define P(reg) do { \ val = get_smp_##reg(); \ printk(#reg ":\t%08x\n",val); \ } while(0) P(ctrl); P(status); P(reim); P(mbox0); P(mbox1); //P(val); P(lock); printk("cp0 status:\t%08x\n",read_c0_status()); printk("cp0 cause:\t%08x\n",read_c0_cause()); }
asmlinkage void plat_irq_dispatch(void) { unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM; int irq; irq = irq_ffs(pending); if (irq == MIPSCPU_INT_I8259A) malta_hw0_irqdispatch(); else if (irq > 0) do_IRQ(MIPS_CPU_IRQ_BASE + irq); else spurious_interrupt(); }
asmlinkage void plat_irq_dispatch(void) { u32 cause; #if defined(CONFIG_BCM_PWRMNGT) || defined(CONFIG_BCM_PWRMNGT_MODULE) // BcmPwrMngtResumeFullSpeed(); #endif while((cause = (read_c0_cause() & read_c0_status() & CAUSEF_IP))) { if (cause & CAUSEF_IP7) { do_IRQ(MIPS_TIMER_INT); } else if (cause & CAUSEF_IP0) do_IRQ(INTERRUPT_ID_SOFTWARE_0); else if (cause & CAUSEF_IP1) do_IRQ(INTERRUPT_ID_SOFTWARE_1); #if defined(CONFIG_BCM93380) #if defined(CONFIG_BCM_LOT1) else if (cause & CAUSEF_IP4) irq_dispatch_int(3); else if (cause & CAUSEF_IP6) irq_dispatch_int(4); #endif else if (cause & CAUSEF_IP3) irq_dispatch_int(0); else if (cause & CAUSEF_IP5) irq_dispatch_int(1); #elif defined(CONFIG_BCMKILAUEA) || defined(CONFIG_BCM93383) #if defined(CONFIG_BCM_LOT1) else if (cause & CAUSEF_IP4) irq_dispatch_int(3); else if (cause & CAUSEF_IP6) irq_dispatch_int(4); #else else if (cause & CAUSEF_IP5) irq_dispatch_int(0); else if (cause & CAUSEF_IP2) irq_dispatch_int(1); #endif #else #if defined (CONFIG_SMP) else if (cause & (CAUSEF_IP2 | CAUSEF_IP3)) #else else if (cause & CAUSEF_IP2) #endif irq_dispatch_int(); #endif } }
/* * IRQs on the Atlas board look basically like (all external interrupt * sources are combined together on hardware interrupt 0 (MIPS IRQ 2)): * * MIPS IRQ Source * -------- ------ * 0 Software 0 (reschedule IPI on MT) * 1 Software 1 (remote call IPI on MT) * 2 Combined Atlas hardware interrupt (hw0) * 3 Hardware (ignored) * 4 Hardware (ignored) * 5 Hardware (ignored) * 6 Hardware (ignored) * 7 R4k timer (what we use) * * We handle the IRQ according to _our_ priority which is: * * Highest ---- R4k Timer * Lowest ---- Software 0 * * then we just return, if multiple IRQs are pending then we will just take * another exception, big deal. */ asmlinkage void plat_irq_dispatch(struct pt_regs *regs) { unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM; int irq; irq = irq_ffs(pending); if (irq == MIPSCPU_INT_ATLAS) atlas_hw0_irqdispatch(regs); else if (irq >= 0) do_IRQ(MIPSCPU_INT_BASE + irq, regs); else spurious_interrupt(regs); }
void gic_send_ipi(unsigned int intr) { #if gic_wedgeb2bok == 0 unsigned long flags; #endif pr_debug("CPU%d: %s status %08x\n", smp_processor_id(), __func__, read_c0_status()); if (!gic_wedgeb2bok) spin_lock_irqsave(&gic_wedgeb2b_lock, flags); GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), 0x80000000 | intr); if (!gic_wedgeb2bok) { (void) GIC_REG(SHARED, GIC_SH_CONFIG); spin_unlock_irqrestore(&gic_wedgeb2b_lock, flags); } }
asmlinkage void plat_irq_dispatch(void) { unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM; if (pending & STATUSF_IP7) do_IRQ(CPU_IRQ_BASE + 7); else if (pending & VR5477INTS) vrc5477_irq_dispatch(); else if (pending & STATUSF_IP0) do_IRQ(CPU_IRQ_BASE); else if (pending & STATUSF_IP1) do_IRQ(CPU_IRQ_BASE + 1); else spurious_interrupt(); }
asmlinkage void plat_irq_dispatch(struct pt_regs *regs) { unsigned int pending = read_c0_cause() & read_c0_status(); if (pending & STATUSF_IP7) do_IRQ(CPU_IRQ_BASE + 7, regs); else if (pending & VR5477INTS) vrc5477_irq_dispatch(regs); else if (pending & STATUSF_IP0) do_IRQ(CPU_IRQ_BASE, regs); else if (pending & STATUSF_IP1) do_IRQ(CPU_IRQ_BASE + 1, regs); else spurious_interrupt(regs); }