Commit 70ea255d8be9ca5af3eb20a6ad000ea4ab1e2d17

Authored by edgar_igl
1 parent ab86bb3b

ETRAX: Correctly update the interrupt vector when interrupts get masked.

Cannot believe this bug has been around for so long.

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6207 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 38 additions and 64 deletions
hw/etraxfs_pic.c
@@ -41,13 +41,40 @@ struct fs_pic_state_t @@ -41,13 +41,40 @@ struct fs_pic_state_t
41 uint32_t r_guru; 41 uint32_t r_guru;
42 }; 42 };
43 43
44 -static uint32_t pic_readb (void *opaque, target_phys_addr_t addr)  
45 -{  
46 - return 0;  
47 -}  
48 -static uint32_t pic_readw (void *opaque, target_phys_addr_t addr)  
49 -{  
50 - return 0; 44 +static void pic_update(struct fs_pic_state_t *fs)
  45 +{
  46 + CPUState *env = fs->env;
  47 + int i;
  48 + uint32_t vector = 0;
  49 +
  50 + fs->r_masked_vect = fs->r_vect & fs->rw_mask;
  51 +
  52 + /* The ETRAX interrupt controller signals interrupts to teh core
  53 + through an interrupt request wire and an irq vector bus. If
  54 + multiple interrupts are simultaneously active it chooses vector
  55 + 0x30 and lets the sw choose the priorities. */
  56 + if (fs->r_masked_vect) {
  57 + uint32_t mv = fs->r_masked_vect;
  58 + for (i = 0; i < 31; i++) {
  59 + if (mv & 1) {
  60 + vector = 0x31 + i;
  61 + /* Check for multiple interrupts. */
  62 + if (mv > 1)
  63 + vector = 0x30;
  64 + break;
  65 + }
  66 + mv >>= 1;
  67 + }
  68 + if (vector) {
  69 + env->interrupt_vector = vector;
  70 + D(printf("%s vector=%x\n", __func__, vector));
  71 + cpu_interrupt(env, CPU_INTERRUPT_HARD);
  72 + }
  73 + } else {
  74 + env->interrupt_vector = 0;
  75 + cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
  76 + D(printf("%s reset irqs\n", __func__));
  77 + }
51 } 78 }
52 79
53 static uint32_t pic_readl (void *opaque, target_phys_addr_t addr) 80 static uint32_t pic_readl (void *opaque, target_phys_addr_t addr)
@@ -82,16 +109,6 @@ static uint32_t pic_readl (void *opaque, target_phys_addr_t addr) @@ -82,16 +109,6 @@ static uint32_t pic_readl (void *opaque, target_phys_addr_t addr)
82 } 109 }
83 110
84 static void 111 static void
85 -pic_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)  
86 -{  
87 -}  
88 -  
89 -static void  
90 -pic_writew (void *opaque, target_phys_addr_t addr, uint32_t value)  
91 -{  
92 -}  
93 -  
94 -static void  
95 pic_writel (void *opaque, target_phys_addr_t addr, uint32_t value) 112 pic_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
96 { 113 {
97 struct fs_pic_state_t *fs = opaque; 114 struct fs_pic_state_t *fs = opaque;
@@ -100,18 +117,7 @@ pic_writel (void *opaque, target_phys_addr_t addr, uint32_t value) @@ -100,18 +117,7 @@ pic_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
100 { 117 {
101 case 0x0: 118 case 0x0:
102 fs->rw_mask = value; 119 fs->rw_mask = value;
103 - break;  
104 - case 0x4:  
105 - fs->r_vect = value;  
106 - break;  
107 - case 0x8:  
108 - fs->r_masked_vect = value;  
109 - break;  
110 - case 0xc:  
111 - fs->r_nmi = value;  
112 - break;  
113 - case 0x10:  
114 - fs->r_guru = value; 120 + pic_update(fs);
115 break; 121 break;
116 default: 122 default:
117 cpu_abort(fs->env, "invalid PIC register.\n"); 123 cpu_abort(fs->env, "invalid PIC register.\n");
@@ -120,14 +126,12 @@ pic_writel (void *opaque, target_phys_addr_t addr, uint32_t value) @@ -120,14 +126,12 @@ pic_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
120 } 126 }
121 127
122 static CPUReadMemoryFunc *pic_read[] = { 128 static CPUReadMemoryFunc *pic_read[] = {
123 - &pic_readb,  
124 - &pic_readw, 129 + NULL, NULL,
125 &pic_readl, 130 &pic_readl,
126 }; 131 };
127 132
128 static CPUWriteMemoryFunc *pic_write[] = { 133 static CPUWriteMemoryFunc *pic_write[] = {
129 - &pic_writeb,  
130 - &pic_writew, 134 + NULL, NULL,
131 &pic_writel, 135 &pic_writel,
132 }; 136 };
133 137
@@ -142,9 +146,6 @@ void irq_info(void) @@ -142,9 +146,6 @@ void irq_info(void)
142 static void irq_handler(void *opaque, int irq, int level) 146 static void irq_handler(void *opaque, int irq, int level)
143 { 147 {
144 struct fs_pic_state_t *fs = (void *)opaque; 148 struct fs_pic_state_t *fs = (void *)opaque;
145 - CPUState *env = fs->env;  
146 - int i;  
147 - uint32_t vector = 0;  
148 149
149 D(printf("%s irq=%d level=%d mask=%x v=%x mv=%x\n", 150 D(printf("%s irq=%d level=%d mask=%x v=%x mv=%x\n",
150 __func__, irq, level, 151 __func__, irq, level,
@@ -153,34 +154,8 @@ static void irq_handler(void *opaque, int irq, int level) @@ -153,34 +154,8 @@ static void irq_handler(void *opaque, int irq, int level)
153 irq -= 1; 154 irq -= 1;
154 fs->r_vect &= ~(1 << irq); 155 fs->r_vect &= ~(1 << irq);
155 fs->r_vect |= (!!level << irq); 156 fs->r_vect |= (!!level << irq);
156 - fs->r_masked_vect = fs->r_vect & fs->rw_mask;  
157 157
158 - /* The ETRAX interrupt controller signals interrupts to teh core  
159 - through an interrupt request wire and an irq vector bus. If  
160 - multiple interrupts are simultaneously active it chooses vector  
161 - 0x30 and lets the sw choose the priorities. */  
162 - if (fs->r_masked_vect) {  
163 - uint32_t mv = fs->r_masked_vect;  
164 - for (i = 0; i < 31; i++) {  
165 - if (mv & 1) {  
166 - vector = 0x31 + i;  
167 - /* Check for multiple interrupts. */  
168 - if (mv > 1)  
169 - vector = 0x30;  
170 - break;  
171 - }  
172 - mv >>= 1;  
173 - }  
174 - if (vector) {  
175 - env->interrupt_vector = vector;  
176 - D(printf("%s vector=%x\n", __func__, vector));  
177 - cpu_interrupt(env, CPU_INTERRUPT_HARD);  
178 - }  
179 - } else {  
180 - env->interrupt_vector = 0;  
181 - cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);  
182 - D(printf("%s reset irqs\n", __func__));  
183 - } 158 + pic_update(fs);
184 } 159 }
185 160
186 static void nmi_handler(void *opaque, int irq, int level) 161 static void nmi_handler(void *opaque, int irq, int level)
@@ -209,7 +184,6 @@ static void guru_handler(void *opaque, int irq, int level) @@ -209,7 +184,6 @@ static void guru_handler(void *opaque, int irq, int level)
209 184
210 } 185 }
211 186
212 -  
213 struct etraxfs_pic *etraxfs_pic_init(CPUState *env, target_phys_addr_t base) 187 struct etraxfs_pic *etraxfs_pic_init(CPUState *env, target_phys_addr_t base)
214 { 188 {
215 struct fs_pic_state_t *fs = NULL; 189 struct fs_pic_state_t *fs = NULL;