Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20210330' into staging

 * net/npcm7xx_emc.c: Fix handling of receiving packets when RSDR not set
 * hw/display/xlnx_dp: Free FIFOs adding xlnx_dp_finalize()
 * hw/arm/smmuv3: Drop unused CDM_VALID() and is_cd_valid()
 * target/arm: Make number of counters in PMCR follow the CPU
 * hw/timer/renesas_tmr: Add default-case asserts in read_tcnt()

# gpg: Signature made Tue 30 Mar 2021 14:23:33 BST
# gpg:                using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE
# gpg:                issuer "peter.maydell@linaro.org"
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [ultimate]
# gpg:                 aka "Peter Maydell <pmaydell@gmail.com>" [ultimate]
# gpg:                 aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [ultimate]
# Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83  15CF 3C25 25ED 1436 0CDE

* remotes/pmaydell/tags/pull-target-arm-20210330:
  hw/timer/renesas_tmr: Add default-case asserts in read_tcnt()
  target/arm: Make number of counters in PMCR follow the CPU
  hw/arm/smmuv3: Drop unused CDM_VALID() and is_cd_valid()
  hw/display/xlnx_dp: Free FIFOs adding xlnx_dp_finalize()
  net/npcm7xx_emc.c: Fix handling of receiving packets when RSDR not set

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
index b6f7e53..3dac576 100644
--- a/hw/arm/smmuv3-internal.h
+++ b/hw/arm/smmuv3-internal.h
@@ -595,13 +595,6 @@
 #define CD_A(x)          extract32((x)->word[1], 14, 1)
 #define CD_AARCH64(x)    extract32((x)->word[1], 9 , 1)
 
-#define CDM_VALID(x)    ((x)->word[0] & 0x1)
-
-static inline int is_cd_valid(SMMUv3State *s, STE *ste, CD *cd)
-{
-    return CD_VALID(cd);
-}
-
 /**
  * tg2granule - Decodes the CD translation granule size field according
  * to the ttbr in use
diff --git a/hw/display/xlnx_dp.c b/hw/display/xlnx_dp.c
index c56e6ec..4fd6aeb 100644
--- a/hw/display/xlnx_dp.c
+++ b/hw/display/xlnx_dp.c
@@ -1260,6 +1260,14 @@
     fifo8_create(&s->tx_fifo, 16);
 }
 
+static void xlnx_dp_finalize(Object *obj)
+{
+    XlnxDPState *s = XLNX_DP(obj);
+
+    fifo8_destroy(&s->tx_fifo);
+    fifo8_destroy(&s->rx_fifo);
+}
+
 static void xlnx_dp_realize(DeviceState *dev, Error **errp)
 {
     XlnxDPState *s = XLNX_DP(dev);
@@ -1359,6 +1367,7 @@
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(XlnxDPState),
     .instance_init = xlnx_dp_init,
+    .instance_finalize = xlnx_dp_finalize,
     .class_init    = xlnx_dp_class_init,
 };
 
diff --git a/hw/net/npcm7xx_emc.c b/hw/net/npcm7xx_emc.c
index 714a742..7c892f8 100644
--- a/hw/net/npcm7xx_emc.c
+++ b/hw/net/npcm7xx_emc.c
@@ -702,7 +702,9 @@
                    !(value & REG_MCMDR_RXON)) {
             emc->regs[REG_MGSTA] |= REG_MGSTA_RXHA;
         }
-        if (!(value & REG_MCMDR_RXON)) {
+        if (value & REG_MCMDR_RXON) {
+            emc->rx_active = true;
+        } else {
             emc_halt_rx(emc, 0);
         }
         break;
diff --git a/hw/timer/renesas_tmr.c b/hw/timer/renesas_tmr.c
index eed3991..d96002e 100644
--- a/hw/timer/renesas_tmr.c
+++ b/hw/timer/renesas_tmr.c
@@ -146,6 +146,8 @@
         case CSS_CASCADING:
             tcnt[1] = tmr->tcnt[1];
             break;
+        default:
+            g_assert_not_reached();
         }
         switch (FIELD_EX8(tmr->tccr[0], TCCR, CSS)) {
         case CSS_INTERNAL:
@@ -159,6 +161,8 @@
         case CSS_EXTERNAL: /* QEMU doesn't implement this */
             tcnt[0] = tmr->tcnt[0];
             break;
