mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-07 09:43:56 -06:00
target-arm queue:
* Fix physical address resolution for Stage2 * pl011: refactoring, implement reset method * Support GICv3 with hvf acceleration * sbsa-ref: remove cortex-a76 from list of supported cpus * Correct syndrome for ATS12NSO* traps at Secure EL1 * Fix priority of HSTR_EL2 traps vs UNDEFs * Implement FEAT_FGT for '-cpu max' -----BEGIN PGP SIGNATURE----- iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmPdGisZHHBldGVyLm1h eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3iTND/4qnI00PcqPhdZAD083admx Tn+7OaTd8aaWHDMvbnV3fNsvAEt//j8DdzeBGDLbgfhBuOCPB8z7oDSr7oqczmys Yjnh25o6IDUYtMnKR+dBwFKGvAqWwM4UdEllkHJvvM+QpnlH7iu9lCkgYr6PvBYA h4ajfZ5J7C2OmFJZqsKa2Ot3mveFxos1QzgWSmsWNGTJiZTOCiD7AvuCnEsBBaVP pESY+5eGjVmjv6ocHxcHG4LA456bHAf6JiCgKqgwowRBlJenpsnNgKleIN4gQA/J wtfLALNe6FkTV9tzK/MgtO1qOhxkUHrnTrYTtTLmk4H1VryFdDvomYB34zBIgfMY l1LmMba6UCoxtck13D5jv1xkE56o7Z3kqrhyOvP+aHFdi+dvYQ/z+b8pqUeYeSiu EbVWa/270JwVdbBT08vfW33Ci9n7fxZtRCrvj2viMgOiQOKwXYEb5AVxM9TRZSKC Y+1m5frW2HQ+KNvjEyHdMJ8q4nFhaS5Bq2A2RMaQCV2QBuBJvFkGL3ul6M0lw/eq cAZDKN6H/8N2l2DPcPHUy6RMiqUPSnemvFI814ElKeHGa1V1c7Iw9C4lWAV5Ue5E gotHC1ros89xV0Eg0gaB9UgX8TgbQUfc3g1g6YUvTCfQdvxL0H1rY+wUWU1h1V2r VdhxI95gUkgmoVnk8KnwIw== =hk0j -----END PGP SIGNATURE----- Merge tag 'pull-target-arm-20230203' of https://git.linaro.org/people/pmaydell/qemu-arm into staging target-arm queue: * Fix physical address resolution for Stage2 * pl011: refactoring, implement reset method * Support GICv3 with hvf acceleration * sbsa-ref: remove cortex-a76 from list of supported cpus * Correct syndrome for ATS12NSO* traps at Secure EL1 * Fix priority of HSTR_EL2 traps vs UNDEFs * Implement FEAT_FGT for '-cpu max' # -----BEGIN PGP SIGNATURE----- # # iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmPdGisZHHBldGVyLm1h # eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3iTND/4qnI00PcqPhdZAD083admx # Tn+7OaTd8aaWHDMvbnV3fNsvAEt//j8DdzeBGDLbgfhBuOCPB8z7oDSr7oqczmys # Yjnh25o6IDUYtMnKR+dBwFKGvAqWwM4UdEllkHJvvM+QpnlH7iu9lCkgYr6PvBYA # h4ajfZ5J7C2OmFJZqsKa2Ot3mveFxos1QzgWSmsWNGTJiZTOCiD7AvuCnEsBBaVP # pESY+5eGjVmjv6ocHxcHG4LA456bHAf6JiCgKqgwowRBlJenpsnNgKleIN4gQA/J # wtfLALNe6FkTV9tzK/MgtO1qOhxkUHrnTrYTtTLmk4H1VryFdDvomYB34zBIgfMY # l1LmMba6UCoxtck13D5jv1xkE56o7Z3kqrhyOvP+aHFdi+dvYQ/z+b8pqUeYeSiu # EbVWa/270JwVdbBT08vfW33Ci9n7fxZtRCrvj2viMgOiQOKwXYEb5AVxM9TRZSKC # Y+1m5frW2HQ+KNvjEyHdMJ8q4nFhaS5Bq2A2RMaQCV2QBuBJvFkGL3ul6M0lw/eq # cAZDKN6H/8N2l2DPcPHUy6RMiqUPSnemvFI814ElKeHGa1V1c7Iw9C4lWAV5Ue5E # gotHC1ros89xV0Eg0gaB9UgX8TgbQUfc3g1g6YUvTCfQdvxL0H1rY+wUWU1h1V2r # VdhxI95gUkgmoVnk8KnwIw== # =hk0j # -----END PGP SIGNATURE----- # gpg: Signature made Fri 03 Feb 2023 14:28:59 GMT # 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] # gpg: aka "Peter Maydell <peter@archaic.org.uk>" [ultimate] # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * tag 'pull-target-arm-20230203' of https://git.linaro.org/people/pmaydell/qemu-arm: (33 commits) target/arm: Enable FEAT_FGT on '-cpu max' target/arm: Implement MDCR_EL2.TDCC and MDCR_EL3.TDCC traps target/arm: Implement the HFGITR_EL2.SVC_EL0 and SVC_EL1 traps target/arm: Implement the HFGITR_EL2.ERET trap target/arm: Mark up sysregs for HFGITR bits 48..63 target/arm: Mark up sysregs for HFGITR bits 18..47 target/arm: Mark up sysregs for HFGITR bits 12..17 target/arm: Mark up sysregs for HFGITR bits 0..11 target/arm: Mark up sysregs for HDFGRTR bits 12..63 target/arm: Mark up sysregs for HDFGRTR bits 0..11 target/arm: Mark up sysregs for HFGRTR bits 36..63 target/arm: Mark up sysregs for HFGRTR bits 24..35 target/arm: Mark up sysregs for HFGRTR bits 12..23 target/arm: Mark up sysregs for HFGRTR bits 0..11 target/arm: Implement FGT trapping infrastructure target/arm: Define the FEAT_FGT registers target/arm: Disable HSTR_EL2 traps if EL2 is not enabled target/arm: Make HSTR_EL2 traps take priority over UNDEF-at-EL1 target/arm: All UNDEF-at-EL0 traps take priority over HSTR_EL2 traps target/arm: Move do_coproc_insn() syndrome calculation earlier ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
0730eab4d3
21 changed files with 1340 additions and 189 deletions
|
@ -29,6 +29,7 @@
|
|||
#include "exec/hwaddr.h"
|
||||
#include "kvm_arm.h"
|
||||
#include "hw/arm/boot.h"
|
||||
#include "hw/arm/smmuv3.h"
|
||||
#include "hw/block/flash.h"
|
||||
#include "hw/boards.h"
|
||||
#include "hw/ide/internal.h"
|
||||
|
@ -145,7 +146,6 @@ static const int sbsa_ref_irqmap[] = {
|
|||
static const char * const valid_cpus[] = {
|
||||
ARM_CPU_TYPE_NAME("cortex-a57"),
|
||||
ARM_CPU_TYPE_NAME("cortex-a72"),
|
||||
ARM_CPU_TYPE_NAME("cortex-a76"),
|
||||
ARM_CPU_TYPE_NAME("neoverse-n1"),
|
||||
ARM_CPU_TYPE_NAME("max"),
|
||||
};
|
||||
|
@ -574,7 +574,7 @@ static void create_smmu(const SBSAMachineState *sms, PCIBus *bus)
|
|||
DeviceState *dev;
|
||||
int i;
|
||||
|
||||
dev = qdev_new("arm-smmuv3");
|
||||
dev = qdev_new(TYPE_ARM_SMMUV3);
|
||||
|
||||
object_property_set_link(OBJECT(dev), "primary-bus", OBJECT(bus),
|
||||
&error_abort);
|
||||
|
|
203
hw/arm/virt.c
203
hw/arm/virt.c
|
@ -47,8 +47,10 @@
|
|||
#include "sysemu/numa.h"
|
||||
#include "sysemu/runstate.h"
|
||||
#include "sysemu/tpm.h"
|
||||
#include "sysemu/tcg.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "sysemu/hvf.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "hw/loader.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/bitops.h"
|
||||
|
@ -1343,7 +1345,7 @@ static void create_smmu(const VirtMachineState *vms,
|
|||
return;
|
||||
}
|
||||
|
||||
dev = qdev_new("arm-smmuv3");
|
||||
dev = qdev_new(TYPE_ARM_SMMUV3);
|
||||
|
||||
object_property_set_link(OBJECT(dev), "primary-bus", OBJECT(bus),
|
||||
&error_abort);
|
||||
|
@ -1820,6 +1822,84 @@ static void virt_set_memmap(VirtMachineState *vms, int pa_bits)
|
|||
}
|
||||
}
|
||||
|
||||
static VirtGICType finalize_gic_version_do(const char *accel_name,
|
||||
VirtGICType gic_version,
|
||||
int gics_supported,
|
||||
unsigned int max_cpus)
|
||||
{
|
||||
/* Convert host/max/nosel to GIC version number */
|
||||
switch (gic_version) {
|
||||
case VIRT_GIC_VERSION_HOST:
|
||||
if (!kvm_enabled()) {
|
||||
error_report("gic-version=host requires KVM");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* For KVM, gic-version=host means gic-version=max */
|
||||
return finalize_gic_version_do(accel_name, VIRT_GIC_VERSION_MAX,
|
||||
gics_supported, max_cpus);
|
||||
case VIRT_GIC_VERSION_MAX:
|
||||
if (gics_supported & VIRT_GIC_VERSION_4_MASK) {
|
||||
gic_version = VIRT_GIC_VERSION_4;
|
||||
} else if (gics_supported & VIRT_GIC_VERSION_3_MASK) {
|
||||
gic_version = VIRT_GIC_VERSION_3;
|
||||
} else {
|
||||
gic_version = VIRT_GIC_VERSION_2;
|
||||
}
|
||||
break;
|
||||
case VIRT_GIC_VERSION_NOSEL:
|
||||
if ((gics_supported & VIRT_GIC_VERSION_2_MASK) &&
|
||||
max_cpus <= GIC_NCPU) {
|
||||
gic_version = VIRT_GIC_VERSION_2;
|
||||
} else if (gics_supported & VIRT_GIC_VERSION_3_MASK) {
|
||||
/*
|
||||
* in case the host does not support v2 emulation or
|
||||
* the end-user requested more than 8 VCPUs we now default
|
||||
* to v3. In any case defaulting to v2 would be broken.
|
||||
*/
|
||||
gic_version = VIRT_GIC_VERSION_3;
|
||||
} else if (max_cpus > GIC_NCPU) {
|
||||
error_report("%s only supports GICv2 emulation but more than 8 "
|
||||
"vcpus are requested", accel_name);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case VIRT_GIC_VERSION_2:
|
||||
case VIRT_GIC_VERSION_3:
|
||||
case VIRT_GIC_VERSION_4:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check chosen version is effectively supported */
|
||||
switch (gic_version) {
|
||||
case VIRT_GIC_VERSION_2:
|
||||
if (!(gics_supported & VIRT_GIC_VERSION_2_MASK)) {
|
||||
error_report("%s does not support GICv2 emulation", accel_name);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case VIRT_GIC_VERSION_3:
|
||||
if (!(gics_supported & VIRT_GIC_VERSION_3_MASK)) {
|
||||
error_report("%s does not support GICv3 emulation", accel_name);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case VIRT_GIC_VERSION_4:
|
||||
if (!(gics_supported & VIRT_GIC_VERSION_4_MASK)) {
|
||||
error_report("%s does not support GICv4 emulation, is virtualization=on?",
|
||||
accel_name);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
error_report("logic error in finalize_gic_version");
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
|
||||
return gic_version;
|
||||
}
|
||||
|
||||
/*
|
||||
* finalize_gic_version - Determines the final gic_version
|
||||
* according to the gic-version property
|
||||
|
@ -1828,118 +1908,49 @@ static void virt_set_memmap(VirtMachineState *vms, int pa_bits)
|
|||
*/
|
||||
static void finalize_gic_version(VirtMachineState *vms)
|
||||
{
|
||||
const char *accel_name = current_accel_name();
|
||||
unsigned int max_cpus = MACHINE(vms)->smp.max_cpus;
|
||||
int gics_supported = 0;
|
||||
|
||||
if (kvm_enabled()) {
|
||||
int probe_bitmap;
|
||||
/* Determine which GIC versions the current environment supports */
|
||||
if (kvm_enabled() && kvm_irqchip_in_kernel()) {
|
||||
int probe_bitmap = kvm_arm_vgic_probe();
|
||||
|
||||
if (!kvm_irqchip_in_kernel()) {
|
||||
switch (vms->gic_version) {
|
||||
case VIRT_GIC_VERSION_HOST:
|
||||
warn_report(
|
||||
"gic-version=host not relevant with kernel-irqchip=off "
|
||||
"as only userspace GICv2 is supported. Using v2 ...");
|
||||
return;
|
||||
case VIRT_GIC_VERSION_MAX:
|
||||
case VIRT_GIC_VERSION_NOSEL:
|
||||
vms->gic_version = VIRT_GIC_VERSION_2;
|
||||
return;
|
||||
case VIRT_GIC_VERSION_2:
|
||||
return;
|
||||
case VIRT_GIC_VERSION_3:
|
||||
error_report(
|
||||
"gic-version=3 is not supported with kernel-irqchip=off");
|
||||
exit(1);
|
||||
case VIRT_GIC_VERSION_4:
|
||||
error_report(
|
||||
"gic-version=4 is not supported with kernel-irqchip=off");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
probe_bitmap = kvm_arm_vgic_probe();
|
||||
if (!probe_bitmap) {
|
||||
error_report("Unable to determine GIC version supported by host");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
switch (vms->gic_version) {
|
||||
case VIRT_GIC_VERSION_HOST:
|
||||
case VIRT_GIC_VERSION_MAX:
|
||||
if (probe_bitmap & KVM_ARM_VGIC_V3) {
|
||||
vms->gic_version = VIRT_GIC_VERSION_3;
|
||||
} else {
|
||||
vms->gic_version = VIRT_GIC_VERSION_2;
|
||||
}
|
||||
return;
|
||||
case VIRT_GIC_VERSION_NOSEL:
|
||||
if ((probe_bitmap & KVM_ARM_VGIC_V2) && max_cpus <= GIC_NCPU) {
|
||||
vms->gic_version = VIRT_GIC_VERSION_2;
|
||||
} else if (probe_bitmap & KVM_ARM_VGIC_V3) {
|
||||
/*
|
||||
* in case the host does not support v2 in-kernel emulation or
|
||||
* the end-user requested more than 8 VCPUs we now default
|
||||
* to v3. In any case defaulting to v2 would be broken.
|
||||
*/
|
||||
vms->gic_version = VIRT_GIC_VERSION_3;
|
||||
} else if (max_cpus > GIC_NCPU) {
|
||||
error_report("host only supports in-kernel GICv2 emulation "
|
||||
"but more than 8 vcpus are requested");
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case VIRT_GIC_VERSION_2:
|
||||
case VIRT_GIC_VERSION_3:
|
||||
break;
|
||||
case VIRT_GIC_VERSION_4:
|
||||
error_report("gic-version=4 is not supported with KVM");
|
||||
exit(1);
|
||||
if (probe_bitmap & KVM_ARM_VGIC_V2) {
|
||||
gics_supported |= VIRT_GIC_VERSION_2_MASK;
|
||||
}
|
||||
|
||||
/* Check chosen version is effectively supported by the host */
|
||||
if (vms->gic_version == VIRT_GIC_VERSION_2 &&
|
||||
!(probe_bitmap & KVM_ARM_VGIC_V2)) {
|
||||
error_report("host does not support in-kernel GICv2 emulation");
|
||||
exit(1);
|
||||
} else if (vms->gic_version == VIRT_GIC_VERSION_3 &&
|
||||
!(probe_bitmap & KVM_ARM_VGIC_V3)) {
|
||||
error_report("host does not support in-kernel GICv3 emulation");
|
||||
exit(1);
|
||||
if (probe_bitmap & KVM_ARM_VGIC_V3) {
|
||||
gics_supported |= VIRT_GIC_VERSION_3_MASK;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* TCG mode */
|
||||
switch (vms->gic_version) {
|
||||
case VIRT_GIC_VERSION_NOSEL:
|
||||
vms->gic_version = VIRT_GIC_VERSION_2;
|
||||
break;
|
||||
case VIRT_GIC_VERSION_MAX:
|
||||
} else if (kvm_enabled() && !kvm_irqchip_in_kernel()) {
|
||||
/* KVM w/o kernel irqchip can only deal with GICv2 */
|
||||
gics_supported |= VIRT_GIC_VERSION_2_MASK;
|
||||
accel_name = "KVM with kernel-irqchip=off";
|
||||
} else if (tcg_enabled() || hvf_enabled() || qtest_enabled()) {
|
||||
gics_supported |= VIRT_GIC_VERSION_2_MASK;
|
||||
if (module_object_class_by_name("arm-gicv3")) {
|
||||
/* CONFIG_ARM_GICV3_TCG was set */
|
||||
gics_supported |= VIRT_GIC_VERSION_3_MASK;
|
||||
if (vms->virt) {
|
||||
/* GICv4 only makes sense if CPU has EL2 */
|
||||
vms->gic_version = VIRT_GIC_VERSION_4;
|
||||
} else {
|
||||
vms->gic_version = VIRT_GIC_VERSION_3;
|
||||
gics_supported |= VIRT_GIC_VERSION_4_MASK;
|
||||
}
|
||||
} else {
|
||||
vms->gic_version = VIRT_GIC_VERSION_2;
|
||||
}
|
||||
break;
|
||||
case VIRT_GIC_VERSION_HOST:
|
||||
error_report("gic-version=host requires KVM");
|
||||
} else {
|
||||
error_report("Unsupported accelerator, can not determine GIC support");
|
||||
exit(1);
|
||||
case VIRT_GIC_VERSION_4:
|
||||
if (!vms->virt) {
|
||||
error_report("gic-version=4 requires virtualization enabled");
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case VIRT_GIC_VERSION_2:
|
||||
case VIRT_GIC_VERSION_3:
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Then convert helpers like host/max to concrete GIC versions and ensure
|
||||
* the desired version is supported
|
||||
*/
|
||||
vms->gic_version = finalize_gic_version_do(accel_name, vms->gic_version,
|
||||
gics_supported, max_cpus);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -81,6 +81,27 @@ static void pl011_update(PL011State *s)
|
|||
}
|
||||
}
|
||||
|
||||
static bool pl011_is_fifo_enabled(PL011State *s)
|
||||
{
|
||||
return (s->lcr & 0x10) != 0;
|
||||
}
|
||||
|
||||
static inline unsigned pl011_get_fifo_depth(PL011State *s)
|
||||
{
|
||||
/* Note: FIFO depth is expected to be power-of-2 */
|
||||
return pl011_is_fifo_enabled(s) ? PL011_FIFO_DEPTH : 1;
|
||||
}
|
||||
|
||||
static inline void pl011_reset_fifo(PL011State *s)
|
||||
{
|
||||
s->read_count = 0;
|
||||
s->read_pos = 0;
|
||||
|
||||
/* Reset FIFO flags */
|
||||
s->flags &= ~(PL011_FLAG_RXFF | PL011_FLAG_TXFF);
|
||||
s->flags |= PL011_FLAG_RXFE | PL011_FLAG_TXFE;
|
||||
}
|
||||
|
||||
static uint64_t pl011_read(void *opaque, hwaddr offset,
|
||||
unsigned size)
|
||||
{
|
||||
|
@ -94,8 +115,7 @@ static uint64_t pl011_read(void *opaque, hwaddr offset,
|
|||
c = s->read_fifo[s->read_pos];
|
||||
if (s->read_count > 0) {
|
||||
s->read_count--;
|
||||
if (++s->read_pos == 16)
|
||||
s->read_pos = 0;
|
||||
s->read_pos = (s->read_pos + 1) & (pl011_get_fifo_depth(s) - 1);
|
||||
}
|
||||
if (s->read_count == 0) {
|
||||
s->flags |= PL011_FLAG_RXFE;
|
||||
|
@ -229,8 +249,7 @@ static void pl011_write(void *opaque, hwaddr offset,
|
|||
case 11: /* UARTLCR_H */
|
||||
/* Reset the FIFO state on FIFO enable or disable */
|
||||
if ((s->lcr ^ value) & 0x10) {
|
||||
s->read_count = 0;
|
||||
s->read_pos = 0;
|
||||
pl011_reset_fifo(s);
|
||||
}
|
||||
if ((s->lcr ^ value) & 0x1) {
|
||||
int break_enable = value & 0x1;
|
||||
|
@ -273,11 +292,7 @@ static int pl011_can_receive(void *opaque)
|
|||
PL011State *s = (PL011State *)opaque;
|
||||
int r;
|
||||
|
||||
if (s->lcr & 0x10) {
|
||||
r = s->read_count < 16;
|
||||
} else {
|
||||
r = s->read_count < 1;
|
||||
}
|
||||
r = s->read_count < pl011_get_fifo_depth(s);
|
||||
trace_pl011_can_receive(s->lcr, s->read_count, r);
|
||||
return r;
|
||||
}
|
||||
|
@ -286,15 +301,15 @@ static void pl011_put_fifo(void *opaque, uint32_t value)
|
|||
{
|
||||
PL011State *s = (PL011State *)opaque;
|
||||
int slot;
|
||||
unsigned pipe_depth;
|
||||
|
||||
slot = s->read_pos + s->read_count;
|
||||
if (slot >= 16)
|
||||
slot -= 16;
|
||||
pipe_depth = pl011_get_fifo_depth(s);
|
||||
slot = (s->read_pos + s->read_count) & (pipe_depth - 1);
|
||||
s->read_fifo[slot] = value;
|
||||
s->read_count++;
|
||||
s->flags &= ~PL011_FLAG_RXFE;
|
||||
trace_pl011_put_fifo(value, s->read_count);
|
||||
if (!(s->lcr & 0x10) || s->read_count == 16) {
|
||||
if (s->read_count == pipe_depth) {
|
||||
trace_pl011_put_fifo_full();
|
||||
s->flags |= PL011_FLAG_RXFF;
|
||||
}
|
||||
|
@ -346,10 +361,35 @@ static const VMStateDescription vmstate_pl011_clock = {
|
|||
}
|
||||
};
|
||||
|
||||
static int pl011_post_load(void *opaque, int version_id)
|
||||
{
|
||||
PL011State* s = opaque;
|
||||
|
||||
/* Sanity-check input state */
|
||||
if (s->read_pos >= ARRAY_SIZE(s->read_fifo) ||
|
||||
s->read_count > ARRAY_SIZE(s->read_fifo)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!pl011_is_fifo_enabled(s) && s->read_count > 0 && s->read_pos > 0) {
|
||||
/*
|
||||
* Older versions of PL011 didn't ensure that the single
|
||||
* character in the FIFO in FIFO-disabled mode is in
|
||||
* element 0 of the array; convert to follow the current
|
||||
* code's assumptions.
|
||||
*/
|
||||
s->read_fifo[0] = s->read_fifo[s->read_pos];
|
||||
s->read_pos = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_pl011 = {
|
||||
.name = "pl011",
|
||||
.version_id = 2,
|
||||
.minimum_version_id = 2,
|
||||
.post_load = pl011_post_load,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT32(readbuff, PL011State),
|
||||
VMSTATE_UINT32(flags, PL011State),
|
||||
|
@ -359,7 +399,7 @@ static const VMStateDescription vmstate_pl011 = {
|
|||
VMSTATE_UINT32(dmacr, PL011State),
|
||||
VMSTATE_UINT32(int_enabled, PL011State),
|
||||
VMSTATE_UINT32(int_level, PL011State),
|
||||
VMSTATE_UINT32_ARRAY(read_fifo, PL011State, 16),
|
||||
VMSTATE_UINT32_ARRAY(read_fifo, PL011State, PL011_FIFO_DEPTH),
|
||||
VMSTATE_UINT32(ilpr, PL011State),
|
||||
VMSTATE_UINT32(ibrd, PL011State),
|
||||
VMSTATE_UINT32(fbrd, PL011State),
|
||||
|
@ -396,11 +436,6 @@ static void pl011_init(Object *obj)
|
|||
s->clk = qdev_init_clock_in(DEVICE(obj), "clk", pl011_clock_update, s,
|
||||
ClockUpdate);
|
||||
|
||||
s->read_trigger = 1;
|
||||
s->ifl = 0x12;
|
||||
s->cr = 0x300;
|
||||
s->flags = 0x90;
|
||||
|
||||
s->id = pl011_id_arm;
|
||||
}
|
||||
|
||||
|
@ -412,11 +447,31 @@ static void pl011_realize(DeviceState *dev, Error **errp)
|
|||
pl011_event, NULL, s, NULL, true);
|
||||
}
|
||||
|
||||
static void pl011_reset(DeviceState *dev)
|
||||
{
|
||||
PL011State *s = PL011(dev);
|
||||
|
||||
s->lcr = 0;
|
||||
s->rsr = 0;
|
||||
s->dmacr = 0;
|
||||
s->int_enabled = 0;
|
||||
s->int_level = 0;
|
||||
s->ilpr = 0;
|
||||
s->ibrd = 0;
|
||||
s->fbrd = 0;
|
||||
s->read_trigger = 1;
|
||||
s->ifl = 0x12;
|
||||
s->cr = 0x300;
|
||||
s->flags = 0;
|
||||
pl011_reset_fifo(s);
|
||||
}
|
||||
|
||||
static void pl011_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
|
||||
dc->realize = pl011_realize;
|
||||
dc->reset = pl011_reset;
|
||||
dc->vmsd = &vmstate_pl011;
|
||||
device_class_set_props(dc, pl011_properties);
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#include "hw/irq.h"
|
||||
#include "cpu.h"
|
||||
#include "target/arm/cpregs.h"
|
||||
#include "sysemu/tcg.h"
|
||||
#include "sysemu/qtest.h"
|
||||
|
||||
/*
|
||||
* Special case return value from hppvi_index(); must be larger than
|
||||
|
@ -2376,6 +2378,7 @@ static const ARMCPRegInfo gicv3_cpuif_reginfo[] = {
|
|||
.opc0 = 3, .opc1 = 0, .crn = 12, .crm = 12, .opc2 = 6,
|
||||
.type = ARM_CP_IO | ARM_CP_NO_RAW,
|
||||
.access = PL1_RW, .accessfn = gicv3_fiq_access,
|
||||
.fgt = FGT_ICC_IGRPENN_EL1,
|
||||
.readfn = icc_igrpen_read,
|
||||
.writefn = icc_igrpen_write,
|
||||
},
|
||||
|
@ -2384,6 +2387,7 @@ static const ARMCPRegInfo gicv3_cpuif_reginfo[] = {
|
|||
.opc0 = 3, .opc1 = 0, .crn = 12, .crm = 12, .opc2 = 7,
|
||||
.type = ARM_CP_IO | ARM_CP_NO_RAW,
|
||||
.access = PL1_RW, .accessfn = gicv3_irq_access,
|
||||
.fgt = FGT_ICC_IGRPENN_EL1,
|
||||
.readfn = icc_igrpen_read,
|
||||
.writefn = icc_igrpen_write,
|
||||
},
|
||||
|
@ -2810,6 +2814,8 @@ void gicv3_init_cpuif(GICv3State *s)
|
|||
* which case we'd get the wrong value.
|
||||
* So instead we define the regs with no ri->opaque info, and
|
||||
* get back to the GICv3CPUState from the CPUARMState.
|
||||
*
|
||||
* These CP regs callbacks can be called from either TCG or HVF code.
|
||||
*/
|
||||
define_arm_cp_regs(cpu, gicv3_cpuif_reginfo);
|
||||
|
||||
|
@ -2905,6 +2911,16 @@ void gicv3_init_cpuif(GICv3State *s)
|
|||
define_arm_cp_regs(cpu, gicv3_cpuif_ich_apxr23_reginfo);
|
||||
}
|
||||
}
|
||||
arm_register_el_change_hook(cpu, gicv3_cpuif_el_change_hook, cs);
|
||||
if (tcg_enabled() || qtest_enabled()) {
|
||||
/*
|
||||
* We can only trap EL changes with TCG. However the GIC interrupt
|
||||
* state only changes on EL changes involving EL2 or EL3, so for
|
||||
* the non-TCG case this is OK, as EL2 and EL3 can't exist.
|
||||
*/
|
||||
arm_register_el_change_hook(cpu, gicv3_cpuif_el_change_hook, cs);
|
||||
} else {
|
||||
assert(!arm_feature(&cpu->env, ARM_FEATURE_EL2));
|
||||
assert(!arm_feature(&cpu->env, ARM_FEATURE_EL3));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue