ARM MPCore tweaks

Allow the user to specify the number of cores present on the
RealView EB + ARM11MPCore board.  Also split into its own config
rather than guessing from the CPU name.

Signed-off-by: Paul Brook <paul@codesourcery.com>
This commit is contained in:
Paul Brook 2009-11-13 04:31:22 +00:00
parent 26e92f6552
commit c988bfadc9
4 changed files with 131 additions and 47 deletions

View File

@ -48,6 +48,11 @@ typedef struct gic_irq_state
} gic_irq_state;
#define ALL_CPU_MASK ((1 << NCPU) - 1)
#if NCPU > 1
#define NUM_CPU(s) ((s)->num_cpu)
#else
#define NUM_CPU(s) 1
#endif
#define GIC_SET_ENABLED(irq) s->irq_state[irq].enabled = 1
#define GIC_CLEAR_ENABLED(irq) s->irq_state[irq].enabled = 0
@ -95,6 +100,10 @@ typedef struct gic_state
int running_priority[NCPU];
int current_pending[NCPU];
#if NCPU > 1
int num_cpu;
#endif
int iomemtype;
} gic_state;
@ -109,7 +118,7 @@ static void gic_update(gic_state *s)
int cpu;
int cm;
for (cpu = 0; cpu < NCPU; cpu++) {
for (cpu = 0; cpu < NUM_CPU(s); cpu++) {
cm = 1 << cpu;
s->current_pending[cpu] = 1023;
if (!s->enabled || !s->cpu_enabled[cpu]) {
@ -255,7 +264,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
if (offset == 0)
return s->enabled;
if (offset == 4)
return ((GIC_NIRQ / 32) - 1) | ((NCPU - 1) << 5);
return ((GIC_NIRQ / 32) - 1) | ((NUM_CPU(s) - 1) << 5);
if (offset < 0x08)
return 0;
#endif
@ -620,7 +629,7 @@ static void gic_reset(gic_state *s)
{
int i;
memset(s->irq_state, 0, GIC_NIRQ * sizeof(gic_irq_state));
for (i = 0 ; i < NCPU; i++) {
for (i = 0 ; i < NUM_CPU(s); i++) {
s->priority_mask[i] = 0xf0;
s->current_pending[i] = 1023;
s->running_irq[i] = 1023;
@ -651,7 +660,7 @@ static void gic_save(QEMUFile *f, void *opaque)
int j;
qemu_put_be32(f, s->enabled);
for (i = 0; i < NCPU; i++) {
for (i = 0; i < NUM_CPU(s); i++) {
qemu_put_be32(f, s->cpu_enabled[i]);
#ifndef NVIC
qemu_put_be32(f, s->irq_target[i]);
@ -688,7 +697,7 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id)
return -EINVAL;
s->enabled = qemu_get_be32(f);
for (i = 0; i < NCPU; i++) {
for (i = 0; i < NUM_CPU(s); i++) {
s->cpu_enabled[i] = qemu_get_be32(f);
#ifndef NVIC
s->irq_target[i] = qemu_get_be32(f);
@ -717,12 +726,19 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id)
return 0;
}
#if NCPU > 1
static void gic_init(gic_state *s, int num_cpu)
#else
static void gic_init(gic_state *s)
#endif
{
int i;
#if NCPU > 1
s->num_cpu = num_cpu;
#endif
qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, GIC_NIRQ - 32);
for (i = 0; i < NCPU; i++) {
for (i = 0; i < NUM_CPU(s); i++) {
sysbus_init_irq(&s->busdev, &s->parent_irq[i]);
}
s->iomemtype = cpu_register_io_memory(gic_dist_readfn,

View File

@ -44,6 +44,7 @@ typedef struct mpcore_priv_state {
uint32_t scu_control;
int iomemtype;
mpcore_timer_state timer[8];
uint32_t num_cpu;
} mpcore_priv_state;
/* Per-CPU Timers. */
@ -166,7 +167,8 @@ static uint32_t mpcore_priv_read(void *opaque, target_phys_addr_t offset)
case 0x00: /* Control. */
return s->scu_control;
case 0x04: /* Configuration. */
return 0xf3;
id = ((1 << s->num_cpu) - 1) << 4;
return id | (s->num_cpu - 1);
case 0x08: /* CPU status. */
return 0;
case 0x0c: /* Invalidate all. */
@ -180,6 +182,9 @@ static uint32_t mpcore_priv_read(void *opaque, target_phys_addr_t offset)
id = gic_get_current_cpu();
} else {
id = (offset - 0x200) >> 8;
if (id >= s->num_cpu) {
return 0;
}
}
return gic_cpu_read(&s->gic, id, offset & 0xff);
} else if (offset < 0xb00) {
@ -188,6 +193,9 @@ static uint32_t mpcore_priv_read(void *opaque, target_phys_addr_t offset)
id = gic_get_current_cpu();
} else {
id = (offset - 0x700) >> 8;
if (id >= s->num_cpu) {
return 0;
}
}
id <<= 1;
if (offset & 0x20)
@ -224,7 +232,9 @@ static void mpcore_priv_write(void *opaque, target_phys_addr_t offset,
} else {
id = (offset - 0x200) >> 8;
}
gic_cpu_write(&s->gic, id, offset & 0xff, value);
if (id < s->num_cpu) {
gic_cpu_write(&s->gic, id, offset & 0xff, value);
}
} else if (offset < 0xb00) {
/* Timers. */
if (offset < 0x700) {
@ -232,10 +242,12 @@ static void mpcore_priv_write(void *opaque, target_phys_addr_t offset,
} else {
id = (offset - 0x700) >> 8;
}
id <<= 1;
if (offset & 0x20)
id++;
mpcore_timer_write(&s->timer[id], offset & 0xf, value);
if (id < s->num_cpu) {
id <<= 1;
if (offset & 0x20)
id++;
mpcore_timer_write(&s->timer[id], offset & 0xf, value);
}
return;
}
return;
@ -267,11 +279,11 @@ static int mpcore_priv_init(SysBusDevice *dev)
mpcore_priv_state *s = FROM_SYSBUSGIC(mpcore_priv_state, dev);
int i;
gic_init(&s->gic);
gic_init(&s->gic, s->num_cpu);
s->iomemtype = cpu_register_io_memory(mpcore_priv_readfn,
mpcore_priv_writefn, s);
sysbus_init_mmio_cb(dev, 0x2000, mpcore_priv_map);
for (i = 0; i < 8; i++) {
for (i = 0; i < s->num_cpu * 2; i++) {
mpcore_timer_init(s, &s->timer[i], i);
}
return 0;
@ -284,6 +296,7 @@ typedef struct {
SysBusDevice busdev;
qemu_irq cpuic[32];
qemu_irq rvic[4][64];
uint32_t num_cpu;
} mpcore_rirq_state;
/* Map baseboard IRQs onto CPU IRQ lines. */
@ -315,11 +328,16 @@ static int realview_mpcore_init(SysBusDevice *dev)
mpcore_rirq_state *s = FROM_SYSBUS(mpcore_rirq_state, dev);
DeviceState *gic;
DeviceState *priv;
SysBusDevice *bus_priv;
int n;
int i;
priv = sysbus_create_simple("arm11mpcore_priv", MPCORE_PRIV_BASE, NULL);
sysbus_pass_irq(dev, sysbus_from_qdev(priv));
priv = qdev_create(NULL, "arm11mpcore_priv");
qdev_prop_set_uint32(priv, "num-cpu", s->num_cpu);
qdev_init_nofail(priv);
bus_priv = sysbus_from_qdev(priv);
sysbus_mmio_map(bus_priv, 0, MPCORE_PRIV_BASE);
sysbus_pass_irq(dev, bus_priv);
for (i = 0; i < 32; i++) {
s->cpuic[i] = qdev_get_gpio_in(priv, i);
}
@ -335,12 +353,30 @@ static int realview_mpcore_init(SysBusDevice *dev)
return 0;
}
static SysBusDeviceInfo mpcore_rirq_info = {
.init = realview_mpcore_init,
.qdev.name = "realview_mpcore",
.qdev.size = sizeof(mpcore_rirq_state),
.qdev.props = (Property[]) {
DEFINE_PROP_UINT32("num-cpu", mpcore_rirq_state, num_cpu, 1),
DEFINE_PROP_END_OF_LIST(),
}
};
static SysBusDeviceInfo mpcore_priv_info = {
.init = mpcore_priv_init,
.qdev.name = "arm11mpcore_priv",
.qdev.size = sizeof(mpcore_priv_state),
.qdev.props = (Property[]) {
DEFINE_PROP_UINT32("num-cpu", mpcore_priv_state, num_cpu, 1),
DEFINE_PROP_END_OF_LIST(),
}
};
static void mpcore_register_devices(void)
{
sysbus_register_dev("realview_mpcore", sizeof(mpcore_rirq_state),
realview_mpcore_init);
sysbus_register_dev("arm11mpcore_priv", sizeof(mpcore_priv_state),
mpcore_priv_init);
sysbus_register_withprop(&mpcore_rirq_info);
sysbus_register_withprop(&mpcore_priv_info);
}
device_init(mpcore_register_devices)

View File

@ -35,14 +35,21 @@ static void secondary_cpu_reset(void *opaque)
env->regs[15] = 0x80000000;
}
enum realview_board_type {
BOARD_EB,
BOARD_EB_MPCORE
};
static void realview_init(ram_addr_t ram_size,
const char *boot_device,
const char *kernel_filename, const char *kernel_cmdline,
const char *initrd_filename, const char *cpu_model)
const char *initrd_filename, const char *cpu_model,
enum realview_board_type board_type)
{
CPUState *env;
CPUState *env = NULL;
ram_addr_t ram_offset;
DeviceState *dev;
SysBusDevice *busdev;
qemu_irq *irqp;
qemu_irq pic[64];
PCIBus *pci_bus;
@ -50,19 +57,10 @@ static void realview_init(ram_addr_t ram_size,
int n;
int done_smc = 0;
qemu_irq cpu_irq[4];
int ncpu;
int is_mpcore = (board_type == BOARD_EB_MPCORE);
uint32_t proc_id = 0;
if (!cpu_model)
cpu_model = "arm926";
/* FIXME: obey smp_cpus. */
if (strcmp(cpu_model, "arm11mpcore") == 0) {
ncpu = 4;
} else {
ncpu = 1;
}
for (n = 0; n < ncpu; n++) {
for (n = 0; n < smp_cpus; n++) {
env = cpu_init(cpu_model);
if (!env) {
fprintf(stderr, "Unable to find CPU definition\n");
@ -91,15 +89,16 @@ static void realview_init(ram_addr_t ram_size,
arm_sysctl_init(0x10000000, 0xc1400400, proc_id);
if (ncpu == 1) {
/* ??? The documentation says GIC1 is nFIQ and either GIC2 or GIC3
is nIRQ (there are inconsistencies). However Linux 2.6.17 expects
GIC1 to be nIRQ and ignores all the others, so do that for now. */
dev = sysbus_create_simple("realview_gic", 0x10040000, cpu_irq[0]);
if (is_mpcore) {
dev = qdev_create(NULL, "realview_mpcore");
qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
qdev_init_nofail(dev);
busdev = sysbus_from_qdev(dev);
for (n = 0; n < smp_cpus; n++) {
sysbus_connect_irq(busdev, n, cpu_irq[n]);
}
} else {
dev = sysbus_create_varargs("realview_mpcore", -1,
cpu_irq[0], cpu_irq[1], cpu_irq[2],
cpu_irq[3], NULL);
dev = sysbus_create_simple("realview_gic", 0x10040000, cpu_irq[0]);
}
for (n = 0; n < 64; n++) {
pic[n] = qdev_get_gpio_in(dev, n);
@ -210,20 +209,53 @@ static void realview_init(ram_addr_t ram_size,
realview_binfo.kernel_filename = kernel_filename;
realview_binfo.kernel_cmdline = kernel_cmdline;
realview_binfo.initrd_filename = initrd_filename;
realview_binfo.nb_cpus = ncpu;
realview_binfo.nb_cpus = smp_cpus;
arm_load_kernel(first_cpu, &realview_binfo);
}
static QEMUMachine realview_machine = {
.name = "realview",
static void realview_eb_init(ram_addr_t ram_size,
const char *boot_device,
const char *kernel_filename, const char *kernel_cmdline,
const char *initrd_filename, const char *cpu_model)
{
if (!cpu_model) {
cpu_model = "arm926";
}
realview_init(ram_size, boot_device, kernel_filename, kernel_cmdline,
initrd_filename, cpu_model, BOARD_EB);
}
static void realview_eb_mpcore_init(ram_addr_t ram_size,
const char *boot_device,
const char *kernel_filename, const char *kernel_cmdline,
const char *initrd_filename, const char *cpu_model)
{
if (!cpu_model) {
cpu_model = "arm11mpcore";
}
realview_init(ram_size, boot_device, kernel_filename, kernel_cmdline,
initrd_filename, cpu_model, BOARD_EB_MPCORE);
}
static QEMUMachine realview_eb_machine = {
.name = "realview-eb",
.desc = "ARM RealView Emulation Baseboard (ARM926EJ-S)",
.init = realview_init,
.init = realview_eb_init,
.use_scsi = 1,
};
static QEMUMachine realview_eb_mpcore_machine = {
.name = "realview-eb-mpcore",
.desc = "ARM RealView Emulation Baseboard (ARM11MPCore)",
.init = realview_eb_mpcore_init,
.use_scsi = 1,
.max_cpus = 4,
};
static void realview_machine_init(void)
{
qemu_register_machine(&realview_machine);
qemu_register_machine(&realview_eb_machine);
qemu_register_machine(&realview_eb_mpcore_machine);
}
machine_init(realview_machine_init);

View File

@ -1663,7 +1663,7 @@ The ARM RealView Emulation baseboard is emulated with the following devices:
@itemize @minus
@item
ARM926E, ARM1136, ARM11MPCORE(x4) or Cortex-A8 CPU
ARM926E, ARM1136, ARM11MPCORE or Cortex-A8 CPU
@item
ARM AMBA Generic/Distributed Interrupt Controller
@item