Revision c988bfad
b/hw/arm_gic.c | ||
---|---|---|
48 | 48 |
} gic_irq_state; |
49 | 49 |
|
50 | 50 |
#define ALL_CPU_MASK ((1 << NCPU) - 1) |
51 |
#if NCPU > 1 |
|
52 |
#define NUM_CPU(s) ((s)->num_cpu) |
|
53 |
#else |
|
54 |
#define NUM_CPU(s) 1 |
|
55 |
#endif |
|
51 | 56 |
|
52 | 57 |
#define GIC_SET_ENABLED(irq) s->irq_state[irq].enabled = 1 |
53 | 58 |
#define GIC_CLEAR_ENABLED(irq) s->irq_state[irq].enabled = 0 |
... | ... | |
95 | 100 |
int running_priority[NCPU]; |
96 | 101 |
int current_pending[NCPU]; |
97 | 102 |
|
103 |
#if NCPU > 1 |
|
104 |
int num_cpu; |
|
105 |
#endif |
|
106 |
|
|
98 | 107 |
int iomemtype; |
99 | 108 |
} gic_state; |
100 | 109 |
|
... | ... | |
109 | 118 |
int cpu; |
110 | 119 |
int cm; |
111 | 120 |
|
112 |
for (cpu = 0; cpu < NCPU; cpu++) {
|
|
121 |
for (cpu = 0; cpu < NUM_CPU(s); cpu++) {
|
|
113 | 122 |
cm = 1 << cpu; |
114 | 123 |
s->current_pending[cpu] = 1023; |
115 | 124 |
if (!s->enabled || !s->cpu_enabled[cpu]) { |
... | ... | |
255 | 264 |
if (offset == 0) |
256 | 265 |
return s->enabled; |
257 | 266 |
if (offset == 4) |
258 |
return ((GIC_NIRQ / 32) - 1) | ((NCPU - 1) << 5);
|
|
267 |
return ((GIC_NIRQ / 32) - 1) | ((NUM_CPU(s) - 1) << 5);
|
|
259 | 268 |
if (offset < 0x08) |
260 | 269 |
return 0; |
261 | 270 |
#endif |
... | ... | |
620 | 629 |
{ |
621 | 630 |
int i; |
622 | 631 |
memset(s->irq_state, 0, GIC_NIRQ * sizeof(gic_irq_state)); |
623 |
for (i = 0 ; i < NCPU; i++) {
|
|
632 |
for (i = 0 ; i < NUM_CPU(s); i++) {
|
|
624 | 633 |
s->priority_mask[i] = 0xf0; |
625 | 634 |
s->current_pending[i] = 1023; |
626 | 635 |
s->running_irq[i] = 1023; |
... | ... | |
651 | 660 |
int j; |
652 | 661 |
|
653 | 662 |
qemu_put_be32(f, s->enabled); |
654 |
for (i = 0; i < NCPU; i++) {
|
|
663 |
for (i = 0; i < NUM_CPU(s); i++) {
|
|
655 | 664 |
qemu_put_be32(f, s->cpu_enabled[i]); |
656 | 665 |
#ifndef NVIC |
657 | 666 |
qemu_put_be32(f, s->irq_target[i]); |
... | ... | |
688 | 697 |
return -EINVAL; |
689 | 698 |
|
690 | 699 |
s->enabled = qemu_get_be32(f); |
691 |
for (i = 0; i < NCPU; i++) {
|
|
700 |
for (i = 0; i < NUM_CPU(s); i++) {
|
|
692 | 701 |
s->cpu_enabled[i] = qemu_get_be32(f); |
693 | 702 |
#ifndef NVIC |
694 | 703 |
s->irq_target[i] = qemu_get_be32(f); |
... | ... | |
717 | 726 |
return 0; |
718 | 727 |
} |
719 | 728 |
|
729 |
#if NCPU > 1 |
|
730 |
static void gic_init(gic_state *s, int num_cpu) |
|
731 |
#else |
|
720 | 732 |
static void gic_init(gic_state *s) |
733 |
#endif |
|
721 | 734 |
{ |
722 | 735 |
int i; |
723 | 736 |
|
737 |
#if NCPU > 1 |
|
738 |
s->num_cpu = num_cpu; |
|
739 |
#endif |
|
724 | 740 |
qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, GIC_NIRQ - 32); |
725 |
for (i = 0; i < NCPU; i++) {
|
|
741 |
for (i = 0; i < NUM_CPU(s); i++) {
|
|
726 | 742 |
sysbus_init_irq(&s->busdev, &s->parent_irq[i]); |
727 | 743 |
} |
728 | 744 |
s->iomemtype = cpu_register_io_memory(gic_dist_readfn, |
b/hw/mpcore.c | ||
---|---|---|
44 | 44 |
uint32_t scu_control; |
45 | 45 |
int iomemtype; |
46 | 46 |
mpcore_timer_state timer[8]; |
47 |
uint32_t num_cpu; |
|
47 | 48 |
} mpcore_priv_state; |
48 | 49 |
|
49 | 50 |
/* Per-CPU Timers. */ |
... | ... | |
166 | 167 |
case 0x00: /* Control. */ |
167 | 168 |
return s->scu_control; |
168 | 169 |
case 0x04: /* Configuration. */ |
169 |
return 0xf3; |
|
170 |
id = ((1 << s->num_cpu) - 1) << 4; |
|
171 |
return id | (s->num_cpu - 1); |
|
170 | 172 |
case 0x08: /* CPU status. */ |
171 | 173 |
return 0; |
172 | 174 |
case 0x0c: /* Invalidate all. */ |
... | ... | |
180 | 182 |
id = gic_get_current_cpu(); |
181 | 183 |
} else { |
182 | 184 |
id = (offset - 0x200) >> 8; |
185 |
if (id >= s->num_cpu) { |
|
186 |
return 0; |
|
187 |
} |
|
183 | 188 |
} |
184 | 189 |
return gic_cpu_read(&s->gic, id, offset & 0xff); |
185 | 190 |
} else if (offset < 0xb00) { |
... | ... | |
188 | 193 |
id = gic_get_current_cpu(); |
189 | 194 |
} else { |
190 | 195 |
id = (offset - 0x700) >> 8; |
196 |
if (id >= s->num_cpu) { |
|
197 |
return 0; |
|
198 |
} |
|
191 | 199 |
} |
192 | 200 |
id <<= 1; |
193 | 201 |
if (offset & 0x20) |
... | ... | |
224 | 232 |
} else { |
225 | 233 |
id = (offset - 0x200) >> 8; |
226 | 234 |
} |
227 |
gic_cpu_write(&s->gic, id, offset & 0xff, value); |
|
235 |
if (id < s->num_cpu) { |
|
236 |
gic_cpu_write(&s->gic, id, offset & 0xff, value); |
|
237 |
} |
|
228 | 238 |
} else if (offset < 0xb00) { |
229 | 239 |
/* Timers. */ |
230 | 240 |
if (offset < 0x700) { |
... | ... | |
232 | 242 |
} else { |
233 | 243 |
id = (offset - 0x700) >> 8; |
234 | 244 |
} |
235 |
id <<= 1; |
|
236 |
if (offset & 0x20) |
|
237 |
id++; |
|
238 |
mpcore_timer_write(&s->timer[id], offset & 0xf, value); |
|
245 |
if (id < s->num_cpu) { |
|
246 |
id <<= 1; |
|
247 |
if (offset & 0x20) |
|
248 |
id++; |
|
249 |
mpcore_timer_write(&s->timer[id], offset & 0xf, value); |
|
250 |
} |
|
239 | 251 |
return; |
240 | 252 |
} |
241 | 253 |
return; |
... | ... | |
267 | 279 |
mpcore_priv_state *s = FROM_SYSBUSGIC(mpcore_priv_state, dev); |
268 | 280 |
int i; |
269 | 281 |
|
270 |
gic_init(&s->gic); |
|
282 |
gic_init(&s->gic, s->num_cpu);
|
|
271 | 283 |
s->iomemtype = cpu_register_io_memory(mpcore_priv_readfn, |
272 | 284 |
mpcore_priv_writefn, s); |
273 | 285 |
sysbus_init_mmio_cb(dev, 0x2000, mpcore_priv_map); |
274 |
for (i = 0; i < 8; i++) {
|
|
286 |
for (i = 0; i < s->num_cpu * 2; i++) {
|
|
275 | 287 |
mpcore_timer_init(s, &s->timer[i], i); |
276 | 288 |
} |
277 | 289 |
return 0; |
... | ... | |
284 | 296 |
SysBusDevice busdev; |
285 | 297 |
qemu_irq cpuic[32]; |
286 | 298 |
qemu_irq rvic[4][64]; |
299 |
uint32_t num_cpu; |
|
287 | 300 |
} mpcore_rirq_state; |
288 | 301 |
|
289 | 302 |
/* Map baseboard IRQs onto CPU IRQ lines. */ |
... | ... | |
315 | 328 |
mpcore_rirq_state *s = FROM_SYSBUS(mpcore_rirq_state, dev); |
316 | 329 |
DeviceState *gic; |
317 | 330 |
DeviceState *priv; |
331 |
SysBusDevice *bus_priv; |
|
318 | 332 |
int n; |
319 | 333 |
int i; |
320 | 334 |
|
321 |
priv = sysbus_create_simple("arm11mpcore_priv", MPCORE_PRIV_BASE, NULL); |
|
322 |
sysbus_pass_irq(dev, sysbus_from_qdev(priv)); |
|
335 |
priv = qdev_create(NULL, "arm11mpcore_priv"); |
|
336 |
qdev_prop_set_uint32(priv, "num-cpu", s->num_cpu); |
|
337 |
qdev_init_nofail(priv); |
|
338 |
bus_priv = sysbus_from_qdev(priv); |
|
339 |
sysbus_mmio_map(bus_priv, 0, MPCORE_PRIV_BASE); |
|
340 |
sysbus_pass_irq(dev, bus_priv); |
|
323 | 341 |
for (i = 0; i < 32; i++) { |
324 | 342 |
s->cpuic[i] = qdev_get_gpio_in(priv, i); |
325 | 343 |
} |
... | ... | |
335 | 353 |
return 0; |
336 | 354 |
} |
337 | 355 |
|
356 |
static SysBusDeviceInfo mpcore_rirq_info = { |
|
357 |
.init = realview_mpcore_init, |
|
358 |
.qdev.name = "realview_mpcore", |
|
359 |
.qdev.size = sizeof(mpcore_rirq_state), |
|
360 |
.qdev.props = (Property[]) { |
|
361 |
DEFINE_PROP_UINT32("num-cpu", mpcore_rirq_state, num_cpu, 1), |
|
362 |
DEFINE_PROP_END_OF_LIST(), |
|
363 |
} |
|
364 |
}; |
|
365 |
|
|
366 |
static SysBusDeviceInfo mpcore_priv_info = { |
|
367 |
.init = mpcore_priv_init, |
|
368 |
.qdev.name = "arm11mpcore_priv", |
|
369 |
.qdev.size = sizeof(mpcore_priv_state), |
|
370 |
.qdev.props = (Property[]) { |
|
371 |
DEFINE_PROP_UINT32("num-cpu", mpcore_priv_state, num_cpu, 1), |
|
372 |
DEFINE_PROP_END_OF_LIST(), |
|
373 |
} |
|
374 |
}; |
|
375 |
|
|
338 | 376 |
static void mpcore_register_devices(void) |
339 | 377 |
{ |
340 |
sysbus_register_dev("realview_mpcore", sizeof(mpcore_rirq_state), |
|
341 |
realview_mpcore_init); |
|
342 |
sysbus_register_dev("arm11mpcore_priv", sizeof(mpcore_priv_state), |
|
343 |
mpcore_priv_init); |
|
378 |
sysbus_register_withprop(&mpcore_rirq_info); |
|
379 |
sysbus_register_withprop(&mpcore_priv_info); |
|
344 | 380 |
} |
345 | 381 |
|
346 | 382 |
device_init(mpcore_register_devices) |
b/hw/realview.c | ||
---|---|---|
35 | 35 |
env->regs[15] = 0x80000000; |
36 | 36 |
} |
37 | 37 |
|
38 |
enum realview_board_type { |
|
39 |
BOARD_EB, |
|
40 |
BOARD_EB_MPCORE |
|
41 |
}; |
|
42 |
|
|
38 | 43 |
static void realview_init(ram_addr_t ram_size, |
39 | 44 |
const char *boot_device, |
40 | 45 |
const char *kernel_filename, const char *kernel_cmdline, |
41 |
const char *initrd_filename, const char *cpu_model) |
|
46 |
const char *initrd_filename, const char *cpu_model, |
|
47 |
enum realview_board_type board_type) |
|
42 | 48 |
{ |
43 |
CPUState *env; |
|
49 |
CPUState *env = NULL;
|
|
44 | 50 |
ram_addr_t ram_offset; |
45 | 51 |
DeviceState *dev; |
52 |
SysBusDevice *busdev; |
|
46 | 53 |
qemu_irq *irqp; |
47 | 54 |
qemu_irq pic[64]; |
48 | 55 |
PCIBus *pci_bus; |
... | ... | |
50 | 57 |
int n; |
51 | 58 |
int done_smc = 0; |
52 | 59 |
qemu_irq cpu_irq[4]; |
53 |
int ncpu;
|
|
60 |
int is_mpcore = (board_type == BOARD_EB_MPCORE);
|
|
54 | 61 |
uint32_t proc_id = 0; |
55 | 62 |
|
56 |
if (!cpu_model) |
|
57 |
cpu_model = "arm926"; |
|
58 |
/* FIXME: obey smp_cpus. */ |
|
59 |
if (strcmp(cpu_model, "arm11mpcore") == 0) { |
|
60 |
ncpu = 4; |
|
61 |
} else { |
|
62 |
ncpu = 1; |
|
63 |
} |
|
64 |
|
|
65 |
for (n = 0; n < ncpu; n++) { |
|
63 |
for (n = 0; n < smp_cpus; n++) { |
|
66 | 64 |
env = cpu_init(cpu_model); |
67 | 65 |
if (!env) { |
68 | 66 |
fprintf(stderr, "Unable to find CPU definition\n"); |
... | ... | |
91 | 89 |
|
92 | 90 |
arm_sysctl_init(0x10000000, 0xc1400400, proc_id); |
93 | 91 |
|
94 |
if (ncpu == 1) { |
|
95 |
/* ??? The documentation says GIC1 is nFIQ and either GIC2 or GIC3 |
|
96 |
is nIRQ (there are inconsistencies). However Linux 2.6.17 expects |
|
97 |
GIC1 to be nIRQ and ignores all the others, so do that for now. */ |
|
98 |
dev = sysbus_create_simple("realview_gic", 0x10040000, cpu_irq[0]); |
|
92 |
if (is_mpcore) { |
|
93 |
dev = qdev_create(NULL, "realview_mpcore"); |
|
94 |
qdev_prop_set_uint32(dev, "num-cpu", smp_cpus); |
|
95 |
qdev_init_nofail(dev); |
|
96 |
busdev = sysbus_from_qdev(dev); |
|
97 |
for (n = 0; n < smp_cpus; n++) { |
|
98 |
sysbus_connect_irq(busdev, n, cpu_irq[n]); |
|
99 |
} |
|
99 | 100 |
} else { |
100 |
dev = sysbus_create_varargs("realview_mpcore", -1, |
|
101 |
cpu_irq[0], cpu_irq[1], cpu_irq[2], |
|
102 |
cpu_irq[3], NULL); |
|
101 |
dev = sysbus_create_simple("realview_gic", 0x10040000, cpu_irq[0]); |
|
103 | 102 |
} |
104 | 103 |
for (n = 0; n < 64; n++) { |
105 | 104 |
pic[n] = qdev_get_gpio_in(dev, n); |
... | ... | |
210 | 209 |
realview_binfo.kernel_filename = kernel_filename; |
211 | 210 |
realview_binfo.kernel_cmdline = kernel_cmdline; |
212 | 211 |
realview_binfo.initrd_filename = initrd_filename; |
213 |
realview_binfo.nb_cpus = ncpu;
|
|
212 |
realview_binfo.nb_cpus = smp_cpus;
|
|
214 | 213 |
arm_load_kernel(first_cpu, &realview_binfo); |
215 | 214 |
} |
216 | 215 |
|
217 |
static QEMUMachine realview_machine = { |
|
218 |
.name = "realview", |
|
216 |
static void realview_eb_init(ram_addr_t ram_size, |
|
217 |
const char *boot_device, |
|
218 |
const char *kernel_filename, const char *kernel_cmdline, |
|
219 |
const char *initrd_filename, const char *cpu_model) |
|
220 |
{ |
|
221 |
if (!cpu_model) { |
|
222 |
cpu_model = "arm926"; |
|
223 |
} |
|
224 |
realview_init(ram_size, boot_device, kernel_filename, kernel_cmdline, |
|
225 |
initrd_filename, cpu_model, BOARD_EB); |
|
226 |
} |
|
227 |
|
|
228 |
static void realview_eb_mpcore_init(ram_addr_t ram_size, |
|
229 |
const char *boot_device, |
|
230 |
const char *kernel_filename, const char *kernel_cmdline, |
|
231 |
const char *initrd_filename, const char *cpu_model) |
|
232 |
{ |
|
233 |
if (!cpu_model) { |
|
234 |
cpu_model = "arm11mpcore"; |
|
235 |
} |
|
236 |
realview_init(ram_size, boot_device, kernel_filename, kernel_cmdline, |
|
237 |
initrd_filename, cpu_model, BOARD_EB_MPCORE); |
|
238 |
} |
|
239 |
|
|
240 |
static QEMUMachine realview_eb_machine = { |
|
241 |
.name = "realview-eb", |
|
219 | 242 |
.desc = "ARM RealView Emulation Baseboard (ARM926EJ-S)", |
220 |
.init = realview_init, |
|
243 |
.init = realview_eb_init, |
|
244 |
.use_scsi = 1, |
|
245 |
}; |
|
246 |
|
|
247 |
static QEMUMachine realview_eb_mpcore_machine = { |
|
248 |
.name = "realview-eb-mpcore", |
|
249 |
.desc = "ARM RealView Emulation Baseboard (ARM11MPCore)", |
|
250 |
.init = realview_eb_mpcore_init, |
|
221 | 251 |
.use_scsi = 1, |
252 |
.max_cpus = 4, |
|
222 | 253 |
}; |
223 | 254 |
|
224 | 255 |
static void realview_machine_init(void) |
225 | 256 |
{ |
226 |
qemu_register_machine(&realview_machine); |
|
257 |
qemu_register_machine(&realview_eb_machine); |
|
258 |
qemu_register_machine(&realview_eb_mpcore_machine); |
|
227 | 259 |
} |
228 | 260 |
|
229 | 261 |
machine_init(realview_machine_init); |
b/qemu-doc.texi | ||
---|---|---|
1663 | 1663 |
|
1664 | 1664 |
@itemize @minus |
1665 | 1665 |
@item |
1666 |
ARM926E, ARM1136, ARM11MPCORE(x4) or Cortex-A8 CPU
|
|
1666 |
ARM926E, ARM1136, ARM11MPCORE or Cortex-A8 CPU |
|
1667 | 1667 |
@item |
1668 | 1668 |
ARM AMBA Generic/Distributed Interrupt Controller |
1669 | 1669 |
@item |
Also available in: Unified diff