+        default:
+            g_assert_not_reached();
         }
     } else {
         tcnt[0] = tmr->tcnt[0];
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 193a49e..fe68f46 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -942,6 +942,7 @@
         uint64_t id_aa64mmfr2;
         uint64_t id_aa64dfr0;
         uint64_t id_aa64dfr1;
+        uint64_t reset_pmcr_el0;
     } isar;
     uint64_t midr;
     uint32_t revidr;
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index f0a9e96..5d9d56a 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -141,6 +141,7 @@
     cpu->gic_num_lrs = 4;
     cpu->gic_vpribits = 5;
     cpu->gic_vprebits = 5;
+    cpu->isar.reset_pmcr_el0 = 0x41013000;
     define_arm_cp_regs(cpu, cortex_a72_a57_a53_cp_reginfo);
 }
 
@@ -194,6 +195,7 @@
     cpu->gic_num_lrs = 4;
     cpu->gic_vpribits = 5;
     cpu->gic_vprebits = 5;
+    cpu->isar.reset_pmcr_el0 = 0x41033000;
     define_arm_cp_regs(cpu, cortex_a72_a57_a53_cp_reginfo);
 }
 
@@ -245,6 +247,7 @@
     cpu->gic_num_lrs = 4;
     cpu->gic_vpribits = 5;
     cpu->gic_vprebits = 5;
+    cpu->isar.reset_pmcr_el0 = 0x41023000;
     define_arm_cp_regs(cpu, cortex_a72_a57_a53_cp_reginfo);
 }
 
diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c
index 046e476..8252fd2 100644
--- a/target/arm/cpu_tcg.c
+++ b/target/arm/cpu_tcg.c
@@ -301,6 +301,7 @@
     cpu->ccsidr[1] = 0x2007e01a; /* 16k L1 icache. */
     cpu->ccsidr[2] = 0xf0000000; /* No L2 icache. */
     cpu->reset_auxcr = 2;
+    cpu->isar.reset_pmcr_el0 = 0x41002000;
     define_arm_cp_regs(cpu, cortexa8_cp_reginfo);
 }
 
@@ -373,6 +374,7 @@
     cpu->clidr = (1 << 27) | (1 << 24) | 3;
     cpu->ccsidr[0] = 0xe00fe019; /* 16k L1 dcache. */
     cpu->ccsidr[1] = 0x200fe019; /* 16k L1 icache. */
+    cpu->isar.reset_pmcr_el0 = 0x41093000;
     define_arm_cp_regs(cpu, cortexa9_cp_reginfo);
 }
 
@@ -443,6 +445,7 @@
     cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */
     cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */
     cpu->ccsidr[2] = 0x711fe07a; /* 4096K L2 unified cache */
+    cpu->isar.reset_pmcr_el0 = 0x41072000;
     define_arm_cp_regs(cpu, cortexa15_cp_reginfo); /* Same as A15 */
 }
 
@@ -485,6 +488,7 @@
     cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */
     cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */
     cpu->ccsidr[2] = 0x711fe07a; /* 4096K L2 unified cache */
+    cpu->isar.reset_pmcr_el0 = 0x410F3000;
     define_arm_cp_regs(cpu, cortexa15_cp_reginfo);
 }
 
@@ -717,6 +721,7 @@
     cpu->isar.id_isar6 = 0x0;
     cpu->mp_is_up = true;
     cpu->pmsav7_dregion = 16;
+    cpu->isar.reset_pmcr_el0 = 0x41151800;
     define_arm_cp_regs(cpu, cortexr5_cp_reginfo);
 }
 
