Skip to contentSkip to conversation

ARM Cortex R5 Support

PATCH Applied Peter Crosthwaite 3 participants 16 messages Jun 17, 2015 – Jun 18, 2015 Arm/Zynq architecture

lore
Share & tools
lore
#0 lore raw

v3 cover ARM Cortex R5 Support

Hi Peter and all,

This patch series adds ARM Cortex R5 processor support. The PMSAv7 MPU is implemented. Two R5s are added to the Xilinx ZynqMP SoC.

Changed since v2:
Rebased (early patches merged)
Added boot CPU selection.
Addressed PMM review (see indiv. patches)

Changed since v1:
Addressed PMM and Alistair reviews (see indiv. patches) Adding prepatory refactorings to target-arm (new patches)
- TLBTR VMSA conditional (1)
- V7MP CP regs VMSA conditional (2)
- Refactor get_phys_addr FSR return path (4)
- Add MPUIR.U config (5)
- Improved cpu configurability around MPUs (6-7)

Regards,
Peter

Peter Crosthwaite (7):
target-arm/helper.c: define MPUIR register
target-arm: Add registers for PMSAv7
target-arm: Implement PMSAv7 MPU
target-arm: Add support for Cortex-R5
arm: xlnx-zynqmp: Preface CPU variables with "apu"
arm: xlnx-zynqmp: Add boot-cpu property
arm: xlnx-zynqmp: Add 2xCortexR5 CPUs

 hw/arm/xlnx-ep108.c          |   2 +-
 hw/arm/xlnx-zynqmp.c         |  79 +++++++++++--
 include/hw/arm/xlnx-zynqmp.h |   9 +-
 target-arm/cpu-qom.h         |   2 +
 target-arm/cpu.c             |  62 ++++++++++
 target-arm/cpu.h             |  11 ++
 target-arm/helper.c          | 274 +++++++++++++++++++++++++++++++++++++++++--
 target-arm/machine.c         |  34 ++++++
 8 files changed, 449 insertions(+), 24 deletions(-)
Signature · 1 line
2.4.3.3.g905f831
#1 lore raw

PATCH v3 1/7 target-arm/helper.c: define MPUIR register

Define the MPUIR register for MPU supporting ARMv6 and onwards. Currently we only support unified MPU.

The size of the unified MPU is defined via the number of "dregions". So just a single config is added to specify this size. (When split MPU is implemented we will add an extra iregions config).

---
changed since v2 (PMM review):
Fix commit message wording issues.
change assertion to realize error.
allow 0 regions.
raise error of >255 memory regions.
changed since v1:
Add #regions configuration
conditionalize MPUIR existence

 target-arm/cpu-qom.h |  2 ++
 target-arm/cpu.c     | 18 ++++++++++++++++++
 target-arm/helper.c  | 10 ++++++++++
 3 files changed, 30 insertions(+)
target-arm/cpu-qom.h +2 -0
index 072aa9b..3cbc4a0 100644
@@ -105,6 +105,8 @@ typedef struct ARMCPU {
 
     /* CPU has memory protection unit */
     bool has_mpu;
+    /* PMSAv7 MPU number of supported regions */
+    uint32_t pmsav7_dregion;
 
     /* PSCI conduit used to invoke PSCI methods
      * 0 - disabled, 1 - smc, 2 - hvc
target-arm/cpu.c +18 -0
index 7496983..a3d702f 100644
@@ -457,6 +457,9 @@ static Property arm_cpu_has_el3_property =
 static Property arm_cpu_has_mpu_property =
             DEFINE_PROP_BOOL("has-mpu", ARMCPU, has_mpu, true);
 
+static Property arm_cpu_pmsav7_dregion_property =
+            DEFINE_PROP_UINT32("pmsav7-dregion", ARMCPU, pmsav7_dregion, 16);
+
 static void arm_cpu_post_init(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
@@ -488,6 +491,11 @@ static void arm_cpu_post_init(Object *obj)
     if (arm_feature(&cpu->env, ARM_FEATURE_MPU)) {
         qdev_property_add_static(DEVICE(obj), &arm_cpu_has_mpu_property,
                                  &error_abort);
+        if (arm_feature(&cpu->env, ARM_FEATURE_V7)) {
+            qdev_property_add_static(DEVICE(obj),
+                                     &arm_cpu_pmsav7_dregion_property,
+                                     &error_abort);
+        }
     }
 
 }
@@ -580,6 +588,16 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
         unset_feature(env, ARM_FEATURE_MPU);
     }
 
+    if (arm_feature(env, ARM_FEATURE_MPU) &&
+        arm_feature(env, ARM_FEATURE_V7)) {
+        uint32_t nr = cpu->pmsav7_dregion;
+
+        if (nr > 0xff) {
+            error_setg(errp, "PMSAv7 MPU #regions invalid %" PRIu32 "\n", nr);
+            return;
+        }
+    }
+
     register_cp_regs_for_features(cpu);
     arm_cpu_register_gdb_regs_for_features(cpu);
 
target-arm/helper.c +10 -0
index 00509b1..685f972 100644
@@ -3465,6 +3465,13 @@ void register_cp_regs_for_features(ARMCPU *cpu)
               .cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 3,
               .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0,
         };
+        /* MPUIR is specific to PMSA V6+ */
+        ARMCPRegInfo id_mpuir_reginfo = {
+              .name = "MPUIR",
+              .cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 4,
+              .access = PL1_R, .type = ARM_CP_CONST,
+              .resetvalue = cpu->pmsav7_dregion << 8
+        };
         ARMCPRegInfo crn0_wi_reginfo = {
             .name = "CRN0_WI", .cp = 15, .crn = 0, .crm = CP_ANY,
             .opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_W,
@@ -3487,6 +3494,7 @@ void register_cp_regs_for_features(ARMCPU *cpu)
                 r->access = PL1_RW;
             }
             id_tlbtr_reginfo.access = PL1_RW;
+            id_tlbtr_reginfo.access = PL1_RW;
         }
         if (arm_feature(env, ARM_FEATURE_V8)) {
             define_arm_cp_regs(cpu, id_v8_midr_cp_reginfo);
@@ -3496,6 +3504,8 @@ void register_cp_regs_for_features(ARMCPU *cpu)
         define_arm_cp_regs(cpu, id_cp_reginfo);
         if (!arm_feature(env, ARM_FEATURE_MPU)) {
             define_one_arm_cp_reg(cpu, &id_tlbtr_reginfo);
+        } else if (arm_feature(env, ARM_FEATURE_V7)) {
+            define_one_arm_cp_reg(cpu, &id_mpuir_reginfo);
         }
     }
 
Signature · 1 line
2.4.3.3.g905f831
#2 lore raw

PATCH v3 2/7 target-arm: Add registers for PMSAv7

In reply to Peter Crosthwaite

Define the arm CP registers for PMSAv7 and their accessor functions. RGNR serves as a shared index that indexes into arrays storing the DRBAR, DRSR and DRACR registers. DRBAR and friends have to be VMSDd separately from the CP interface using a new PMSA specific VMSD subsection.

---
changed since v2 (PMM review):
conditionalise pointer allocation on non-zero regions Handle 0 regions in CP accessors
Tweak RGNR GUEST_ERROR message with s/>/>= Resolve conflict with VSMD subsection.needed refactor changed since v1 (PMM review):
Use raw_ptr
Implement reset as memset
Implement VMSD support
Add out-of-bounds guard or rgnr_write Dynamically allocate registers
Move arrays out of cp15 struct into dedicated substruct

 target-arm/cpu.c     |  6 ++++
 target-arm/cpu.h     | 10 ++++++
 target-arm/helper.c  | 90 ++++++++++++++++++++++++++++++++++++++++++++++++----
 target-arm/machine.c | 34 ++++++++++++++++++++
 4 files changed, 133 insertions(+), 7 deletions(-)
target-arm/cpu.c +6 -0
index a3d702f..4010d81 100644
@@ -596,6 +596,12 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
             error_setg(errp, "PMSAv7 MPU #regions invalid %" PRIu32 "\n", nr);
             return;
         }
+
+        if (nr) {
+            env->pmsav7.drbar = g_new0(uint32_t, nr);
+            env->pmsav7.drsr = g_new0(uint32_t, nr);
+            env->pmsav7.dracr = g_new0(uint32_t, nr);
+        }
     }
 
     register_cp_regs_for_features(cpu);
target-arm/cpu.h +10 -0
index c9d2330..6e82893 100644
@@ -284,6 +284,9 @@ typedef struct CPUARMState {
             };
             uint64_t par_el[4];
         };
+
+        uint32_t c6_rgnr;
+
         uint32_t c9_insn; /* Cache lockdown registers.  */
         uint32_t c9_data;
         uint64_t c9_pmcr; /* performance monitor control register */
@@ -482,6 +485,13 @@ typedef struct CPUARMState {
     /* Internal CPU feature flags.  */
     uint64_t features;
 
+    /* PMSAv7 MPU */
+    struct {
+        uint32_t *drbar;
+        uint32_t *drsr;
+        uint32_t *dracr;
+    } pmsav7;
+
     void *nvic;
     const struct arm_boot_info *boot_info;
 } CPUARMState;
target-arm/helper.c +83 -7

102 lines not on this page · raw message

target-arm/machine.c +34 -0
index 36365a5..9eb51df 100644
@@ -125,6 +125,39 @@ static const VMStateDescription vmstate_thumb2ee = {
     }
 };
 
+static bool pmsav7_needed(void *opaque)
+{
+    ARMCPU *cpu = opaque;
+    CPUARMState *env = &cpu->env;
+
+    return arm_feature(env, ARM_FEATURE_MPU) &&
+           arm_feature(env, ARM_FEATURE_V7);
+}
+
+static bool pmsav7_rgnr_vmstate_validate(void *opaque, int version_id)
+{
+    ARMCPU *cpu = opaque;
+
+    return cpu->env.cp15.c6_rgnr < cpu->pmsav7_dregion;
+}
+
+static const VMStateDescription vmstate_pmsav7 = {
+    .name = "cpu/pmsav7",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .needed = pmsav7_needed,
+    .fields = (VMStateField[]) {
+        VMSTATE_VARRAY_UINT32(env.pmsav7.drbar, ARMCPU, pmsav7_dregion, 0,
+                              vmstate_info_uint32, uint32_t),
+        VMSTATE_VARRAY_UINT32(env.pmsav7.drsr, ARMCPU, pmsav7_dregion, 0,
+                              vmstate_info_uint32, uint32_t),
+        VMSTATE_VARRAY_UINT32(env.pmsav7.dracr, ARMCPU, pmsav7_dregion, 0,
+                              vmstate_info_uint32, uint32_t),
+        VMSTATE_VALIDATE("rgnr is valid", pmsav7_rgnr_vmstate_validate),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 static int get_cpsr(QEMUFile *f, void *opaque, size_t size)
 {
     ARMCPU *cpu = opaque;
@@ -291,6 +324,7 @@ const VMStateDescription vmstate_arm_cpu = {
         &vmstate_iwmmxt,
         &vmstate_m,
         &vmstate_thumb2ee,
+        &vmstate_pmsav7,
         NULL
     }
 };
Signature · 1 line
2.4.3.3.g905f831
#3 lore raw

PATCH v3 3/7 target-arm: Implement PMSAv7 MPU

In reply to Peter Crosthwaite

Unified MPU only. Uses ARM architecture major revision to switch between PMSAv5 and v7 when ARM_FEATURE_MPU is set. PMSA v6 remains unsupported and is asserted against.

---
changed since v2
Add missing -1 on initialiser
Use default if dregions == 0
Drop unneeded else
changed since v1 (PMM review):
Add comment about PMSAv6 non-support
Fix case where MPU is completely disabled Ignore regions with 0 size.
GUEST_ERROR invalid base address alignments UNIMP regions that are smaller than TARGET_PAGE_SIZE use extract32 to get SR disable bits
Fixed up DRACR AP bit error message.
Correct bullet point about MPU FSR format Rebased against new FSR return system removed *prot switch-case

 target-arm/cpu.h    |   1 +
 target-arm/helper.c | 174 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 174 insertions(+), 1 deletion(-)
target-arm/cpu.h +1 -0
index 6e82893..16fd1aa 100644
@@ -560,6 +560,7 @@ void pmccntr_sync(CPUARMState *env);
 #define SCTLR_DT      (1U << 16) /* up to ??, RAO in v6 and v7 */
 #define SCTLR_nTWI    (1U << 16) /* v8 onward */
 #define SCTLR_HA      (1U << 17)
+#define SCTLR_BR      (1U << 17) /* PMSA only */
 #define SCTLR_IT      (1U << 18) /* up to ??, RAO in v6 and v7 */
 #define SCTLR_nTWE    (1U << 18) /* v8 onward */
 #define SCTLR_WXN     (1U << 19)
target-arm/helper.c +173 -1

198 lines not on this page · raw message

Signature · 1 line
2.4.3.3.g905f831
#4 lore raw

PATCH v3 4/7 target-arm: Add support for Cortex-R5

In reply to Peter Crosthwaite

Introduce a CPU model for the Cortex R5 processor. ARMv7 with MPU, and both thumb and ARM div instructions.

Also implement dummy ATCM and BTCM. These CPs are defined for R5 but don't have a lot of meaning in QEMU yet. Raz them so the guest can proceed if they are read. The TCM registers will return a size of 0, indicating no TCM.

---
Based loosely on an old patch of Andreas' for the cortex-r4. changed since v1:
Squashed in R5 specific CP regs patch
Reordered to be after supporting patches
set mp_is_up

 target-arm/cpu.c | 38 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)
target-arm/cpu.c +38 -0
index 4010d81..dce91bb 100644
@@ -847,6 +847,43 @@ static void arm_v7m_class_init(ObjectClass *oc, void *data)
     cc->cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt;
 }
 
