Commit ba3c64fb476d57c35013970ac444f04f35893ca9
1 parent
b9788fc4
Initial SPARC SMP support (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1694 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
12 changed files
with
196 additions
and
54 deletions
Changelog
cpu-all.h
... | ... | @@ -734,6 +734,7 @@ extern int code_copy_enabled; |
734 | 734 | #define CPU_INTERRUPT_EXITTB 0x04 /* exit the current TB (use for x86 a20 case) */ |
735 | 735 | #define CPU_INTERRUPT_TIMER 0x08 /* internal timer exception pending */ |
736 | 736 | #define CPU_INTERRUPT_FIQ 0x10 /* Fast interrupt pending. */ |
737 | +#define CPU_INTERRUPT_HALT 0x20 /* CPU halt wanted */ | |
737 | 738 | |
738 | 739 | void cpu_interrupt(CPUState *s, int mask); |
739 | 740 | void cpu_reset_interrupt(CPUState *env, int mask); | ... | ... |
cpu-exec.c
... | ... | @@ -274,6 +274,15 @@ int cpu_exec(CPUState *env1) |
274 | 274 | return EXCP_HALTED; |
275 | 275 | } |
276 | 276 | } |
277 | +#elif defined(TARGET_SPARC) | |
278 | + if (env1->halted) { | |
279 | + if ((env1->interrupt_request & CPU_INTERRUPT_HARD) && | |
280 | + (env1->psret != 0)) { | |
281 | + env1->halted = 0; | |
282 | + } else { | |
283 | + return EXCP_HALTED; | |
284 | + } | |
285 | + } | |
277 | 286 | #elif defined(TARGET_ARM) |
278 | 287 | if (env1->halted) { |
279 | 288 | /* An interrupt wakes the CPU even if the I and F CPSR bits are |
... | ... | @@ -522,7 +531,10 @@ int cpu_exec(CPUState *env1) |
522 | 531 | } else if (interrupt_request & CPU_INTERRUPT_TIMER) { |
523 | 532 | //do_interrupt(0, 0, 0, 0, 0); |
524 | 533 | env->interrupt_request &= ~CPU_INTERRUPT_TIMER; |
525 | - } | |
534 | + } else if (interrupt_request & CPU_INTERRUPT_HALT) { | |
535 | + env1->halted = 1; | |
536 | + return EXCP_HALTED; | |
537 | + } | |
526 | 538 | #elif defined(TARGET_ARM) |
527 | 539 | if (interrupt_request & CPU_INTERRUPT_FIQ |
528 | 540 | && !(env->uncached_cpsr & CPSR_F)) { | ... | ... |
hw/slavio_intctl.c
... | ... | @@ -53,6 +53,7 @@ typedef struct SLAVIO_INTCTLState { |
53 | 53 | #ifdef DEBUG_IRQ_COUNT |
54 | 54 | uint64_t irq_count[32]; |
55 | 55 | #endif |
56 | + CPUState *cpu_envs[MAX_CPUS]; | |
56 | 57 | } SLAVIO_INTCTLState; |
57 | 58 | |
58 | 59 | #define INTCTL_MAXADDR 0xf |
... | ... | @@ -96,6 +97,7 @@ static void slavio_intctl_mem_writel(void *opaque, target_phys_addr_t addr, uint |
96 | 97 | case 2: // set softint |
97 | 98 | val &= 0xfffe0000; |
98 | 99 | s->intreg_pending[cpu] |= val; |
100 | + slavio_check_interrupts(s); | |
99 | 101 | DPRINTF("Set cpu %d irq mask %x, curmask %x\n", cpu, val, s->intreg_pending[cpu]); |
100 | 102 | break; |
101 | 103 | default: |
... | ... | @@ -216,7 +218,7 @@ static void slavio_check_interrupts(void *opaque) |
216 | 218 | CPUState *env; |
217 | 219 | SLAVIO_INTCTLState *s = opaque; |
218 | 220 | uint32_t pending = s->intregm_pending; |
219 | - unsigned int i, max = 0; | |
221 | + unsigned int i, j, max = 0; | |
220 | 222 | |
221 | 223 | pending &= ~s->intregm_disabled; |
222 | 224 | |
... | ... | @@ -227,20 +229,52 @@ static void slavio_check_interrupts(void *opaque) |
227 | 229 | max = intbit_to_level[i]; |
228 | 230 | } |
229 | 231 | } |
230 | - env = first_cpu; | |
231 | - if (env->interrupt_index == 0) { | |
232 | - DPRINTF("Triggered pil %d\n", max); | |
232 | + env = s->cpu_envs[s->target_cpu]; | |
233 | + if (!env) { | |
234 | + DPRINTF("No CPU %d, not triggered (pending %x)\n", s->target_cpu, pending); | |
235 | + } | |
236 | + else { | |
237 | + if (env->halted) | |
238 | + env->halted = 0; | |
239 | + if (env->interrupt_index == 0) { | |
240 | + DPRINTF("Triggered CPU %d pil %d\n", s->target_cpu, max); | |
233 | 241 | #ifdef DEBUG_IRQ_COUNT |
234 | - s->irq_count[max]++; | |
242 | + s->irq_count[max]++; | |
235 | 243 | #endif |
236 | - env->interrupt_index = TT_EXTINT | max; | |
237 | - cpu_interrupt(env, CPU_INTERRUPT_HARD); | |
244 | + env->interrupt_index = TT_EXTINT | max; | |
245 | + cpu_interrupt(env, CPU_INTERRUPT_HARD); | |
246 | + } | |
247 | + else | |
248 | + DPRINTF("Not triggered (pending %x), pending exception %x\n", pending, env->interrupt_index); | |
238 | 249 | } |
239 | - else | |
240 | - DPRINTF("Not triggered (pending %x), pending exception %x\n", pending, env->interrupt_index); | |
241 | 250 | } |
242 | 251 | else |
243 | 252 | DPRINTF("Not triggered (pending %x), disabled %x\n", pending, s->intregm_disabled); |
253 | + | |
254 | + for (i = 0; i < MAX_CPUS; i++) { | |
255 | + max = 0; | |
256 | + env = s->cpu_envs[i]; | |
257 | + if (!env) | |
258 | + continue; | |
259 | + for (j = 17; j < 32; j++) { | |
260 | + if (s->intreg_pending[i] & (1 << j)) { | |
261 | + if (max < j - 16) | |
262 | + max = j - 16; | |
263 | + } | |
264 | + } | |
265 | + if (max > 0) { | |
266 | + if (env->halted) | |
267 | + env->halted = 0; | |
268 | + if (env->interrupt_index == 0) { | |
269 | + DPRINTF("Triggered softint %d for cpu %d (pending %x)\n", max, i, pending); | |
270 | +#ifdef DEBUG_IRQ_COUNT | |
271 | + s->irq_count[max]++; | |
272 | +#endif | |
273 | + env->interrupt_index = TT_EXTINT | max; | |
274 | + cpu_interrupt(env, CPU_INTERRUPT_HARD); | |
275 | + } | |
276 | + } | |
277 | + } | |
244 | 278 | } |
245 | 279 | |
246 | 280 | /* |
... | ... | @@ -251,7 +285,7 @@ void slavio_pic_set_irq(void *opaque, int irq, int level) |
251 | 285 | { |
252 | 286 | SLAVIO_INTCTLState *s = opaque; |
253 | 287 | |
254 | - DPRINTF("Set irq %d level %d\n", irq, level); | |
288 | + DPRINTF("Set cpu %d irq %d level %d\n", s->target_cpu, irq, level); | |
255 | 289 | if (irq < 32) { |
256 | 290 | uint32_t mask = 1 << irq; |
257 | 291 | uint32_t pil = intbit_to_level[irq]; |
... | ... | @@ -269,6 +303,29 @@ void slavio_pic_set_irq(void *opaque, int irq, int level) |
269 | 303 | slavio_check_interrupts(s); |
270 | 304 | } |
271 | 305 | |
306 | +void slavio_pic_set_irq_cpu(void *opaque, int irq, int level, unsigned int cpu) | |
307 | +{ | |
308 | + SLAVIO_INTCTLState *s = opaque; | |
309 | + | |
310 | + DPRINTF("Set cpu %d local irq %d level %d\n", cpu, irq, level); | |
311 | + if (cpu == (unsigned int)-1) { | |
312 | + slavio_pic_set_irq(opaque, irq, level); | |
313 | + return; | |
314 | + } | |
315 | + if (irq < 32) { | |
316 | + uint32_t pil = intbit_to_level[irq]; | |
317 | + if (pil > 0) { | |
318 | + if (level) { | |
319 | + s->intreg_pending[cpu] |= 1 << pil; | |
320 | + } | |
321 | + else { | |
322 | + s->intreg_pending[cpu] &= ~(1 << pil); | |
323 | + } | |
324 | + } | |
325 | + } | |
326 | + slavio_check_interrupts(s); | |
327 | +} | |
328 | + | |
272 | 329 | static void slavio_intctl_save(QEMUFile *f, void *opaque) |
273 | 330 | { |
274 | 331 | SLAVIO_INTCTLState *s = opaque; |
... | ... | @@ -312,6 +369,12 @@ static void slavio_intctl_reset(void *opaque) |
312 | 369 | s->target_cpu = 0; |
313 | 370 | } |
314 | 371 | |
372 | +void slavio_intctl_set_cpu(void *opaque, unsigned int cpu, CPUState *env) | |
373 | +{ | |
374 | + SLAVIO_INTCTLState *s = opaque; | |
375 | + s->cpu_envs[cpu] = env; | |
376 | +} | |
377 | + | |
315 | 378 | void *slavio_intctl_init(uint32_t addr, uint32_t addrg) |
316 | 379 | { |
317 | 380 | int slavio_intctl_io_memory, slavio_intctlm_io_memory, i; | ... | ... |
hw/slavio_misc.c
... | ... | @@ -124,9 +124,8 @@ static void slavio_misc_mem_writeb(void *opaque, target_phys_addr_t addr, uint32 |
124 | 124 | case 0xa000000: |
125 | 125 | MISC_DPRINTF("Write power management %2.2x\n", val & 0xff); |
126 | 126 | #if 0 |
127 | - // XXX: halting CPU does not work | |
128 | - raise_exception(EXCP_HLT); | |
129 | - cpu_loop_exit(); | |
127 | + // XXX almost works | |
128 | + cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HALT); | |
130 | 129 | #endif |
131 | 130 | break; |
132 | 131 | } | ... | ... |
hw/slavio_serial.c
... | ... | @@ -45,6 +45,8 @@ |
45 | 45 | #ifdef DEBUG_SERIAL |
46 | 46 | #define SER_DPRINTF(fmt, args...) \ |
47 | 47 | do { printf("SER: " fmt , ##args); } while (0) |
48 | +#define pic_set_irq(irq, level) \ | |
49 | +do { printf("SER: set_irq(%d): %d\n", (irq), (level)); pic_set_irq((irq),(level));} while (0) | |
48 | 50 | #else |
49 | 51 | #define SER_DPRINTF(fmt, args...) |
50 | 52 | #endif |
... | ... | @@ -174,6 +176,50 @@ static void slavio_serial_reset(void *opaque) |
174 | 176 | slavio_serial_reset_chn(&s->chn[1]); |
175 | 177 | } |
176 | 178 | |
179 | +static inline void clr_rxint(ChannelState *s) | |
180 | +{ | |
181 | + s->rxint = 0; | |
182 | + if (s->chn == 0) | |
183 | + s->rregs[3] &= ~0x20; | |
184 | + else { | |
185 | + s->otherchn->rregs[3] &= ~4; | |
186 | + } | |
187 | + slavio_serial_update_irq(s); | |
188 | +} | |
189 | + | |
190 | +static inline void set_rxint(ChannelState *s) | |
191 | +{ | |
192 | + s->rxint = 1; | |
193 | + if (s->chn == 0) | |
194 | + s->rregs[3] |= 0x20; | |
195 | + else { | |
196 | + s->otherchn->rregs[3] |= 4; | |
197 | + } | |
198 | + slavio_serial_update_irq(s); | |
199 | +} | |
200 | + | |
201 | +static inline void clr_txint(ChannelState *s) | |
202 | +{ | |
203 | + s->txint = 0; | |
204 | + if (s->chn == 0) | |
205 | + s->rregs[3] &= ~0x10; | |
206 | + else { | |
207 | + s->otherchn->rregs[3] &= ~2; | |
208 | + } | |
209 | + slavio_serial_update_irq(s); | |
210 | +} | |
211 | + | |
212 | +static inline void set_txint(ChannelState *s) | |
213 | +{ | |
214 | + s->txint = 1; | |
215 | + if (s->chn == 0) | |
216 | + s->rregs[3] |= 0x10; | |
217 | + else { | |
218 | + s->otherchn->rregs[3] |= 2; | |
219 | + } | |
220 | + slavio_serial_update_irq(s); | |
221 | +} | |
222 | + | |
177 | 223 | static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) |
178 | 224 | { |
179 | 225 | SerialState *ser = opaque; |
... | ... | @@ -198,10 +244,14 @@ static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint |
198 | 244 | newreg |= 0x8; |
199 | 245 | break; |
200 | 246 | case 0x20: |
201 | - s->rxint = 0; | |
247 | + clr_rxint(s); | |
202 | 248 | break; |
203 | 249 | case 0x28: |
204 | - s->txint = 0; | |
250 | + clr_txint(s); | |
251 | + break; | |
252 | + case 0x38: | |
253 | + clr_rxint(s); | |
254 | + clr_txint(s); | |
205 | 255 | break; |
206 | 256 | default: |
207 | 257 | break; |
... | ... | @@ -247,12 +297,7 @@ static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint |
247 | 297 | s->txint = 1; |
248 | 298 | s->rregs[0] |= 4; // Tx buffer empty |
249 | 299 | s->rregs[1] |= 1; // All sent |
250 | - // Interrupts reported only on channel A | |
251 | - if (s->chn == 0) | |
252 | - s->rregs[3] |= 0x10; | |
253 | - else { | |
254 | - s->otherchn->rregs[3] |= 2; | |
255 | - } | |
300 | + set_txint(s); | |
256 | 301 | slavio_serial_update_irq(s); |
257 | 302 | } |
258 | 303 | break; |
... | ... | @@ -280,6 +325,7 @@ static uint32_t slavio_serial_mem_readb(void *opaque, target_phys_addr_t addr) |
280 | 325 | return ret; |
281 | 326 | case 1: |
282 | 327 | s->rregs[0] &= ~1; |
328 | + clr_rxint(s); | |
283 | 329 | if (s->type == kbd) |
284 | 330 | ret = get_queue(s); |
285 | 331 | else |
... | ... | @@ -304,16 +350,10 @@ static int serial_can_receive(void *opaque) |
304 | 350 | |
305 | 351 | static void serial_receive_byte(ChannelState *s, int ch) |
306 | 352 | { |
353 | + SER_DPRINTF("put ch %d\n", ch); | |
307 | 354 | s->rregs[0] |= 1; |
308 | - // Interrupts reported only on channel A | |
309 | - if (s->chn == 0) | |
310 | - s->rregs[3] |= 0x20; | |
311 | - else { | |
312 | - s->otherchn->rregs[3] |= 4; | |
313 | - } | |
314 | 355 | s->rx = ch; |
315 | - s->rxint = 1; | |
316 | - slavio_serial_update_irq(s); | |
356 | + set_rxint(s); | |
317 | 357 | } |
318 | 358 | |
319 | 359 | static void serial_receive_break(ChannelState *s) | ... | ... |
hw/slavio_timer.c
... | ... | @@ -42,6 +42,9 @@ do { printf("TIMER: " fmt , ##args); } while (0) |
42 | 42 | * The 31-bit counter is incremented every 500ns by bit 9. Bits 8..0 |
43 | 43 | * are zero. Bit 31 is 1 when count has been reached. |
44 | 44 | * |
45 | + * Per-CPU timers interrupt local CPU, system timer uses normal | |
46 | + * interrupt routing. | |
47 | + * | |
45 | 48 | */ |
46 | 49 | |
47 | 50 | typedef struct SLAVIO_TIMERState { |
... | ... | @@ -53,11 +56,11 @@ typedef struct SLAVIO_TIMERState { |
53 | 56 | int irq; |
54 | 57 | int reached, stopped; |
55 | 58 | int mode; // 0 = processor, 1 = user, 2 = system |
59 | + unsigned int cpu; | |
56 | 60 | } SLAVIO_TIMERState; |
57 | 61 | |
58 | 62 | #define TIMER_MAXADDR 0x1f |
59 | 63 | #define CNT_FREQ 2000000 |
60 | -#define MAX_CPUS 16 | |
61 | 64 | |
62 | 65 | // Update count, set irq, update expire_time |
63 | 66 | static void slavio_timer_get_out(SLAVIO_TIMERState *s) |
... | ... | @@ -73,7 +76,7 @@ static void slavio_timer_get_out(SLAVIO_TIMERState *s) |
73 | 76 | else |
74 | 77 | ticks = qemu_get_clock(vm_clock) - s->tick_offset; |
75 | 78 | |
76 | - out = (ticks >= s->expire_time); | |
79 | + out = (ticks > s->expire_time); | |
77 | 80 | if (out) |
78 | 81 | s->reached = 0x80000000; |
79 | 82 | if (!s->limit) |
... | ... | @@ -100,7 +103,7 @@ static void slavio_timer_get_out(SLAVIO_TIMERState *s) |
100 | 103 | DPRINTF("irq %d limit %d reached %d d %lld count %d s->c %x diff %lld stopped %d mode %d\n", s->irq, limit, s->reached?1:0, (ticks-s->count_load_time), count, s->count, s->expire_time - ticks, s->stopped, s->mode); |
101 | 104 | |
102 | 105 | if (s->mode != 1) |
103 | - pic_set_irq(s->irq, out); | |
106 | + pic_set_irq_cpu(s->irq, out, s->cpu); | |
104 | 107 | } |
105 | 108 | |
106 | 109 | // timer callback |
... | ... | @@ -127,7 +130,7 @@ static uint32_t slavio_timer_mem_readl(void *opaque, target_phys_addr_t addr) |
127 | 130 | // part of counter (user mode) |
128 | 131 | if (s->mode != 1) { |
129 | 132 | // clear irq |
130 | - pic_set_irq(s->irq, 0); | |
133 | + pic_set_irq_cpu(s->irq, 0, s->cpu); | |
131 | 134 | s->count_load_time = qemu_get_clock(vm_clock); |
132 | 135 | s->reached = 0; |
133 | 136 | return s->limit; |
... | ... | @@ -263,7 +266,7 @@ static void slavio_timer_reset(void *opaque) |
263 | 266 | slavio_timer_get_out(s); |
264 | 267 | } |
265 | 268 | |
266 | -static void slavio_timer_init_internal(uint32_t addr, int irq, int mode) | |
269 | +void slavio_timer_init(uint32_t addr, int irq, int mode, unsigned int cpu) | |
267 | 270 | { |
268 | 271 | int slavio_timer_io_memory; |
269 | 272 | SLAVIO_TIMERState *s; |
... | ... | @@ -273,6 +276,7 @@ static void slavio_timer_init_internal(uint32_t addr, int irq, int mode) |
273 | 276 | return; |
274 | 277 | s->irq = irq; |
275 | 278 | s->mode = mode; |
279 | + s->cpu = cpu; | |
276 | 280 | s->irq_timer = qemu_new_timer(vm_clock, slavio_timer_irq, s); |
277 | 281 | |
278 | 282 | slavio_timer_io_memory = cpu_register_io_memory(0, slavio_timer_mem_read, |
... | ... | @@ -282,14 +286,3 @@ static void slavio_timer_init_internal(uint32_t addr, int irq, int mode) |
282 | 286 | qemu_register_reset(slavio_timer_reset, s); |
283 | 287 | slavio_timer_reset(s); |
284 | 288 | } |
285 | - | |
286 | -void slavio_timer_init(uint32_t addr1, int irq1, uint32_t addr2, int irq2) | |
287 | -{ | |
288 | - int i; | |
289 | - | |
290 | - for (i = 0; i < MAX_CPUS; i++) { | |
291 | - slavio_timer_init_internal(addr1 + i * TARGET_PAGE_SIZE, irq1, 0); | |
292 | - } | |
293 | - | |
294 | - slavio_timer_init_internal(addr2, irq2, 2); | |
295 | -} | ... | ... |
hw/sun4m.c
... | ... | @@ -56,6 +56,7 @@ |
56 | 56 | #define PHYS_JJ_FDC 0x71400000 /* Floppy */ |
57 | 57 | #define PHYS_JJ_FLOPPY_IRQ 22 |
58 | 58 | #define PHYS_JJ_ME_IRQ 30 /* Module error, power fail */ |
59 | +#define MAX_CPUS 16 | |
59 | 60 | |
60 | 61 | /* TSC handling */ |
61 | 62 | |
... | ... | @@ -128,6 +129,8 @@ static void nvram_init(m48t59_t *nvram, uint8_t *macaddr, const char *cmdline, |
128 | 129 | nvram_set_string(nvram, 0x00, "QEMU_BIOS", 16); |
129 | 130 | nvram_set_lword(nvram, 0x10, 0x00000001); /* structure v1 */ |
130 | 131 | // NVRAM_size, arch not applicable |
132 | + m48t59_write(nvram, 0x2D, smp_cpus & 0xff); | |
133 | + m48t59_write(nvram, 0x2E, 0); | |
131 | 134 | m48t59_write(nvram, 0x2F, nographic & 0xff); |
132 | 135 | nvram_set_lword(nvram, 0x30, RAM_size); |
133 | 136 | m48t59_write(nvram, 0x34, boot_device & 0xff); |
... | ... | @@ -179,6 +182,11 @@ void pic_set_irq(int irq, int level) |
179 | 182 | slavio_pic_set_irq(slavio_intctl, irq, level); |
180 | 183 | } |
181 | 184 | |
185 | +void pic_set_irq_cpu(int irq, int level, unsigned int cpu) | |
186 | +{ | |
187 | + slavio_pic_set_irq_cpu(slavio_intctl, irq, level, cpu); | |
188 | +} | |
189 | + | |
182 | 190 | static void *tcx; |
183 | 191 | |
184 | 192 | void vga_update_display() |
... | ... | @@ -222,7 +230,7 @@ static void sun4m_init(int ram_size, int vga_ram_size, int boot_device, |
222 | 230 | const char *kernel_filename, const char *kernel_cmdline, |
223 | 231 | const char *initrd_filename) |
224 | 232 | { |
225 | - CPUState *env; | |
233 | + CPUState *env, *envs[MAX_CPUS]; | |
226 | 234 | char buf[1024]; |
227 | 235 | int ret, linux_boot; |
228 | 236 | unsigned int i; |
... | ... | @@ -230,19 +238,31 @@ static void sun4m_init(int ram_size, int vga_ram_size, int boot_device, |
230 | 238 | |
231 | 239 | linux_boot = (kernel_filename != NULL); |
232 | 240 | |
233 | - env = cpu_init(); | |
234 | - register_savevm("cpu", 0, 3, cpu_save, cpu_load, env); | |
235 | - qemu_register_reset(main_cpu_reset, env); | |
236 | - | |
241 | + /* init CPUs */ | |
242 | + for(i = 0; i < smp_cpus; i++) { | |
243 | + env = cpu_init(); | |
244 | + envs[i] = env; | |
245 | + if (i != 0) | |
246 | + env->halted = 1; | |
247 | + register_savevm("cpu", i, 3, cpu_save, cpu_load, env); | |
248 | + qemu_register_reset(main_cpu_reset, env); | |
249 | + } | |
237 | 250 | /* allocate RAM */ |
238 | 251 | cpu_register_physical_memory(0, ram_size, 0); |
239 | 252 | |
240 | 253 | iommu = iommu_init(PHYS_JJ_IOMMU); |
241 | 254 | slavio_intctl = slavio_intctl_init(PHYS_JJ_INTR0, PHYS_JJ_INTR_G); |
255 | + for(i = 0; i < smp_cpus; i++) { | |
256 | + slavio_intctl_set_cpu(slavio_intctl, i, envs[i]); | |
257 | + } | |
258 | + | |
242 | 259 | tcx = tcx_init(ds, PHYS_JJ_TCX_FB, phys_ram_base + ram_size, ram_size, vram_size, graphic_width, graphic_height); |
243 | 260 | lance_init(&nd_table[0], PHYS_JJ_LE_IRQ, PHYS_JJ_LE, PHYS_JJ_LEDMA); |
244 | 261 | nvram = m48t59_init(0, PHYS_JJ_EEPROM, 0, PHYS_JJ_EEPROM_SIZE, 8); |
245 | - slavio_timer_init(PHYS_JJ_CLOCK, PHYS_JJ_CLOCK_IRQ, PHYS_JJ_CLOCK1, PHYS_JJ_CLOCK1_IRQ); | |
262 | + for (i = 0; i < MAX_CPUS; i++) { | |
263 | + slavio_timer_init(PHYS_JJ_CLOCK + i * TARGET_PAGE_SIZE, PHYS_JJ_CLOCK_IRQ, 0, i); | |
264 | + } | |
265 | + slavio_timer_init(PHYS_JJ_CLOCK1, PHYS_JJ_CLOCK1_IRQ, 2, (unsigned int)-1); | |
246 | 266 | slavio_serial_ms_kbd_init(PHYS_JJ_MS_KBD, PHYS_JJ_MS_KBD_IRQ); |
247 | 267 | // Slavio TTYA (base+4, Linux ttyS0) is the first Qemu serial device |
248 | 268 | // Slavio TTYB (base+0, Linux ttyS1) is the second Qemu serial device | ... | ... |
monitor.c
... | ... | @@ -259,6 +259,10 @@ static void do_info_cpus(void) |
259 | 259 | term_printf(" nip=0x" TARGET_FMT_lx, env->nip); |
260 | 260 | if (env->halted) |
261 | 261 | term_printf(" (halted)"); |
262 | +#elif defined(TARGET_SPARC) | |
263 | + term_printf(" pc=0x" TARGET_FMT_lx " npc=0x" TARGET_FMT_lx, env->pc, env->npc); | |
264 | + if (env->halted) | |
265 | + term_printf(" (halted)"); | |
262 | 266 | #endif |
263 | 267 | term_printf("\n"); |
264 | 268 | } | ... | ... |
target-sparc/cpu.h
vl.c
... | ... | @@ -153,6 +153,11 @@ USBPort *vm_usb_ports[MAX_VM_USB_PORTS]; |
153 | 153 | USBDevice *vm_usb_hub; |
154 | 154 | static VLANState *first_vlan; |
155 | 155 | int smp_cpus = 1; |
156 | +#ifdef TARGET_SPARC | |
157 | +#define MAX_CPUS 16 | |
158 | +#else | |
159 | +#define MAX_CPUS 8 | |
160 | +#endif | |
156 | 161 | |
157 | 162 | /***********************************************************/ |
158 | 163 | /* x86 ISA bus support */ |
... | ... | @@ -4547,7 +4552,7 @@ int main(int argc, char **argv) |
4547 | 4552 | break; |
4548 | 4553 | case QEMU_OPTION_smp: |
4549 | 4554 | smp_cpus = atoi(optarg); |
4550 | - if (smp_cpus < 1 || smp_cpus > 8) { | |
4555 | + if (smp_cpus < 1 || smp_cpus > MAX_CPUS) { | |
4551 | 4556 | fprintf(stderr, "Invalid number of CPUs\n"); |
4552 | 4557 | exit(1); |
4553 | 4558 | } | ... | ... |
vl.h
... | ... | @@ -806,6 +806,7 @@ void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val); |
806 | 806 | /* sun4m.c */ |
807 | 807 | extern QEMUMachine sun4m_machine; |
808 | 808 | uint32_t iommu_translate(uint32_t addr); |
809 | +void pic_set_irq_cpu(int irq, int level, unsigned int cpu); | |
809 | 810 | |
810 | 811 | /* iommu.c */ |
811 | 812 | void *iommu_init(uint32_t addr); |
... | ... | @@ -823,16 +824,18 @@ void tcx_screen_dump(void *opaque, const char *filename); |
823 | 824 | |
824 | 825 | /* slavio_intctl.c */ |
825 | 826 | void *slavio_intctl_init(); |
827 | +void slavio_intctl_set_cpu(void *opaque, unsigned int cpu, CPUState *env); | |
826 | 828 | void slavio_pic_info(void *opaque); |
827 | 829 | void slavio_irq_info(void *opaque); |
828 | 830 | void slavio_pic_set_irq(void *opaque, int irq, int level); |
831 | +void slavio_pic_set_irq_cpu(void *opaque, int irq, int level, unsigned int cpu); | |
829 | 832 | |
830 | 833 | /* magic-load.c */ |
831 | 834 | int load_elf(const char *filename, uint8_t *addr); |
832 | 835 | int load_aout(const char *filename, uint8_t *addr); |
833 | 836 | |
834 | 837 | /* slavio_timer.c */ |
835 | -void slavio_timer_init(uint32_t addr1, int irq1, uint32_t addr2, int irq2); | |
838 | +void slavio_timer_init(uint32_t addr, int irq, int mode, unsigned int cpu); | |
836 | 839 | |
837 | 840 | /* slavio_serial.c */ |
838 | 841 | SerialState *slavio_serial_init(int base, int irq, CharDriverState *chr1, CharDriverState *chr2); | ... | ... |