diff --git a/target/arm/helper.c b/target/arm/helper.c
index d9220be..8fb6cc9 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -38,7 +38,6 @@
 #endif
 
 #define ARM_CPU_FREQ 1000000000 /* FIXME: 1 GHz, should be configurable */
-#define PMCR_NUM_COUNTERS 4 /* QEMU IMPDEF choice */
 
 #ifndef CONFIG_USER_ONLY
 
@@ -1149,7 +1148,9 @@
 
 static inline uint32_t pmu_num_counters(CPUARMState *env)
 {
-  return (env->cp15.c9_pmcr & PMCRN_MASK) >> PMCRN_SHIFT;
+    ARMCPU *cpu = env_archcpu(env);
+
+    return (cpu->isar.reset_pmcr_el0 & PMCRN_MASK) >> PMCRN_SHIFT;
 }
 
 /* Bits allowed to be set/cleared for PMCNTEN* and PMINTEN* */
@@ -5753,13 +5754,6 @@
       .resetvalue = 0,
       .writefn = gt_hyp_ctl_write, .raw_writefn = raw_write },
 #endif
-    /* The only field of MDCR_EL2 that has a defined architectural reset value
-     * is MDCR_EL2.HPMN which should reset to the value of PMCR_EL0.N.
-     */
-    { .name = "MDCR_EL2", .state = ARM_CP_STATE_BOTH,
-      .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 1,
-      .access = PL2_RW, .resetvalue = PMCR_NUM_COUNTERS,
-      .fieldoffset = offsetof(CPUARMState, cp15.mdcr_el2), },
     { .name = "HPFAR", .state = ARM_CP_STATE_AA32,
       .cp = 15, .opc1 = 4, .crn = 6, .crm = 0, .opc2 = 4,
       .access = PL2_RW, .accessfn = access_el3_aa32ns,
@@ -6689,7 +6683,7 @@
      * field as main ID register, and we implement four counters in
      * addition to the cycle count register.
      */
-    unsigned int i, pmcrn = PMCR_NUM_COUNTERS;
+    unsigned int i, pmcrn = pmu_num_counters(&cpu->env);
     ARMCPRegInfo pmcr = {
         .name = "PMCR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 0,
         .access = PL0_RW,
@@ -6704,10 +6698,10 @@
         .access = PL0_RW, .accessfn = pmreg_access,
         .type = ARM_CP_IO,
         .fieldoffset = offsetof(CPUARMState, cp15.c9_pmcr),
-        .resetvalue = (cpu->midr & 0xff000000) | (pmcrn << PMCRN_SHIFT) |
-                      PMCRLC,
+        .resetvalue = cpu->isar.reset_pmcr_el0,
         .writefn = pmcr_write, .raw_writefn = raw_write,
     };
+
     define_one_arm_cp_reg(cpu, &pmcr);
     define_one_arm_cp_reg(cpu, &pmcr64);
     for (i = 0; i < pmcrn; i++) {
@@ -7825,6 +7819,17 @@
               .fieldoffset = offsetof(CPUARMState, cp15.vmpidr_el2) },
             REGINFO_SENTINEL
         };
+        /*
+         * The only field of MDCR_EL2 that has a defined architectural reset
+         * value is MDCR_EL2.HPMN which should reset to the value of PMCR_EL0.N.
+         */
+        ARMCPRegInfo mdcr_el2 = {
+            .name = "MDCR_EL2", .state = ARM_CP_STATE_BOTH,
+            .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 1,
+            .access = PL2_RW, .resetvalue = pmu_num_counters(env),
+            .fieldoffset = offsetof(CPUARMState, cp15.mdcr_el2),
+        };
+        define_one_arm_cp_reg(cpu, &mdcr_el2);
         define_arm_cp_regs(cpu, vpidr_regs);
         define_arm_cp_regs(cpu, el2_cp_reginfo);
         if (arm_feature(env, ARM_FEATURE_V8)) {
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
index dff85f6..581335e 100644
--- a/target/arm/kvm64.c
+++ b/target/arm/kvm64.c
@@ -566,6 +566,8 @@
                               ARM64_SYS_REG(3, 0, 0, 7, 1));
         err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr2,
                               ARM64_SYS_REG(3, 0, 0, 7, 2));