+static const ARMCPRegInfo cortexr5_cp_reginfo[] = {
+    /* Dummy the TCM region regs for the moment */
+    { .name = "ATCM", .cp = 15, .opc1 = 0, .crn = 9, .crm = 1, .opc2 = 0,
+      .access = PL1_RW, .type = ARM_CP_CONST },
+    { .name = "BTCM", .cp = 15, .opc1 = 0, .crn = 9, .crm = 1, .opc2 = 1,
+      .access = PL1_RW, .type = ARM_CP_CONST },
+    REGINFO_SENTINEL
+};
+
+static void cortex_r5_initfn(Object *obj)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+
+    set_feature(&cpu->env, ARM_FEATURE_V7);
+    set_feature(&cpu->env, ARM_FEATURE_THUMB_DIV);
+    set_feature(&cpu->env, ARM_FEATURE_ARM_DIV);
+    set_feature(&cpu->env, ARM_FEATURE_V7MP);
+    set_feature(&cpu->env, ARM_FEATURE_MPU);
+    cpu->midr = 0x411fc153; /* r1p3 */
+    cpu->id_pfr0 = 0x0131;
+    cpu->id_pfr1 = 0x001;
+    cpu->id_dfr0 = 0x010400;
+    cpu->id_afr0 = 0x0;
+    cpu->id_mmfr0 = 0x0210030;
+    cpu->id_mmfr1 = 0x00000000;
+    cpu->id_mmfr2 = 0x01200000;
+    cpu->id_mmfr3 = 0x0211;
+    cpu->id_isar0 = 0x2101111;
+    cpu->id_isar1 = 0x13112111;
+    cpu->id_isar2 = 0x21232141;
+    cpu->id_isar3 = 0x01112131;
+    cpu->id_isar4 = 0x0010142;
+    cpu->id_isar5 = 0x0;
+    cpu->mp_is_up = true;
+    define_arm_cp_regs(cpu, cortexr5_cp_reginfo);
+}
+
 static const ARMCPRegInfo cortexa8_cp_reginfo[] = {
     { .name = "L2LOCKDOWN", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 0,
       .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
@@ -1238,6 +1275,7 @@ static const ARMCPUInfo arm_cpus[] = {
     { .name = "arm11mpcore", .initfn = arm11mpcore_initfn },
     { .name = "cortex-m3",   .initfn = cortex_m3_initfn,
                              .class_init = arm_v7m_class_init },
+    { .name = "cortex-r5",   .initfn = cortex_r5_initfn },
     { .name = "cortex-a8",   .initfn = cortex_a8_initfn },
     { .name = "cortex-a9",   .initfn = cortex_a9_initfn },
     { .name = "cortex-a15",  .initfn = cortex_a15_initfn },
Signature · 1 line
2.4.3.3.g905f831
Reviewed-by on v3 4/7
#5 lore raw

Re: [Qemu-devel] [PATCH target-arm v3 4/7] target-arm: Add support for Cortex-R5

Quoted 9 lines · Peter Crosthwaite

Introduce a CPU model for the Cortex R5 processor. ARMv7 with MPU, and both thumb and ARM div instructions.

Also implement dummy ATCM and BTCM. These CPs are defined for R5 but don't have a lot of meaning in QEMU yet. Raz them so the guest can proceed if they are read. The TCM registers will return a size of 0, indicating no TCM.

Quoted 70 lines

---
Based loosely on an old patch of Andreas' for the cortex-r4. changed since v1:
Squashed in R5 specific CP regs patch
Reordered to be after supporting patches
set mp_is_up

 target-arm/cpu.c | 38 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)
target-arm/cpu.c +38 -0
index 4010d81..dce91bb 100644
@@ -847,6 +847,43 @@ static void arm_v7m_class_init(ObjectClass *oc, void *data)
     cc->cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt;
 }
 
+static const ARMCPRegInfo cortexr5_cp_reginfo[] = {
+    /* Dummy the TCM region regs for the moment */
+    { .name = "ATCM", .cp = 15, .opc1 = 0, .crn = 9, .crm = 1, .opc2 = 0,
+      .access = PL1_RW, .type = ARM_CP_CONST },
+    { .name = "BTCM", .cp = 15, .opc1 = 0, .crn = 9, .crm = 1, .opc2 = 1,
+      .access = PL1_RW, .type = ARM_CP_CONST },
+    REGINFO_SENTINEL
+};
+
+static void cortex_r5_initfn(Object *obj)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+
+    set_feature(&cpu->env, ARM_FEATURE_V7);
+    set_feature(&cpu->env, ARM_FEATURE_THUMB_DIV);
+    set_feature(&cpu->env, ARM_FEATURE_ARM_DIV);
+    set_feature(&cpu->env, ARM_FEATURE_V7MP);
+    set_feature(&cpu->env, ARM_FEATURE_MPU);
+    cpu->midr = 0x411fc153; /* r1p3 */
+    cpu->id_pfr0 = 0x0131;
+    cpu->id_pfr1 = 0x001;
+    cpu->id_dfr0 = 0x010400;
+    cpu->id_afr0 = 0x0;
+    cpu->id_mmfr0 = 0x0210030;
+    cpu->id_mmfr1 = 0x00000000;
+    cpu->id_mmfr2 = 0x01200000;
+    cpu->id_mmfr3 = 0x0211;
+    cpu->id_isar0 = 0x2101111;
+    cpu->id_isar1 = 0x13112111;
+    cpu->id_isar2 = 0x21232141;
+    cpu->id_isar3 = 0x01112131;
+    cpu->id_isar4 = 0x0010142;
+    cpu->id_isar5 = 0x0;
+    cpu->mp_is_up = true;
+    define_arm_cp_regs(cpu, cortexr5_cp_reginfo);
+}
+
 static const ARMCPRegInfo cortexa8_cp_reginfo[] = {
     { .name = "L2LOCKDOWN", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 0,
       .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
@@ -1238,6 +1275,7 @@ static const ARMCPUInfo arm_cpus[] = {
     { .name = "arm11mpcore", .initfn = arm11mpcore_initfn },
     { .name = "cortex-m3",   .initfn = cortex_m3_initfn,
                              .class_init = arm_v7m_class_init },
+    { .name = "cortex-r5",   .initfn = cortex_r5_initfn },
     { .name = "cortex-a8",   .initfn = cortex_a8_initfn },
     { .name = "cortex-a9",   .initfn = cortex_a9_initfn },
     { .name = "cortex-a15",  .initfn = cortex_a15_initfn },
Signature · 1 line
2.4.3.3.g905f831
#6 lore raw

PATCH v3 5/7 arm: xlnx-zynqmp: Preface CPU variables with "apu"

In reply to Peter Crosthwaite

The CPUs currently supported by zynqmp are the APU (application processing unit) CPUs. There are other CPUs in Zynqmp so unqualified "cpus" in ambiguous. Preface the variables with "APU" accordingly, to prepare support adding the RPU (realtime processing unit) processors.

---
changed since v1:
s/acpu/apu-cpu/

 hw/arm/xlnx-ep108.c          |  2 +-
 hw/arm/xlnx-zynqmp.c         | 26 ++++++++++++++------------
 include/hw/arm/xlnx-zynqmp.h |  4 ++--
 3 files changed, 17 insertions(+), 15 deletions(-)
hw/arm/xlnx-ep108.c +1 -1
index b924f5e..7a98dd6 100644
@@ -65,7 +65,7 @@ static void xlnx_ep108_init(MachineState *machine)
     xlnx_ep108_binfo.kernel_cmdline = machine->kernel_cmdline;
     xlnx_ep108_binfo.initrd_filename = machine->initrd_filename;
     xlnx_ep108_binfo.loader_start = 0;
-    arm_load_kernel(&s->soc.cpu[0], &xlnx_ep108_binfo);
+    arm_load_kernel(&s->soc.apu_cpu[0], &xlnx_ep108_binfo);
 }
 
 static QEMUMachine xlnx_ep108_machine = {
hw/arm/xlnx-zynqmp.c +14 -12
index 6b01965..353ecad 100644
@@ -64,10 +64,10 @@ static void xlnx_zynqmp_init(Object *obj)
     XlnxZynqMPState *s = XLNX_ZYNQMP(obj);
     int i;
 
-    for (i = 0; i < XLNX_ZYNQMP_NUM_CPUS; i++) {
-        object_initialize(&s->cpu[i], sizeof(s->cpu[i]),
+    for (i = 0; i < XLNX_ZYNQMP_NUM_APU_CPUS; i++) {
+        object_initialize(&s->apu_cpu[i], sizeof(s->apu_cpu[i]),
                           "cortex-a53-" TYPE_ARM_CPU);
-        object_property_add_child(obj, "cpu[*]", OBJECT(&s->cpu[i]),
+        object_property_add_child(obj, "apu-cpu[*]", OBJECT(&s->apu_cpu[i]),
                                   &error_abort);
     }
 
@@ -95,7 +95,7 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
 
     qdev_prop_set_uint32(DEVICE(&s->gic), "num-irq", GIC_NUM_SPI_INTR + 32);
     qdev_prop_set_uint32(DEVICE(&s->gic), "revision", 2);
-    qdev_prop_set_uint32(DEVICE(&s->gic), "num-cpu", XLNX_ZYNQMP_NUM_CPUS);
+    qdev_prop_set_uint32(DEVICE(&s->gic), "num-cpu", XLNX_ZYNQMP_NUM_APU_CPUS);
     object_property_set_bool(OBJECT(&s->gic), true, "realized", &err);
     if (err) {
         error_propagate((errp), (err));
@@ -121,38 +121,40 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
         }
     }
 
-    for (i = 0; i < XLNX_ZYNQMP_NUM_CPUS; i++) {
+    for (i = 0; i < XLNX_ZYNQMP_NUM_APU_CPUS; i++) {
         qemu_irq irq;
 
-        object_property_set_int(OBJECT(&s->cpu[i]), QEMU_PSCI_CONDUIT_SMC,
+        object_property_set_int(OBJECT(&s->apu_cpu[i]), QEMU_PSCI_CONDUIT_SMC,
                                 "psci-conduit", &error_abort);
         if (i > 0) {
             /* Secondary CPUs start in PSCI powered-down state */
-            object_property_set_bool(OBJECT(&s->cpu[i]), true,
+            object_property_set_bool(OBJECT(&s->apu_cpu[i]), true,
                                      "start-powered-off", &error_abort);
         }
 
-        object_property_set_int(OBJECT(&s->cpu[i]), GIC_BASE_ADDR,
+        object_property_set_int(OBJECT(&s->apu_cpu[i]), GIC_BASE_ADDR,
                                 "reset-cbar", &err);
         if (err) {
             error_propagate((errp), (err));
             return;
         }
 
-        object_property_set_bool(OBJECT(&s->cpu[i]), true, "realized", &err);
+        object_property_set_bool(OBJECT(&s->apu_cpu[i]), true, "realized",
+                                 &err);
         if (err) {
             error_propagate((errp), (err));
             return;
         }
 
         sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i,
-                           qdev_get_gpio_in(DEVICE(&s->cpu[i]), ARM_CPU_IRQ));
+                           qdev_get_gpio_in(DEVICE(&s->apu_cpu[i]),
+                                            ARM_CPU_IRQ));
         irq = qdev_get_gpio_in(DEVICE(&s->gic),
                                arm_gic_ppi_index(i, ARM_PHYS_TIMER_PPI));
-        qdev_connect_gpio_out(DEVICE(&s->cpu[i]), 0, irq);
+        qdev_connect_gpio_out(DEVICE(&s->apu_cpu[i]), 0, irq);
         irq = qdev_get_gpio_in(DEVICE(&s->gic),
                                arm_gic_ppi_index(i, ARM_VIRT_TIMER_PPI));
-        qdev_connect_gpio_out(DEVICE(&s->cpu[i]), 1, irq);
+        qdev_connect_gpio_out(DEVICE(&s->apu_cpu[i]), 1, irq);
     }
 
     for (i = 0; i < GIC_NUM_SPI_INTR; i++) {
include/hw/arm/xlnx-zynqmp.h +2 -2
index 79c2b0b..d042df1 100644
@@ -27,7 +27,7 @@
 #define XLNX_ZYNQMP(obj) OBJECT_CHECK(XlnxZynqMPState, (obj), \
                                        TYPE_XLNX_ZYNQMP)
 
-#define XLNX_ZYNQMP_NUM_CPUS 4
+#define XLNX_ZYNQMP_NUM_APU_CPUS 4
 #define XLNX_ZYNQMP_NUM_GEMS 4
 #define XLNX_ZYNQMP_NUM_UARTS 2
 
@@ -47,7 +47,7 @@ typedef struct XlnxZynqMPState {
     DeviceState parent_obj;
 
     /*< public >*/
-    ARMCPU cpu[XLNX_ZYNQMP_NUM_CPUS];
+    ARMCPU apu_cpu[XLNX_ZYNQMP_NUM_APU_CPUS];
     GICState gic;
     MemoryRegion gic_mr[XLNX_ZYNQMP_GIC_REGIONS][XLNX_ZYNQMP_GIC_ALIASES];
     CadenceGEMState gem[XLNX_ZYNQMP_NUM_GEMS];
Signature · 1 line
2.4.3.3.g905f831
Reviewed-by on v3 5/7
#7 lore raw

Re: [Qemu-devel] [PATCH target-arm v3 5/7] arm: xlnx-zynqmp: Preface CPU variables with "apu"

Quoted 5 lines · Peter Crosthwaite

The CPUs currently supported by zynqmp are the APU (application processing unit) CPUs. There are other CPUs in Zynqmp so unqualified "cpus" in ambiguous. Preface the variables with "APU" accordingly, to prepare support adding the RPU (realtime processing unit) processors.

Quoted 124 lines

---
changed since v1:
s/acpu/apu-cpu/

 hw/arm/xlnx-ep108.c          |  2 +-
 hw/arm/xlnx-zynqmp.c         | 26 ++++++++++++++------------
 include/hw/arm/xlnx-zynqmp.h |  4 ++--
 3 files changed, 17 insertions(+), 15 deletions(-)
hw/arm/xlnx-ep108.c +1 -1
index b924f5e..7a98dd6 100644
@@ -65,7 +65,7 @@ static void xlnx_ep108_init(MachineState *machine)
     xlnx_ep108_binfo.kernel_cmdline = machine->kernel_cmdline;
     xlnx_ep108_binfo.initrd_filename = machine->initrd_filename;
     xlnx_ep108_binfo.loader_start = 0;
-    arm_load_kernel(&s->soc.cpu[0], &xlnx_ep108_binfo);
+    arm_load_kernel(&s->soc.apu_cpu[0], &xlnx_ep108_binfo);
 }
 
 static QEMUMachine xlnx_ep108_machine = {
hw/arm/xlnx-zynqmp.c +14 -12
index 6b01965..353ecad 100644
@@ -64,10 +64,10 @@ static void xlnx_zynqmp_init(Object *obj)
     XlnxZynqMPState *s = XLNX_ZYNQMP(obj);
     int i;
 
-    for (i = 0; i < XLNX_ZYNQMP_NUM_CPUS; i++) {
-        object_initialize(&s->cpu[i], sizeof(s->cpu[i]),
+    for (i = 0; i < XLNX_ZYNQMP_NUM_APU_CPUS; i++) {
+        object_initialize(&s->apu_cpu[i], sizeof(s->apu_cpu[i]),
                           "cortex-a53-" TYPE_ARM_CPU);
-        object_property_add_child(obj, "cpu[*]", OBJECT(&s->cpu[i]),
+        object_property_add_child(obj, "apu-cpu[*]", OBJECT(&s->apu_cpu[i]),
                                   &error_abort);
     }
 
@@ -95,7 +95,7 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
 
     qdev_prop_set_uint32(DEVICE(&s->gic), "num-irq", GIC_NUM_SPI_INTR + 32);
     qdev_prop_set_uint32(DEVICE(&s->gic), "revision", 2);
-    qdev_prop_set_uint32(DEVICE(&s->gic), "num-cpu", XLNX_ZYNQMP_NUM_CPUS);
+    qdev_prop_set_uint32(DEVICE(&s->gic), "num-cpu", XLNX_ZYNQMP_NUM_APU_CPUS);
     object_property_set_bool(OBJECT(&s->gic), true, "realized", &err);
     if (err) {
         error_propagate((errp), (err));
@@ -121,38 +121,40 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
         }
     }
 
-    for (i = 0; i < XLNX_ZYNQMP_NUM_CPUS; i++) {
+    for (i = 0; i < XLNX_ZYNQMP_NUM_APU_CPUS; i++) {
         qemu_irq irq;
 
-        object_property_set_int(OBJECT(&s->cpu[i]), QEMU_PSCI_CONDUIT_SMC,
+        object_property_set_int(OBJECT(&s->apu_cpu[i]), QEMU_PSCI_CONDUIT_SMC,
                                 "psci-conduit", &error_abort);
         if (i > 0) {
             /* Secondary CPUs start in PSCI powered-down state */
-            object_property_set_bool(OBJECT(&s->cpu[i]), true,
+            object_property_set_bool(OBJECT(&s->apu_cpu[i]), true,
                                      "start-powered-off", &error_abort);
         }
 
-        object_property_set_int(OBJECT(&s->cpu[i]), GIC_BASE_ADDR,
+        object_property_set_int(OBJECT(&s->apu_cpu[i]), GIC_BASE_ADDR,
                                 "reset-cbar", &err);
         if (err) {
             error_propagate((errp), (err));
             return;
         }
 
-        object_property_set_bool(OBJECT(&s->cpu[i]), true, "realized", &err);
+        object_property_set_bool(OBJECT(&s->apu_cpu[i]), true, "realized",
+                                 &err);
         if (err) {
             error_propagate((errp), (err));
             return;
         }
 
         sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i,
-                           qdev_get_gpio_in(DEVICE(&s->cpu[i]), ARM_CPU_IRQ));
+                           qdev_get_gpio_in(DEVICE(&s->apu_cpu[i]),
+                                            ARM_CPU_IRQ));
         irq = qdev_get_gpio_in(DEVICE(&s->gic),
                                arm_gic_ppi_index(i, ARM_PHYS_TIMER_PPI));
-        qdev_connect_gpio_out(DEVICE(&s->cpu[i]), 0, irq);
+        qdev_connect_gpio_out(DEVICE(&s->apu_cpu[i]), 0, irq);
         irq = qdev_get_gpio_in(DEVICE(&s->gic),
                                arm_gic_ppi_index(i, ARM_VIRT_TIMER_PPI));
-        qdev_connect_gpio_out(DEVICE(&s->cpu[i]), 1, irq);
+        qdev_connect_gpio_out(DEVICE(&s->apu_cpu[i]), 1, irq);
     }
 
     for (i = 0; i < GIC_NUM_SPI_INTR; i++) {
include/hw/arm/xlnx-zynqmp.h +2 -2
index 79c2b0b..d042df1 100644
@@ -27,7 +27,7 @@
 #define XLNX_ZYNQMP(obj) OBJECT_CHECK(XlnxZynqMPState, (obj), \
                                        TYPE_XLNX_ZYNQMP)
 
-#define XLNX_ZYNQMP_NUM_CPUS 4
+#define XLNX_ZYNQMP_NUM_APU_CPUS 4
 #define XLNX_ZYNQMP_NUM_GEMS 4
 #define XLNX_ZYNQMP_NUM_UARTS 2
 
@@ -47,7 +47,7 @@ typedef struct XlnxZynqMPState {
     DeviceState parent_obj;
 
     /*< public >*/
-    ARMCPU cpu[XLNX_ZYNQMP_NUM_CPUS];
+    ARMCPU apu_cpu[XLNX_ZYNQMP_NUM_APU_CPUS];
     GICState gic;
     MemoryRegion gic_mr[XLNX_ZYNQMP_GIC_REGIONS][XLNX_ZYNQMP_GIC_ALIASES];
     CadenceGEMState gem[XLNX_ZYNQMP_NUM_GEMS];
Signature · 1 line
2.4.3.3.g905f831
#8 lore raw

PATCH v3 6/7 arm: xlnx-zynqmp: Add boot-cpu property

In reply to Peter Crosthwaite

Add a string property that specifies the primary boot cpu. All CPUs except the one selected will start-powered-off. This allows for elf boots on any CPU, which prepares support for booting R5 elfs directly on the R5 processors.

---
 hw/arm/xlnx-ep108.c          |  2 +-
 hw/arm/xlnx-zynqmp.c         | 19 ++++++++++++++++++-
 include/hw/arm/xlnx-zynqmp.h |  3 +++
 3 files changed, 22 insertions(+), 2 deletions(-)
hw/arm/xlnx-ep108.c +1 -1
index 7a98dd6..f94da86 100644
@@ -65,7 +65,7 @@ static void xlnx_ep108_init(MachineState *machine)
     xlnx_ep108_binfo.kernel_cmdline = machine->kernel_cmdline;
     xlnx_ep108_binfo.initrd_filename = machine->initrd_filename;
     xlnx_ep108_binfo.loader_start = 0;
-    arm_load_kernel(&s->soc.apu_cpu[0], &xlnx_ep108_binfo);
+    arm_load_kernel(s->soc.boot_cpu_ptr, &xlnx_ep108_binfo);
 }
 
 static QEMUMachine xlnx_ep108_machine = {
hw/arm/xlnx-zynqmp.c +18 -1
index 353ecad..0c966da 100644
@@ -90,6 +90,7 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
     XlnxZynqMPState *s = XLNX_ZYNQMP(dev);
     MemoryRegion *system_memory = get_system_memory();
     uint8_t i;
+    const char *boot_cpu = s->boot_cpu ? s->boot_cpu : "apu-cpu[0]";
     qemu_irq gic_spi[GIC_NUM_SPI_INTR];
     Error *err = NULL;
 
@@ -123,13 +124,18 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
 
     for (i = 0; i < XLNX_ZYNQMP_NUM_APU_CPUS; i++) {
         qemu_irq irq;
+        char *name;
 
         object_property_set_int(OBJECT(&s->apu_cpu[i]), QEMU_PSCI_CONDUIT_SMC,
                                 "psci-conduit", &error_abort);
-        if (i > 0) {
+
+        name = object_get_canonical_path_component(OBJECT(&s->apu_cpu[i]));
+        if (strcmp(name, boot_cpu)) {
             /* Secondary CPUs start in PSCI powered-down state */
             object_property_set_bool(OBJECT(&s->apu_cpu[i]), true,
                                      "start-powered-off", &error_abort);
+        } else {
+            s->boot_cpu_ptr = &s->apu_cpu[i];
         }
 
         object_property_set_int(OBJECT(&s->apu_cpu[i]), GIC_BASE_ADDR,
@@ -157,6 +163,11 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
         qdev_connect_gpio_out(DEVICE(&s->apu_cpu[i]), 1, irq);
     }
 
+    if (!s->boot_cpu_ptr) {
+        error_setg(errp, "ZynqMP Boot cpu %s not found\n", boot_cpu);
+        return;
+    }
+
     for (i = 0; i < GIC_NUM_SPI_INTR; i++) {
         gic_spi[i] = qdev_get_gpio_in(DEVICE(&s->gic), i);
     }
@@ -190,10 +201,16 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
     }
 }
 
+static Property xlnx_zynqmp_props[] = {
+    DEFINE_PROP_STRING("boot-cpu", XlnxZynqMPState, boot_cpu),
+    DEFINE_PROP_END_OF_LIST()
+};
+
 static void xlnx_zynqmp_class_init(ObjectClass *oc, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(oc);
 
+    dc->props = xlnx_zynqmp_props;
     dc->realize = xlnx_zynqmp_realize;
 }
 
include/hw/arm/xlnx-zynqmp.h +3 -0
index d042df1..4f14a22 100644
@@ -52,6 +52,9 @@ typedef struct XlnxZynqMPState {
     MemoryRegion gic_mr[XLNX_ZYNQMP_GIC_REGIONS][XLNX_ZYNQMP_GIC_ALIASES];
     CadenceGEMState gem[XLNX_ZYNQMP_NUM_GEMS];
     CadenceUARTState uart[XLNX_ZYNQMP_NUM_UARTS];
+
+    char *boot_cpu;
+    ARMCPU *boot_cpu_ptr;
 }  XlnxZynqMPState;
 
 #define XLNX_ZYNQMP_H
Signature · 1 line
2.4.3.3.g905f831
#9 lore raw

PATCH v3 7/7 arm: xlnx-zynqmp: Add 2xCortexR5 CPUs

In reply to Peter Crosthwaite

Add the 2xCortexR5 CPUs to zynqmp board. They are powered off on reset (this is true of real hardware) by default or selectable as the boot processor.

---
changed since v2:
Add boot-cpu start-powered-off conditional
changed since v1:
s/rcpu/rpu-cpu/

 hw/arm/xlnx-zynqmp.c         | 34 ++++++++++++++++++++++++++++++++++
 include/hw/arm/xlnx-zynqmp.h |  2 ++
 2 files changed, 36 insertions(+)
hw/arm/xlnx-zynqmp.c +34 -0
index 0c966da..5e72078 100644
@@ -71,6 +71,13 @@ static void xlnx_zynqmp_init(Object *obj)
                                   &error_abort);
     }
 
+    for (i = 0; i < XLNX_ZYNQMP_NUM_RPU_CPUS; i++) {
+        object_initialize(&s->rpu_cpu[i], sizeof(s->rpu_cpu[i]),
+                          "cortex-r5-" TYPE_ARM_CPU);
+        object_property_add_child(obj, "rpu-cpu[*]", OBJECT(&s->rpu_cpu[i]),
+                                  &error_abort);
+    }
+
     object_initialize(&s->gic, sizeof(s->gic), TYPE_ARM_GIC);
     qdev_set_parent_bus(DEVICE(&s->gic), sysbus_get_default());
 
@@ -163,6 +170,33 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
         qdev_connect_gpio_out(DEVICE(&s->apu_cpu[i]), 1, irq);
     }
 
+    for (i = 0; i < XLNX_ZYNQMP_NUM_RPU_CPUS; i++) {
+        char *name;
+
+        name = object_get_canonical_path_component(OBJECT(&s->rpu_cpu[i]));
+        if (strcmp(name, boot_cpu)) {
+            /* Secondary CPUs start in PSCI powered-down state */
+            object_property_set_bool(OBJECT(&s->rpu_cpu[i]), true,
+                                     "start-powered-off", &error_abort);
+        } else {
+            s->boot_cpu_ptr = &s->rpu_cpu[i];
+        }
+
+        object_property_set_bool(OBJECT(&s->rpu_cpu[i]), true, "reset-hivecs",
+                                 &err);
+        if (err != NULL) {
+            error_propagate(errp, err);
+            return;
+        }
+
+        object_property_set_bool(OBJECT(&s->rpu_cpu[i]), true, "realized",
+                                 &err);
+        if (err) {
+            error_propagate((errp), (err));
+            return;
+        }
+    }
+
     if (!s->boot_cpu_ptr) {
         error_setg(errp, "ZynqMP Boot cpu %s not found\n", boot_cpu);
         return;
include/hw/arm/xlnx-zynqmp.h +2 -0
index 4f14a22..c379632 100644
@@ -28,6 +28,7 @@
                                        TYPE_XLNX_ZYNQMP)
 
 #define XLNX_ZYNQMP_NUM_APU_CPUS 4
+#define XLNX_ZYNQMP_NUM_RPU_CPUS 2
 #define XLNX_ZYNQMP_NUM_GEMS 4
 #define XLNX_ZYNQMP_NUM_UARTS 2
 
@@ -48,6 +49,7 @@ typedef struct XlnxZynqMPState {
 
     /*< public >*/
     ARMCPU apu_cpu[XLNX_ZYNQMP_NUM_APU_CPUS];
+    ARMCPU rpu_cpu[XLNX_ZYNQMP_NUM_RPU_CPUS];
     GICState gic;
     MemoryRegion gic_mr[XLNX_ZYNQMP_GIC_REGIONS][XLNX_ZYNQMP_GIC_ALIASES];
     CadenceGEMState gem[XLNX_ZYNQMP_NUM_GEMS];
Signature · 1 line
2.4.3.3.g905f831
#10 lore raw

Re: [Qemu-devel] [PATCH target-arm v3 7/7] arm: xlnx-zynqmp: Add 2xCortexR5 CPUs

Quoted 3 lines · Peter Crosthwaite

Add the 2xCortexR5 CPUs to zynqmp board. They are powered off on reset (this is true of real hardware) by default or selectable as the boot processor.

Hi Peter,

I think it would be good if you could model at least a minimal way to release the R5s from reset the "real" way. The R5s are not covered by PSCI in real code and not all code uses PSCI, in particular not any R5 code.

How would the R5s be useful with upstream with this version? Maybe I'm missing something.

Cheers,
Edgar

Quoted 87 lines

---
changed since v2:
Add boot-cpu start-powered-off conditional
changed since v1:
s/rcpu/rpu-cpu/

 hw/arm/xlnx-zynqmp.c         | 34 ++++++++++++++++++++++++++++++++++
 include/hw/arm/xlnx-zynqmp.h |  2 ++
 2 files changed, 36 insertions(+)
hw/arm/xlnx-zynqmp.c +34 -0
index 0c966da..5e72078 100644
@@ -71,6 +71,13 @@ static void xlnx_zynqmp_init(Object *obj)
                                   &error_abort);
     }
 
+    for (i = 0; i < XLNX_ZYNQMP_NUM_RPU_CPUS; i++) {
+        object_initialize(&s->rpu_cpu[i], sizeof(s->rpu_cpu[i]),
+                          "cortex-r5-" TYPE_ARM_CPU);
+        object_property_add_child(obj, "rpu-cpu[*]", OBJECT(&s->rpu_cpu[i]),
+                                  &error_abort);
+    }
+
     object_initialize(&s->gic, sizeof(s->gic), TYPE_ARM_GIC);
     qdev_set_parent_bus(DEVICE(&s->gic), sysbus_get_default());
 
@@ -163,6 +170,33 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
         qdev_connect_gpio_out(DEVICE(&s->apu_cpu[i]), 1, irq);
     }
 
+    for (i = 0; i < XLNX_ZYNQMP_NUM_RPU_CPUS; i++) {
+        char *name;
+
+        name = object_get_canonical_path_component(OBJECT(&s->rpu_cpu[i]));
+        if (strcmp(name, boot_cpu)) {
+            /* Secondary CPUs start in PSCI powered-down state */
+            object_property_set_bool(OBJECT(&s->rpu_cpu[i]), true,
+                                     "start-powered-off", &error_abort);
+        } else {
+            s->boot_cpu_ptr = &s->rpu_cpu[i];
+        }
+
+        object_property_set_bool(OBJECT(&s->rpu_cpu[i]), true, "reset-hivecs",
+                                 &err);
+        if (err != NULL) {
+            error_propagate(errp, err);
+            return;
+        }
+
+        object_property_set_bool(OBJECT(&s->rpu_cpu[i]), true, "realized",
+                                 &err);
+        if (err) {
+            error_propagate((errp), (err));
+            return;
+        }
+    }
+
     if (!s->boot_cpu_ptr) {
         error_setg(errp, "ZynqMP Boot cpu %s not found\n", boot_cpu);
         return;
include/hw/arm/xlnx-zynqmp.h +2 -0
index 4f14a22..c379632 100644
@@ -28,6 +28,7 @@
                                        TYPE_XLNX_ZYNQMP)
 
 #define XLNX_ZYNQMP_NUM_APU_CPUS 4
+#define XLNX_ZYNQMP_NUM_RPU_CPUS 2
 #define XLNX_ZYNQMP_NUM_GEMS 4
 #define XLNX_ZYNQMP_NUM_UARTS 2
 
@@ -48,6 +49,7 @@ typedef struct XlnxZynqMPState {
 
     /*< public >*/
     ARMCPU apu_cpu[XLNX_ZYNQMP_NUM_APU_CPUS];
+    ARMCPU rpu_cpu[XLNX_ZYNQMP_NUM_RPU_CPUS];
     GICState gic;
     MemoryRegion gic_mr[XLNX_ZYNQMP_GIC_REGIONS][XLNX_ZYNQMP_GIC_ALIASES];
     CadenceGEMState gem[XLNX_ZYNQMP_NUM_GEMS];
Signature · 1 line
2.4.3.3.g905f831
#11 lore raw

Re: [Qemu-devel] [PATCH target-arm v3 7/7] arm: xlnx-zynqmp: Add 2xCortexR5 CPUs

Quoted 7 lines · Edgar E. Iglesias
Quoted 3 lines · Peter Crosthwaite

Add the 2xCortexR5 CPUs to zynqmp board. They are powered off on reset (this is true of real hardware) by default or selectable as the boot processor.

Hi Peter,

Quoted 8 lines

I think it would be good if you could model at least a minimal way to release the R5s from reset the "real" way. The R5s are not covered by PSCI in real code and not all code uses PSCI, in particular not any R5 code.

How would the R5s be useful with upstream with this version? Maybe I'm missing something.

You can nominate an R5 instead of A53 as the one non-powered-off cpu by setting the zynqmp boot-cpu property with -global:

$ qemu-system-aarch64 -M xlnx-ep108 -m 2048 -nographic -kernel
./r5_image.elf -global xlnx,zynqmp.boot-cpu="rpu-cpu[0]"

This works with elf boots.

Regards,
Peter

Quoted 92 lines

Cheers,
Edgar

Quoted 87 lines

---
changed since v2:
Add boot-cpu start-powered-off conditional
changed since v1:
s/rcpu/rpu-cpu/

 hw/arm/xlnx-zynqmp.c         | 34 ++++++++++++++++++++++++++++++++++
 include/hw/arm/xlnx-zynqmp.h |  2 ++
 2 files changed, 36 insertions(+)
hw/arm/xlnx-zynqmp.c +34 -0
index 0c966da..5e72078 100644
@@ -71,6 +71,13 @@ static void xlnx_zynqmp_init(Object *obj)
                                   &error_abort);
     }
 
+    for (i = 0; i < XLNX_ZYNQMP_NUM_RPU_CPUS; i++) {
+        object_initialize(&s->rpu_cpu[i], sizeof(s->rpu_cpu[i]),
+                          "cortex-r5-" TYPE_ARM_CPU);
+        object_property_add_child(obj, "rpu-cpu[*]", OBJECT(&s->rpu_cpu[i]),
+                                  &error_abort);
+    }
+
     object_initialize(&s->gic, sizeof(s->gic), TYPE_ARM_GIC);
     qdev_set_parent_bus(DEVICE(&s->gic), sysbus_get_default());
 
@@ -163,6 +170,33 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
         qdev_connect_gpio_out(DEVICE(&s->apu_cpu[i]), 1, irq);
     }
 
+    for (i = 0; i < XLNX_ZYNQMP_NUM_RPU_CPUS; i++) {
+        char *name;
+
+        name = object_get_canonical_path_component(OBJECT(&s->rpu_cpu[i]));
+        if (strcmp(name, boot_cpu)) {
+            /* Secondary CPUs start in PSCI powered-down state */
+            object_property_set_bool(OBJECT(&s->rpu_cpu[i]), true,
+                                     "start-powered-off", &error_abort);
+        } else {
+            s->boot_cpu_ptr = &s->rpu_cpu[i];
+        }
+
+        object_property_set_bool(OBJECT(&s->rpu_cpu[i]), true, "reset-hivecs",
+                                 &err);
+        if (err != NULL) {
+            error_propagate(errp, err);
+            return;
+        }
+
+        object_property_set_bool(OBJECT(&s->rpu_cpu[i]), true, "realized",
+                                 &err);
+        if (err) {
+            error_propagate((errp), (err));
+            return;
+        }
+    }
+
     if (!s->boot_cpu_ptr) {
         error_setg(errp, "ZynqMP Boot cpu %s not found\n", boot_cpu);
         return;
include/hw/arm/xlnx-zynqmp.h +2 -1
index 4f14a22..c379632 100644
@@ -28,6 +28,7 @@
                                        TYPE_XLNX_ZYNQMP)
 
 #define XLNX_ZYNQMP_NUM_APU_CPUS 4
+#define XLNX_ZYNQMP_NUM_RPU_CPUS 2
 #define XLNX_ZYNQMP_NUM_GEMS 4
 #define XLNX_ZYNQMP_NUM_UARTS 2
 
@@ -48,6 +49,7 @@ typedef struct XlnxZynqMPState {
 
     /*< public >*/
     ARMCPU apu_cpu[XLNX_ZYNQMP_NUM_APU_CPUS];
+    ARMCPU rpu_cpu[XLNX_ZYNQMP_NUM_RPU_CPUS];
     GICState gic;
     MemoryRegion gic_mr[XLNX_ZYNQMP_GIC_REGIONS][XLNX_ZYNQMP_GIC_ALIASES];
     CadenceGEMState gem[XLNX_ZYNQMP_NUM_GEMS];
--

2.4.3.3.g905f831

#12 lore raw

Re: [Qemu-devel] [PATCH target-arm v3 7/7] arm: xlnx-zynqmp: Add 2xCortexR5 CPUs

Quoted 18 lines · Peter Crosthwaite
Quoted 7 lines · Edgar E. Iglesias
Quoted 3 lines · Peter Crosthwaite

Add the 2xCortexR5 CPUs to zynqmp board. They are powered off on reset (this is true of real hardware) by default or selectable as the boot processor.

Hi Peter,

Quoted 8 lines

I think it would be good if you could model at least a minimal way to release the R5s from reset the "real" way. The R5s are not covered by PSCI in real code and not all code uses PSCI, in particular not any R5 code.

How would the R5s be useful with upstream with this version? Maybe I'm missing something.

Quoted 7 lines

You can nominate an R5 instead of A53 as the one non-powered-off cpu by setting the zynqmp boot-cpu property with -global:

$ qemu-system-aarch64 -M xlnx-ep108 -m 2048 -nographic -kernel
./r5_image.elf -global xlnx,zynqmp.boot-cpu="rpu-cpu[0]"

This works with elf boots.

In that mode, how do I release the A53s (or the other R5)? Will it be either one R5 or the A53s?

Cheers,
Edgar

Quoted 96 lines

Regards,
Peter

Quoted 92 lines

Cheers,
Edgar

Quoted 87 lines

---
changed since v2:
Add boot-cpu start-powered-off conditional
changed since v1:
s/rcpu/rpu-cpu/

 hw/arm/xlnx-zynqmp.c         | 34 ++++++++++++++++++++++++++++++++++
 include/hw/arm/xlnx-zynqmp.h |  2 ++
 2 files changed, 36 insertions(+)
hw/arm/xlnx-zynqmp.c +34 -0
index 0c966da..5e72078 100644
@@ -71,6 +71,13 @@ static void xlnx_zynqmp_init(Object *obj)
                                   &error_abort);
     }
 
+    for (i = 0; i < XLNX_ZYNQMP_NUM_RPU_CPUS; i++) {
+        object_initialize(&s->rpu_cpu[i], sizeof(s->rpu_cpu[i]),
+                          "cortex-r5-" TYPE_ARM_CPU);
+        object_property_add_child(obj, "rpu-cpu[*]", OBJECT(&s->rpu_cpu[i]),
+                                  &error_abort);
+    }
+
     object_initialize(&s->gic, sizeof(s->gic), TYPE_ARM_GIC);
     qdev_set_parent_bus(DEVICE(&s->gic), sysbus_get_default());
 
@@ -163,6 +170,33 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
         qdev_connect_gpio_out(DEVICE(&s->apu_cpu[i]), 1, irq);
     }
 
+    for (i = 0; i < XLNX_ZYNQMP_NUM_RPU_CPUS; i++) {
+        char *name;
+
+        name = object_get_canonical_path_component(OBJECT(&s->rpu_cpu[i]));
+        if (strcmp(name, boot_cpu)) {
+            /* Secondary CPUs start in PSCI powered-down state */
+            object_property_set_bool(OBJECT(&s->rpu_cpu[i]), true,
+                                     "start-powered-off", &error_abort);
+        } else {
+            s->boot_cpu_ptr = &s->rpu_cpu[i];
+        }
+
+        object_property_set_bool(OBJECT(&s->rpu_cpu[i]), true, "reset-hivecs",
+                                 &err);
+        if (err != NULL) {
+            error_propagate(errp, err);
+            return;
+        }
+
+        object_property_set_bool(OBJECT(&s->rpu_cpu[i]), true, "realized",
+                                 &err);
+        if (err) {
+            error_propagate((errp), (err));
+            return;
+        }
+    }
+
     if (!s->boot_cpu_ptr) {
         error_setg(errp, "ZynqMP Boot cpu %s not found\n", boot_cpu);
         return;
include/hw/arm/xlnx-zynqmp.h +2 -1
index 4f14a22..c379632 100644
@@ -28,6 +28,7 @@
                                        TYPE_XLNX_ZYNQMP)
 
 #define XLNX_ZYNQMP_NUM_APU_CPUS 4
+#define XLNX_ZYNQMP_NUM_RPU_CPUS 2
 #define XLNX_ZYNQMP_NUM_GEMS 4
 #define XLNX_ZYNQMP_NUM_UARTS 2
 
@@ -48,6 +49,7 @@ typedef struct XlnxZynqMPState {
 
     /*< public >*/
     ARMCPU apu_cpu[XLNX_ZYNQMP_NUM_APU_CPUS];
+    ARMCPU rpu_cpu[XLNX_ZYNQMP_NUM_RPU_CPUS];
     GICState gic;
     MemoryRegion gic_mr[XLNX_ZYNQMP_GIC_REGIONS][XLNX_ZYNQMP_GIC_ALIASES];
     CadenceGEMState gem[XLNX_ZYNQMP_NUM_GEMS];
--

2.4.3.3.g905f831

#13 lore raw

Re: [Qemu-devel] [PATCH target-arm v3 7/7] arm: xlnx-zynqmp: Add 2xCortexR5 CPUs

Quoted 22 lines · Edgar E. Iglesias
Quoted 21 lines · Peter Crosthwaite
Quoted 7 lines · Edgar E. Iglesias
Quoted 3 lines · Peter Crosthwaite

Add the 2xCortexR5 CPUs to zynqmp board. They are powered off on reset (this is true of real hardware) by default or selectable as the boot processor.

Hi Peter,

Quoted 8 lines

I think it would be good if you could model at least a minimal way to release the R5s from reset the "real" way. The R5s are not covered by PSCI in real code and not all code uses PSCI, in particular not any R5 code.

How would the R5s be useful with upstream with this version? Maybe I'm missing something.

You can nominate an R5 instead of A53 as the one non-powered-off cpu by setting the zynqmp boot-cpu property with -global:

Quoted 8 lines
Quoted 4 lines
$ qemu-system-aarch64 -M xlnx-ep108 -m 2048 -nographic -kernel
./r5_image.elf -global xlnx,zynqmp.boot-cpu="rpu-cpu[0]"

This works with elf boots.

In that mode, how do I release the A53s (or the other R5)? Will it be either one R5 or the A53s?

Just one or the other so far unless you do a backdoor PSCI release from SW. Loading multiple softwares needs either a more dynamic bootloader process or the reset controller model, both of which I want to follow up later with.

Regards,
Peter

Quoted 101 lines

Cheers,
Edgar

Quoted 96 lines

Regards,
Peter

Quoted 92 lines

Cheers,
Edgar

Quoted 87 lines

---
changed since v2:
Add boot-cpu start-powered-off conditional
changed since v1:
s/rcpu/rpu-cpu/

 hw/arm/xlnx-zynqmp.c         | 34 ++++++++++++++++++++++++++++++++++
 include/hw/arm/xlnx-zynqmp.h |  2 ++
 2 files changed, 36 insertions(+)
hw/arm/xlnx-zynqmp.c +34 -0
index 0c966da..5e72078 100644
@@ -71,6 +71,13 @@ static void xlnx_zynqmp_init(Object *obj)
                                   &error_abort);
     }
 
+    for (i = 0; i < XLNX_ZYNQMP_NUM_RPU_CPUS; i++) {
+        object_initialize(&s->rpu_cpu[i], sizeof(s->rpu_cpu[i]),
+                          "cortex-r5-" TYPE_ARM_CPU);
+        object_property_add_child(obj, "rpu-cpu[*]", OBJECT(&s->rpu_cpu[i]),
+                                  &error_abort);
+    }
+
     object_initialize(&s->gic, sizeof(s->gic), TYPE_ARM_GIC);
     qdev_set_parent_bus(DEVICE(&s->gic), sysbus_get_default());
 
@@ -163,6 +170,33 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
         qdev_connect_gpio_out(DEVICE(&s->apu_cpu[i]), 1, irq);
     }
 
+    for (i = 0; i < XLNX_ZYNQMP_NUM_RPU_CPUS; i++) {
+        char *name;
+
+        name = object_get_canonical_path_component(OBJECT(&s->rpu_cpu[i]));
+        if (strcmp(name, boot_cpu)) {
+            /* Secondary CPUs start in PSCI powered-down state */
+            object_property_set_bool(OBJECT(&s->rpu_cpu[i]), true,
+                                     "start-powered-off", &error_abort);
+        } else {
+            s->boot_cpu_ptr = &s->rpu_cpu[i];
+        }
+
+        object_property_set_bool(OBJECT(&s->rpu_cpu[i]), true, "reset-hivecs",
+                                 &err);
+        if (err != NULL) {
+            error_propagate(errp, err);
+            return;
+        }
+
+        object_property_set_bool(OBJECT(&s->rpu_cpu[i]), true, "realized",
+                                 &err);
+        if (err) {
+            error_propagate((errp), (err));
+            return;
+        }
+    }
+
     if (!s->boot_cpu_ptr) {
         error_setg(errp, "ZynqMP Boot cpu %s not found\n", boot_cpu);
         return;
include/hw/arm/xlnx-zynqmp.h +2 -1
index 4f14a22..c379632 100644
@@ -28,6 +28,7 @@
                                        TYPE_XLNX_ZYNQMP)
 
 #define XLNX_ZYNQMP_NUM_APU_CPUS 4
+#define XLNX_ZYNQMP_NUM_RPU_CPUS 2
 #define XLNX_ZYNQMP_NUM_GEMS 4
 #define XLNX_ZYNQMP_NUM_UARTS 2
 
@@ -48,6 +49,7 @@ typedef struct XlnxZynqMPState {
 
     /*< public >*/
     ARMCPU apu_cpu[XLNX_ZYNQMP_NUM_APU_CPUS];
+    ARMCPU rpu_cpu[XLNX_ZYNQMP_NUM_RPU_CPUS];
     GICState gic;
     MemoryRegion gic_mr[XLNX_ZYNQMP_GIC_REGIONS][XLNX_ZYNQMP_GIC_ALIASES];
     CadenceGEMState gem[XLNX_ZYNQMP_NUM_GEMS];
--

2.4.3.3.g905f831

#14 lore raw

Re: [Qemu-devel] [PATCH target-arm v3 7/7] arm: xlnx-zynqmp: Add 2xCortexR5 CPUs

Quoted 27 lines · Peter Crosthwaite
Quoted 25 lines · Edgar E. Iglesias
Quoted 24 lines · Peter Crosthwaite
Quoted 7 lines · Edgar E. Iglesias
Quoted 3 lines · Peter Crosthwaite

Add the 2xCortexR5 CPUs to zynqmp board. They are powered off on reset (this is true of real hardware) by default or selectable as the boot processor.

Hi Peter,

Quoted 8 lines

I think it would be good if you could model at least a minimal way to release the R5s from reset the "real" way. The R5s are not covered by PSCI in real code and not all code uses PSCI, in particular not any R5 code.

How would the R5s be useful with upstream with this version? Maybe I'm missing something.

You can nominate an R5 instead of A53 as the one non-powered-off cpu by setting the zynqmp boot-cpu property with -global:

$ qemu-system-aarch64 -M xlnx-ep108 -m 2048 -nographic -kernel
./r5_image.elf -global xlnx,zynqmp.boot-cpu="rpu-cpu[0]"
Quoted 8 lines
Quoted 5 lines
Quoted 1 line

This works with elf boots.

In that mode, how do I release the A53s (or the other R5)? Will it be either one R5 or the A53s?

Just one or the other so far unless you do a backdoor PSCI release from SW. Loading multiple softwares needs either a more dynamic

Note that you can't do PSCI from the R5s. The A53s could wake the R5s with PSCI in this QEMU but not on real SW stack which is a little confusing...

Quoted 2 lines

bootloader process or the reset controller model, both of which I want to follow up later with.

OK, it's quite limited ATM but I guess it's a step forward...

Thanks,
Edgar

Quoted 105 lines

Regards,
Peter

Quoted 101 lines

Cheers,
Edgar

Quoted 96 lines

Regards,
Peter

Quoted 92 lines

Cheers,
Edgar

Quoted 87 lines

---
changed since v2:
Add boot-cpu start-powered-off conditional
changed since v1:
s/rcpu/rpu-cpu/

 hw/arm/xlnx-zynqmp.c         | 34 ++++++++++++++++++++++++++++++++++
 include/hw/arm/xlnx-zynqmp.h |  2 ++
 2 files changed, 36 insertions(+)
hw/arm/xlnx-zynqmp.c +34 -0
index 0c966da..5e72078 100644
@@ -71,6 +71,13 @@ static void xlnx_zynqmp_init(Object *obj)
                                   &error_abort);
     }
 
+    for (i = 0; i < XLNX_ZYNQMP_NUM_RPU_CPUS; i++) {
+        object_initialize(&s->rpu_cpu[i], sizeof(s->rpu_cpu[i]),
+                          "cortex-r5-" TYPE_ARM_CPU);
+        object_property_add_child(obj, "rpu-cpu[*]", OBJECT(&s->rpu_cpu[i]),
+                                  &error_abort);
+    }
+
     object_initialize(&s->gic, sizeof(s->gic), TYPE_ARM_GIC);
     qdev_set_parent_bus(DEVICE(&s->gic), sysbus_get_default());
 
@@ -163,6 +170,33 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
         qdev_connect_gpio_out(DEVICE(&s->apu_cpu[i]), 1, irq);
     }
 
