qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH 1/4] vexpress: Set reset-cbar property for CPUs


From: Peter Crosthwaite
Subject: Re: [Qemu-devel] [PATCH 1/4] vexpress: Set reset-cbar property for CPUs
Date: Tue, 25 Feb 2014 18:42:47 +1000

On Tue, Feb 25, 2014 at 6:23 AM, Peter Maydell <address@hidden> wrote:
> Newer versions of the Linux kernel (as of commit bc41b8724 in 3.12)
> now assume that if the CPU is a Cortex-A9 and the reset value of the
> PERIPHBASE/CBAR register is zero then the CPU is a specific buggy
> single core A9 SoC, and will not try to start other cores. Since we
> now have a CPU property for the reset value of the CBAR, we can
> just fix the vexpress board model to correctly set CBAR so SMP
> works again. To avoid duplicate boilerplate code in both the A9
> and A15 daughterboard init functions, we split out the CPU and
> private memory region init to its own function.
>
> Signed-off-by: Peter Maydell <address@hidden>
> Reported-by: Rob Herring <address@hidden>

Reviewed-by: Peter Crosthwaite <address@hidden>

> ---
>  hw/arm/vexpress.c | 123 
> +++++++++++++++++++++++++++---------------------------
>  1 file changed, 61 insertions(+), 62 deletions(-)
>
> diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
> index ef1707a..67628af 100644
> --- a/hw/arm/vexpress.c
> +++ b/hw/arm/vexpress.c
> @@ -32,6 +32,7 @@
>  #include "sysemu/blockdev.h"
>  #include "hw/block/flash.h"
>  #include "sysemu/device_tree.h"
> +#include "qemu/error-report.h"
>  #include <libfdt.h>
>
>  #define VEXPRESS_BOARD_ID 0x8e0
> @@ -173,6 +174,64 @@ struct VEDBoardInfo {
>      DBoardInitFn *init;
>  };
>
> +static void init_cpus(const char *cpu_model, const char *privdev,
> +                      hwaddr periphbase, qemu_irq *pic)
> +{
> +    ObjectClass *cpu_oc = cpu_class_by_name(TYPE_ARM_CPU, cpu_model);
> +    DeviceState *dev;
> +    SysBusDevice *busdev;
> +    int n;
> +
> +    if (!cpu_oc) {
> +        fprintf(stderr, "Unable to find CPU definition\n");
> +        exit(1);
> +    }
> +
> +    /* Create the actual CPUs */
> +    for (n = 0; n < smp_cpus; n++) {
> +        Object *cpuobj = object_new(object_class_get_name(cpu_oc));
> +        Error *err = NULL;
> +
> +        object_property_set_int(cpuobj, periphbase, "reset-cbar", &err);
> +        if (err) {
> +            error_report("%s", error_get_pretty(err));
> +            exit(1);
> +        }
> +        object_property_set_bool(cpuobj, true, "realized", &err);
> +        if (err) {
> +            error_report("%s", error_get_pretty(err));
> +            exit(1);
> +        }
> +    }
> +
> +    /* Create the private peripheral devices (including the GIC);
> +     * this must happen after the CPUs are created because a15mpcore_priv
> +     * wires itself up to the CPU's generic_timer gpio out lines.
> +     */
> +    dev = qdev_create(NULL, privdev);
> +    qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
> +    qdev_init_nofail(dev);
> +    busdev = SYS_BUS_DEVICE(dev);
> +    sysbus_mmio_map(busdev, 0, periphbase);
> +
> +    /* Interrupts [42:0] are from the motherboard;
> +     * [47:43] are reserved; [63:48] are daughterboard
> +     * peripherals. Note that some documentation numbers
> +     * external interrupts starting from 32 (because there
> +     * are internal interrupts 0..31).
> +     */
> +    for (n = 0; n < 64; n++) {
> +        pic[n] = qdev_get_gpio_in(dev, n);
> +    }
> +
> +    /* Connect the CPUs to the GIC */
> +    for (n = 0; n < smp_cpus; n++) {
> +        DeviceState *cpudev = DEVICE(qemu_get_cpu(n));
> +
> +        sysbus_connect_irq(busdev, n, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
> +    }
> +}
> +
>  static void a9_daughterboard_init(const VEDBoardInfo *daughterboard,
>                                    ram_addr_t ram_size,
>                                    const char *cpu_model,
> @@ -181,25 +240,12 @@ static void a9_daughterboard_init(const VEDBoardInfo 
> *daughterboard,
>      MemoryRegion *sysmem = get_system_memory();
>      MemoryRegion *ram = g_new(MemoryRegion, 1);
>      MemoryRegion *lowram = g_new(MemoryRegion, 1);
> -    DeviceState *dev;
> -    SysBusDevice *busdev;
> -    int n;
> -    qemu_irq cpu_irq[4];
>      ram_addr_t low_ram_size;
>
>      if (!cpu_model) {
>          cpu_model = "cortex-a9";
>      }
>
> -    for (n = 0; n < smp_cpus; n++) {
> -        ARMCPU *cpu = cpu_arm_init(cpu_model);
> -        if (!cpu) {
> -            fprintf(stderr, "Unable to find CPU definition\n");
> -            exit(1);
> -        }
> -        cpu_irq[n] = qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ);
> -    }
> -
>      if (ram_size > 0x40000000) {
>          /* 1GB is the maximum the address space permits */
>          fprintf(stderr, "vexpress-a9: cannot model more than 1GB RAM\n");
> @@ -221,23 +267,7 @@ static void a9_daughterboard_init(const VEDBoardInfo 
> *daughterboard,
>      memory_region_add_subregion(sysmem, 0x60000000, ram);
>
>      /* 0x1e000000 A9MPCore (SCU) private memory region */
> -    dev = qdev_create(NULL, "a9mpcore_priv");
> -    qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
> -    qdev_init_nofail(dev);
> -    busdev = SYS_BUS_DEVICE(dev);
> -    sysbus_mmio_map(busdev, 0, 0x1e000000);
> -    for (n = 0; n < smp_cpus; n++) {
> -        sysbus_connect_irq(busdev, n, cpu_irq[n]);
> -    }
> -    /* Interrupts [42:0] are from the motherboard;
> -     * [47:43] are reserved; [63:48] are daughterboard
> -     * peripherals. Note that some documentation numbers
> -     * external interrupts starting from 32 (because the
> -     * A9MP has internal interrupts 0..31).
> -     */
> -    for (n = 0; n < 64; n++) {
> -        pic[n] = qdev_get_gpio_in(dev, n);
> -    }
> +    init_cpus(cpu_model, "a9mpcore_priv", 0x1e000000, pic);
>
>      /* Daughterboard peripherals : 0x10020000 .. 0x20000000 */
>
> @@ -296,29 +326,14 @@ static void a15_daughterboard_init(const VEDBoardInfo 
> *daughterboard,
>                                     const char *cpu_model,
>                                     qemu_irq *pic)
>  {
> -    int n;
>      MemoryRegion *sysmem = get_system_memory();
>      MemoryRegion *ram = g_new(MemoryRegion, 1);
>      MemoryRegion *sram = g_new(MemoryRegion, 1);
> -    qemu_irq cpu_irq[4];
> -    DeviceState *dev;
> -    SysBusDevice *busdev;
>
>      if (!cpu_model) {
>          cpu_model = "cortex-a15";
>      }
>
> -    for (n = 0; n < smp_cpus; n++) {
> -        ARMCPU *cpu;
> -
> -        cpu = cpu_arm_init(cpu_model);
> -        if (!cpu) {
> -            fprintf(stderr, "Unable to find CPU definition\n");
> -            exit(1);
> -        }
> -        cpu_irq[n] = qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ);
> -    }
> -
>      {
>          /* We have to use a separate 64 bit variable here to avoid the gcc
>           * "comparison is always false due to limited range of data type"
> @@ -337,23 +352,7 @@ static void a15_daughterboard_init(const VEDBoardInfo 
> *daughterboard,
>      memory_region_add_subregion(sysmem, 0x80000000, ram);
>
>      /* 0x2c000000 A15MPCore private memory region (GIC) */
> -    dev = qdev_create(NULL, "a15mpcore_priv");
> -    qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
> -    qdev_init_nofail(dev);
> -    busdev = SYS_BUS_DEVICE(dev);
> -    sysbus_mmio_map(busdev, 0, 0x2c000000);
> -    for (n = 0; n < smp_cpus; n++) {
> -        sysbus_connect_irq(busdev, n, cpu_irq[n]);
> -    }
> -    /* Interrupts [42:0] are from the motherboard;
> -     * [47:43] are reserved; [63:48] are daughterboard
> -     * peripherals. Note that some documentation numbers
> -     * external interrupts starting from 32 (because there
> -     * are internal interrupts 0..31).
> -     */
> -    for (n = 0; n < 64; n++) {
> -        pic[n] = qdev_get_gpio_in(dev, n);
> -    }
> +    init_cpus(cpu_model, "a15mpcore_priv", 0x2c000000, pic);
>
>      /* A15 daughterboard peripherals: */
>
> --
> 1.8.5
>
>



reply via email to

[Prev in Thread] Current Thread [Next in Thread]