+        err |= read_sys_reg64(fdarray[2], &ahcf->isar.reset_pmcr_el0,
+                              ARM64_SYS_REG(3, 3, 9, 12, 0));
 
         /*
          * Note that if AArch32 support is not present in the host,
diff --git a/tests/qtest/npcm7xx_emc-test.c b/tests/qtest/npcm7xx_emc-test.c
index 7a28173..9eec71d 100644
--- a/tests/qtest/npcm7xx_emc-test.c
+++ b/tests/qtest/npcm7xx_emc-test.c
@@ -492,9 +492,6 @@
         mcmdr |= REG_MCMDR_TXON;
         emc_write(qts, mod, REG_MCMDR, mcmdr);
     }
-
-    /* Prod the device to send the packet. */
-    emc_write(qts, mod, REG_TSDR, 1);
 }
 
 static void emc_send_verify1(QTestState *qts, const EMCModule *mod, int fd,
@@ -558,6 +555,9 @@
     enable_tx(qts, mod, &desc[0], NUM_TX_DESCRIPTORS, desc_addr,
               with_irq ? REG_MIEN_ENTXINTR : 0);
 
+    /* Prod the device to send the packet. */
+    emc_write(qts, mod, REG_TSDR, 1);
+
     /*
      * It's problematic to observe the interrupt for each packet.
      * Instead just wait until all the packets go out.
@@ -643,13 +643,10 @@
         mcmdr |= REG_MCMDR_RXON | mcmdr_flags;
         emc_write(qts, mod, REG_MCMDR, mcmdr);
     }
-
-    /* Prod the device to accept a packet. */
-    emc_write(qts, mod, REG_RSDR, 1);
 }
 
 static void emc_recv_verify(QTestState *qts, const EMCModule *mod, int fd,
-                            bool with_irq)
+                            bool with_irq, bool pump_rsdr)
 {
     NPCM7xxEMCRxDesc desc[NUM_RX_DESCRIPTORS];
     uint32_t desc_addr = DESC_ADDR;
@@ -679,6 +676,15 @@
     enable_rx(qts, mod, &desc[0], NUM_RX_DESCRIPTORS, desc_addr,
               with_irq ? REG_MIEN_ENRXINTR : 0, 0);
 
+    /*
+     * If requested, prod the device to accept a packet.
+     * This isn't necessary, the linux driver doesn't do this.
+     * Test doing/not-doing this for robustness.
+     */
+    if (pump_rsdr) {
+        emc_write(qts, mod, REG_RSDR, 1);
+    }
+
     /* Send test packet to device's socket. */
     ret = iov_send(fd, iov, 2, 0, sizeof(len) + sizeof(test));
     g_assert_cmpint(ret, == , sizeof(test) + sizeof(len));
@@ -826,8 +832,14 @@
 
     qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
 
-    emc_recv_verify(qts, td->module, test_sockets[0], /*with_irq=*/false);
-    emc_recv_verify(qts, td->module, test_sockets[0], /*with_irq=*/true);
+    emc_recv_verify(qts, td->module, test_sockets[0], /*with_irq=*/false,
+                    /*pump_rsdr=*/false);
+    emc_recv_verify(qts, td->module, test_sockets[0], /*with_irq=*/false,
+                    /*pump_rsdr=*/true);
+    emc_recv_verify(qts, td->module, test_sockets[0], /*with_irq=*/true,
+                    /*pump_rsdr=*/false);
+    emc_recv_verify(qts, td->module, test_sockets[0], /*with_irq=*/true,
+                    /*pump_rsdr=*/true);
     emc_test_ptle(qts, td->module, test_sockets[0]);
 
     qtest_quit(qts);