From: Aurelien Jarno <aurelien@aurel32.net>
To: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH] Reworking MIPS interrupts handling
Date: Tue, 23 Jan 2007 21:00:53 +0100 [thread overview]
Message-ID: <20070123200052.GA11429@amd64.aurel32.net> (raw)
In-Reply-To: <20070123184220.GA9659@amd64.aurel32.net>
On Tue, Jan 23, 2007 at 07:42:20PM +0100, Aurelien Jarno wrote:
> Hi all,
>
> Please find below a patch to fix the IRQ issue on the MIPS platform. I
> have tested it on both 2.4 and 2.6 kernel and it works fine.
>
Here is an updated patch including the comments from Paul Brook via IRC.
Thanks Paul for the review.
--- hw/mips_int.c 2007-01-18 20:37:29.623079789 +0100
+++ hw/mips_int.c 2007-01-23 20:55:13.000000000 +0100
@@ -0,0 +1,39 @@
+#include "vl.h"
+#include "cpu.h"
+
+/* Raise IRQ to CPU if necessary. It must be called every time the active
+ IRQ may change */
+void cpu_mips_update_irq(CPUState *env)
+{
+ if ((env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
+ (env->CP0_Status & (1 << CP0St_IE)) &&
+ !(env->hflags & MIPS_HFLAG_EXL) &&
+ !(env->hflags & MIPS_HFLAG_ERL) &&
+ !(env->hflags & MIPS_HFLAG_DM)) {
+ if (! (env->interrupt_request & CPU_INTERRUPT_HARD)) {
+ cpu_interrupt(env, CPU_INTERRUPT_HARD);
+ }
+ } else {
+ cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+ }
+}
+
+void cpu_mips_irq_request(void *opaque, int irq, int level)
+{
+ CPUState *env = first_cpu;
+
+ uint32_t mask;
+
+ if (irq >= 16)
+ return;
+
+ mask = 1 << (irq + CP0Ca_IP);
+
+ if (level) {
+ env->CP0_Cause |= mask;
+ } else {
+ env->CP0_Cause &= ~mask;
+ }
+ cpu_mips_update_irq(env);
+}
+
? hw/mips_int.c
Index: Makefile.target
===================================================================
RCS file: /sources/qemu/qemu/Makefile.target,v
retrieving revision 1.140
diff -u -d -p -r1.140 Makefile.target
--- Makefile.target 21 Jan 2007 22:40:04 -0000 1.140
+++ Makefile.target 23 Jan 2007 19:57:09 -0000
@@ -376,7 +376,7 @@ VL_OBJS+= grackle_pci.o prep_pci.o unin_
CPPFLAGS += -DHAS_AUDIO
endif
ifeq ($(TARGET_ARCH), mips)
-VL_OBJS+= mips_r4k.o mips_malta.o mips_timer.o dma.o vga.o serial.o i8254.o i8259.o
+VL_OBJS+= mips_r4k.o mips_malta.o mips_timer.o mips_int.o dma.o vga.o serial.o i8254.o i8259.o
VL_OBJS+= ide.o gt64xxx.o pckbd.o ps2.o fdc.o mc146818rtc.o usb-uhci.o acpi.o
VL_OBJS+= piix_pci.o parallel.o mixeng.o cirrus_vga.o $(SOUND_HW) $(AUDIODRV)
DEFINES += -DHAS_AUDIO
Index: cpu-exec.c
===================================================================
RCS file: /sources/qemu/qemu/cpu-exec.c,v
retrieving revision 1.88
diff -u -d -p -r1.88 cpu-exec.c
--- cpu-exec.c 7 Dec 2006 18:28:42 -0000 1.88
+++ cpu-exec.c 23 Jan 2007 19:57:10 -0000
@@ -535,7 +535,6 @@ int cpu_exec(CPUState *env1)
env->exception_index = EXCP_EXT_INTERRUPT;
env->error_code = 0;
do_interrupt(env);
- env->interrupt_request &= ~CPU_INTERRUPT_HARD;
#if defined(__sparc__) && !defined(HOST_SOLARIS)
tmp_T0 = 0;
#else
Index: vl.h
===================================================================
RCS file: /sources/qemu/qemu/vl.h,v
retrieving revision 1.175
diff -u -d -p -r1.175 vl.h
--- vl.h 21 Jan 2007 16:47:01 -0000 1.175
+++ vl.h 23 Jan 2007 19:57:10 -0000
@@ -1067,6 +1067,9 @@ extern QEMUMachine mips_machine;
/* mips_malta.c */
extern QEMUMachine mips_malta_machine;
+/* mips_int */
+extern void cpu_mips_irq_request(void *opaque, int irq, int level);
+
/* mips_timer.c */
extern void cpu_mips_clock_init(CPUState *);
extern void cpu_mips_irqctrl_init (void);
Index: hw/gt64xxx.c
===================================================================
RCS file: /sources/qemu/qemu/hw/gt64xxx.c,v
retrieving revision 1.2
diff -u -d -p -r1.2 gt64xxx.c
--- hw/gt64xxx.c 17 Jan 2007 23:35:01 -0000 1.2
+++ hw/gt64xxx.c 23 Jan 2007 19:57:10 -0000
@@ -1,7 +1,7 @@
/*
* QEMU GT64120 PCI host
*
- * Copyright (c) 2006 Aurelien Jarno
+ * Copyright (c) 2006,2007 Aurelien Jarno
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -433,7 +436,8 @@ static uint32_t gt64120_readl (void *opa
val = s->regs[saddr];
break;
case GT_PCI0_IACK:
- val = pic_intack_read(isa_pic);
+ /* Read the IRQ number */
+ val = pic_read_irq(isa_pic);
break;
/* SDRAM Parameters */
Index: hw/i8259.c
===================================================================
RCS file: /sources/qemu/qemu/hw/i8259.c,v
retrieving revision 1.19
diff -u -d -p -r1.19 i8259.c
--- hw/i8259.c 25 Jun 2006 18:15:31 -0000 1.19
+++ hw/i8259.c 23 Jan 2007 19:57:10 -0000
@@ -161,6 +161,13 @@ void pic_update_irq(PicState2 *s)
#endif
s->irq_request(s->irq_request_opaque, 1);
}
+
+/* all targets should do this rather than acking the IRQ in the cpu */
+#if defined(TARGET_MIPS)
+ else {
+ s->irq_request(s->irq_request_opaque, 0);
+ }
+#endif
}
#ifdef DEBUG_IRQ_LATENCY
Index: hw/mips_malta.c
===================================================================
RCS file: /sources/qemu/qemu/hw/mips_malta.c,v
retrieving revision 1.4
diff -u -d -p -r1.4 mips_malta.c
--- hw/mips_malta.c 20 Jan 2007 00:29:01 -0000 1.4
+++ hw/mips_malta.c 23 Jan 2007 19:57:10 -0000
@@ -54,16 +54,10 @@ typedef struct {
static PITState *pit;
+/* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
static void pic_irq_request(void *opaque, int level)
{
- CPUState *env = first_cpu;
- if (level) {
- env->CP0_Cause |= 0x00000400;
- cpu_interrupt(env, CPU_INTERRUPT_HARD);
- } else {
- env->CP0_Cause &= ~0x00000400;
- cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
- }
+ cpu_mips_irq_request(opaque, 2, level);
}
/* Malta FPGA */
Index: hw/mips_r4k.c
===================================================================
RCS file: /sources/qemu/qemu/hw/mips_r4k.c,v
retrieving revision 1.31
diff -u -d -p -r1.31 mips_r4k.c
--- hw/mips_r4k.c 6 Jan 2007 02:24:15 -0000 1.31
+++ hw/mips_r4k.c 23 Jan 2007 19:57:10 -0000
@@ -38,14 +38,7 @@ static PITState *pit; /* PIT i8254 */
/*The PIC is attached to the MIPS CPU INT0 pin */
static void pic_irq_request(void *opaque, int level)
{
- CPUState *env = first_cpu;
- if (level) {
- env->CP0_Cause |= 0x00000400;
- cpu_interrupt(env, CPU_INTERRUPT_HARD);
- } else {
- env->CP0_Cause &= ~0x00000400;
- cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
- }
+ cpu_mips_irq_request(opaque, 2, level);
}
static void mips_qemu_writel (void *opaque, target_phys_addr_t addr,
Index: hw/mips_timer.c
===================================================================
RCS file: /sources/qemu/qemu/hw/mips_timer.c,v
retrieving revision 1.1
diff -u -d -p -r1.1 mips_timer.c
--- hw/mips_timer.c 6 Dec 2006 21:38:37 -0000 1.1
+++ hw/mips_timer.c 23 Jan 2007 19:57:10 -0000
@@ -57,8 +57,7 @@ void cpu_mips_store_count (CPUState *env
void cpu_mips_store_compare (CPUState *env, uint32_t value)
{
cpu_mips_update_count(env, cpu_mips_get_count(env), value);
- env->CP0_Cause &= ~0x00008000;
- cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+ cpu_mips_irq_request(env, 7, 0);
}
static void mips_timer_cb (void *opaque)
@@ -72,8 +71,7 @@ static void mips_timer_cb (void *opaque)
}
#endif
cpu_mips_update_count(env, cpu_mips_get_count(env), env->CP0_Compare);
- env->CP0_Cause |= 0x00008000;
- cpu_interrupt(env, CPU_INTERRUPT_HARD);
+ cpu_mips_irq_request(env, 7, 1);
}
void cpu_mips_clock_init (CPUState *env)
Index: target-mips/cpu.h
===================================================================
RCS file: /sources/qemu/qemu/target-mips/cpu.h,v
retrieving revision 1.17
diff -u -d -p -r1.17 cpu.h
--- target-mips/cpu.h 22 Jan 2007 20:50:42 -0000 1.17
+++ target-mips/cpu.h 23 Jan 2007 19:57:10 -0000
@@ -157,6 +157,7 @@ struct CPUMIPSState {
#define CP0Ca_IV 23
#define CP0Ca_WP 22
#define CP0Ca_IP 8
+#define CP0Ca_IP_mask 0x0000FF00
#define CP0Ca_EC 2
target_ulong CP0_EPC;
uint32_t CP0_PRid;
Index: target-mips/exec.h
===================================================================
RCS file: /sources/qemu/qemu/target-mips/exec.h,v
retrieving revision 1.15
diff -u -d -p -r1.15 exec.h
--- target-mips/exec.h 3 Jan 2007 15:18:08 -0000 1.15
+++ target-mips/exec.h 23 Jan 2007 19:57:10 -0000
@@ -164,6 +164,7 @@ uint32_t cpu_mips_get_random (CPUState *
uint32_t cpu_mips_get_count (CPUState *env);
void cpu_mips_store_count (CPUState *env, uint32_t value);
void cpu_mips_store_compare (CPUState *env, uint32_t value);
+void cpu_mips_update_irq(CPUState *env);
void cpu_mips_clock_init (CPUState *env);
void cpu_mips_tlb_flush (CPUState *env, int flush_global);
Index: target-mips/op.c
===================================================================
RCS file: /sources/qemu/qemu/target-mips/op.c,v
retrieving revision 1.19
diff -u -d -p -r1.19 op.c
--- target-mips/op.c 1 Jan 2007 20:35:21 -0000 1.19
+++ target-mips/op.c 23 Jan 2007 19:57:10 -0000
@@ -1351,7 +1351,7 @@ void op_mtc0_compare (void)
void op_mtc0_status (void)
{
- uint32_t val, old, mask;
+ uint32_t val, old;
val = T0 & (int32_t)0xFA78FF01;
old = env->CP0_Status;
@@ -1368,21 +1368,9 @@ void op_mtc0_status (void)
else
env->hflags &= ~MIPS_HFLAG_EXL;
env->CP0_Status = val;
- /* If we unmasked an asserted IRQ, raise it */
- mask = 0x0000FF00;
if (loglevel & CPU_LOG_TB_IN_ASM)
CALL_FROM_TB2(do_mtc0_status_debug, old, val);
- if ((val & (1 << CP0St_IE)) && !(old & (1 << CP0St_IE)) &&
- !(env->hflags & MIPS_HFLAG_EXL) &&
- !(env->hflags & MIPS_HFLAG_ERL) &&
- !(env->hflags & MIPS_HFLAG_DM) &&
- (env->CP0_Status & env->CP0_Cause & mask)) {
- env->interrupt_request |= CPU_INTERRUPT_HARD;
- if (logfile)
- CALL_FROM_TB0(do_mtc0_status_irqraise_debug);
- } else if (!(val & (1 << CP0St_IE)) && (old & (1 << CP0St_IE))) {
- env->interrupt_request &= ~CPU_INTERRUPT_HARD;
- }
+ CALL_FROM_TB1(cpu_mips_update_irq, env);
RETURN();
}
@@ -1402,22 +1390,13 @@ void op_mtc0_srsctl (void)
void op_mtc0_cause (void)
{
- uint32_t val, old;
+ env->CP0_Cause = (env->CP0_Cause & 0xB000F87C) | (T0 & 0x00C00300);
- val = (env->CP0_Cause & 0xB000F87C) | (T0 & 0x00C00300);
- old = env->CP0_Cause;
- env->CP0_Cause = val;
-#if 0
- {
- int i, mask;
- /* Check if we ever asserted a software IRQ */
- for (i = 0; i < 2; i++) {
- mask = 0x100 << i;
- if ((val & mask) & !(old & mask))
- CALL_FROM_TB1(mips_set_irq, i);
- }
+ /* Handle the software interrupt as an hardware one, as they
+ are very similar */
+ if (T0 & CP0Ca_IP_mask) {
+ CALL_FROM_TB1(cpu_mips_update_irq, env);
}
-#endif
RETURN();
}
@@ -1928,36 +1907,17 @@ void op_pmon (void)
void op_di (void)
{
- uint32_t val;
-
T0 = env->CP0_Status;
- val = T0 & ~(1 << CP0St_IE);
- if (val != T0) {
- env->interrupt_request &= ~CPU_INTERRUPT_HARD;
- env->CP0_Status = val;
- }
+ env->CP0_Status = T0 & ~(1 << CP0St_IE);
+ CALL_FROM_TB1(cpu_mips_update_irq, env);
RETURN();
}
void op_ei (void)
{
- uint32_t val;
-
T0 = env->CP0_Status;
- val = T0 | (1 << CP0St_IE);
- if (val != T0) {
- const uint32_t mask = 0x0000FF00;
-
- env->CP0_Status = val;
- if (!(env->hflags & MIPS_HFLAG_EXL) &&
- !(env->hflags & MIPS_HFLAG_ERL) &&
- !(env->hflags & MIPS_HFLAG_DM) &&
- (env->CP0_Status & env->CP0_Cause & mask)) {
- env->interrupt_request |= CPU_INTERRUPT_HARD;
- if (logfile)
- CALL_FROM_TB0(do_mtc0_status_irqraise_debug);
- }
- }
+ env->CP0_Status = T0 | (1 << CP0St_IE);
+ CALL_FROM_TB1(cpu_mips_update_irq, env);
RETURN();
}
Index: target-mips/op_helper.c
===================================================================
RCS file: /sources/qemu/qemu/target-mips/op_helper.c,v
retrieving revision 1.26
diff -u -d -p -r1.26 op_helper.c
--- target-mips/op_helper.c 22 Jan 2007 20:50:42 -0000 1.26
+++ target-mips/op_helper.c 23 Jan 2007 19:57:10 -0000
@@ -265,6 +265,11 @@ void cpu_mips_store_compare(CPUState *en
cpu_abort(env, "mtc0 compare\n");
}
+void cpu_mips_update_irq(CPUState *env)
+{
+ cpu_abort(env, "mtc0 status / mtc0 cause\n");
+}
+
void do_mtc0_status_debug(uint32_t old, uint32_t val)
{
cpu_abort(env, "mtc0 status debug\n");
--
.''`. Aurelien Jarno | GPG: 1024D/F1BCDB73
: :' : Debian developer | Electrical Engineer
`. `' aurel32@debian.org | aurelien@aurel32.net
`- people.debian.org/~aurel32 | www.aurel32.net
next prev parent reply other threads:[~2007-01-23 20:00 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-01-23 18:42 [Qemu-devel] [PATCH] Reworking MIPS interrupts handling Aurelien Jarno
2007-01-23 20:00 ` Aurelien Jarno [this message]
2007-01-23 20:19 ` Fabrice Bellard
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20070123200052.GA11429@amd64.aurel32.net \
--to=aurelien@aurel32.net \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.