+    for (i = 0; i < XLNX_ZYNQMP_NUM_RPU_CPUS; i++) {
+        char *name;
+
+        name = object_get_canonical_path_component(OBJECT(&s->rpu_cpu[i]));
+        if (strcmp(name, boot_cpu)) {
+            /* Secondary CPUs start in PSCI powered-down state */
+            object_property_set_bool(OBJECT(&s->rpu_cpu[i]), true,
+                                     "start-powered-off", &error_abort);
+        } else {
+            s->boot_cpu_ptr = &s->rpu_cpu[i];
+        }
+
+        object_property_set_bool(OBJECT(&s->rpu_cpu[i]), true, "reset-hivecs",
+                                 &err);
+        if (err != NULL) {
+            error_propagate(errp, err);
+            return;
+        }
+
+        object_property_set_bool(OBJECT(&s->rpu_cpu[i]), true, "realized",
+                                 &err);
+        if (err) {
+            error_propagate((errp), (err));
+            return;
+        }
+    }
+
     if (!s->boot_cpu_ptr) {
         error_setg(errp, "ZynqMP Boot cpu %s not found\n", boot_cpu);
         return;
include/hw/arm/xlnx-zynqmp.h +2 -1
index 4f14a22..c379632 100644
@@ -28,6 +28,7 @@
                                        TYPE_XLNX_ZYNQMP)
 
 #define XLNX_ZYNQMP_NUM_APU_CPUS 4
+#define XLNX_ZYNQMP_NUM_RPU_CPUS 2
 #define XLNX_ZYNQMP_NUM_GEMS 4
 #define XLNX_ZYNQMP_NUM_UARTS 2
 
@@ -48,6 +49,7 @@ typedef struct XlnxZynqMPState {
 
     /*< public >*/
     ARMCPU apu_cpu[XLNX_ZYNQMP_NUM_APU_CPUS];
+    ARMCPU rpu_cpu[XLNX_ZYNQMP_NUM_RPU_CPUS];
     GICState gic;
     MemoryRegion gic_mr[XLNX_ZYNQMP_GIC_REGIONS][XLNX_ZYNQMP_GIC_ALIASES];
     CadenceGEMState gem[XLNX_ZYNQMP_NUM_GEMS];
--

2.4.3.3.g905f831

#15 lore raw
In reply to Peter Crosthwaite
Quoted 4 lines · Peter Crosthwaite

Hi Peter and all,

This patch series adds ARM Cortex R5 processor support. The PMSAv7 MPU is implemented. Two R5s are added to the Xilinx ZynqMP SoC.

Thanks, applied to target-arm.next. (This is by a few days post-softfreeze but the patches were on the list well before the deadline.)

-- PMM