Index: kernel/arch/mips32/include/cp0.h
===================================================================
--- kernel/arch/mips32/include/cp0.h	(revision b5e17b1027804f441fb643a9c7116c13e8f4479b)
+++ kernel/arch/mips32/include/cp0.h	(revision d5b9e8d0db718c208ae5e80f1ed56e9201df1a55)
@@ -45,4 +45,7 @@
 #define cp0_status_im_shift  8
 #define cp0_status_im_mask   0xff00
+
+#define cp0_cause_ip_shift  8
+#define cp0_cause_ip_mask   0xff00
 
 #define cp0_cause_excno(cause)   ((cause >> 2) & 0x1f)
Index: kernel/arch/mips32/src/exception.c
===================================================================
--- kernel/arch/mips32/src/exception.c	(revision b5e17b1027804f441fb643a9c7116c13e8f4479b)
+++ kernel/arch/mips32/src/exception.c	(revision d5b9e8d0db718c208ae5e80f1ed56e9201df1a55)
@@ -165,10 +165,21 @@
 static void interrupt_exception(unsigned int n, istate_t *istate)
 {
+	uint32_t ip;
+	uint32_t im;
+
 	/* Decode interrupt number and process the interrupt */
-	uint32_t cause = (cp0_cause_read() >> 8) & 0xff;
+	ip = (cp0_cause_read() & cp0_cause_ip_mask) >> cp0_cause_ip_shift;
+	im = (cp0_status_read() & cp0_status_im_mask) >> cp0_status_im_shift;
 	
 	unsigned int i;
 	for (i = 0; i < 8; i++) {
-		if (cause & (1 << i)) {
+
+		/*
+		 * The interrupt could only occur if it is unmasked in the
+		 * status register. On the other hand, an interrupt can be
+		 * apparently pending even if it is masked, so we need to
+		 * check both the masked and pending interrupts.
+		 */
+		if (im & ip & (1 << i)) {
 			irq_t *irq = irq_dispatch_and_lock(i);
 			if (irq) {
