Replace the kvm_arm_gicv3_get function with a batched implementation that
uses the batch helpers added in Task 4.
The new function:
1. Detects batch support using kvm_arm_gic_batch_supported()
2. When batch is supported:
- Batches redistributor register accesses for all vCPUs and commits
after the loop, with post-processing for ICFGR1 transformation
and IPRIORITYR byte splitting
- Batches PLPIS propbaser/pendbaser accesses when applicable
- Batches CPU interface basic registers for all enabled vCPUs
- Batches CPU interface APR registers based on num_pri_bits
3. Falls back to existing per-register ioctl calls when batch is not
supported
4. Keeps all distributor accesses unchanged
Also add auxiliary functions to implement batch operations:
-kvm_arm_gic_batch_get_redist: read Redistributor common registers
in batches
-kvm_arm_gic_batch_get_plpis: read the LPI base address registers
in batches
-kvm_arm_gic_batch_get_cpuif_basic: read the CPU interface basic registers
in batches
-kvm_arm_gic_batch_get_cpuif_apr: read the CPU Interface APR Registers
in batches
This reduces the number of KVM device attribute ioctls from
O(num_cpu * registers_per_cpu) to a small constant number of batch commits.
Signed-off-by: Chuan Zheng <[email protected]>
Signed-off-by: Yize Wang <[email protected]>
---
hw/intc/arm_gicv3_kvm.c | 500 +++++++++++++++++++++++++++++++++-------
1 file changed, 412 insertions(+), 88 deletions(-)
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
index 1fdc554fe0..16f851b0ae 100644
--- a/hw/intc/arm_gicv3_kvm.c
+++ b/hw/intc/arm_gicv3_kvm.c
@@ -923,11 +923,293 @@ static void kvm_arm_gicv3_put(GICv3State *s)
info_report("kvm_arm_gicv3_put, time=%ldms", end_time - start_time);
}
+/* Read Redistributor common registers in batches */
+static void kvm_arm_gic_batch_get_redist(GICv3State *s,
+ GICv3BatchEntry **entries,
+ int *batch_n,
+ int *batch_capacity)
+{
+ uint32_t *redist_priority = g_new(uint32_t,
+ s->num_cpu * (GIC_INTERNAL / 4));
+
+ for (int ncpu = 0; ncpu < s->num_cpu; ncpu++) {
+ GICv3CPUState *c = &s->cpu[ncpu];
+ int pri_base = ncpu * (GIC_INTERNAL / 4);
+
+ /* Redistributor state (one per CPU) */
+ kvm_arm_gic_batch_add(entries, batch_n, batch_capacity,
+ KVM_DEV_ARM_VGIC_GRP_REDIST_REGS,
+ KVM_VGIC_ATTR(GICR_CTLR, c->gicr_typer),
+ &c->gicr_ctlr);
+ kvm_arm_gic_batch_add(entries, batch_n, batch_capacity,
+ KVM_DEV_ARM_VGIC_GRP_REDIST_REGS,
+ KVM_VGIC_ATTR(GICR_STATUSR, c->gicr_typer),
+ &c->gicr_statusr[GICV3_NS]);
+ kvm_arm_gic_batch_add(entries, batch_n, batch_capacity,
+ KVM_DEV_ARM_VGIC_GRP_REDIST_REGS,
+ KVM_VGIC_ATTR(GICR_WAKER, c->gicr_typer),
+ &c->gicr_waker);
+ kvm_arm_gic_batch_add(entries, batch_n, batch_capacity,
+ KVM_DEV_ARM_VGIC_GRP_REDIST_REGS,
+ KVM_VGIC_ATTR(GICR_IGROUPR0, c->gicr_typer),
+ &c->gicr_igroupr0);
+ kvm_arm_gic_batch_add(entries, batch_n, batch_capacity,
+ KVM_DEV_ARM_VGIC_GRP_REDIST_REGS,
+ KVM_VGIC_ATTR(GICR_ISENABLER0, c->gicr_typer),
+ &c->gicr_ienabler0);
+ kvm_arm_gic_batch_add(entries, batch_n, batch_capacity,
+ KVM_DEV_ARM_VGIC_GRP_REDIST_REGS,
+ KVM_VGIC_ATTR(GICR_ICFGR1, c->gicr_typer),
+ &c->edge_trigger);
+ kvm_arm_gic_batch_add(entries, batch_n, batch_capacity,
+ KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO,
+ KVM_VGIC_ATTR(0, c->gicr_typer) |
+ (VGIC_LEVEL_INFO_LINE_LEVEL <<
+ KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT),
+ &c->level);
+ kvm_arm_gic_batch_add(entries, batch_n, batch_capacity,
+ KVM_DEV_ARM_VGIC_GRP_REDIST_REGS,
+ KVM_VGIC_ATTR(GICR_ISPENDR0, c->gicr_typer),
+ &c->gicr_ipendr0);
+ kvm_arm_gic_batch_add(entries, batch_n, batch_capacity,
+ KVM_DEV_ARM_VGIC_GRP_REDIST_REGS,
+ KVM_VGIC_ATTR(GICR_ISACTIVER0, c->gicr_typer),
+ &c->gicr_iactiver0);
+
+ for (int i = 0; i < GIC_INTERNAL; i += 4) {
+ kvm_arm_gic_batch_add(entries, batch_n, batch_capacity,
+ KVM_DEV_ARM_VGIC_GRP_REDIST_REGS,
+ KVM_VGIC_ATTR(GICR_IPRIORITYR + i,
+ c->gicr_typer),
+ &redist_priority[pri_base + i / 4]);
+ }
+ }
+ kvm_arm_gic_batch_commit(s->dev_fd, *entries, *batch_n, false);
+
+ /* Post-process redistributor results */
+ for (int ncpu = 0; ncpu < s->num_cpu; ncpu++) {
+ GICv3CPUState *c = &s->cpu[ncpu];
+ int pri_base = ncpu * (GIC_INTERNAL / 4);
+
+ c->edge_trigger = half_unshuffle32(c->edge_trigger >> 1) << 16;
+
+ for (int i = 0; i < GIC_INTERNAL; i += 4) {
+ uint32_t val = redist_priority[pri_base + i / 4];
+ c->gicr_ipriorityr[i] = extract32(val, 0, 8);
+ c->gicr_ipriorityr[i + 1] = extract32(val, 8, 8);
+ c->gicr_ipriorityr[i + 2] = extract32(val, 16, 8);
+ c->gicr_ipriorityr[i + 3] = extract32(val, 24, 8);
+ }
+ }
+
+ g_free(redist_priority);
+}
+
+/* Read the LPI base address registers in batches */
+static void kvm_arm_gic_batch_get_plpis(GICv3State *s,
+ GICv3BatchEntry **entries,
+ uint64_t redist_typer,
+ int *batch_n,
+ int *batch_capacity)
+{
+ if (!(redist_typer & GICR_TYPER_PLPIS)) {
+ return;
+ }
+
+ uint32_t *plpis = g_new(uint32_t, s->num_cpu * 4);
+
+ for (int ncpu = 0; ncpu < s->num_cpu; ncpu++) {
+ GICv3CPUState *c = &s->cpu[ncpu];
+ int base = ncpu * 4;
+
+ kvm_arm_gic_batch_add(entries, batch_n, batch_capacity,
+ KVM_DEV_ARM_VGIC_GRP_REDIST_REGS,
+ KVM_VGIC_ATTR(GICR_PROPBASER, c->gicr_typer),
+ &plpis[base]);
+ kvm_arm_gic_batch_add(entries, batch_n, batch_capacity,
+ KVM_DEV_ARM_VGIC_GRP_REDIST_REGS,
+ KVM_VGIC_ATTR(GICR_PROPBASER + 4, c->gicr_typer),
+ &plpis[base + 1]);
+ kvm_arm_gic_batch_add(entries, batch_n, batch_capacity,
+ KVM_DEV_ARM_VGIC_GRP_REDIST_REGS,
+ KVM_VGIC_ATTR(GICR_PENDBASER, c->gicr_typer),
+ &plpis[base + 2]);
+ kvm_arm_gic_batch_add(entries, batch_n, batch_capacity,
+ KVM_DEV_ARM_VGIC_GRP_REDIST_REGS,
+ KVM_VGIC_ATTR(GICR_PENDBASER + 4, c->gicr_typer),
+ &plpis[base + 3]);
+ }
+
+ kvm_arm_gic_batch_commit(s->dev_fd, *entries, *batch_n, false);
+
+ for (int ncpu = 0; ncpu < s->num_cpu; ncpu++) {
+ GICv3CPUState *c = &s->cpu[ncpu];
+ int base = ncpu * 4;
+
+ c->gicr_propbaser = ((uint64_t)plpis[base + 1] << 32) | plpis[base];
+ c->gicr_pendbaser = ((uint64_t)plpis[base + 3] << 32) | plpis[base +
2];
+ }
+
+ g_free(plpis);
+}
+
+/* Read the CPU interface basic registers in batches */
+static void kvm_arm_gic_batch_get_cpuif_basic(GICv3State *s,
+ GICv3BatchEntry **entries,
+ int *batch_n,
+ int *batch_capacity)
+{
+ uint32_t *cpuif_sre = g_new0(uint32_t, s->num_cpu);
+ uint32_t *cpuif_ctlr = g_new0(uint32_t, s->num_cpu);
+ uint32_t *cpuif_igrpen0 = g_new0(uint32_t, s->num_cpu);
+ uint32_t *cpuif_igrpen1 = g_new0(uint32_t, s->num_cpu);
+ uint32_t *cpuif_pmr = g_new0(uint32_t, s->num_cpu);
+ uint32_t *cpuif_bpr0 = g_new0(uint32_t, s->num_cpu);
+ uint32_t *cpuif_bpr1 = g_new0(uint32_t, s->num_cpu);
+
+ /* CPU Interface - basic registers */
+ for (int ncpu = 0; ncpu < s->num_cpu; ncpu++) {
+ GICv3CPUState *c = &s->cpu[ncpu];
+
+ cpuif_sre[ncpu] = c->icc_sre_el1;
+ kvm_arm_gic_batch_add(entries, batch_n, batch_capacity,
+ KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS,
+ KVM_VGIC_ATTR(ICC_SRE_EL1, c->gicr_typer),
+ &cpuif_sre[ncpu]);
+
+ cpuif_ctlr[ncpu] = c->icc_ctlr_el1[GICV3_NS];
+ kvm_arm_gic_batch_add(entries, batch_n, batch_capacity,
+ KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS,
+ KVM_VGIC_ATTR(ICC_CTLR_EL1, c->gicr_typer),
+ &cpuif_ctlr[ncpu]);
+
+ cpuif_igrpen0[ncpu] = c->icc_igrpen[GICV3_G0];
+ kvm_arm_gic_batch_add(entries, batch_n, batch_capacity,
+ KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS,
+ KVM_VGIC_ATTR(ICC_IGRPEN0_EL1, c->gicr_typer),
+ &cpuif_igrpen0[ncpu]);
+
+ cpuif_igrpen1[ncpu] = c->icc_igrpen[GICV3_G1NS];
+ kvm_arm_gic_batch_add(entries, batch_n, batch_capacity,
+ KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS,
+ KVM_VGIC_ATTR(ICC_IGRPEN1_EL1, c->gicr_typer),
+ &cpuif_igrpen1[ncpu]);
+
+ cpuif_pmr[ncpu] = c->icc_pmr_el1;
+ kvm_arm_gic_batch_add(entries, batch_n, batch_capacity,
+ KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS,
+ KVM_VGIC_ATTR(ICC_PMR_EL1, c->gicr_typer),
+ &cpuif_pmr[ncpu]);
+
+ cpuif_bpr0[ncpu] = c->icc_bpr[GICV3_G0];
+ kvm_arm_gic_batch_add(entries, batch_n, batch_capacity,
+ KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS,
+ KVM_VGIC_ATTR(ICC_BPR0_EL1, c->gicr_typer),
+ &cpuif_bpr0[ncpu]);
+
+ cpuif_bpr1[ncpu] = c->icc_bpr[GICV3_G1NS];
+ kvm_arm_gic_batch_add(entries, batch_n, batch_capacity,
+ KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS,
+ KVM_VGIC_ATTR(ICC_BPR1_EL1, c->gicr_typer),
+ &cpuif_bpr1[ncpu]);
+ }
+ kvm_arm_gic_batch_commit(s->dev_fd, *entries, *batch_n, false);
+
+ /* Copy back basic CPU interface registers */
+ for (int ncpu = 0; ncpu < s->num_cpu; ncpu++) {
+ GICv3CPUState *c = &s->cpu[ncpu];
+
+ c->icc_sre_el1 = cpuif_sre[ncpu];
+ c->icc_ctlr_el1[GICV3_NS] = cpuif_ctlr[ncpu];
+ c->icc_igrpen[GICV3_G0] = cpuif_igrpen0[ncpu];
+ c->icc_igrpen[GICV3_G1NS] = cpuif_igrpen1[ncpu];
+ c->icc_pmr_el1 = cpuif_pmr[ncpu];
+ c->icc_bpr[GICV3_G0] = cpuif_bpr0[ncpu];
+ c->icc_bpr[GICV3_G1NS] = cpuif_bpr1[ncpu];
+ }
+
+ g_free(cpuif_sre);
+ g_free(cpuif_ctlr);
+ g_free(cpuif_igrpen0);
+ g_free(cpuif_igrpen1);
+ g_free(cpuif_pmr);
+ g_free(cpuif_bpr0);
+ g_free(cpuif_bpr1);
+}
+
+/* Read the CPU Interface APR Registers in Batches */
+static void kvm_arm_gic_batch_get_cpuif_apr(GICv3State *s,
+ GICv3BatchEntry **entries,
+ int *batch_n,
+ int *batch_capacity)
+{
+ for (int ncpu = 0; ncpu < s->num_cpu; ncpu++) {
+ GICv3CPUState *c = &s->cpu[ncpu];
+ int num_pri_bits;
+
+ num_pri_bits = ((c->icc_ctlr_el1[GICV3_NS] &
+ ICC_CTLR_EL1_PRIBITS_MASK) >>
+ ICC_CTLR_EL1_PRIBITS_SHIFT) + 1;
+
+ /* Group 0 APR */
+ switch (num_pri_bits) {
+ case 7:
+ kvm_arm_gic_batch_add(entries, batch_n, batch_capacity,
+ KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS,
+ KVM_VGIC_ATTR(ICC_AP0R_EL1(3),
c->gicr_typer),
+ (uint32_t *)&c->icc_apr[GICV3_G0][3]);
+ kvm_arm_gic_batch_add(entries, batch_n, batch_capacity,
+ KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS,
+ KVM_VGIC_ATTR(ICC_AP0R_EL1(2),
c->gicr_typer),
+ (uint32_t *)&c->icc_apr[GICV3_G0][2]);
+ /* fall through */
+ case 6:
+ kvm_arm_gic_batch_add(entries, batch_n, batch_capacity,
+ KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS,
+ KVM_VGIC_ATTR(ICC_AP0R_EL1(1),
c->gicr_typer),
+ (uint32_t *)&c->icc_apr[GICV3_G0][1]);
+ /* fall through */
+ default:
+ kvm_arm_gic_batch_add(entries, batch_n, batch_capacity,
+ KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS,
+ KVM_VGIC_ATTR(ICC_AP0R_EL1(0),
c->gicr_typer),
+ (uint32_t *)&c->icc_apr[GICV3_G0][0]);
+ }
+
+ /* Group 1 APR */
+ switch (num_pri_bits) {
+ case 7:
+ kvm_arm_gic_batch_add(entries, batch_n, batch_capacity,
+ KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS,
+ KVM_VGIC_ATTR(ICC_AP1R_EL1(3),
c->gicr_typer),
+ (uint32_t *)&c->icc_apr[GICV3_G1NS][3]);
+ kvm_arm_gic_batch_add(entries, batch_n, batch_capacity,
+ KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS,
+ KVM_VGIC_ATTR(ICC_AP1R_EL1(2),
c->gicr_typer),
+ (uint32_t *)&c->icc_apr[GICV3_G1NS][2]);
+ /* fall through */
+ case 6:
+ kvm_arm_gic_batch_add(entries, batch_n, batch_capacity,
+ KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS,
+ KVM_VGIC_ATTR(ICC_AP1R_EL1(1),
c->gicr_typer),
+ (uint32_t *)&c->icc_apr[GICV3_G1NS][1]);
+ /* fall through */
+ default:
+ kvm_arm_gic_batch_add(entries, batch_n, batch_capacity,
+ KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS,
+ KVM_VGIC_ATTR(ICC_AP1R_EL1(0),
c->gicr_typer),
+ (uint32_t *)&c->icc_apr[GICV3_G1NS][0]);
+ }
+ }
+ kvm_arm_gic_batch_commit(s->dev_fd, *entries, *batch_n, false);
+}
+
static void kvm_arm_gicv3_get(GICv3State *s)
{
uint32_t regl, regh, reg;
uint64_t reg64, redist_typer;
int ncpu, i;
+ bool batch_supported;
int64_t start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
kvm_arm_gicv3_check(s);
@@ -939,58 +1221,80 @@ static void kvm_arm_gicv3_get(GICv3State *s)
kvm_gicd_access(s, GICD_CTLR, ®, false);
s->gicd_ctlr = reg;
- /* Redistributor state (one per CPU) */
+ /* Check whether the kernel supports batch operations */
+ batch_supported = kvm_arm_gic_batch_supported(s->dev_fd);
- for (ncpu = 0; ncpu < s->num_cpu; ncpu++) {
- GICv3CPUState *c = &s->cpu[ncpu];
+ if (batch_supported) {
+ {
+ GICv3BatchEntry *entries = g_new(GICv3BatchEntry, 256);
+ int batch_n = 0;
+ int batch_capacity = 256;
- kvm_gicr_access(s, GICR_CTLR, ncpu, ®, false);
- c->gicr_ctlr = reg;
-
- kvm_gicr_access(s, GICR_STATUSR, ncpu, ®, false);
- c->gicr_statusr[GICV3_NS] = reg;
-
- kvm_gicr_access(s, GICR_WAKER, ncpu, ®, false);
- c->gicr_waker = reg;
-
- kvm_gicr_access(s, GICR_IGROUPR0, ncpu, ®, false);
- c->gicr_igroupr0 = reg;
- kvm_gicr_access(s, GICR_ISENABLER0, ncpu, ®, false);
- c->gicr_ienabler0 = reg;
- kvm_gicr_access(s, GICR_ICFGR1, ncpu, ®, false);
- c->edge_trigger = half_unshuffle32(reg >> 1) << 16;
- kvm_gic_line_level_access(s, 0, ncpu, ®, false);
- c->level = reg;
- kvm_gicr_access(s, GICR_ISPENDR0, ncpu, ®, false);
- c->gicr_ipendr0 = reg;
- kvm_gicr_access(s, GICR_ISACTIVER0, ncpu, ®, false);
- c->gicr_iactiver0 = reg;
-
- for (i = 0; i < GIC_INTERNAL; i += 4) {
- kvm_gicr_access(s, GICR_IPRIORITYR + i, ncpu, ®, false);
- c->gicr_ipriorityr[i] = extract32(reg, 0, 8);
- c->gicr_ipriorityr[i + 1] = extract32(reg, 8, 8);
- c->gicr_ipriorityr[i + 2] = extract32(reg, 16, 8);
- c->gicr_ipriorityr[i + 3] = extract32(reg, 24, 8);
- }
- }
+ /* Redistributor state (one per CPU) */
+ kvm_arm_gic_batch_get_redist(s, &entries, &batch_n,
+ &batch_capacity);
+
+ /* reset batch_n */
+ batch_n = 0;
+
+ /* PLPIS */
+ kvm_arm_gic_batch_get_plpis(s, &entries, redist_typer,
+ &batch_n, &batch_capacity);
- if (redist_typer & GICR_TYPER_PLPIS) {
+ g_free(entries);
+ }
+ } else {
+ /* Redistributor state (one per CPU) */
for (ncpu = 0; ncpu < s->num_cpu; ncpu++) {
GICv3CPUState *c = &s->cpu[ncpu];
- kvm_gicr_access(s, GICR_PROPBASER, ncpu, ®l, false);
- kvm_gicr_access(s, GICR_PROPBASER + 4, ncpu, ®h, false);
- c->gicr_propbaser = ((uint64_t)regh << 32) | regl;
+ kvm_gicr_access(s, GICR_CTLR, ncpu, ®, false);
+ c->gicr_ctlr = reg;
+
+ kvm_gicr_access(s, GICR_STATUSR, ncpu, ®, false);
+ c->gicr_statusr[GICV3_NS] = reg;
+
+ kvm_gicr_access(s, GICR_WAKER, ncpu, ®, false);
+ c->gicr_waker = reg;
+
+ kvm_gicr_access(s, GICR_IGROUPR0, ncpu, ®, false);
+ c->gicr_igroupr0 = reg;
+ kvm_gicr_access(s, GICR_ISENABLER0, ncpu, ®, false);
+ c->gicr_ienabler0 = reg;
+ kvm_gicr_access(s, GICR_ICFGR1, ncpu, ®, false);
+ c->edge_trigger = half_unshuffle32(reg >> 1) << 16;
+ kvm_gic_line_level_access(s, 0, ncpu, ®, false);
+ c->level = reg;
+ kvm_gicr_access(s, GICR_ISPENDR0, ncpu, ®, false);
+ c->gicr_ipendr0 = reg;
+ kvm_gicr_access(s, GICR_ISACTIVER0, ncpu, ®, false);
+ c->gicr_iactiver0 = reg;
+
+ for (i = 0; i < GIC_INTERNAL; i += 4) {
+ kvm_gicr_access(s, GICR_IPRIORITYR + i, ncpu, ®, false);
+ c->gicr_ipriorityr[i] = extract32(reg, 0, 8);
+ c->gicr_ipriorityr[i + 1] = extract32(reg, 8, 8);
+ c->gicr_ipriorityr[i + 2] = extract32(reg, 16, 8);
+ c->gicr_ipriorityr[i + 3] = extract32(reg, 24, 8);
+ }
+ }
+
+ if (redist_typer & GICR_TYPER_PLPIS) {
+ for (ncpu = 0; ncpu < s->num_cpu; ncpu++) {
+ GICv3CPUState *c = &s->cpu[ncpu];
- kvm_gicr_access(s, GICR_PENDBASER, ncpu, ®l, false);
- kvm_gicr_access(s, GICR_PENDBASER + 4, ncpu, ®h, false);
- c->gicr_pendbaser = ((uint64_t)regh << 32) | regl;
+ kvm_gicr_access(s, GICR_PROPBASER, ncpu, ®l, false);
+ kvm_gicr_access(s, GICR_PROPBASER + 4, ncpu, ®h, false);
+ c->gicr_propbaser = ((uint64_t)regh << 32) | regl;
+
+ kvm_gicr_access(s, GICR_PENDBASER, ncpu, ®l, false);
+ kvm_gicr_access(s, GICR_PENDBASER + 4, ncpu, ®h, false);
+ c->gicr_pendbaser = ((uint64_t)regh << 32) | regl;
+ }
}
}
/* Distributor state (shared between all CPUs */
-
kvm_gicd_access(s, GICD_STATUSR, ®, false);
s->gicd_statusr[GICV3_NS] = reg;
@@ -1025,58 +1329,78 @@ static void kvm_arm_gicv3_get(GICv3State *s)
s->gicd_irouter[i] = ((uint64_t)regh << 32) | regl;
}
- /*****************************************************************
- * CPU Interface(s) State
- */
+ /* CPU Interface(s) State */
+ if (batch_supported) {
+ {
+ GICv3BatchEntry *entries = g_new(GICv3BatchEntry, 256);
+ int batch_n = 0;
+ int batch_capacity = 256;
- for (ncpu = 0; ncpu < s->num_cpu; ncpu++) {
- GICv3CPUState *c = &s->cpu[ncpu];
- int num_pri_bits;
+ /* CPU Interface - basic registers */
+ kvm_arm_gic_batch_get_cpuif_basic(s, &entries, &batch_n,
+ &batch_capacity);
- kvm_gicc_access(s, ICC_SRE_EL1, ncpu, &c->icc_sre_el1, false);
- kvm_gicc_access(s, ICC_CTLR_EL1, ncpu,
- &c->icc_ctlr_el1[GICV3_NS], false);
- kvm_gicc_access(s, ICC_IGRPEN0_EL1, ncpu,
- &c->icc_igrpen[GICV3_G0], false);
- kvm_gicc_access(s, ICC_IGRPEN1_EL1, ncpu,
- &c->icc_igrpen[GICV3_G1NS], false);
- kvm_gicc_access(s, ICC_PMR_EL1, ncpu, &c->icc_pmr_el1, false);
- kvm_gicc_access(s, ICC_BPR0_EL1, ncpu, &c->icc_bpr[GICV3_G0], false);
- kvm_gicc_access(s, ICC_BPR1_EL1, ncpu, &c->icc_bpr[GICV3_G1NS], false);
- num_pri_bits = ((c->icc_ctlr_el1[GICV3_NS] &
- ICC_CTLR_EL1_PRIBITS_MASK) >>
- ICC_CTLR_EL1_PRIBITS_SHIFT) + 1;
+ /* reset batch_n */
+ batch_n = 0;
- switch (num_pri_bits) {
- case 7:
- kvm_gicc_access(s, ICC_AP0R_EL1(3), ncpu, ®64, false);
- c->icc_apr[GICV3_G0][3] = reg64;
- kvm_gicc_access(s, ICC_AP0R_EL1(2), ncpu, ®64, false);
- c->icc_apr[GICV3_G0][2] = reg64;
- /* fall through */
- case 6:
- kvm_gicc_access(s, ICC_AP0R_EL1(1), ncpu, ®64, false);
- c->icc_apr[GICV3_G0][1] = reg64;
- /* fall through */
- default:
- kvm_gicc_access(s, ICC_AP0R_EL1(0), ncpu, ®64, false);
- c->icc_apr[GICV3_G0][0] = reg64;
+ /* CPU Interface - APR registers */
+ kvm_arm_gic_batch_get_cpuif_apr(s, &entries, &batch_n,
+ &batch_capacity);
+
+ g_free(entries);
}
+ } else {
+ for (ncpu = 0; ncpu < s->num_cpu; ncpu++) {
+ GICv3CPUState *c = &s->cpu[ncpu];
+ int num_pri_bits;
- switch (num_pri_bits) {
- case 7:
- kvm_gicc_access(s, ICC_AP1R_EL1(3), ncpu, ®64, false);
- c->icc_apr[GICV3_G1NS][3] = reg64;
- kvm_gicc_access(s, ICC_AP1R_EL1(2), ncpu, ®64, false);
- c->icc_apr[GICV3_G1NS][2] = reg64;
- /* fall through */
- case 6:
- kvm_gicc_access(s, ICC_AP1R_EL1(1), ncpu, ®64, false);
- c->icc_apr[GICV3_G1NS][1] = reg64;
- /* fall through */
- default:
- kvm_gicc_access(s, ICC_AP1R_EL1(0), ncpu, ®64, false);
- c->icc_apr[GICV3_G1NS][0] = reg64;
+ kvm_gicc_access(s, ICC_SRE_EL1, ncpu, &c->icc_sre_el1, false);
+ kvm_gicc_access(s, ICC_CTLR_EL1, ncpu,
+ &c->icc_ctlr_el1[GICV3_NS], false);
+ kvm_gicc_access(s, ICC_IGRPEN0_EL1, ncpu,
+ &c->icc_igrpen[GICV3_G0], false);
+ kvm_gicc_access(s, ICC_IGRPEN1_EL1, ncpu,
+ &c->icc_igrpen[GICV3_G1NS], false);
+ kvm_gicc_access(s, ICC_PMR_EL1, ncpu, &c->icc_pmr_el1, false);
+ kvm_gicc_access(s, ICC_BPR0_EL1, ncpu, &c->icc_bpr[GICV3_G0],
+ false);
+ kvm_gicc_access(s, ICC_BPR1_EL1, ncpu, &c->icc_bpr[GICV3_G1NS],
+ false);
+ num_pri_bits = ((c->icc_ctlr_el1[GICV3_NS] &
+ ICC_CTLR_EL1_PRIBITS_MASK) >>
+ ICC_CTLR_EL1_PRIBITS_SHIFT) + 1;
+
+ switch (num_pri_bits) {
+ case 7:
+ kvm_gicc_access(s, ICC_AP0R_EL1(3), ncpu, ®64, false);
+ c->icc_apr[GICV3_G0][3] = reg64;
+ kvm_gicc_access(s, ICC_AP0R_EL1(2), ncpu, ®64, false);
+ c->icc_apr[GICV3_G0][2] = reg64;
+ /* fall through */
+ case 6:
+ kvm_gicc_access(s, ICC_AP0R_EL1(1), ncpu, ®64, false);
+ c->icc_apr[GICV3_G0][1] = reg64;
+ /* fall through */
+ default:
+ kvm_gicc_access(s, ICC_AP0R_EL1(0), ncpu, ®64, false);
+ c->icc_apr[GICV3_G0][0] = reg64;
+ }
+
+ switch (num_pri_bits) {
+ case 7:
+ kvm_gicc_access(s, ICC_AP1R_EL1(3), ncpu, ®64, false);
+ c->icc_apr[GICV3_G1NS][3] = reg64;
+ kvm_gicc_access(s, ICC_AP1R_EL1(2), ncpu, ®64, false);
+ c->icc_apr[GICV3_G1NS][2] = reg64;
+ /* fall through */
+ case 6:
+ kvm_gicc_access(s, ICC_AP1R_EL1(1), ncpu, ®64, false);
+ c->icc_apr[GICV3_G1NS][1] = reg64;
+ /* fall through */
+ default:
+ kvm_gicc_access(s, ICC_AP1R_EL1(0), ncpu, ®64, false);
+ c->icc_apr[GICV3_G1NS][0] = reg64;
+ }
}
}
int64_t end_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
--
2.43.0