1
Probably the last arm pullreq before softfreeze...
1
As promised, more Arm patches. The big thing in here is the
2
MPS2-AN521 board model.
2
3
3
The following changes since commit 58560ad254fbda71d4daa6622d71683190070ee2:
4
thanks
5
-- PMM
4
6
5
Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-4.2-20191024' into staging (2019-10-24 16:22:58 +0100)
7
The following changes since commit cfe6c547690b06fbce54a6d0f7b05dd7f18e36ea:
8
9
Merge remote-tracking branch 'remotes/xanclic/tags/pull-block-2019-01-31' into staging (2019-01-31 19:26:09 +0000)
6
10
7
are available in the Git repository at:
11
are available in the Git repository at:
8
12
9
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20191024
13
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20190201
10
14
11
for you to fetch changes up to a01a4a3e85ae8f6fe21adbedc80f7013faabdcf4:
15
for you to fetch changes up to 7743b70ffe7a8ce168adce2cf50ad156b1fefb8c:
12
16
13
hw/arm/highbank: Use AddressSpace when using write_secondary_boot() (2019-10-24 17:16:30 +0100)
17
tests/microbit-test: Add tests for nRF51 NVMC (2019-02-01 15:32:17 +0000)
14
18
15
----------------------------------------------------------------
19
----------------------------------------------------------------
16
target-arm queue:
20
target-arm queue:
17
* raspi boards: some cleanup
21
* New machine mps2-an521 -- this is a model of the AN521 FPGA image for the MPS2 devboard
18
* raspi: implement the bcm2835 system timer device
22
* Fix various places where we failed to UNDEF invalid A64 instructions
19
* raspi: implement a dummy thermal sensor
23
* Don't UNDEF a valid FCMLA on 32-bit inputs
20
* KVM: support providing SVE to the guest
24
* Fix some bugs in the newly-added PAuth implementation
21
* misc devices: switch to ptimer transaction API
25
* microbit: Implement NVMC non-volatile memory controller
22
* cache TB flag state to improve performance of cpu_get_tb_cpu_state
23
* aspeed: Add an AST2600 eval board
24
26
25
----------------------------------------------------------------
27
----------------------------------------------------------------
26
Andrew Jones (9):
28
Aaron Lindsay OS (2):
27
target/arm/monitor: Introduce qmp_query_cpu_model_expansion
29
target/arm: Send interrupts on PMU counter overflow
28
tests: arm: Introduce cpu feature tests
30
target/arm: Add a timer to predict PMU counter overflow
29
target/arm: Allow SVE to be disabled via a CPU property
30
target/arm/cpu64: max cpu: Introduce sve<N> properties
31
target/arm/kvm64: Add kvm_arch_get/put_sve
32
target/arm/kvm64: max cpu: Enable SVE when available
33
target/arm/kvm: scratch vcpu: Preserve input kvm_vcpu_init features
34
target/arm/cpu64: max cpu: Support sve properties with KVM
35
target/arm/kvm: host cpu: Add support for sve<N> properties
36
31
37
Cédric Le Goater (2):
32
Julia Suvorova (1):
38
hw/gpio: Fix property accessors of the AST2600 GPIO 1.8V model
33
arm: Clarify the logic of set_pc()
39
aspeed: Add an AST2600 eval board
40
34
41
Peter Maydell (8):
35
Peter Maydell (33):
42
hw/net/fsl_etsec/etsec.c: Switch to transaction-based ptimer API
36
armv7m: Don't assume the NVIC's CPU is CPU 0
43
hw/timer/xilinx_timer.c: Switch to transaction-based ptimer API
37
armv7m: Make cpu object a child of the armv7m container
44
hw/dma/xilinx_axidma.c: Switch to transaction-based ptimer API
38
armv7m: Pass through start-powered-off CPU property
45
hw/timer/slavio_timer: Remove useless check for NULL t->timer
39
hw/arm/iotkit: Rename IoTKit to ARMSSE
46
hw/timer/slavio_timer.c: Switch to transaction-based ptimer API
40
hw/arm/iotkit: Refactor into abstract base class and subclass
47
hw/timer/grlib_gptimer.c: Switch to transaction-based ptimer API
41
hw/arm/iotkit: Rename 'iotkit' local variables and functions
48
hw/m68k/mcf5206.c: Switch to transaction-based ptimer API
42
hw/arm/iotkit: Rename files to hw/arm/armsse.[ch]
49
hw/watchdog/milkymist-sysctl.c: Switch to transaction-based ptimer API
43
hw/misc/iotkit-secctl: Support 4 internal MPCs
44
hw/arm/armsse: Make number of SRAM banks parameterised
45
hw/arm/armsse: Make SRAM bank size configurable
46
hw/arm/armsse: Support dual-CPU configuration
47
hw/arm/armsse: Give each CPU its own view of memory
48
hw/arm/armsse: Put each CPU in its own cluster object
49
iotkit-sysinfo: Make SYS_VERSION and SYS_CONFIG configurable
50
hw/arm/armsse: Add unimplemented-device stubs for MHUs
51
hw/arm/armsse: Add unimplemented-device stubs for PPUs
52
hw/arm/armsse: Add unimplemented-device stub for cache control registers
53
hw/arm/armsse: Add unimplemented-device stub for CPU local control registers
54
hw/misc/armsse-cpuid: Implement SSE-200 CPU_IDENTITY register block
55
hw/arm/armsse: Add CPU_IDENTITY block to SSE-200
56
hw/arm/armsse: Add SSE-200 model
57
hw/arm/mps2-tz: Add IRQ infrastructure to support SSE-200
58
hw/arm/mps2-tz: Add mps2-an521 model
59
target/arm/translate-a64: Don't underdecode system instructions
60
target/arm/translate-a64: Don't underdecode PRFM
61
target/arm/translate-a64: Don't underdecode SIMD ld/st multiple
62
target/arm/translate-a64: Don't underdecode SIMD ld/st single
63
target/arm/translate-a64: Don't underdecode add/sub extended register
64
target/arm/translate-a64: Don't underdecode FP insns
65
target/arm/translate-a64: Don't underdecode SDOT and UDOT
66
exec.c: Don't reallocate IOMMUNotifiers that are in use
67
target/arm/translate-a64: Fix FCMLA decoding error
68
target/arm/translate-a64: Fix mishandling of size in FCMLA decode
50
69
51
Philippe Mathieu-Daudé (8):
70
Remi Denis-Courmont (2):
52
hw/misc/bcm2835_thermal: Add a dummy BCM2835 thermal sensor
71
target/arm: fix AArch64 virtual address space size
53
hw/arm/bcm2835_peripherals: Use the thermal sensor block
72
target/arm: fix decoding of B{,L}RA{A,B}
54
hw/timer/bcm2835: Add the BCM2835 SYS_timer
55
hw/arm/bcm2835_peripherals: Use the SYS_timer
56
hw/arm/bcm2836: Make the SoC code modular
57
hw/arm/bcm2836: Rename cpus[] as cpu[].core
58
hw/arm/raspi: Use AddressSpace when using arm_boot::write_secondary_boot
59
hw/arm/highbank: Use AddressSpace when using write_secondary_boot()
60
73
61
Richard Henderson (24):
74
Richard Henderson (5):
62
target/arm: Split out rebuild_hflags_common
75
target/arm: Enable API, APK bits in SCR, HCR
63
target/arm: Split out rebuild_hflags_a64
76
target/arm: Always enable pac keys for user-only
64
target/arm: Split out rebuild_hflags_common_32
77
aarch64-linux-user: Update HWCAP bits from linux 5.0-rc1
65
target/arm: Split arm_cpu_data_is_big_endian
78
aarch64-linux-user: Enable HWCAP bits for PAuth
66
target/arm: Split out rebuild_hflags_m32
79
linux-user: Initialize aarch64 pac keys
67
target/arm: Reduce tests vs M-profile in cpu_get_tb_cpu_state
68
target/arm: Split out rebuild_hflags_a32
69
target/arm: Split out rebuild_hflags_aprofile
70
target/arm: Hoist XSCALE_CPAR, VECLEN, VECSTRIDE in cpu_get_tb_cpu_state
71
target/arm: Simplify set of PSTATE_SS in cpu_get_tb_cpu_state
72
target/arm: Hoist computation of TBFLAG_A32.VFPEN
73
target/arm: Add arm_rebuild_hflags
74
target/arm: Split out arm_mmu_idx_el
75
target/arm: Hoist store to cs_base in cpu_get_tb_cpu_state
76
target/arm: Add HELPER(rebuild_hflags_{a32, a64, m32})
77
target/arm: Rebuild hflags at EL changes
78
target/arm: Rebuild hflags at MSR writes
79
target/arm: Rebuild hflags at CPSR writes
80
target/arm: Rebuild hflags at Xscale SCTLR writes
81
target/arm: Rebuild hflags for M-profile
82
target/arm: Rebuild hflags for M-profile NVIC
83
linux-user/aarch64: Rebuild hflags for TARGET_WORDS_BIGENDIAN
84
linux-user/arm: Rebuild hflags for TARGET_WORDS_BIGENDIAN
85
target/arm: Rely on hflags correct in cpu_get_tb_cpu_state
86
80
87
hw/misc/Makefile.objs | 1 +
81
Steffen Görtz (3):
88
hw/timer/Makefile.objs | 1 +
82
hw/nvram/nrf51_nvm: Add nRF51 non-volatile memories
89
tests/Makefile.include | 5 +-
83
arm: Instantiate NRF51 special NVM's and NVMC
90
qapi/machine-target.json | 6 +-
84
tests/microbit-test: Add tests for nRF51 NVMC
91
hw/net/fsl_etsec/etsec.h | 1 -
92
include/hw/arm/aspeed.h | 1 +
93
include/hw/arm/bcm2835_peripherals.h | 5 +-
94
include/hw/arm/bcm2836.h | 4 +-
95
include/hw/arm/raspi_platform.h | 1 +
96
include/hw/misc/bcm2835_thermal.h | 27 ++
97
include/hw/timer/bcm2835_systmr.h | 33 +++
98
include/qemu/bitops.h | 1 +
99
target/arm/cpu.h | 105 +++++--
100
target/arm/helper.h | 4 +
101
target/arm/internals.h | 9 +
102
target/arm/kvm_arm.h | 39 +++
103
hw/arm/aspeed.c | 23 ++
104
hw/arm/bcm2835_peripherals.c | 30 +-
105
hw/arm/bcm2836.c | 44 +--
106
hw/arm/highbank.c | 3 +-
107
hw/arm/raspi.c | 14 +-
108
hw/dma/xilinx_axidma.c | 9 +-
109
hw/gpio/aspeed_gpio.c | 8 +-
110
hw/intc/armv7m_nvic.c | 22 +-
111
hw/m68k/mcf5206.c | 15 +-
112
hw/misc/bcm2835_thermal.c | 135 +++++++++
113
hw/net/fsl_etsec/etsec.c | 9 +-
114
hw/timer/bcm2835_systmr.c | 163 +++++++++++
115
hw/timer/grlib_gptimer.c | 28 +-
116
hw/timer/milkymist-sysctl.c | 25 +-
117
hw/timer/slavio_timer.c | 32 ++-
118
hw/timer/xilinx_timer.c | 13 +-
119
linux-user/aarch64/cpu_loop.c | 1 +
120
linux-user/arm/cpu_loop.c | 1 +
121
linux-user/syscall.c | 1 +
122
target/arm/cpu.c | 26 +-
123
target/arm/cpu64.c | 364 +++++++++++++++++++++--
124
target/arm/helper-a64.c | 3 +
125
target/arm/helper.c | 403 +++++++++++++++++---------
126
target/arm/kvm.c | 25 +-
127
target/arm/kvm32.c | 6 +-
128
target/arm/kvm64.c | 325 ++++++++++++++++++---
129
target/arm/m_helper.c | 6 +
130
target/arm/machine.c | 1 +
131
target/arm/monitor.c | 158 ++++++++++
132
target/arm/op_helper.c | 4 +
133
target/arm/translate-a64.c | 13 +-
134
target/arm/translate.c | 33 ++-
135
tests/arm-cpu-features.c | 540 +++++++++++++++++++++++++++++++++++
136
docs/arm-cpu-features.rst | 317 ++++++++++++++++++++
137
hw/timer/trace-events | 5 +
138
51 files changed, 2725 insertions(+), 323 deletions(-)
139
create mode 100644 include/hw/misc/bcm2835_thermal.h
140
create mode 100644 include/hw/timer/bcm2835_systmr.h
141
create mode 100644 hw/misc/bcm2835_thermal.c
142
create mode 100644 hw/timer/bcm2835_systmr.c
143
create mode 100644 tests/arm-cpu-features.c
144
create mode 100644 docs/arm-cpu-features.rst
145
85
86
kumar sourav (1):
87
hw/arm/nrf51_soc: set object owner in memory_region_init_ram
88
89
hw/arm/Makefile.objs | 2 +-
90
hw/misc/Makefile.objs | 1 +
91
hw/nvram/Makefile.objs | 1 +
92
include/hw/arm/{iotkit.h => armsse.h} | 113 ++-
93
include/hw/arm/armv7m.h | 1 +
94
include/hw/arm/nrf51_soc.h | 2 +
95
include/hw/misc/armsse-cpuid.h | 41 ++
96
include/hw/misc/iotkit-secctl.h | 6 +-
97
include/hw/misc/iotkit-sysinfo.h | 6 +
98
include/hw/nvram/nrf51_nvm.h | 64 ++
99
include/qom/cpu.h | 16 +-
100
linux-user/aarch64/target_syscall.h | 2 +
101
target/arm/cpu.h | 12 +-
102
exec.c | 10 +-
103
hw/arm/armsse.c | 1241 +++++++++++++++++++++++++++++++++
104
hw/arm/armv7m.c | 23 +-
105
hw/arm/boot.c | 4 -
106
hw/arm/iotkit.c | 759 --------------------
107
hw/arm/mps2-tz.c | 121 +++-
108
hw/arm/nrf51_soc.c | 44 +-
109
hw/intc/armv7m_nvic.c | 3 +-
110
hw/misc/armsse-cpuid.c | 134 ++++
111
hw/misc/iotkit-secctl.c | 5 +-
112
hw/misc/iotkit-sysinfo.c | 15 +-
113
hw/nvram/nrf51_nvm.c | 388 +++++++++++
114
linux-user/aarch64/cpu_loop.c | 31 +-
115
linux-user/elfload.c | 10 +
116
target/arm/arm-powerctl.c | 3 -
117
target/arm/cpu.c | 41 +-
118
target/arm/cpu64.c | 75 --
119
target/arm/helper.c | 139 +++-
120
target/arm/translate-a64.c | 59 +-
121
tests/microbit-test.c | 108 +++
122
MAINTAINERS | 6 +-
123
default-configs/arm-softmmu.mak | 3 +-
124
hw/misc/trace-events | 4 +
125
36 files changed, 2552 insertions(+), 941 deletions(-)
126
rename include/hw/arm/{iotkit.h => armsse.h} (53%)
127
create mode 100644 include/hw/misc/armsse-cpuid.h
128
create mode 100644 include/hw/nvram/nrf51_nvm.h
129
create mode 100644 hw/arm/armsse.c
130
delete mode 100644 hw/arm/iotkit.c
131
create mode 100644 hw/misc/armsse-cpuid.c
132
create mode 100644 hw/nvram/nrf51_nvm.c
133
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: kumar sourav <sourav.jb1988@gmail.com>
2
2
3
write_secondary_boot() is used in SMP configurations where the
3
set object owner in memory_region_init_ram() instead
4
CPU address space might not be the main System Bus.
4
of NULL.
5
The rom_add_blob_fixed_as() function allow us to specify an
6
address space. Use it to write each boot blob in the corresponding
7
CPU address space.
8
5
9
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Signed-off-by: kumar sourav <sourav.jb1988@gmail.com>
10
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
Message-id: 20191019234715.25750-11-f4bug@amsat.org
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Message-id: 20190125155630.17430-1-sourav.jb1988@gmail.com
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
11
---
14
hw/arm/raspi.c | 14 ++++++++------
12
hw/arm/nrf51_soc.c | 3 ++-
15
1 file changed, 8 insertions(+), 6 deletions(-)
13
1 file changed, 2 insertions(+), 1 deletion(-)
16
14
17
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
15
diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c
18
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/raspi.c
17
--- a/hw/arm/nrf51_soc.c
20
+++ b/hw/arm/raspi.c
18
+++ b/hw/arm/nrf51_soc.c
21
@@ -XXX,XX +XXX,XX @@ static void write_smpboot(ARMCPU *cpu, const struct arm_boot_info *info)
19
@@ -XXX,XX +XXX,XX @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
22
QEMU_BUILD_BUG_ON((BOARDSETUP_ADDR & 0xf) != 0
20
}
23
|| (BOARDSETUP_ADDR >> 4) >= 0x100);
21
memory_region_add_subregion(&s->container, NRF51_FLASH_BASE, &s->flash);
24
22
25
- rom_add_blob_fixed("raspi_smpboot", smpboot, sizeof(smpboot),
23
- memory_region_init_ram(&s->sram, NULL, "nrf51.sram", s->sram_size, &err);
26
- info->smp_loader_start);
24
+ memory_region_init_ram(&s->sram, OBJECT(s), "nrf51.sram", s->sram_size,
27
+ rom_add_blob_fixed_as("raspi_smpboot", smpboot, sizeof(smpboot),
25
+ &err);
28
+ info->smp_loader_start,
26
if (err) {
29
+ arm_boot_address_space(cpu, info));
27
error_propagate(errp, err);
30
}
28
return;
31
32
static void write_smpboot64(ARMCPU *cpu, const struct arm_boot_info *info)
33
{
34
+ AddressSpace *as = arm_boot_address_space(cpu, info);
35
/* Unlike the AArch32 version we don't need to call the board setup hook.
36
* The mechanism for doing the spin-table is also entirely different.
37
* We must have four 64-bit fields at absolute addresses
38
@@ -XXX,XX +XXX,XX @@ static void write_smpboot64(ARMCPU *cpu, const struct arm_boot_info *info)
39
0, 0, 0, 0
40
};
41
42
- rom_add_blob_fixed("raspi_smpboot", smpboot, sizeof(smpboot),
43
- info->smp_loader_start);
44
- rom_add_blob_fixed("raspi_spintables", spintables, sizeof(spintables),
45
- SPINTABLE_ADDR);
46
+ rom_add_blob_fixed_as("raspi_smpboot", smpboot, sizeof(smpboot),
47
+ info->smp_loader_start, as);
48
+ rom_add_blob_fixed_as("raspi_spintables", spintables, sizeof(spintables),
49
+ SPINTABLE_ADDR, as);
50
}
51
52
static void write_board_setup(ARMCPU *cpu, const struct arm_boot_info *info)
53
--
29
--
54
2.20.1
30
2.20.1
55
31
56
32
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Currently the ARMv7M NVIC object's realize method assumes that the
2
CPU the NVIC is attached to is CPU 0, because it thinks there can
3
only ever be one CPU in the system. To allow a dual-Cortex-M33
4
setup we need to remove this assumption; instead the armv7m
5
wrapper object tells the NVIC its CPU, in the same way that it
6
already tells the CPU what the NVIC is.
2
7
3
Continue setting, but not relying upon, env->hflags.
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20190121185118.18550-2-peter.maydell@linaro.org
12
---
13
hw/arm/armv7m.c | 6 ++++--
14
hw/intc/armv7m_nvic.c | 3 +--
15
2 files changed, 5 insertions(+), 4 deletions(-)
4
16
5
Suggested-by: Peter Maydell <peter.maydell@linaro.org>
17
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
18
index XXXXXXX..XXXXXXX 100644
7
Message-id: 20191023150057.25731-22-richard.henderson@linaro.org
19
--- a/hw/arm/armv7m.c
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
+++ b/hw/arm/armv7m.c
9
---
21
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
10
hw/intc/armv7m_nvic.c | 22 +++++++++++++---------
22
}
11
1 file changed, 13 insertions(+), 9 deletions(-)
23
}
12
24
25
- /* Tell the CPU where the NVIC is; it will fail realize if it doesn't
26
- * have one.
27
+ /*
28
+ * Tell the CPU where the NVIC is; it will fail realize if it doesn't
29
+ * have one. Similarly, tell the NVIC where its CPU is.
30
*/
31
s->cpu->env.nvic = &s->nvic;
32
+ s->nvic.cpu = s->cpu;
33
34
object_property_set_bool(OBJECT(s->cpu), true, "realized", &err);
35
if (err != NULL) {
13
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
36
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
14
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/intc/armv7m_nvic.c
38
--- a/hw/intc/armv7m_nvic.c
16
+++ b/hw/intc/armv7m_nvic.c
39
+++ b/hw/intc/armv7m_nvic.c
17
@@ -XXX,XX +XXX,XX @@ static MemTxResult nvic_sysreg_write(void *opaque, hwaddr addr,
40
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
18
}
41
Error *err = NULL;
19
}
42
int regionlen;
20
nvic_irq_update(s);
43
21
- return MEMTX_OK;
44
- s->cpu = ARM_CPU(qemu_get_cpu(0));
22
+ goto exit_ok;
45
-
23
case 0x200 ... 0x23f: /* NVIC Set pend */
46
+ /* The armv7m container object will have set our CPU pointer */
24
/* the special logic in armv7m_nvic_set_pending()
47
if (!s->cpu || !arm_feature(&s->cpu->env, ARM_FEATURE_M)) {
25
* is not needed since IRQs are never escalated
48
error_setg(errp, "The NVIC can only be used with a Cortex-M CPU");
26
@@ -XXX,XX +XXX,XX @@ static MemTxResult nvic_sysreg_write(void *opaque, hwaddr addr,
49
return;
27
}
28
}
29
nvic_irq_update(s);
30
- return MEMTX_OK;
31
+ goto exit_ok;
32
case 0x300 ... 0x33f: /* NVIC Active */
33
- return MEMTX_OK; /* R/O */
34
+ goto exit_ok; /* R/O */
35
case 0x400 ... 0x5ef: /* NVIC Priority */
36
startvec = (offset - 0x400) + NVIC_FIRST_IRQ; /* vector # */
37
38
@@ -XXX,XX +XXX,XX @@ static MemTxResult nvic_sysreg_write(void *opaque, hwaddr addr,
39
}
40
}
41
nvic_irq_update(s);
42
- return MEMTX_OK;
43
+ goto exit_ok;
44
case 0xd18 ... 0xd1b: /* System Handler Priority (SHPR1) */
45
if (!arm_feature(&s->cpu->env, ARM_FEATURE_M_MAIN)) {
46
- return MEMTX_OK;
47
+ goto exit_ok;
48
}
49
/* fall through */
50
case 0xd1c ... 0xd23: /* System Handler Priority (SHPR2, SHPR3) */
51
@@ -XXX,XX +XXX,XX @@ static MemTxResult nvic_sysreg_write(void *opaque, hwaddr addr,
52
set_prio(s, hdlidx, sbank, newprio);
53
}
54
nvic_irq_update(s);
55
- return MEMTX_OK;
56
+ goto exit_ok;
57
case 0xd28 ... 0xd2b: /* Configurable Fault Status (CFSR) */
58
if (!arm_feature(&s->cpu->env, ARM_FEATURE_M_MAIN)) {
59
- return MEMTX_OK;
60
+ goto exit_ok;
61
}
62
/* All bits are W1C, so construct 32 bit value with 0s in
63
* the parts not written by the access size
64
@@ -XXX,XX +XXX,XX @@ static MemTxResult nvic_sysreg_write(void *opaque, hwaddr addr,
65
*/
66
s->cpu->env.v7m.cfsr[M_REG_NS] &= ~(value & R_V7M_CFSR_BFSR_MASK);
67
}
68
- return MEMTX_OK;
69
+ goto exit_ok;
70
}
71
if (size == 4) {
72
nvic_writel(s, offset, value, attrs);
73
- return MEMTX_OK;
74
+ goto exit_ok;
75
}
76
qemu_log_mask(LOG_GUEST_ERROR,
77
"NVIC: Bad write of size %d at offset 0x%x\n", size, offset);
78
/* This is UNPREDICTABLE; treat as RAZ/WI */
79
+
80
+ exit_ok:
81
+ /* Ensure any changes made are reflected in the cached hflags. */
82
+ arm_rebuild_hflags(&s->cpu->env);
83
return MEMTX_OK;
84
}
85
86
--
50
--
87
2.20.1
51
2.20.1
88
52
89
53
diff view generated by jsdifflib
1
Switch the mcf5206 code away from bottom-half based ptimers to
1
Rather than just creating the CPUs with object_new, make them child
2
the new transaction-based ptimer API. This just requires adding
2
objects of the armv7m container. This will allow the cluster code to
3
begin/commit calls around the various places that modify the ptimer
3
find the CPUs if an armv7m object is made a child of a cluster object.
4
state, and using the new ptimer_init() function to create the timer.
4
object_new_with_props() will do the parenting for us.
5
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Thomas Huth <thuth@redhat.com>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Message-id: 20191021140600.10725-1-peter.maydell@linaro.org
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20190121185118.18550-3-peter.maydell@linaro.org
9
---
10
---
10
hw/m68k/mcf5206.c | 15 +++++++++------
11
hw/arm/armv7m.c | 7 ++++++-
11
1 file changed, 9 insertions(+), 6 deletions(-)
12
1 file changed, 6 insertions(+), 1 deletion(-)
12
13
13
diff --git a/hw/m68k/mcf5206.c b/hw/m68k/mcf5206.c
14
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/m68k/mcf5206.c
16
--- a/hw/arm/armv7m.c
16
+++ b/hw/m68k/mcf5206.c
17
+++ b/hw/arm/armv7m.c
17
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
18
19
19
#include "qemu/osdep.h"
20
memory_region_add_subregion_overlap(&s->container, 0, s->board_memory, -1);
20
#include "qemu/error-report.h"
21
21
-#include "qemu/main-loop.h"
22
- s->cpu = ARM_CPU(object_new(s->cpu_type));
22
#include "cpu.h"
23
+ s->cpu = ARM_CPU(object_new_with_props(s->cpu_type, OBJECT(s), "cpu",
23
#include "hw/hw.h"
24
+ &err, NULL));
24
#include "hw/irq.h"
25
+ if (err != NULL) {
25
@@ -XXX,XX +XXX,XX @@ static void m5206_timer_recalibrate(m5206_timer_state *s)
26
+ error_propagate(errp, err);
26
int prescale;
27
+ return;
27
int mode;
28
29
+ ptimer_transaction_begin(s->timer);
30
ptimer_stop(s->timer);
31
32
- if ((s->tmr & TMR_RST) == 0)
33
- return;
34
+ if ((s->tmr & TMR_RST) == 0) {
35
+ goto exit;
36
+ }
28
+ }
37
29
38
prescale = (s->tmr >> 8) + 1;
30
object_property_set_link(OBJECT(s->cpu), OBJECT(&s->container), "memory",
39
mode = (s->tmr >> 1) & 3;
31
&error_abort);
40
@@ -XXX,XX +XXX,XX @@ static void m5206_timer_recalibrate(m5206_timer_state *s)
41
ptimer_set_limit(s->timer, s->trr, 0);
42
43
ptimer_run(s->timer, 0);
44
+exit:
45
+ ptimer_transaction_commit(s->timer);
46
}
47
48
static void m5206_timer_trigger(void *opaque)
49
@@ -XXX,XX +XXX,XX @@ static void m5206_timer_write(m5206_timer_state *s, uint32_t addr, uint32_t val)
50
s->tcr = val;
51
break;
52
case 0xc:
53
+ ptimer_transaction_begin(s->timer);
54
ptimer_set_count(s->timer, val);
55
+ ptimer_transaction_commit(s->timer);
56
break;
57
case 0x11:
58
s->ter &= ~val;
59
@@ -XXX,XX +XXX,XX @@ static void m5206_timer_write(m5206_timer_state *s, uint32_t addr, uint32_t val)
60
static m5206_timer_state *m5206_timer_init(qemu_irq irq)
61
{
62
m5206_timer_state *s;
63
- QEMUBH *bh;
64
65
s = g_new0(m5206_timer_state, 1);
66
- bh = qemu_bh_new(m5206_timer_trigger, s);
67
- s->timer = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
68
+ s->timer = ptimer_init(m5206_timer_trigger, s, PTIMER_POLICY_DEFAULT);
69
s->irq = irq;
70
m5206_timer_reset(s);
71
return s;
72
--
32
--
73
2.20.1
33
2.20.1
74
34
75
35
diff view generated by jsdifflib
1
From: Cédric Le Goater <clg@kaod.org>
1
Expose "start-powered-off" as a property of the ARMv7M container,
2
which we just pass through to the CPU object in the same way that we
3
do for "init-svtor" and "idau". (We want this for the SSE-200, which
4
powers up only the first CPU at reset and leaves the second powered
5
down.)
2
6
3
Signed-off-by: Cédric Le Goater <clg@kaod.org>
7
As with the other CPU properties here, we can't just use alias
4
Reviewed-by: Joel Stanley <joel@jms.id.au>
8
properties, because the CPU QOM object is not created until armv7m
5
Message-id: 20191023130455.1347-3-clg@kaod.org
9
realize time.
10
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20190121185118.18550-4-peter.maydell@linaro.org
7
---
14
---
8
include/hw/arm/aspeed.h | 1 +
15
include/hw/arm/armv7m.h | 1 +
9
hw/arm/aspeed.c | 23 +++++++++++++++++++++++
16
hw/arm/armv7m.c | 10 ++++++++++
10
2 files changed, 24 insertions(+)
17
2 files changed, 11 insertions(+)
11
18
12
diff --git a/include/hw/arm/aspeed.h b/include/hw/arm/aspeed.h
19
diff --git a/include/hw/arm/armv7m.h b/include/hw/arm/armv7m.h
13
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
14
--- a/include/hw/arm/aspeed.h
21
--- a/include/hw/arm/armv7m.h
15
+++ b/include/hw/arm/aspeed.h
22
+++ b/include/hw/arm/armv7m.h
16
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedBoardConfig {
23
@@ -XXX,XX +XXX,XX @@ typedef struct ARMv7MState {
17
const char *desc;
24
Object *idau;
18
const char *soc_name;
25
uint32_t init_svtor;
19
uint32_t hw_strap1;
26
bool enable_bitband;
20
+ uint32_t hw_strap2;
27
+ bool start_powered_off;
21
const char *fmc_model;
28
} ARMv7MState;
22
const char *spi_model;
29
23
uint32_t num_cs;
30
#endif
24
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
31
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
25
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/arm/aspeed.c
33
--- a/hw/arm/armv7m.c
27
+++ b/hw/arm/aspeed.c
34
+++ b/hw/arm/armv7m.c
28
@@ -XXX,XX +XXX,XX @@ struct AspeedBoardState {
35
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
29
/* Witherspoon hardware value: 0xF10AD216 (but use romulus definition) */
36
return;
30
#define WITHERSPOON_BMC_HW_STRAP1 ROMULUS_BMC_HW_STRAP1
37
}
31
38
}
32
+/* AST2600 evb hardware value */
39
+ if (object_property_find(OBJECT(s->cpu), "start-powered-off", NULL)) {
33
+#define AST2600_EVB_HW_STRAP1 0x000000C0
40
+ object_property_set_bool(OBJECT(s->cpu), s->start_powered_off,
34
+#define AST2600_EVB_HW_STRAP2 0x00000003
41
+ "start-powered-off", &err);
35
+
42
+ if (err != NULL) {
36
/*
43
+ error_propagate(errp, err);
37
* The max ram region is for firmwares that scan the address space
44
+ return;
38
* with load/store to guess how much RAM the SoC has.
45
+ }
39
@@ -XXX,XX +XXX,XX @@ static void aspeed_board_init(MachineState *machine,
46
+ }
40
&error_abort);
47
41
object_property_set_int(OBJECT(&bmc->soc), cfg->hw_strap1, "hw-strap1",
48
/*
42
&error_abort);
49
* Tell the CPU where the NVIC is; it will fail realize if it doesn't
43
+ object_property_set_int(OBJECT(&bmc->soc), cfg->hw_strap2, "hw-strap2",
50
@@ -XXX,XX +XXX,XX @@ static Property armv7m_properties[] = {
44
+ &error_abort);
51
DEFINE_PROP_LINK("idau", ARMv7MState, idau, TYPE_IDAU_INTERFACE, Object *),
45
object_property_set_int(OBJECT(&bmc->soc), cfg->num_cs, "num-cs",
52
DEFINE_PROP_UINT32("init-svtor", ARMv7MState, init_svtor, 0),
46
&error_abort);
53
DEFINE_PROP_BOOL("enable-bitband", ARMv7MState, enable_bitband, false),
47
object_property_set_int(OBJECT(&bmc->soc), machine->smp.cpus, "num-cpus",
54
+ DEFINE_PROP_BOOL("start-powered-off", ARMv7MState, start_powered_off,
48
@@ -XXX,XX +XXX,XX @@ static void ast2500_evb_i2c_init(AspeedBoardState *bmc)
55
+ false),
49
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 11), "ds1338", 0x32);
56
DEFINE_PROP_END_OF_LIST(),
50
}
51
52
+static void ast2600_evb_i2c_init(AspeedBoardState *bmc)
53
+{
54
+ /* Start with some devices on our I2C busses */
55
+ ast2500_evb_i2c_init(bmc);
56
+}
57
+
58
static void romulus_bmc_i2c_init(AspeedBoardState *bmc)
59
{
60
AspeedSoCState *soc = &bmc->soc;
61
@@ -XXX,XX +XXX,XX @@ static const AspeedBoardConfig aspeed_boards[] = {
62
.num_cs = 2,
63
.i2c_init = witherspoon_bmc_i2c_init,
64
.ram = 512 * MiB,
65
+ }, {
66
+ .name = MACHINE_TYPE_NAME("ast2600-evb"),
67
+ .desc = "Aspeed AST2600 EVB (Cortex A7)",
68
+ .soc_name = "ast2600-a0",
69
+ .hw_strap1 = AST2600_EVB_HW_STRAP1,
70
+ .hw_strap2 = AST2600_EVB_HW_STRAP2,
71
+ .fmc_model = "w25q512jv",
72
+ .spi_model = "mx66u51235f",
73
+ .num_cs = 1,
74
+ .i2c_init = ast2600_evb_i2c_init,
75
+ .ram = 1 * GiB,
76
},
77
};
57
};
78
58
79
--
59
--
80
2.20.1
60
2.20.1
81
61
82
62
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
1
The Arm IoTKit was effectively the forerunner of a series of
2
2
subsystems for embedded SoCs, named the SSE-050, SSE-100 and SSE-200:
3
Add support for the query-cpu-model-expansion QMP command to Arm. We
3
https://developer.arm.com/products/system-design/subsystems
4
do this selectively, only exposing CPU properties which represent
4
These are generally quite similar, though later iterations have
5
optional CPU features which the user may want to enable/disable.
5
extra devices that earlier ones do not.
6
Additionally we restrict the list of queryable cpu models to 'max',
6
7
'host', or the current type when KVM is in use. And, finally, we only
7
We want to add a model of the SSE-200, which means refactoring the
8
implement expansion type 'full', as Arm does not yet have a "base"
8
IoTKit code into an abstract base class and subclasses (using the
9
CPU type. More details and example queries are described in a new
9
same design that the bcm283x SoC and Aspeed SoC family
10
document (docs/arm-cpu-features.rst).
10
implementations do). As a first step, rename the IoTKit struct and
11
11
QOM macros to ARMSSE, which is what we're going to name the base
12
Note, certainly more features may be added to the list of advertised
12
class. We temporarily retain TYPE_IOTKIT to avoid changing the
13
features, e.g. 'vfp' and 'neon'. The only requirement is that we can
13
code that instantiates a TYPE_IOTKIT device here and then changing
14
detect invalid configurations and emit failures at QMP query time.
14
it back again when it is re-introduced as a subclass.
15
For 'vfp' and 'neon' this will require some refactoring to share a
15
16
validation function between the QMP query and the CPU realize
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
functions.
17
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
18
19
Signed-off-by: Andrew Jones <drjones@redhat.com>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Reviewed-by: Eric Auger <eric.auger@redhat.com>
19
Message-id: 20190121185118.18550-5-peter.maydell@linaro.org
22
Reviewed-by: Beata Michalska <beata.michalska@linaro.org>
23
Message-id: 20191024121808.9612-2-drjones@redhat.com
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
---
20
---
26
qapi/machine-target.json | 6 +-
21
include/hw/arm/iotkit.h | 22 ++++++++++-----
27
target/arm/monitor.c | 146 ++++++++++++++++++++++++++++++++++++++
22
hw/arm/iotkit.c | 59 +++++++++++++++++++++--------------------
28
docs/arm-cpu-features.rst | 137 +++++++++++++++++++++++++++++++++++
23
hw/arm/mps2-tz.c | 2 +-
29
3 files changed, 286 insertions(+), 3 deletions(-)
24
3 files changed, 47 insertions(+), 36 deletions(-)
30
create mode 100644 docs/arm-cpu-features.rst
25
31
26
diff --git a/include/hw/arm/iotkit.h b/include/hw/arm/iotkit.h
32
diff --git a/qapi/machine-target.json b/qapi/machine-target.json
33
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
34
--- a/qapi/machine-target.json
28
--- a/include/hw/arm/iotkit.h
35
+++ b/qapi/machine-target.json
29
+++ b/include/hw/arm/iotkit.h
36
@@ -XXX,XX +XXX,XX @@
30
@@ -XXX,XX +XXX,XX @@
37
##
31
/*
38
{ 'struct': 'CpuModelExpansionInfo',
32
- * ARM IoT Kit
39
'data': { 'model': 'CpuModelInfo' },
33
+ * ARM SSE (Subsystems for Embedded): IoTKit
40
- 'if': 'defined(TARGET_S390X) || defined(TARGET_I386)' }
34
*
41
+ 'if': 'defined(TARGET_S390X) || defined(TARGET_I386) || defined(TARGET_ARM)' }
35
* Copyright (c) 2018 Linaro Limited
42
36
* Written by Peter Maydell
43
##
37
@@ -XXX,XX +XXX,XX @@
44
# @query-cpu-model-expansion:
38
* (at your option) any later version.
45
@@ -XXX,XX +XXX,XX @@
46
# query-cpu-model-expansion while using these is not advised.
47
#
48
# Some architectures may not support all expansion types. s390x supports
49
-# "full" and "static".
50
+# "full" and "static". Arm only supports "full".
51
#
52
# Returns: a CpuModelExpansionInfo. Returns an error if expanding CPU models is
53
# not supported, if the model cannot be expanded, if the model contains
54
@@ -XXX,XX +XXX,XX @@
55
'data': { 'type': 'CpuModelExpansionType',
56
'model': 'CpuModelInfo' },
57
'returns': 'CpuModelExpansionInfo',
58
- 'if': 'defined(TARGET_S390X) || defined(TARGET_I386)' }
59
+ 'if': 'defined(TARGET_S390X) || defined(TARGET_I386) || defined(TARGET_ARM)' }
60
61
##
62
# @CpuDefinitionInfo:
63
diff --git a/target/arm/monitor.c b/target/arm/monitor.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/target/arm/monitor.c
66
+++ b/target/arm/monitor.c
67
@@ -XXX,XX +XXX,XX @@
68
*/
39
*/
69
40
70
#include "qemu/osdep.h"
41
-/* This is a model of the Arm IoT Kit which is documented in
71
+#include "hw/boards.h"
42
+/*
72
#include "kvm_arm.h"
43
+ * This is a model of the Arm "Subsystems for Embedded" family of
73
+#include "qapi/error.h"
44
+ * hardware, which include the IoT Kit and the SSE-050, SSE-100 and
74
+#include "qapi/visitor.h"
45
+ * SSE-200. Currently we model only the Arm IoT Kit which is documented in
75
+#include "qapi/qobject-input-visitor.h"
46
* http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
76
+#include "qapi/qapi-commands-machine-target.h"
47
* It contains:
77
#include "qapi/qapi-commands-misc-target.h"
48
* a Cortex-M33
78
+#include "qapi/qmp/qerror.h"
49
@@ -XXX,XX +XXX,XX @@
79
+#include "qapi/qmp/qdict.h"
50
#include "hw/or-irq.h"
80
+#include "qom/qom-qobject.h"
51
#include "hw/core/split-irq.h"
81
52
82
static GICCapability *gic_cap_new(int version)
53
-#define TYPE_IOTKIT "iotkit"
83
{
54
-#define IOTKIT(obj) OBJECT_CHECK(IoTKit, (obj), TYPE_IOTKIT)
84
@@ -XXX,XX +XXX,XX @@ GICCapabilityList *qmp_query_gic_capabilities(Error **errp)
55
+#define TYPE_ARMSSE "iotkit"
85
56
+#define ARMSSE(obj) OBJECT_CHECK(ARMSSE, (obj), TYPE_ARMSSE)
86
return head;
87
}
88
+
57
+
89
+/*
58
+/*
90
+ * These are cpu model features we want to advertise. The order here
59
+ * For the moment TYPE_IOTKIT is a synonym for TYPE_ARMSSE (and the
91
+ * matters as this is the order in which qmp_query_cpu_model_expansion
60
+ * latter's underlying name is left as "iotkit"); in a later
92
+ * will attempt to set them. If there are dependencies between features,
61
+ * commit it will become a subclass of TYPE_ARMSSE.
93
+ * then the order that considers those dependencies must be used.
94
+ */
62
+ */
95
+static const char *cpu_model_advertised_features[] = {
63
+#define TYPE_IOTKIT TYPE_ARMSSE
96
+ "aarch64", "pmu",
64
97
+ NULL
65
/* We have an IRQ splitter and an OR gate input for each external PPC
98
+};
66
* and the 2 internal PPCs
99
+
67
@@ -XXX,XX +XXX,XX @@
100
+CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
68
#define NUM_EXTERNAL_PPCS (IOTS_NUM_AHB_EXP_PPC + IOTS_NUM_APB_EXP_PPC)
101
+ CpuModelInfo *model,
69
#define NUM_PPCS (NUM_EXTERNAL_PPCS + 2)
102
+ Error **errp)
70
103
+{
71
-typedef struct IoTKit {
104
+ CpuModelExpansionInfo *expansion_info;
72
+typedef struct ARMSSE {
105
+ const QDict *qdict_in = NULL;
73
/*< private >*/
106
+ QDict *qdict_out;
74
SysBusDevice parent_obj;
107
+ ObjectClass *oc;
75
108
+ Object *obj;
76
@@ -XXX,XX +XXX,XX @@ typedef struct IoTKit {
109
+ const char *name;
77
MemoryRegion *board_memory;
110
+ int i;
78
uint32_t exp_numirq;
111
+
79
uint32_t mainclk_frq;
112
+ if (type != CPU_MODEL_EXPANSION_TYPE_FULL) {
80
-} IoTKit;
113
+ error_setg(errp, "The requested expansion type is not supported");
81
+} ARMSSE;
114
+ return NULL;
82
115
+ }
83
#endif
116
+
84
diff --git a/hw/arm/iotkit.c b/hw/arm/iotkit.c
117
+ if (!kvm_enabled() && !strcmp(model->name, "host")) {
85
index XXXXXXX..XXXXXXX 100644
118
+ error_setg(errp, "The CPU type '%s' requires KVM", model->name);
86
--- a/hw/arm/iotkit.c
119
+ return NULL;
87
+++ b/hw/arm/iotkit.c
120
+ }
88
@@ -XXX,XX +XXX,XX @@
121
+
89
/*
122
+ oc = cpu_class_by_name(TYPE_ARM_CPU, model->name);
90
- * Arm IoT Kit
123
+ if (!oc) {
91
+ * Arm SSE (Subsystems for Embedded): IoTKit
124
+ error_setg(errp, "The CPU type '%s' is not a recognized ARM CPU type",
92
*
125
+ model->name);
93
* Copyright (c) 2018 Linaro Limited
126
+ return NULL;
94
* Written by Peter Maydell
127
+ }
95
@@ -XXX,XX +XXX,XX @@
128
+
96
/* Create an alias region of @size bytes starting at @base
129
+ if (kvm_enabled()) {
97
* which mirrors the memory starting at @orig.
130
+ const char *cpu_type = current_machine->cpu_type;
98
*/
131
+ int len = strlen(cpu_type) - strlen(ARM_CPU_TYPE_SUFFIX);
99
-static void make_alias(IoTKit *s, MemoryRegion *mr, const char *name,
132
+ bool supported = false;
100
+static void make_alias(ARMSSE *s, MemoryRegion *mr, const char *name,
133
+
101
hwaddr base, hwaddr size, hwaddr orig)
134
+ if (!strcmp(model->name, "host") || !strcmp(model->name, "max")) {
102
{
135
+ /* These are kvmarm's recommended cpu types */
103
memory_region_init_alias(mr, NULL, name, &s->container, orig, size);
136
+ supported = true;
104
@@ -XXX,XX +XXX,XX @@ static void irq_status_forwarder(void *opaque, int n, int level)
137
+ } else if (strlen(model->name) == len &&
105
138
+ !strncmp(model->name, cpu_type, len)) {
106
static void nsccfg_handler(void *opaque, int n, int level)
139
+ /* KVM is enabled and we're using this type, so it works. */
107
{
140
+ supported = true;
108
- IoTKit *s = IOTKIT(opaque);
141
+ }
109
+ ARMSSE *s = ARMSSE(opaque);
142
+ if (!supported) {
110
143
+ error_setg(errp, "We cannot guarantee the CPU type '%s' works "
111
s->nsccfg = level;
144
+ "with KVM on this host", model->name);
112
}
145
+ return NULL;
113
146
+ }
114
-static void iotkit_forward_ppc(IoTKit *s, const char *ppcname, int ppcnum)
147
+ }
115
+static void iotkit_forward_ppc(ARMSSE *s, const char *ppcname, int ppcnum)
148
+
116
{
149
+ if (model->props) {
117
/* Each of the 4 AHB and 4 APB PPCs that might be present in a
150
+ qdict_in = qobject_to(QDict, model->props);
118
- * system using the IoTKit has a collection of control lines which
151
+ if (!qdict_in) {
119
+ * system using the ARMSSE has a collection of control lines which
152
+ error_setg(errp, QERR_INVALID_PARAMETER_TYPE, "props", "dict");
120
* are provided by the security controller and which we want to
153
+ return NULL;
121
- * expose as control lines on the IoTKit device itself, so the
154
+ }
122
- * code using the IoTKit can wire them up to the PPCs.
155
+ }
123
+ * expose as control lines on the ARMSSE device itself, so the
156
+
124
+ * code using the ARMSSE can wire them up to the PPCs.
157
+ obj = object_new(object_class_get_name(oc));
125
*/
158
+
126
SplitIRQ *splitter = &s->ppc_irq_splitter[ppcnum];
159
+ if (qdict_in) {
127
DeviceState *iotkitdev = DEVICE(s);
160
+ Visitor *visitor;
128
@@ -XXX,XX +XXX,XX @@ static void iotkit_forward_ppc(IoTKit *s, const char *ppcname, int ppcnum)
161
+ Error *err = NULL;
129
g_free(name);
162
+
130
}
163
+ visitor = qobject_input_visitor_new(model->props);
131
164
+ visit_start_struct(visitor, NULL, NULL, 0, &err);
132
-static void iotkit_forward_sec_resp_cfg(IoTKit *s)
165
+ if (err) {
133
+static void iotkit_forward_sec_resp_cfg(ARMSSE *s)
166
+ visit_free(visitor);
134
{
167
+ object_unref(obj);
135
/* Forward the 3rd output from the splitter device as a
168
+ error_propagate(errp, err);
136
* named GPIO output of the iotkit object.
169
+ return NULL;
137
@@ -XXX,XX +XXX,XX @@ static void iotkit_forward_sec_resp_cfg(IoTKit *s)
170
+ }
138
171
+
139
static void iotkit_init(Object *obj)
172
+ i = 0;
140
{
173
+ while ((name = cpu_model_advertised_features[i++]) != NULL) {
141
- IoTKit *s = IOTKIT(obj);
174
+ if (qdict_get(qdict_in, name)) {
142
+ ARMSSE *s = ARMSSE(obj);
175
+ object_property_set(obj, visitor, name, &err);
143
int i;
176
+ if (err) {
144
177
+ break;
145
memory_region_init(&s->container, obj, "iotkit-container", UINT64_MAX);
178
+ }
146
@@ -XXX,XX +XXX,XX @@ static void iotkit_init(Object *obj)
179
+ }
147
180
+ }
148
static void iotkit_exp_irq(void *opaque, int n, int level)
181
+
149
{
182
+ if (!err) {
150
- IoTKit *s = IOTKIT(opaque);
183
+ visit_check_struct(visitor, &err);
151
+ ARMSSE *s = ARMSSE(opaque);
184
+ }
152
185
+ visit_end_struct(visitor, NULL);
153
qemu_set_irq(s->exp_irqs[n], level);
186
+ visit_free(visitor);
154
}
187
+ if (err) {
155
188
+ object_unref(obj);
156
static void iotkit_mpcexp_status(void *opaque, int n, int level)
189
+ error_propagate(errp, err);
157
{
190
+ return NULL;
158
- IoTKit *s = IOTKIT(opaque);
191
+ }
159
+ ARMSSE *s = ARMSSE(opaque);
192
+ }
160
qemu_set_irq(s->mpcexp_status_in[n], level);
193
+
161
}
194
+ expansion_info = g_new0(CpuModelExpansionInfo, 1);
162
195
+ expansion_info->model = g_malloc0(sizeof(*expansion_info->model));
163
static void iotkit_realize(DeviceState *dev, Error **errp)
196
+ expansion_info->model->name = g_strdup(model->name);
164
{
197
+
165
- IoTKit *s = IOTKIT(dev);
198
+ qdict_out = qdict_new();
166
+ ARMSSE *s = ARMSSE(dev);
199
+
167
int i;
200
+ i = 0;
168
MemoryRegion *mr;
201
+ while ((name = cpu_model_advertised_features[i++]) != NULL) {
169
Error *err = NULL;
202
+ ObjectProperty *prop = object_property_find(obj, name, NULL);
170
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
203
+ if (prop) {
171
* devices exist in both address spaces but with hard-wired security
204
+ Error *err = NULL;
172
* permissions that will cause the CPU to fault for non-secure accesses.
205
+ QObject *value;
173
*
206
+
174
- * The IoTKit has an IDAU (Implementation Defined Access Unit),
207
+ assert(prop->get);
175
+ * The ARMSSE has an IDAU (Implementation Defined Access Unit),
208
+ value = object_property_get_qobject(obj, name, &err);
176
* which specifies hard-wired security permissions for different
209
+ assert(!err);
177
- * areas of the physical address space. For the IoTKit IDAU, the
210
+
178
+ * areas of the physical address space. For the ARMSSE IDAU, the
211
+ qdict_put_obj(qdict_out, name, value);
179
* top 4 bits of the physical address are the IDAU region ID, and
212
+ }
180
* if bit 28 (ie the lowest bit of the ID) is 0 then this is an NS
213
+ }
181
* region, otherwise it is an S region.
214
+
182
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
215
+ if (!qdict_size(qdict_out)) {
183
* 0x20000000..0x2007ffff 32KB FPGA block RAM
216
+ qobject_unref(qdict_out);
184
* 0x30000000..0x3fffffff alias of 0x20000000..0x2fffffff
217
+ } else {
185
* 0x40000000..0x4000ffff base peripheral region 1
218
+ expansion_info->model->props = QOBJECT(qdict_out);
186
- * 0x40010000..0x4001ffff CPU peripherals (none for IoTKit)
219
+ expansion_info->model->has_props = true;
187
+ * 0x40010000..0x4001ffff CPU peripherals (none for ARMSSE)
220
+ }
188
* 0x40020000..0x4002ffff system control element peripherals
221
+
189
* 0x40080000..0x400fffff base peripheral region 2
222
+ object_unref(obj);
190
* 0x50000000..0x5fffffff alias of 0x40000000..0x4fffffff
223
+
191
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
224
+ return expansion_info;
192
qdev_connect_gpio_out_named(dev_secctl, "nsc_cfg", 0, s->nsc_cfg_in);
225
+}
193
226
diff --git a/docs/arm-cpu-features.rst b/docs/arm-cpu-features.rst
194
/* The sec_resp_cfg output from the security controller must be split into
227
new file mode 100644
195
- * multiple lines, one for each of the PPCs within the IoTKit and one
228
index XXXXXXX..XXXXXXX
196
- * that will be an output from the IoTKit to the system.
229
--- /dev/null
197
+ * multiple lines, one for each of the PPCs within the ARMSSE and one
230
+++ b/docs/arm-cpu-features.rst
198
+ * that will be an output from the ARMSSE to the system.
231
@@ -XXX,XX +XXX,XX @@
199
*/
232
+================
200
object_property_set_int(OBJECT(&s->sec_resp_splitter), 3,
233
+ARM CPU Features
201
"num-lines", &err);
234
+================
202
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
235
+
203
236
+Examples of probing and using ARM CPU features
204
/* 0x40010000 .. 0x4001ffff: private CPU region: unused in IoTKit */
237
+
205
238
+Introduction
206
- /* 0x40020000 .. 0x4002ffff : IoTKit system control peripheral region */
239
+============
207
+ /* 0x40020000 .. 0x4002ffff : ARMSSE system control peripheral region */
240
+
208
/* Devices behind APB PPC1:
241
+CPU features are optional features that a CPU of supporting type may
209
* 0x4002f000: S32K timer
242
+choose to implement or not. In QEMU, optional CPU features have
210
*/
243
+corresponding boolean CPU proprieties that, when enabled, indicate
211
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
244
+that the feature is implemented, and, conversely, when disabled,
212
qdev_get_gpio_in(DEVICE(&s->nmi_orgate), 0));
245
+indicate that it is not implemented. An example of an ARM CPU feature
213
sysbus_mmio_map(SYS_BUS_DEVICE(&s->s32kwatchdog), 0, 0x5002e000);
246
+is the Performance Monitoring Unit (PMU). CPU types such as the
214
247
+Cortex-A15 and the Cortex-A57, which respectively implement ARM
215
- /* 0x40080000 .. 0x4008ffff : IoTKit second Base peripheral region */
248
+architecture reference manuals ARMv7-A and ARMv8-A, may both optionally
216
+ /* 0x40080000 .. 0x4008ffff : ARMSSE second Base peripheral region */
249
+implement PMUs. For example, if a user wants to use a Cortex-A15 without
217
250
+a PMU, then the `-cpu` parameter should contain `pmu=off` on the QEMU
218
qdev_prop_set_uint32(DEVICE(&s->nswatchdog), "wdogclk-frq", s->mainclk_frq);
251
+command line, i.e. `-cpu cortex-a15,pmu=off`.
219
object_property_set_bool(OBJECT(&s->nswatchdog), true, "realized", &err);
252
+
220
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
253
+As not all CPU types support all optional CPU features, then whether or
221
* Expose our container region to the board model; this corresponds
254
+not a CPU property exists depends on the CPU type. For example, CPUs
222
* to the AHB Slave Expansion ports which allow bus master devices
255
+that implement the ARMv8-A architecture reference manual may optionally
223
* (eg DMA controllers) in the board model to make transactions into
256
+support the AArch32 CPU feature, which may be enabled by disabling the
224
- * devices in the IoTKit.
257
+`aarch64` CPU property. A CPU type such as the Cortex-A15, which does
225
+ * devices in the ARMSSE.
258
+not implement ARMv8-A, will not have the `aarch64` CPU property.
226
*/
259
+
227
sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->container);
260
+QEMU's support may be limited for some CPU features, only partially
228
261
+supporting the feature or only supporting the feature under certain
229
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
262
+configurations. For example, the `aarch64` CPU feature, which, when
230
static void iotkit_idau_check(IDAUInterface *ii, uint32_t address,
263
+disabled, enables the optional AArch32 CPU feature, is only supported
231
int *iregion, bool *exempt, bool *ns, bool *nsc)
264
+when using the KVM accelerator and when running on a host CPU type that
232
{
265
+supports the feature.
233
- /* For IoTKit systems the IDAU responses are simple logical functions
266
+
234
+ /*
267
+CPU Feature Probing
235
+ * For ARMSSE systems the IDAU responses are simple logical functions
268
+===================
236
* of the address bits. The NSC attribute is guest-adjustable via the
269
+
237
* NSCCFG register in the security controller.
270
+Determining which CPU features are available and functional for a given
238
*/
271
+CPU type is possible with the `query-cpu-model-expansion` QMP command.
239
- IoTKit *s = IOTKIT(ii);
272
+Below are some examples where `scripts/qmp/qmp-shell` (see the top comment
240
+ ARMSSE *s = ARMSSE(ii);
273
+block in the script for usage) is used to issue the QMP commands.
241
int region = extract32(address, 28, 4);
274
+
242
275
+(1) Determine which CPU features are available for the `max` CPU type
243
*ns = !(region & 1);
276
+ (Note, we started QEMU with qemu-system-aarch64, so `max` is
244
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription iotkit_vmstate = {
277
+ implementing the ARMv8-A reference manual in this case)::
245
.version_id = 1,
278
+
246
.minimum_version_id = 1,
279
+ (QEMU) query-cpu-model-expansion type=full model={"name":"max"}
247
.fields = (VMStateField[]) {
280
+ { "return": {
248
- VMSTATE_UINT32(nsccfg, IoTKit),
281
+ "model": { "name": "max", "props": {
249
+ VMSTATE_UINT32(nsccfg, ARMSSE),
282
+ "pmu": true, "aarch64": true
250
VMSTATE_END_OF_LIST()
283
+ }}}}
251
}
284
+
252
};
285
+We see that the `max` CPU type has the `pmu` and `aarch64` CPU features.
253
286
+We also see that the CPU features are enabled, as they are all `true`.
254
static Property iotkit_properties[] = {
287
+
255
- DEFINE_PROP_LINK("memory", IoTKit, board_memory, TYPE_MEMORY_REGION,
288
+(2) Let's try to disable the PMU::
256
+ DEFINE_PROP_LINK("memory", ARMSSE, board_memory, TYPE_MEMORY_REGION,
289
+
257
MemoryRegion *),
290
+ (QEMU) query-cpu-model-expansion type=full model={"name":"max","props":{"pmu":false}}
258
- DEFINE_PROP_UINT32("EXP_NUMIRQ", IoTKit, exp_numirq, 64),
291
+ { "return": {
259
- DEFINE_PROP_UINT32("MAINCLK", IoTKit, mainclk_frq, 0),
292
+ "model": { "name": "max", "props": {
260
+ DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
293
+ "pmu": false, "aarch64": true
261
+ DEFINE_PROP_UINT32("MAINCLK", ARMSSE, mainclk_frq, 0),
294
+ }}}}
262
DEFINE_PROP_END_OF_LIST()
295
+
263
};
296
+We see it worked, as `pmu` is now `false`.
264
297
+
265
static void iotkit_reset(DeviceState *dev)
298
+(3) Let's try to disable `aarch64`, which enables the AArch32 CPU feature::
266
{
299
+
267
- IoTKit *s = IOTKIT(dev);
300
+ (QEMU) query-cpu-model-expansion type=full model={"name":"max","props":{"aarch64":false}}
268
+ ARMSSE *s = ARMSSE(dev);
301
+ {"error": {
269
302
+ "class": "GenericError", "desc":
270
s->nsccfg = 0;
303
+ "'aarch64' feature cannot be disabled unless KVM is enabled and 32-bit EL1 is supported"
271
}
304
+ }}
272
@@ -XXX,XX +XXX,XX @@ static void iotkit_class_init(ObjectClass *klass, void *data)
305
+
273
}
306
+It looks like this feature is limited to a configuration we do not
274
307
+currently have.
275
static const TypeInfo iotkit_info = {
308
+
276
- .name = TYPE_IOTKIT,
309
+(4) Let's try probing CPU features for the Cortex-A15 CPU type::
277
+ .name = TYPE_ARMSSE,
310
+
278
.parent = TYPE_SYS_BUS_DEVICE,
311
+ (QEMU) query-cpu-model-expansion type=full model={"name":"cortex-a15"}
279
- .instance_size = sizeof(IoTKit),
312
+ {"return": {"model": {"name": "cortex-a15", "props": {"pmu": true}}}}
280
+ .instance_size = sizeof(ARMSSE),
313
+
281
.instance_init = iotkit_init,
314
+Only the `pmu` CPU feature is available.
282
.class_init = iotkit_class_init,
315
+
283
.interfaces = (InterfaceInfo[]) {
316
+A note about CPU feature dependencies
284
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
317
+-------------------------------------
285
index XXXXXXX..XXXXXXX 100644
318
+
286
--- a/hw/arm/mps2-tz.c
319
+It's possible for features to have dependencies on other features. I.e.
287
+++ b/hw/arm/mps2-tz.c
320
+it may be possible to change one feature at a time without error, but
288
@@ -XXX,XX +XXX,XX @@ typedef struct {
321
+when attempting to change all features at once an error could occur
289
typedef struct {
322
+depending on the order they are processed. It's also possible changing
290
MachineState parent;
323
+all at once doesn't generate an error, because a feature's dependencies
291
324
+are satisfied with other features, but the same feature cannot be changed
292
- IoTKit iotkit;
325
+independently without error. For these reasons callers should always
293
+ ARMSSE iotkit;
326
+attempt to make their desired changes all at once in order to ensure the
294
MemoryRegion psram;
327
+collection is valid.
295
MemoryRegion ssram[3];
328
+
296
MemoryRegion ssram1_m;
329
+A note about CPU models and KVM
330
+-------------------------------
331
+
332
+Named CPU models generally do not work with KVM. There are a few cases
333
+that do work, e.g. using the named CPU model `cortex-a57` with KVM on a
334
+seattle host, but mostly if KVM is enabled the `host` CPU type must be
335
+used. This means the guest is provided all the same CPU features as the
336
+host CPU type has. And, for this reason, the `host` CPU type should
337
+enable all CPU features that the host has by default. Indeed it's even
338
+a bit strange to allow disabling CPU features that the host has when using
339
+the `host` CPU type, but in the absence of CPU models it's the best we can
340
+do if we want to launch guests without all the host's CPU features enabled.
341
+
342
+Enabling KVM also affects the `query-cpu-model-expansion` QMP command. The
343
+affect is not only limited to specific features, as pointed out in example
344
+(3) of "CPU Feature Probing", but also to which CPU types may be expanded.
345
+When KVM is enabled, only the `max`, `host`, and current CPU type may be
346
+expanded. This restriction is necessary as it's not possible to know all
347
+CPU types that may work with KVM, but it does impose a small risk of users
348
+experiencing unexpected errors. For example on a seattle, as mentioned
349
+above, the `cortex-a57` CPU type is also valid when KVM is enabled.
350
+Therefore a user could use the `host` CPU type for the current type, but
351
+then attempt to query `cortex-a57`, however that query will fail with our
352
+restrictions. This shouldn't be an issue though as management layers and
353
+users have been preferring the `host` CPU type for use with KVM for quite
354
+some time. Additionally, if the KVM-enabled QEMU instance running on a
355
+seattle host is using the `cortex-a57` CPU type, then querying `cortex-a57`
356
+will work.
357
+
358
+Using CPU Features
359
+==================
360
+
361
+After determining which CPU features are available and supported for a
362
+given CPU type, then they may be selectively enabled or disabled on the
363
+QEMU command line with that CPU type::
364
+
365
+ $ qemu-system-aarch64 -M virt -cpu max,pmu=off
366
+
367
+The example above disables the PMU for the `max` CPU type.
368
+
369
--
297
--
370
2.20.1
298
2.20.1
371
299
372
300
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The Arm SSE-200 Subsystem for Embedded is a revised and
2
extended version of the older IoTKit SoC. Prepare for
3
adding a model of it by refactoring the IoTKit code into
4
an abstract base class which contains the functionality,
5
driven by a class data block specific to each subclass.
6
(This is the same approach used by the existing bcm283x
7
SoC family implementation.)
2
8
3
Continue setting, but not relying upon, env->hflags.
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20190121185118.18550-6-peter.maydell@linaro.org
13
---
14
include/hw/arm/iotkit.h | 22 +++++++++++++++++-----
15
hw/arm/iotkit.c | 34 +++++++++++++++++++++++++++++-----
16
2 files changed, 46 insertions(+), 10 deletions(-)
4
17
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
18
diff --git a/include/hw/arm/iotkit.h b/include/hw/arm/iotkit.h
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20191023150057.25731-19-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
target/arm/op_helper.c | 3 +++
11
1 file changed, 3 insertions(+)
12
13
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
14
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/op_helper.c
20
--- a/include/hw/arm/iotkit.h
16
+++ b/target/arm/op_helper.c
21
+++ b/include/hw/arm/iotkit.h
17
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(usat16)(CPUARMState *env, uint32_t x, uint32_t shift)
22
@@ -XXX,XX +XXX,XX @@
18
void HELPER(setend)(CPUARMState *env)
23
#include "hw/or-irq.h"
24
#include "hw/core/split-irq.h"
25
26
-#define TYPE_ARMSSE "iotkit"
27
+#define TYPE_ARMSSE "arm-sse"
28
#define ARMSSE(obj) OBJECT_CHECK(ARMSSE, (obj), TYPE_ARMSSE)
29
30
/*
31
- * For the moment TYPE_IOTKIT is a synonym for TYPE_ARMSSE (and the
32
- * latter's underlying name is left as "iotkit"); in a later
33
- * commit it will become a subclass of TYPE_ARMSSE.
34
+ * These type names are for specific IoTKit subsystems; other than
35
+ * instantiating them, code using these devices should always handle
36
+ * them via the ARMSSE base class, so they have no IOTKIT() etc macros.
37
*/
38
-#define TYPE_IOTKIT TYPE_ARMSSE
39
+#define TYPE_IOTKIT "iotkit"
40
41
/* We have an IRQ splitter and an OR gate input for each external PPC
42
* and the 2 internal PPCs
43
@@ -XXX,XX +XXX,XX @@ typedef struct ARMSSE {
44
uint32_t mainclk_frq;
45
} ARMSSE;
46
47
+typedef struct ARMSSEInfo ARMSSEInfo;
48
+
49
+typedef struct ARMSSEClass {
50
+ DeviceClass parent_class;
51
+ const ARMSSEInfo *info;
52
+} ARMSSEClass;
53
+
54
+#define ARMSSE_CLASS(klass) \
55
+ OBJECT_CLASS_CHECK(ARMSSEClass, (klass), TYPE_ARMSSE)
56
+#define ARMSSE_GET_CLASS(obj) \
57
+ OBJECT_GET_CLASS(ARMSSEClass, (obj), TYPE_ARMSSE)
58
+
59
#endif
60
diff --git a/hw/arm/iotkit.c b/hw/arm/iotkit.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/hw/arm/iotkit.c
63
+++ b/hw/arm/iotkit.c
64
@@ -XXX,XX +XXX,XX @@
65
#include "hw/arm/iotkit.h"
66
#include "hw/arm/arm.h"
67
68
+struct ARMSSEInfo {
69
+ const char *name;
70
+};
71
+
72
+static const ARMSSEInfo armsse_variants[] = {
73
+ {
74
+ .name = TYPE_IOTKIT,
75
+ },
76
+};
77
+
78
/* Clock frequency in HZ of the 32KHz "slow clock" */
79
#define S32KCLK (32 * 1000)
80
81
@@ -XXX,XX +XXX,XX @@ static void iotkit_class_init(ObjectClass *klass, void *data)
19
{
82
{
20
env->uncached_cpsr ^= CPSR_E;
83
DeviceClass *dc = DEVICE_CLASS(klass);
21
+ arm_rebuild_hflags(env);
84
IDAUInterfaceClass *iic = IDAU_INTERFACE_CLASS(klass);
85
+ ARMSSEClass *asc = ARMSSE_CLASS(klass);
86
87
dc->realize = iotkit_realize;
88
dc->vmsd = &iotkit_vmstate;
89
dc->props = iotkit_properties;
90
dc->reset = iotkit_reset;
91
iic->check = iotkit_idau_check;
92
+ asc->info = data;
22
}
93
}
23
94
24
/* Function checks whether WFx (WFI/WFE) instructions are set up to be trapped.
95
-static const TypeInfo iotkit_info = {
25
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(cpsr_read)(CPUARMState *env)
96
+static const TypeInfo armsse_info = {
26
void HELPER(cpsr_write)(CPUARMState *env, uint32_t val, uint32_t mask)
97
.name = TYPE_ARMSSE,
98
.parent = TYPE_SYS_BUS_DEVICE,
99
.instance_size = sizeof(ARMSSE),
100
.instance_init = iotkit_init,
101
- .class_init = iotkit_class_init,
102
+ .abstract = true,
103
.interfaces = (InterfaceInfo[]) {
104
{ TYPE_IDAU_INTERFACE },
105
{ }
106
}
107
};
108
109
-static void iotkit_register_types(void)
110
+static void armsse_register_types(void)
27
{
111
{
28
cpsr_write(env, val, mask, CPSRWriteByInstr);
112
- type_register_static(&iotkit_info);
29
+ /* TODO: Not all cpsr bits are relevant to hflags. */
113
+ int i;
30
+ arm_rebuild_hflags(env);
114
+
115
+ type_register_static(&armsse_info);
116
+
117
+ for (i = 0; i < ARRAY_SIZE(armsse_variants); i++) {
118
+ TypeInfo ti = {
119
+ .name = armsse_variants[i].name,
120
+ .parent = TYPE_ARMSSE,
121
+ .class_init = iotkit_class_init,
122
+ .class_data = (void *)&armsse_variants[i],
123
+ };
124
+ type_register(&ti);
125
+ }
31
}
126
}
32
127
33
/* Write the CPSR for a 32-bit exception return */
128
-type_init(iotkit_register_types);
129
+type_init(armsse_register_types);
34
--
130
--
35
2.20.1
131
2.20.1
36
132
37
133
diff view generated by jsdifflib
1
Switch the slavio_timer code away from bottom-half based ptimers to
1
Rename various internal uses of 'iotkit' in hw/arm/iotkit.c to
2
the new transaction-based ptimer API. This just requires adding
2
'armsse', for consistency. The remaining occurences are:
3
begin/commit calls around the various places that modify the ptimer
3
* related to the devices TYPE_IOTKIT_SYSCTL, TYPE_IOTKIT_SYSINFO,
4
state, and using the new ptimer_init() function to create the timer.
4
etc, which this refactor is not touching
5
* references that apply specifically to the IoTKit (like
6
the lack of a private CPU region)
7
* the vmstate, which keeps its old "iotkit" name for
8
migration compatibility reasons
5
9
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20191021134357.14266-4-peter.maydell@linaro.org
13
Message-id: 20190121185118.18550-7-peter.maydell@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
14
---
12
hw/timer/slavio_timer.c | 20 ++++++++++++++++----
15
hw/arm/iotkit.c | 68 ++++++++++++++++++++++++-------------------------
13
1 file changed, 16 insertions(+), 4 deletions(-)
16
1 file changed, 34 insertions(+), 34 deletions(-)
14
17
15
diff --git a/hw/timer/slavio_timer.c b/hw/timer/slavio_timer.c
18
diff --git a/hw/arm/iotkit.c b/hw/arm/iotkit.c
16
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/timer/slavio_timer.c
20
--- a/hw/arm/iotkit.c
18
+++ b/hw/timer/slavio_timer.c
21
+++ b/hw/arm/iotkit.c
19
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@ static void nsccfg_handler(void *opaque, int n, int level)
20
#include "hw/sysbus.h"
23
s->nsccfg = level;
21
#include "migration/vmstate.h"
24
}
22
#include "trace.h"
25
23
-#include "qemu/main-loop.h"
26
-static void iotkit_forward_ppc(ARMSSE *s, const char *ppcname, int ppcnum)
24
#include "qemu/module.h"
27
+static void armsse_forward_ppc(ARMSSE *s, const char *ppcname, int ppcnum)
25
28
{
26
/*
29
/* Each of the 4 AHB and 4 APB PPCs that might be present in a
27
@@ -XXX,XX +XXX,XX @@ static void slavio_timer_mem_writel(void *opaque, hwaddr addr,
30
* system using the ARMSSE has a collection of control lines which
28
saddr = addr >> 2;
31
@@ -XXX,XX +XXX,XX @@ static void iotkit_forward_ppc(ARMSSE *s, const char *ppcname, int ppcnum)
29
switch (saddr) {
32
* code using the ARMSSE can wire them up to the PPCs.
30
case TIMER_LIMIT:
33
*/
31
+ ptimer_transaction_begin(t->timer);
34
SplitIRQ *splitter = &s->ppc_irq_splitter[ppcnum];
32
if (slavio_timer_is_user(tc)) {
35
- DeviceState *iotkitdev = DEVICE(s);
33
uint64_t count;
36
+ DeviceState *armssedev = DEVICE(s);
34
37
DeviceState *dev_secctl = DEVICE(&s->secctl);
35
@@ -XXX,XX +XXX,XX @@ static void slavio_timer_mem_writel(void *opaque, hwaddr addr,
38
DeviceState *dev_splitter = DEVICE(splitter);
36
ptimer_set_limit(t->timer, LIMIT_TO_PERIODS(t->limit), 1);
39
char *name;
37
}
40
38
}
41
name = g_strdup_printf("%s_nonsec", ppcname);
39
+ ptimer_transaction_commit(t->timer);
42
- qdev_pass_gpios(dev_secctl, iotkitdev, name);
40
break;
43
+ qdev_pass_gpios(dev_secctl, armssedev, name);
41
case TIMER_COUNTER:
44
g_free(name);
42
if (slavio_timer_is_user(tc)) {
45
name = g_strdup_printf("%s_ap", ppcname);
43
@@ -XXX,XX +XXX,XX @@ static void slavio_timer_mem_writel(void *opaque, hwaddr addr,
46
- qdev_pass_gpios(dev_secctl, iotkitdev, name);
44
t->reached = 0;
47
+ qdev_pass_gpios(dev_secctl, armssedev, name);
45
count = ((uint64_t)t->counthigh) << 32 | t->count;
48
g_free(name);
46
trace_slavio_timer_mem_writel_limit(timer_index, count);
49
name = g_strdup_printf("%s_irq_enable", ppcname);
47
+ ptimer_transaction_begin(t->timer);
50
- qdev_pass_gpios(dev_secctl, iotkitdev, name);
48
ptimer_set_count(t->timer, LIMIT_TO_PERIODS(t->limit - count));
51
+ qdev_pass_gpios(dev_secctl, armssedev, name);
49
+ ptimer_transaction_commit(t->timer);
52
g_free(name);
50
} else {
53
name = g_strdup_printf("%s_irq_clear", ppcname);
51
trace_slavio_timer_mem_writel_counter_invalid();
54
- qdev_pass_gpios(dev_secctl, iotkitdev, name);
52
}
55
+ qdev_pass_gpios(dev_secctl, armssedev, name);
53
@@ -XXX,XX +XXX,XX @@ static void slavio_timer_mem_writel(void *opaque, hwaddr addr,
56
g_free(name);
54
case TIMER_COUNTER_NORST:
57
55
// set limit without resetting counter
58
/* irq_status is a little more tricky, because we need to
56
t->limit = val & TIMER_MAX_COUNT32;
59
@@ -XXX,XX +XXX,XX @@ static void iotkit_forward_ppc(ARMSSE *s, const char *ppcname, int ppcnum)
57
+ ptimer_transaction_begin(t->timer);
60
qdev_connect_gpio_out(dev_splitter, 1,
58
if (t->limit == 0) { /* free-run */
61
qdev_get_gpio_in(DEVICE(&s->ppc_irq_orgate), ppcnum));
59
ptimer_set_limit(t->timer, LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 0);
62
s->irq_status_in[ppcnum] = qdev_get_gpio_in(dev_splitter, 0);
60
} else {
63
- qdev_init_gpio_in_named_with_opaque(iotkitdev, irq_status_forwarder,
61
ptimer_set_limit(t->timer, LIMIT_TO_PERIODS(t->limit), 0);
64
+ qdev_init_gpio_in_named_with_opaque(armssedev, irq_status_forwarder,
62
}
65
s->irq_status_in[ppcnum], name, 1);
63
+ ptimer_transaction_commit(t->timer);
66
g_free(name);
64
break;
67
}
65
case TIMER_STATUS:
68
66
+ ptimer_transaction_begin(t->timer);
69
-static void iotkit_forward_sec_resp_cfg(ARMSSE *s)
67
if (slavio_timer_is_user(tc)) {
70
+static void armsse_forward_sec_resp_cfg(ARMSSE *s)
68
// start/stop user counter
71
{
69
if (val & 1) {
72
/* Forward the 3rd output from the splitter device as a
70
@@ -XXX,XX +XXX,XX @@ static void slavio_timer_mem_writel(void *opaque, hwaddr addr,
73
- * named GPIO output of the iotkit object.
71
}
74
+ * named GPIO output of the armsse object.
72
}
75
*/
73
t->run = val & 1;
76
DeviceState *dev = DEVICE(s);
74
+ ptimer_transaction_commit(t->timer);
77
DeviceState *dev_splitter = DEVICE(&s->sec_resp_splitter);
75
break;
78
@@ -XXX,XX +XXX,XX @@ static void iotkit_forward_sec_resp_cfg(ARMSSE *s)
76
case TIMER_MODE:
79
qdev_connect_gpio_out(dev_splitter, 2, s->sec_resp_cfg_in);
77
if (timer_index == 0) {
80
}
78
@@ -XXX,XX +XXX,XX @@ static void slavio_timer_mem_writel(void *opaque, hwaddr addr,
81
79
unsigned int processor = 1 << i;
82
-static void iotkit_init(Object *obj)
80
CPUTimerState *curr_timer = &s->cputimer[i + 1];
83
+static void armsse_init(Object *obj)
81
84
{
82
+ ptimer_transaction_begin(curr_timer->timer);
85
ARMSSE *s = ARMSSE(obj);
83
// check for a change in timer mode for this processor
86
int i;
84
if ((val & processor) != (s->cputimer_mode & processor)) {
87
85
if (val & processor) { // counter -> user timer
88
- memory_region_init(&s->container, obj, "iotkit-container", UINT64_MAX);
86
@@ -XXX,XX +XXX,XX @@ static void slavio_timer_mem_writel(void *opaque, hwaddr addr,
89
+ memory_region_init(&s->container, obj, "armsse-container", UINT64_MAX);
87
trace_slavio_timer_mem_writel_mode_counter(timer_index);
90
88
}
91
sysbus_init_child_obj(obj, "armv7m", &s->armv7m, sizeof(s->armv7m),
89
}
92
TYPE_ARMV7M);
90
+ ptimer_transaction_commit(curr_timer->timer);
93
@@ -XXX,XX +XXX,XX @@ static void iotkit_init(Object *obj)
91
}
94
sizeof(s->nswatchdog), TYPE_CMSDK_APB_WATCHDOG);
92
} else {
95
sysbus_init_child_obj(obj, "swatchdog", &s->swatchdog,
93
trace_slavio_timer_mem_writel_mode_invalid();
96
sizeof(s->swatchdog), TYPE_CMSDK_APB_WATCHDOG);
94
@@ -XXX,XX +XXX,XX @@ static void slavio_timer_reset(DeviceState *d)
97
- sysbus_init_child_obj(obj, "iotkit-sysctl", &s->sysctl,
95
curr_timer->count = 0;
98
+ sysbus_init_child_obj(obj, "armsse-sysctl", &s->sysctl,
96
curr_timer->reached = 0;
99
sizeof(s->sysctl), TYPE_IOTKIT_SYSCTL);
97
if (i <= s->num_cpus) {
100
- sysbus_init_child_obj(obj, "iotkit-sysinfo", &s->sysinfo,
98
+ ptimer_transaction_begin(curr_timer->timer);
101
+ sysbus_init_child_obj(obj, "armsse-sysinfo", &s->sysinfo,
99
ptimer_set_limit(curr_timer->timer,
102
sizeof(s->sysinfo), TYPE_IOTKIT_SYSINFO);
100
LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 1);
103
object_initialize_child(obj, "nmi-orgate", &s->nmi_orgate,
101
ptimer_run(curr_timer->timer, 0);
104
sizeof(s->nmi_orgate), TYPE_OR_IRQ,
102
curr_timer->run = 1;
105
@@ -XXX,XX +XXX,XX @@ static void iotkit_init(Object *obj)
103
+ ptimer_transaction_commit(curr_timer->timer);
106
}
104
}
107
}
105
}
108
106
s->cputimer_mode = 0;
109
-static void iotkit_exp_irq(void *opaque, int n, int level)
107
@@ -XXX,XX +XXX,XX @@ static void slavio_timer_init(Object *obj)
110
+static void armsse_exp_irq(void *opaque, int n, int level)
108
{
111
{
109
SLAVIO_TIMERState *s = SLAVIO_TIMER(obj);
112
ARMSSE *s = ARMSSE(opaque);
110
SysBusDevice *dev = SYS_BUS_DEVICE(obj);
113
111
- QEMUBH *bh;
114
qemu_set_irq(s->exp_irqs[n], level);
112
unsigned int i;
115
}
113
TimerContext *tc;
116
114
117
-static void iotkit_mpcexp_status(void *opaque, int n, int level)
115
@@ -XXX,XX +XXX,XX @@ static void slavio_timer_init(Object *obj)
118
+static void armsse_mpcexp_status(void *opaque, int n, int level)
116
tc->s = s;
119
{
117
tc->timer_index = i;
120
ARMSSE *s = ARMSSE(opaque);
118
121
qemu_set_irq(s->mpcexp_status_in[n], level);
119
- bh = qemu_bh_new(slavio_timer_irq, tc);
122
}
120
- s->cputimer[i].timer = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
123
121
+ s->cputimer[i].timer = ptimer_init(slavio_timer_irq, tc,
124
-static void iotkit_realize(DeviceState *dev, Error **errp)
122
+ PTIMER_POLICY_DEFAULT);
125
+static void armsse_realize(DeviceState *dev, Error **errp)
123
+ ptimer_transaction_begin(s->cputimer[i].timer);
126
{
124
ptimer_set_period(s->cputimer[i].timer, TIMER_PERIOD);
127
ARMSSE *s = ARMSSE(dev);
125
+ ptimer_transaction_commit(s->cputimer[i].timer);
128
int i;
126
129
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
127
size = i == 0 ? SYS_TIMER_SIZE : CPU_TIMER_SIZE;
130
for (i = 0; i < s->exp_numirq; i++) {
128
snprintf(timer_name, sizeof(timer_name), "timer-%i", i);
131
s->exp_irqs[i] = qdev_get_gpio_in(DEVICE(&s->armv7m), i + 32);
132
}
133
- qdev_init_gpio_in_named(dev, iotkit_exp_irq, "EXP_IRQ", s->exp_numirq);
134
+ qdev_init_gpio_in_named(dev, armsse_exp_irq, "EXP_IRQ", s->exp_numirq);
135
136
/* Set up the big aliases first */
137
make_alias(s, &s->alias1, "alias 1", 0x10000000, 0x10000000, 0x00000000);
138
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
139
qdev_get_gpio_in(dev_splitter, 0));
140
141
/* This RAM lives behind the Memory Protection Controller */
142
- memory_region_init_ram(&s->sram0, NULL, "iotkit.sram0", 0x00008000, &err);
143
+ memory_region_init_ram(&s->sram0, NULL, "armsse.sram0", 0x00008000, &err);
144
if (err) {
145
error_propagate(errp, err);
146
return;
147
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
148
for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) {
149
char *ppcname = g_strdup_printf("ahb_ppcexp%d", i);
150
151
- iotkit_forward_ppc(s, ppcname, i);
152
+ armsse_forward_ppc(s, ppcname, i);
153
g_free(ppcname);
154
}
155
156
for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) {
157
char *ppcname = g_strdup_printf("apb_ppcexp%d", i);
158
159
- iotkit_forward_ppc(s, ppcname, i + IOTS_NUM_AHB_EXP_PPC);
160
+ armsse_forward_ppc(s, ppcname, i + IOTS_NUM_AHB_EXP_PPC);
161
g_free(ppcname);
162
}
163
164
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
165
/* Create GPIO inputs which will pass the line state for our
166
* mpcexp_irq inputs to the correct splitter devices.
167
*/
168
- qdev_init_gpio_in_named(dev, iotkit_mpcexp_status, "mpcexp_status",
169
+ qdev_init_gpio_in_named(dev, armsse_mpcexp_status, "mpcexp_status",
170
IOTS_NUM_EXP_MPC);
171
172
- iotkit_forward_sec_resp_cfg(s);
173
+ armsse_forward_sec_resp_cfg(s);
174
175
/* Forward the MSC related signals */
176
qdev_pass_gpios(dev_secctl, dev, "mscexp_status");
177
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
178
system_clock_scale = NANOSECONDS_PER_SECOND / s->mainclk_frq;
179
}
180
181
-static void iotkit_idau_check(IDAUInterface *ii, uint32_t address,
182
+static void armsse_idau_check(IDAUInterface *ii, uint32_t address,
183
int *iregion, bool *exempt, bool *ns, bool *nsc)
184
{
185
/*
186
@@ -XXX,XX +XXX,XX @@ static void iotkit_idau_check(IDAUInterface *ii, uint32_t address,
187
*iregion = region;
188
}
189
190
-static const VMStateDescription iotkit_vmstate = {
191
+static const VMStateDescription armsse_vmstate = {
192
.name = "iotkit",
193
.version_id = 1,
194
.minimum_version_id = 1,
195
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription iotkit_vmstate = {
196
}
197
};
198
199
-static Property iotkit_properties[] = {
200
+static Property armsse_properties[] = {
201
DEFINE_PROP_LINK("memory", ARMSSE, board_memory, TYPE_MEMORY_REGION,
202
MemoryRegion *),
203
DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
204
@@ -XXX,XX +XXX,XX @@ static Property iotkit_properties[] = {
205
DEFINE_PROP_END_OF_LIST()
206
};
207
208
-static void iotkit_reset(DeviceState *dev)
209
+static void armsse_reset(DeviceState *dev)
210
{
211
ARMSSE *s = ARMSSE(dev);
212
213
s->nsccfg = 0;
214
}
215
216
-static void iotkit_class_init(ObjectClass *klass, void *data)
217
+static void armsse_class_init(ObjectClass *klass, void *data)
218
{
219
DeviceClass *dc = DEVICE_CLASS(klass);
220
IDAUInterfaceClass *iic = IDAU_INTERFACE_CLASS(klass);
221
ARMSSEClass *asc = ARMSSE_CLASS(klass);
222
223
- dc->realize = iotkit_realize;
224
- dc->vmsd = &iotkit_vmstate;
225
- dc->props = iotkit_properties;
226
- dc->reset = iotkit_reset;
227
- iic->check = iotkit_idau_check;
228
+ dc->realize = armsse_realize;
229
+ dc->vmsd = &armsse_vmstate;
230
+ dc->props = armsse_properties;
231
+ dc->reset = armsse_reset;
232
+ iic->check = armsse_idau_check;
233
asc->info = data;
234
}
235
236
@@ -XXX,XX +XXX,XX @@ static const TypeInfo armsse_info = {
237
.name = TYPE_ARMSSE,
238
.parent = TYPE_SYS_BUS_DEVICE,
239
.instance_size = sizeof(ARMSSE),
240
- .instance_init = iotkit_init,
241
+ .instance_init = armsse_init,
242
.abstract = true,
243
.interfaces = (InterfaceInfo[]) {
244
{ TYPE_IDAU_INTERFACE },
245
@@ -XXX,XX +XXX,XX @@ static void armsse_register_types(void)
246
TypeInfo ti = {
247
.name = armsse_variants[i].name,
248
.parent = TYPE_ARMSSE,
249
- .class_init = iotkit_class_init,
250
+ .class_init = armsse_class_init,
251
.class_data = (void *)&armsse_variants[i],
252
};
253
type_register(&ti);
129
--
254
--
130
2.20.1
255
2.20.1
131
256
132
257
diff view generated by jsdifflib
1
In the slavio timer devcie, the ptimer TimerContext::timer is
1
Rename the files that used to be iotkit.[ch] to
2
always created by slavio_timer_init(), so there's no need to
2
armsse.[ch] to reflect the fact they new cover
3
check it for NULL; remove the single unneeded NULL check.
3
multiple Arm subsystems for embedded.
4
5
This will be useful to avoid compiler/Coverity errors when
6
a subsequent change adds a use of t->timer before the location
7
we currently do the NULL check.
8
4
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20191021134357.14266-2-peter.maydell@linaro.org
8
Message-id: 20190121185118.18550-8-peter.maydell@linaro.org
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
9
---
15
hw/timer/slavio_timer.c | 12 +++++-------
10
hw/arm/Makefile.objs | 2 +-
16
1 file changed, 5 insertions(+), 7 deletions(-)
11
include/hw/arm/{iotkit.h => armsse.h} | 4 ++--
12
hw/arm/{iotkit.c => armsse.c} | 2 +-
13
hw/arm/mps2-tz.c | 2 +-
14
MAINTAINERS | 4 ++--
15
default-configs/arm-softmmu.mak | 2 +-
16
6 files changed, 8 insertions(+), 8 deletions(-)
17
rename include/hw/arm/{iotkit.h => armsse.h} (99%)
18
rename hw/arm/{iotkit.c => armsse.c} (99%)
17
19
18
diff --git a/hw/timer/slavio_timer.c b/hw/timer/slavio_timer.c
20
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
19
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/timer/slavio_timer.c
22
--- a/hw/arm/Makefile.objs
21
+++ b/hw/timer/slavio_timer.c
23
+++ b/hw/arm/Makefile.objs
22
@@ -XXX,XX +XXX,XX @@ static void slavio_timer_mem_writel(void *opaque, hwaddr addr,
24
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_ASPEED_SOC) += aspeed_soc.o aspeed.o
23
// set limit, reset counter
25
obj-$(CONFIG_MPS2) += mps2.o
24
qemu_irq_lower(t->irq);
26
obj-$(CONFIG_MPS2) += mps2-tz.o
25
t->limit = val & TIMER_MAX_COUNT32;
27
obj-$(CONFIG_MSF2) += msf2-soc.o msf2-som.o
26
- if (t->timer) {
28
-obj-$(CONFIG_IOTKIT) += iotkit.o
27
- if (t->limit == 0) { /* free-run */
29
+obj-$(CONFIG_ARMSSE) += armsse.o
28
- ptimer_set_limit(t->timer,
30
obj-$(CONFIG_FSL_IMX7) += fsl-imx7.o mcimx7d-sabre.o
29
- LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 1);
31
obj-$(CONFIG_ARM_SMMUV3) += smmu-common.o smmuv3.o
30
- } else {
32
obj-$(CONFIG_FSL_IMX6UL) += fsl-imx6ul.o mcimx6ul-evk.o
31
- ptimer_set_limit(t->timer, LIMIT_TO_PERIODS(t->limit), 1);
33
diff --git a/include/hw/arm/iotkit.h b/include/hw/arm/armsse.h
32
- }
34
similarity index 99%
33
+ if (t->limit == 0) { /* free-run */
35
rename from include/hw/arm/iotkit.h
34
+ ptimer_set_limit(t->timer,
36
rename to include/hw/arm/armsse.h
35
+ LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 1);
37
index XXXXXXX..XXXXXXX 100644
36
+ } else {
38
--- a/include/hw/arm/iotkit.h
37
+ ptimer_set_limit(t->timer, LIMIT_TO_PERIODS(t->limit), 1);
39
+++ b/include/hw/arm/armsse.h
38
}
40
@@ -XXX,XX +XXX,XX @@
39
}
41
* + named GPIO outputs mscexp_ns[0..15]
40
break;
42
*/
43
44
-#ifndef IOTKIT_H
45
-#define IOTKIT_H
46
+#ifndef ARMSSE_H
47
+#define ARMSSE_H
48
49
#include "hw/sysbus.h"
50
#include "hw/arm/armv7m.h"
51
diff --git a/hw/arm/iotkit.c b/hw/arm/armsse.c
52
similarity index 99%
53
rename from hw/arm/iotkit.c
54
rename to hw/arm/armsse.c
55
index XXXXXXX..XXXXXXX 100644
56
--- a/hw/arm/iotkit.c
57
+++ b/hw/arm/armsse.c
58
@@ -XXX,XX +XXX,XX @@
59
#include "trace.h"
60
#include "hw/sysbus.h"
61
#include "hw/registerfields.h"
62
-#include "hw/arm/iotkit.h"
63
+#include "hw/arm/armsse.h"
64
#include "hw/arm/arm.h"
65
66
struct ARMSSEInfo {
67
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
68
index XXXXXXX..XXXXXXX 100644
69
--- a/hw/arm/mps2-tz.c
70
+++ b/hw/arm/mps2-tz.c
71
@@ -XXX,XX +XXX,XX @@
72
#include "hw/misc/mps2-fpgaio.h"
73
#include "hw/misc/tz-mpc.h"
74
#include "hw/misc/tz-msc.h"
75
-#include "hw/arm/iotkit.h"
76
+#include "hw/arm/armsse.h"
77
#include "hw/dma/pl080.h"
78
#include "hw/ssi/pl022.h"
79
#include "hw/devices.h"
80
diff --git a/MAINTAINERS b/MAINTAINERS
81
index XXXXXXX..XXXXXXX 100644
82
--- a/MAINTAINERS
83
+++ b/MAINTAINERS
84
@@ -XXX,XX +XXX,XX @@ F: hw/arm/mps2.c
85
F: hw/arm/mps2-tz.c
86
F: hw/misc/mps2-*.c
87
F: include/hw/misc/mps2-*.h
88
-F: hw/arm/iotkit.c
89
-F: include/hw/arm/iotkit.h
90
+F: hw/arm/armsse.c
91
+F: include/hw/arm/armsse.h
92
F: hw/misc/iotkit-secctl.c
93
F: include/hw/misc/iotkit-secctl.h
94
F: hw/misc/iotkit-sysctl.c
95
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
96
index XXXXXXX..XXXXXXX 100644
97
--- a/default-configs/arm-softmmu.mak
98
+++ b/default-configs/arm-softmmu.mak
99
@@ -XXX,XX +XXX,XX @@ CONFIG_MPS2_SCC=y
100
CONFIG_TZ_MPC=y
101
CONFIG_TZ_MSC=y
102
CONFIG_TZ_PPC=y
103
-CONFIG_IOTKIT=y
104
+CONFIG_ARMSSE=y
105
CONFIG_IOTKIT_SECCTL=y
106
CONFIG_IOTKIT_SYSCTL=y
107
CONFIG_IOTKIT_SYSINFO=y
41
--
108
--
42
2.20.1
109
2.20.1
43
110
44
111
diff view generated by jsdifflib
1
Switch the milkymist-sysctl code away from bottom-half based
1
The SSE-200 has 4 banks of SRAM, each with its own internal
2
ptimers to the new transaction-based ptimer API. This just requires
2
Memory Protection Controller. The interrupt status for these
3
adding begin/commit calls around the various places that modify the
3
extra MPCs appears in the same security controller SECMPCINTSTATUS
4
ptimer state, and using the new ptimer_init() function to create the
4
register as the MPC for the IoTKit's single SRAM bank. Enhance the
5
timer.
5
iotkit-secctl device to allow 4 MPCs. (If the particular IoTKit/SSE
6
variant in use does not have all 4 MPCs then the unused inputs will
7
simply result in the SECMPCINTSTATUS bits being zero as required.)
8
9
The hardcoded constant "1"s in armsse.c indicate the actual number
10
of SRAM MPCs the IoTKit has, and will be replaced in the following
11
commit.
6
12
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20191021141040.11007-1-peter.maydell@linaro.org
15
Message-id: 20190121185118.18550-9-peter.maydell@linaro.org
10
---
16
---
11
hw/timer/milkymist-sysctl.c | 25 ++++++++++++++++++-------
17
include/hw/misc/iotkit-secctl.h | 6 +++---
12
1 file changed, 18 insertions(+), 7 deletions(-)
18
hw/arm/armsse.c | 6 +++---
19
hw/misc/iotkit-secctl.c | 5 +++--
20
3 files changed, 9 insertions(+), 8 deletions(-)
13
21
14
diff --git a/hw/timer/milkymist-sysctl.c b/hw/timer/milkymist-sysctl.c
22
diff --git a/include/hw/misc/iotkit-secctl.h b/include/hw/misc/iotkit-secctl.h
15
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/timer/milkymist-sysctl.c
24
--- a/include/hw/misc/iotkit-secctl.h
17
+++ b/hw/timer/milkymist-sysctl.c
25
+++ b/include/hw/misc/iotkit-secctl.h
18
@@ -XXX,XX +XXX,XX @@
26
@@ -XXX,XX +XXX,XX @@
19
#include "hw/ptimer.h"
27
* + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_enable
20
#include "hw/qdev-properties.h"
28
* + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_clear
21
#include "qemu/error-report.h"
29
* + named GPIO inputs ahb_ppcexp{0,1,2,3}_irq_status
22
-#include "qemu/main-loop.h"
30
- * Controlling the MPC in the IoTKit:
23
#include "qemu/module.h"
31
- * + named GPIO input mpc_status
24
32
+ * Controlling the (up to) 4 MPCs in the IoTKit/SSE:
25
enum {
33
+ * + named GPIO inputs mpc_status[0..3]
26
@@ -XXX,XX +XXX,XX @@ struct MilkymistSysctlState {
34
* Controlling each of the 16 expansion MPCs which a system using the IoTKit
27
35
* might provide:
28
MemoryRegion regs_region;
36
* + named GPIO inputs mpcexp_status[0..15]
29
37
@@ -XXX,XX +XXX,XX @@
30
- QEMUBH *bh0;
38
#define IOTS_NUM_APB_EXP_PPC 4
31
- QEMUBH *bh1;
39
#define IOTS_NUM_AHB_EXP_PPC 4
32
ptimer_state *ptimer0;
40
#define IOTS_NUM_EXP_MPC 16
33
ptimer_state *ptimer1;
41
-#define IOTS_NUM_MPC 1
34
42
+#define IOTS_NUM_MPC 4
35
@@ -XXX,XX +XXX,XX @@ static void sysctl_write(void *opaque, hwaddr addr, uint64_t value,
43
#define IOTS_NUM_EXP_MSC 16
36
s->regs[addr] = value;
44
37
break;
45
typedef struct IoTKitSecCtl IoTKitSecCtl;
38
case R_TIMER0_COMPARE:
46
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
39
+ ptimer_transaction_begin(s->ptimer0);
47
index XXXXXXX..XXXXXXX 100644
40
ptimer_set_limit(s->ptimer0, value, 0);
48
--- a/hw/arm/armsse.c
41
s->regs[addr] = value;
49
+++ b/hw/arm/armsse.c
42
+ ptimer_transaction_commit(s->ptimer0);
50
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
43
break;
51
sizeof(s->mpc_irq_orgate), TYPE_OR_IRQ,
44
case R_TIMER1_COMPARE:
52
&error_abort, NULL);
45
+ ptimer_transaction_begin(s->ptimer1);
53
46
ptimer_set_limit(s->ptimer1, value, 0);
54
- for (i = 0; i < ARRAY_SIZE(s->mpc_irq_splitter); i++) {
47
s->regs[addr] = value;
55
+ for (i = 0; i < IOTS_NUM_EXP_MPC + 1; i++) {
48
+ ptimer_transaction_commit(s->ptimer1);
56
char *name = g_strdup_printf("mpc-irq-splitter-%d", i);
49
break;
57
SplitIRQ *splitter = &s->mpc_irq_splitter[i];
50
case R_TIMER0_CONTROL:
58
51
+ ptimer_transaction_begin(s->ptimer0);
59
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
52
s->regs[addr] = value;
60
53
if (s->regs[R_TIMER0_CONTROL] & CTRL_ENABLE) {
61
/* We must OR together lines from the MPC splitters to go to the NVIC */
54
trace_milkymist_sysctl_start_timer0();
62
object_property_set_int(OBJECT(&s->mpc_irq_orgate),
55
@@ -XXX,XX +XXX,XX @@ static void sysctl_write(void *opaque, hwaddr addr, uint64_t value,
63
- IOTS_NUM_EXP_MPC + IOTS_NUM_MPC, "num-lines", &err);
56
trace_milkymist_sysctl_stop_timer0();
64
+ IOTS_NUM_EXP_MPC + 1, "num-lines", &err);
57
ptimer_stop(s->ptimer0);
65
if (err) {
58
}
66
error_propagate(errp, err);
59
+ ptimer_transaction_commit(s->ptimer0);
67
return;
60
break;
68
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
61
case R_TIMER1_CONTROL:
62
+ ptimer_transaction_begin(s->ptimer1);
63
s->regs[addr] = value;
64
if (s->regs[R_TIMER1_CONTROL] & CTRL_ENABLE) {
65
trace_milkymist_sysctl_start_timer1();
66
@@ -XXX,XX +XXX,XX @@ static void sysctl_write(void *opaque, hwaddr addr, uint64_t value,
67
trace_milkymist_sysctl_stop_timer1();
68
ptimer_stop(s->ptimer1);
69
}
70
+ ptimer_transaction_commit(s->ptimer1);
71
break;
72
case R_ICAP:
73
sysctl_icap_write(s, value);
74
@@ -XXX,XX +XXX,XX @@ static void milkymist_sysctl_reset(DeviceState *d)
75
s->regs[i] = 0;
76
}
69
}
77
70
78
+ ptimer_transaction_begin(s->ptimer0);
71
/* Wire up the splitters for the MPC IRQs */
79
ptimer_stop(s->ptimer0);
72
- for (i = 0; i < IOTS_NUM_EXP_MPC + IOTS_NUM_MPC; i++) {
80
+ ptimer_transaction_commit(s->ptimer0);
73
+ for (i = 0; i < IOTS_NUM_EXP_MPC + 1; i++) {
81
+ ptimer_transaction_begin(s->ptimer1);
74
SplitIRQ *splitter = &s->mpc_irq_splitter[i];
82
ptimer_stop(s->ptimer1);
75
DeviceState *dev_splitter = DEVICE(splitter);
83
+ ptimer_transaction_commit(s->ptimer1);
76
84
77
diff --git a/hw/misc/iotkit-secctl.c b/hw/misc/iotkit-secctl.c
85
/* defaults */
78
index XXXXXXX..XXXXXXX 100644
86
s->regs[R_ICAP] = ICAP_READY;
79
--- a/hw/misc/iotkit-secctl.c
87
@@ -XXX,XX +XXX,XX @@ static void milkymist_sysctl_realize(DeviceState *dev, Error **errp)
80
+++ b/hw/misc/iotkit-secctl.c
81
@@ -XXX,XX +XXX,XX @@ static void iotkit_secctl_mpc_status(void *opaque, int n, int level)
88
{
82
{
89
MilkymistSysctlState *s = MILKYMIST_SYSCTL(dev);
83
IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
90
84
91
- s->bh0 = qemu_bh_new(timer0_hit, s);
85
- s->mpcintstatus = deposit32(s->mpcintstatus, 0, 1, !!level);
92
- s->bh1 = qemu_bh_new(timer1_hit, s);
86
+ s->mpcintstatus = deposit32(s->mpcintstatus, n, 1, !!level);
93
- s->ptimer0 = ptimer_init_with_bh(s->bh0, PTIMER_POLICY_DEFAULT);
94
- s->ptimer1 = ptimer_init_with_bh(s->bh1, PTIMER_POLICY_DEFAULT);
95
+ s->ptimer0 = ptimer_init(timer0_hit, s, PTIMER_POLICY_DEFAULT);
96
+ s->ptimer1 = ptimer_init(timer1_hit, s, PTIMER_POLICY_DEFAULT);
97
98
+ ptimer_transaction_begin(s->ptimer0);
99
ptimer_set_freq(s->ptimer0, s->freq_hz);
100
+ ptimer_transaction_commit(s->ptimer0);
101
+ ptimer_transaction_begin(s->ptimer1);
102
ptimer_set_freq(s->ptimer1, s->freq_hz);
103
+ ptimer_transaction_commit(s->ptimer1);
104
}
87
}
105
88
106
static const VMStateDescription vmstate_milkymist_sysctl = {
89
static void iotkit_secctl_mpcexp_status(void *opaque, int n, int level)
90
@@ -XXX,XX +XXX,XX @@ static void iotkit_secctl_init(Object *obj)
91
qdev_init_gpio_out_named(dev, &s->sec_resp_cfg, "sec_resp_cfg", 1);
92
qdev_init_gpio_out_named(dev, &s->nsc_cfg_irq, "nsc_cfg", 1);
93
94
- qdev_init_gpio_in_named(dev, iotkit_secctl_mpc_status, "mpc_status", 1);
95
+ qdev_init_gpio_in_named(dev, iotkit_secctl_mpc_status, "mpc_status",
96
+ IOTS_NUM_MPC);
97
qdev_init_gpio_in_named(dev, iotkit_secctl_mpcexp_status,
98
"mpcexp_status", IOTS_NUM_EXP_MPC);
99
107
--
100
--
108
2.20.1
101
2.20.1
109
102
110
103
diff view generated by jsdifflib
1
Switch the xilinx_timer code away from bottom-half based ptimers to
1
The SSE-200 has four banks of SRAM, each with its own
2
the new transaction-based ptimer API. This just requires adding
2
Memory Protection Controller, where the IoTKit has only one.
3
begin/commit calls around the various places that modify the ptimer
3
Make the number of SRAM banks a field in ARMSSEInfo.
4
state, and using the new ptimer_init() function to create the timer.
5
4
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Message-id: 20190121185118.18550-10-peter.maydell@linaro.org
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
Message-id: 20191017132122.4402-3-peter.maydell@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
8
---
13
hw/timer/xilinx_timer.c | 13 ++++++++-----
9
include/hw/arm/armsse.h | 9 +++--
14
1 file changed, 8 insertions(+), 5 deletions(-)
10
hw/arm/armsse.c | 78 ++++++++++++++++++++++++++---------------
11
2 files changed, 56 insertions(+), 31 deletions(-)
15
12
16
diff --git a/hw/timer/xilinx_timer.c b/hw/timer/xilinx_timer.c
13
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
17
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/timer/xilinx_timer.c
15
--- a/include/hw/arm/armsse.h
19
+++ b/hw/timer/xilinx_timer.c
16
+++ b/include/hw/arm/armsse.h
20
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@
21
#include "hw/ptimer.h"
18
#define NUM_EXTERNAL_PPCS (IOTS_NUM_AHB_EXP_PPC + IOTS_NUM_APB_EXP_PPC)
22
#include "hw/qdev-properties.h"
19
#define NUM_PPCS (NUM_EXTERNAL_PPCS + 2)
23
#include "qemu/log.h"
20
24
-#include "qemu/main-loop.h"
21
+#define MAX_SRAM_BANKS 4
25
#include "qemu/module.h"
22
+#if MAX_SRAM_BANKS > IOTS_NUM_MPC
26
23
+#error Too many SRAM banks
27
#define D(x)
24
+#endif
25
+
26
typedef struct ARMSSE {
27
/*< private >*/
28
SysBusDevice parent_obj;
29
@@ -XXX,XX +XXX,XX @@ typedef struct ARMSSE {
30
IoTKitSecCtl secctl;
31
TZPPC apb_ppc0;
32
TZPPC apb_ppc1;
33
- TZMPC mpc;
34
+ TZMPC mpc[IOTS_NUM_MPC];
35
CMSDKAPBTIMER timer0;
36
CMSDKAPBTIMER timer1;
37
CMSDKAPBTIMER s32ktimer;
38
@@ -XXX,XX +XXX,XX @@ typedef struct ARMSSE {
39
MemoryRegion alias1;
40
MemoryRegion alias2;
41
MemoryRegion alias3;
42
- MemoryRegion sram0;
43
+ MemoryRegion sram[MAX_SRAM_BANKS];
44
45
qemu_irq *exp_irqs;
46
qemu_irq ppc0_irq;
47
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/hw/arm/armsse.c
50
+++ b/hw/arm/armsse.c
28
@@ -XXX,XX +XXX,XX @@
51
@@ -XXX,XX +XXX,XX @@
29
52
30
struct xlx_timer
53
struct ARMSSEInfo {
54
const char *name;
55
+ int sram_banks;
56
};
57
58
static const ARMSSEInfo armsse_variants[] = {
59
{
60
.name = TYPE_IOTKIT,
61
+ .sram_banks = 1,
62
},
63
};
64
65
@@ -XXX,XX +XXX,XX @@ static void armsse_forward_sec_resp_cfg(ARMSSE *s)
66
static void armsse_init(Object *obj)
31
{
67
{
32
- QEMUBH *bh;
68
ARMSSE *s = ARMSSE(obj);
33
ptimer_state *ptimer;
69
+ ARMSSEClass *asc = ARMSSE_GET_CLASS(obj);
34
void *parent;
70
+ const ARMSSEInfo *info = asc->info;
35
int nr; /* for debug. */
71
int i;
36
@@ -XXX,XX +XXX,XX @@ timer_read(void *opaque, hwaddr addr, unsigned int size)
72
37
return r;
73
+ assert(info->sram_banks <= MAX_SRAM_BANKS);
38
}
74
+
39
75
memory_region_init(&s->container, obj, "armsse-container", UINT64_MAX);
40
+/* Must be called inside ptimer transaction block */
76
41
static void timer_enable(struct xlx_timer *xt)
77
sysbus_init_child_obj(obj, "armv7m", &s->armv7m, sizeof(s->armv7m),
78
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
79
TYPE_TZ_PPC);
80
sysbus_init_child_obj(obj, "apb-ppc1", &s->apb_ppc1, sizeof(s->apb_ppc1),
81
TYPE_TZ_PPC);
82
- sysbus_init_child_obj(obj, "mpc", &s->mpc, sizeof(s->mpc), TYPE_TZ_MPC);
83
+ for (i = 0; i < info->sram_banks; i++) {
84
+ char *name = g_strdup_printf("mpc%d", i);
85
+ sysbus_init_child_obj(obj, name, &s->mpc[i],
86
+ sizeof(s->mpc[i]), TYPE_TZ_MPC);
87
+ g_free(name);
88
+ }
89
object_initialize_child(obj, "mpc-irq-orgate", &s->mpc_irq_orgate,
90
sizeof(s->mpc_irq_orgate), TYPE_OR_IRQ,
91
&error_abort, NULL);
92
93
- for (i = 0; i < IOTS_NUM_EXP_MPC + 1; i++) {
94
+ for (i = 0; i < IOTS_NUM_EXP_MPC + info->sram_banks; i++) {
95
char *name = g_strdup_printf("mpc-irq-splitter-%d", i);
96
SplitIRQ *splitter = &s->mpc_irq_splitter[i];
97
98
@@ -XXX,XX +XXX,XX @@ static void armsse_mpcexp_status(void *opaque, int n, int level)
99
static void armsse_realize(DeviceState *dev, Error **errp)
42
{
100
{
43
uint64_t count;
101
ARMSSE *s = ARMSSE(dev);
44
@@ -XXX,XX +XXX,XX @@ timer_write(void *opaque, hwaddr addr,
102
+ ARMSSEClass *asc = ARMSSE_GET_CLASS(dev);
45
value &= ~TCSR_TINT;
103
+ const ARMSSEInfo *info = asc->info;
46
104
int i;
47
xt->regs[addr] = value & 0x7ff;
105
MemoryRegion *mr;
48
- if (value & TCSR_ENT)
106
Error *err = NULL;
49
+ if (value & TCSR_ENT) {
107
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
50
+ ptimer_transaction_begin(xt->ptimer);
108
qdev_connect_gpio_out_named(dev_secctl, "sec_resp_cfg", 0,
51
timer_enable(xt);
109
qdev_get_gpio_in(dev_splitter, 0));
52
+ ptimer_transaction_commit(xt->ptimer);
110
53
+ }
111
- /* This RAM lives behind the Memory Protection Controller */
54
break;
112
- memory_region_init_ram(&s->sram0, NULL, "armsse.sram0", 0x00008000, &err);
55
113
- if (err) {
56
default:
114
- error_propagate(errp, err);
57
@@ -XXX,XX +XXX,XX @@ static void xilinx_timer_realize(DeviceState *dev, Error **errp)
115
- return;
58
116
+ /* Each SRAM bank lives behind its own Memory Protection Controller */
59
xt->parent = t;
117
+ for (i = 0; i < info->sram_banks; i++) {
60
xt->nr = i;
118
+ char *ramname = g_strdup_printf("armsse.sram%d", i);
61
- xt->bh = qemu_bh_new(timer_hit, xt);
119
+ SysBusDevice *sbd_mpc;
62
- xt->ptimer = ptimer_init_with_bh(xt->bh, PTIMER_POLICY_DEFAULT);
120
+
63
+ xt->ptimer = ptimer_init(timer_hit, xt, PTIMER_POLICY_DEFAULT);
121
+ memory_region_init_ram(&s->sram[i], NULL, ramname, 0x00008000, &err);
64
+ ptimer_transaction_begin(xt->ptimer);
122
+ g_free(ramname);
65
ptimer_set_freq(xt->ptimer, t->freq_hz);
123
+ if (err) {
66
+ ptimer_transaction_commit(xt->ptimer);
124
+ error_propagate(errp, err);
125
+ return;
126
+ }
127
+ object_property_set_link(OBJECT(&s->mpc[i]), OBJECT(&s->sram[i]),
128
+ "downstream", &err);
129
+ if (err) {
130
+ error_propagate(errp, err);
131
+ return;
132
+ }
133
+ object_property_set_bool(OBJECT(&s->mpc[i]), true, "realized", &err);
134
+ if (err) {
135
+ error_propagate(errp, err);
136
+ return;
137
+ }
138
+ /* Map the upstream end of the MPC into the right place... */
139
+ sbd_mpc = SYS_BUS_DEVICE(&s->mpc[i]);
140
+ memory_region_add_subregion(&s->container, 0x20000000 + i * 0x8000,
141
+ sysbus_mmio_get_region(sbd_mpc, 1));
142
+ /* ...and its register interface */
143
+ memory_region_add_subregion(&s->container, 0x50083000 + i * 0x1000,
144
+ sysbus_mmio_get_region(sbd_mpc, 0));
67
}
145
}
68
146
- object_property_set_link(OBJECT(&s->mpc), OBJECT(&s->sram0),
69
memory_region_init_io(&t->mmio, OBJECT(t), &timer_ops, t, "xlnx.xps-timer",
147
- "downstream", &err);
148
- if (err) {
149
- error_propagate(errp, err);
150
- return;
151
- }
152
- object_property_set_bool(OBJECT(&s->mpc), true, "realized", &err);
153
- if (err) {
154
- error_propagate(errp, err);
155
- return;
156
- }
157
- /* Map the upstream end of the MPC into the right place... */
158
- memory_region_add_subregion(&s->container, 0x20000000,
159
- sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mpc),
160
- 1));
161
- /* ...and its register interface */
162
- memory_region_add_subregion(&s->container, 0x50083000,
163
- sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mpc),
164
- 0));
165
166
/* We must OR together lines from the MPC splitters to go to the NVIC */
167
object_property_set_int(OBJECT(&s->mpc_irq_orgate),
168
- IOTS_NUM_EXP_MPC + 1, "num-lines", &err);
169
+ IOTS_NUM_EXP_MPC + info->sram_banks,
170
+ "num-lines", &err);
171
if (err) {
172
error_propagate(errp, err);
173
return;
174
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
175
}
176
177
/* Wire up the splitters for the MPC IRQs */
178
- for (i = 0; i < IOTS_NUM_EXP_MPC + 1; i++) {
179
+ for (i = 0; i < IOTS_NUM_EXP_MPC + info->sram_banks; i++) {
180
SplitIRQ *splitter = &s->mpc_irq_splitter[i];
181
DeviceState *dev_splitter = DEVICE(splitter);
182
183
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
184
"mpcexp_status", i));
185
} else {
186
/* Splitter input is from our own MPC */
187
- qdev_connect_gpio_out_named(DEVICE(&s->mpc), "irq", 0,
188
+ qdev_connect_gpio_out_named(DEVICE(&s->mpc[i - IOTS_NUM_EXP_MPC]),
189
+ "irq", 0,
190
qdev_get_gpio_in(dev_splitter, 0));
191
qdev_connect_gpio_out(dev_splitter, 0,
192
qdev_get_gpio_in_named(dev_secctl,
70
--
193
--
71
2.20.1
194
2.20.1
72
195
73
196
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
For the IoTKit the SRAM bank size is always 32K (15 bits); for the
2
SSE-200 this is a configurable parameter, which defaults to 32K but
3
can be changed when it is built into a particular SoC. For instance
4
the Musca-B1 board sets it to 128K (17 bits).
2
5
3
This file creates the BCM2836/BCM2837 blocks.
6
Make the bank size a QOM property. We follow the SSE-200 hardware in
4
The biggest differences with the BCM2838 we are going to add, are
7
naming the parameter SRAM_ADDR_WIDTH, which specifies the number of
5
the base addresses of the interrupt controller and the peripherals.
8
address bits of a single SRAM bank.
6
Add these addresses in the BCM283XInfo structure to make this
7
block more modular. Remove the MCORE_OFFSET offset as it is
8
not useful and rather confusing.
9
9
10
Reviewed-by: Esteban Bosse <estebanbosse@gmail.com>
11
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
13
Message-id: 20191019234715.25750-6-f4bug@amsat.org
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20190121185118.18550-11-peter.maydell@linaro.org
15
---
13
---
16
hw/arm/bcm2836.c | 18 +++++++++---------
14
include/hw/arm/armsse.h | 1 +
17
1 file changed, 9 insertions(+), 9 deletions(-)
15
hw/arm/armsse.c | 18 ++++++++++++++++--
16
2 files changed, 17 insertions(+), 2 deletions(-)
18
17
19
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
18
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
20
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/arm/bcm2836.c
20
--- a/include/hw/arm/armsse.h
22
+++ b/hw/arm/bcm2836.c
21
+++ b/include/hw/arm/armsse.h
23
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@ typedef struct ARMSSE {
24
#include "hw/arm/raspi_platform.h"
23
MemoryRegion *board_memory;
25
#include "hw/sysbus.h"
24
uint32_t exp_numirq;
26
25
uint32_t mainclk_frq;
27
-/* Peripheral base address seen by the CPU */
26
+ uint32_t sram_addr_width;
28
-#define BCM2836_PERI_BASE 0x3F000000
27
} ARMSSE;
29
-
28
30
-/* "QA7" (Pi2) interrupt controller and mailboxes etc. */
29
typedef struct ARMSSEInfo ARMSSEInfo;
31
-#define BCM2836_CONTROL_BASE 0x40000000
30
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
32
-
31
index XXXXXXX..XXXXXXX 100644
33
struct BCM283XInfo {
32
--- a/hw/arm/armsse.c
34
const char *name;
33
+++ b/hw/arm/armsse.c
35
const char *cpu_type;
34
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
36
+ hwaddr peri_base; /* Peripheral base address seen by the CPU */
35
DeviceState *dev_apb_ppc1;
37
+ hwaddr ctrl_base; /* Interrupt controller and mailboxes etc. */
36
DeviceState *dev_secctl;
38
int clusterid;
37
DeviceState *dev_splitter;
39
};
38
+ uint32_t addr_width_max;
40
39
41
@@ -XXX,XX +XXX,XX @@ static const BCM283XInfo bcm283x_socs[] = {
40
if (!s->board_memory) {
42
{
41
error_setg(errp, "memory property was not set");
43
.name = TYPE_BCM2836,
42
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
44
.cpu_type = ARM_CPU_TYPE_NAME("cortex-a7"),
45
+ .peri_base = 0x3f000000,
46
+ .ctrl_base = 0x40000000,
47
.clusterid = 0xf,
48
},
49
#ifdef TARGET_AARCH64
50
{
51
.name = TYPE_BCM2837,
52
.cpu_type = ARM_CPU_TYPE_NAME("cortex-a53"),
53
+ .peri_base = 0x3f000000,
54
+ .ctrl_base = 0x40000000,
55
.clusterid = 0x0,
56
},
57
#endif
58
@@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
59
}
60
61
sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->peripherals), 0,
62
- BCM2836_PERI_BASE, 1);
63
+ info->peri_base, 1);
64
65
/* bcm2836 interrupt controller (and mailboxes, etc.) */
66
object_property_set_bool(OBJECT(&s->control), true, "realized", &err);
67
@@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
68
return;
43
return;
69
}
44
}
70
45
71
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->control), 0, BCM2836_CONTROL_BASE);
46
+ /* max SRAM_ADDR_WIDTH: 24 - log2(SRAM_NUM_BANK) */
72
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->control), 0, info->ctrl_base);
47
+ assert(is_power_of_2(info->sram_banks));
73
48
+ addr_width_max = 24 - ctz32(info->sram_banks);
74
sysbus_connect_irq(SYS_BUS_DEVICE(&s->peripherals), 0,
49
+ if (s->sram_addr_width < 1 || s->sram_addr_width > addr_width_max) {
75
qdev_get_gpio_in_named(DEVICE(&s->control), "gpu-irq", 0));
50
+ error_setg(errp, "SRAM_ADDR_WIDTH must be between 1 and %d",
76
@@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
51
+ addr_width_max);
77
52
+ return;
78
/* set periphbase/CBAR value for CPU-local registers */
53
+ }
79
object_property_set_int(OBJECT(&s->cpus[n]),
54
+
80
- BCM2836_PERI_BASE + MSYNC_OFFSET,
55
/* Handling of which devices should be available only to secure
81
+ info->peri_base,
56
* code is usually done differently for M profile than for A profile.
82
"reset-cbar", &err);
57
* Instead of putting some devices only into the secure address space,
58
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
59
for (i = 0; i < info->sram_banks; i++) {
60
char *ramname = g_strdup_printf("armsse.sram%d", i);
61
SysBusDevice *sbd_mpc;
62
+ uint32_t sram_bank_size = 1 << s->sram_addr_width;
63
64
- memory_region_init_ram(&s->sram[i], NULL, ramname, 0x00008000, &err);
65
+ memory_region_init_ram(&s->sram[i], NULL, ramname,
66
+ sram_bank_size, &err);
67
g_free(ramname);
83
if (err) {
68
if (err) {
84
error_propagate(errp, err);
69
error_propagate(errp, err);
70
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
71
}
72
/* Map the upstream end of the MPC into the right place... */
73
sbd_mpc = SYS_BUS_DEVICE(&s->mpc[i]);
74
- memory_region_add_subregion(&s->container, 0x20000000 + i * 0x8000,
75
+ memory_region_add_subregion(&s->container,
76
+ 0x20000000 + i * sram_bank_size,
77
sysbus_mmio_get_region(sbd_mpc, 1));
78
/* ...and its register interface */
79
memory_region_add_subregion(&s->container, 0x50083000 + i * 0x1000,
80
@@ -XXX,XX +XXX,XX @@ static Property armsse_properties[] = {
81
MemoryRegion *),
82
DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
83
DEFINE_PROP_UINT32("MAINCLK", ARMSSE, mainclk_frq, 0),
84
+ DEFINE_PROP_UINT32("SRAM_ADDR_WIDTH", ARMSSE, sram_addr_width, 15),
85
DEFINE_PROP_END_OF_LIST()
86
};
87
85
--
88
--
86
2.20.1
89
2.20.1
87
90
88
91
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The SSE-200 has two Cortex-M33 CPUs. These see the same view
2
of memory, with the exception of the "private CPU region" which
3
has per-CPU devices. Internal device interrupts for SSE-200
4
devices are mostly wired up to both CPUs, with the exception of
5
a few per-CPU devices. External GPIO inputs on the SSE-200
6
device are provided for the second CPU's interrupts above 32,
7
as is already the case for the first CPU.
2
8
3
This function assumes nothing about the current state of the cpu,
9
Refactor the code to support creation of multiple CPUs.
4
and writes the computed value to env->hflags.
10
For the moment we leave all CPUs with the same view of
11
memory: this will not work in the multiple-CPU case, but
12
we will fix this in the following commit.
5
13
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20191023150057.25731-13-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 20190121185118.18550-12-peter.maydell@linaro.org
10
---
17
---
11
target/arm/cpu.h | 6 ++++++
18
include/hw/arm/armsse.h | 21 +++-
12
target/arm/helper.c | 30 ++++++++++++++++++++++--------
19
hw/arm/armsse.c | 206 ++++++++++++++++++++++++++++++++--------
13
2 files changed, 28 insertions(+), 8 deletions(-)
20
2 files changed, 180 insertions(+), 47 deletions(-)
14
21
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
22
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
16
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/cpu.h
24
--- a/include/hw/arm/armsse.h
18
+++ b/target/arm/cpu.h
25
+++ b/include/hw/arm/armsse.h
19
@@ -XXX,XX +XXX,XX @@ void arm_register_pre_el_change_hook(ARMCPU *cpu, ARMELChangeHookFn *hook,
26
@@ -XXX,XX +XXX,XX @@
20
void arm_register_el_change_hook(ARMCPU *cpu, ARMELChangeHookFn *hook, void
27
* + QOM property "memory" is a MemoryRegion containing the devices provided
21
*opaque);
28
* by the board model.
22
29
* + QOM property "MAINCLK" is the frequency of the main system clock
23
+/**
30
- * + QOM property "EXP_NUMIRQ" sets the number of expansion interrupts
24
+ * arm_rebuild_hflags:
31
- * + Named GPIO inputs "EXP_IRQ" 0..n are the expansion interrupts, which
25
+ * Rebuild the cached TBFLAGS for arbitrary changed processor state.
32
- * are wired to the NVIC lines 32 .. n+32
26
+ */
33
+ * + QOM property "EXP_NUMIRQ" sets the number of expansion interrupts.
27
+void arm_rebuild_hflags(CPUARMState *env);
34
+ * (In hardware, the SSE-200 permits the number of expansion interrupts
28
+
35
+ * for the two CPUs to be configured separately, but we restrict it to
29
/**
36
+ * being the same for both, to avoid having to have separate Property
30
* aa32_vfp_dreg:
37
+ * lists for different variants. This restriction can be relaxed later
31
* Return a pointer to the Dn register within env in 32-bit mode.
38
+ * if necessary.)
32
diff --git a/target/arm/helper.c b/target/arm/helper.c
39
+ * + Named GPIO inputs "EXP_IRQ" 0..n are the expansion interrupts for CPU 0,
40
+ * which are wired to its NVIC lines 32 .. n+32
41
+ * + Named GPIO inputs "EXP_CPU1_IRQ" 0..n are the expansion interrupts for
42
+ * CPU 1, which are wired to its NVIC lines 32 .. n+32
43
* + sysbus MMIO region 0 is the "AHB Slave Expansion" which allows
44
* bus master devices in the board model to make transactions into
45
* all the devices and memory areas in the IoTKit
46
@@ -XXX,XX +XXX,XX @@
47
#error Too many SRAM banks
48
#endif
49
50
+#define SSE_MAX_CPUS 2
51
+
52
typedef struct ARMSSE {
53
/*< private >*/
54
SysBusDevice parent_obj;
55
56
/*< public >*/
57
- ARMv7MState armv7m;
58
+ ARMv7MState armv7m[SSE_MAX_CPUS];
59
IoTKitSecCtl secctl;
60
TZPPC apb_ppc0;
61
TZPPC apb_ppc1;
62
@@ -XXX,XX +XXX,XX @@ typedef struct ARMSSE {
63
qemu_or_irq mpc_irq_orgate;
64
qemu_or_irq nmi_orgate;
65
66
+ SplitIRQ cpu_irq_splitter[32];
67
+
68
CMSDKAPBDualTimer dualtimer;
69
70
CMSDKAPBWatchdog s32kwatchdog;
71
@@ -XXX,XX +XXX,XX @@ typedef struct ARMSSE {
72
MemoryRegion alias3;
73
MemoryRegion sram[MAX_SRAM_BANKS];
74
75
- qemu_irq *exp_irqs;
76
+ qemu_irq *exp_irqs[SSE_MAX_CPUS];
77
qemu_irq ppc0_irq;
78
qemu_irq ppc1_irq;
79
qemu_irq sec_resp_cfg;
80
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
33
index XXXXXXX..XXXXXXX 100644
81
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/helper.c
82
--- a/hw/arm/armsse.c
35
+++ b/target/arm/helper.c
83
+++ b/hw/arm/armsse.c
36
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
84
@@ -XXX,XX +XXX,XX @@
37
return rebuild_hflags_common(env, fp_el, mmu_idx, flags);
85
struct ARMSSEInfo {
86
const char *name;
87
int sram_banks;
88
+ int num_cpus;
89
};
90
91
static const ARMSSEInfo armsse_variants[] = {
92
{
93
.name = TYPE_IOTKIT,
94
.sram_banks = 1,
95
+ .num_cpus = 1,
96
},
97
};
98
99
/* Clock frequency in HZ of the 32KHz "slow clock" */
100
#define S32KCLK (32 * 1000)
101
102
+/* Is internal IRQ n shared between CPUs in a multi-core SSE ? */
103
+static bool irq_is_common[32] = {
104
+ [0 ... 5] = true,
105
+ /* 6, 7: per-CPU MHU interrupts */
106
+ [8 ... 12] = true,
107
+ /* 13: per-CPU icache interrupt */
108
+ /* 14: reserved */
109
+ [15 ... 20] = true,
110
+ /* 21: reserved */
111
+ [22 ... 26] = true,
112
+ /* 27: reserved */
113
+ /* 28, 29: per-CPU CTI interrupts */
114
+ /* 30, 31: reserved */
115
+};
116
+
117
/* Create an alias region of @size bytes starting at @base
118
* which mirrors the memory starting at @orig.
119
*/
120
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
121
int i;
122
123
assert(info->sram_banks <= MAX_SRAM_BANKS);
124
+ assert(info->num_cpus <= SSE_MAX_CPUS);
125
126
memory_region_init(&s->container, obj, "armsse-container", UINT64_MAX);
127
128
- sysbus_init_child_obj(obj, "armv7m", &s->armv7m, sizeof(s->armv7m),
129
- TYPE_ARMV7M);
130
- qdev_prop_set_string(DEVICE(&s->armv7m), "cpu-type",
131
- ARM_CPU_TYPE_NAME("cortex-m33"));
132
+ for (i = 0; i < info->num_cpus; i++) {
133
+ char *name = g_strdup_printf("armv7m%d", i);
134
+ sysbus_init_child_obj(obj, name, &s->armv7m[i], sizeof(s->armv7m),
135
+ TYPE_ARMV7M);
136
+ qdev_prop_set_string(DEVICE(&s->armv7m[i]), "cpu-type",
137
+ ARM_CPU_TYPE_NAME("cortex-m33"));
138
+ g_free(name);
139
+ }
140
141
sysbus_init_child_obj(obj, "secctl", &s->secctl, sizeof(s->secctl),
142
TYPE_IOTKIT_SECCTL);
143
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
144
TYPE_SPLIT_IRQ, &error_abort, NULL);
145
g_free(name);
146
}
147
+ if (info->num_cpus > 1) {
148
+ for (i = 0; i < ARRAY_SIZE(s->cpu_irq_splitter); i++) {
149
+ if (irq_is_common[i]) {
150
+ char *name = g_strdup_printf("cpu-irq-splitter%d", i);
151
+ SplitIRQ *splitter = &s->cpu_irq_splitter[i];
152
+
153
+ object_initialize_child(obj, name, splitter, sizeof(*splitter),
154
+ TYPE_SPLIT_IRQ, &error_abort, NULL);
155
+ g_free(name);
156
+ }
157
+ }
158
+ }
38
}
159
}
39
160
40
+static uint32_t rebuild_hflags_internal(CPUARMState *env)
161
static void armsse_exp_irq(void *opaque, int n, int level)
162
{
163
- ARMSSE *s = ARMSSE(opaque);
164
+ qemu_irq *irqarray = opaque;
165
166
- qemu_set_irq(s->exp_irqs[n], level);
167
+ qemu_set_irq(irqarray[n], level);
168
}
169
170
static void armsse_mpcexp_status(void *opaque, int n, int level)
171
@@ -XXX,XX +XXX,XX @@ static void armsse_mpcexp_status(void *opaque, int n, int level)
172
qemu_set_irq(s->mpcexp_status_in[n], level);
173
}
174
175
+static qemu_irq armsse_get_common_irq_in(ARMSSE *s, int irqno)
41
+{
176
+{
42
+ int el = arm_current_el(env);
177
+ /*
43
+ int fp_el = fp_exception_el(env, el);
178
+ * Return a qemu_irq which can be used to signal IRQ n to
44
+ ARMMMUIdx mmu_idx = arm_mmu_idx(env);
179
+ * all CPUs in the SSE.
45
+
180
+ */
46
+ if (is_a64(env)) {
181
+ ARMSSEClass *asc = ARMSSE_GET_CLASS(s);
47
+ return rebuild_hflags_a64(env, el, fp_el, mmu_idx);
182
+ const ARMSSEInfo *info = asc->info;
48
+ } else if (arm_feature(env, ARM_FEATURE_M)) {
183
+
49
+ return rebuild_hflags_m32(env, fp_el, mmu_idx);
184
+ assert(irq_is_common[irqno]);
185
+
186
+ if (info->num_cpus == 1) {
187
+ /* Only one CPU -- just connect directly to it */
188
+ return qdev_get_gpio_in(DEVICE(&s->armv7m[0]), irqno);
50
+ } else {
189
+ } else {
51
+ return rebuild_hflags_a32(env, fp_el, mmu_idx);
190
+ /* Connect to the splitter which feeds all CPUs */
191
+ return qdev_get_gpio_in(DEVICE(&s->cpu_irq_splitter[irqno]), 0);
52
+ }
192
+ }
53
+}
193
+}
54
+
194
+
55
+void arm_rebuild_hflags(CPUARMState *env)
195
static void armsse_realize(DeviceState *dev, Error **errp)
56
+{
57
+ env->hflags = rebuild_hflags_internal(env);
58
+}
59
+
60
void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
61
target_ulong *cs_base, uint32_t *pflags)
62
{
196
{
63
- ARMMMUIdx mmu_idx = arm_mmu_idx(env);
197
ARMSSE *s = ARMSSE(dev);
64
- int current_el = arm_current_el(env);
198
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
65
- int fp_el = fp_exception_el(env, current_el);
199
66
uint32_t flags, pstate_for_ss;
200
memory_region_add_subregion_overlap(&s->container, 0, s->board_memory, -1);
67
201
68
+ flags = rebuild_hflags_internal(env);
202
- qdev_prop_set_uint32(DEVICE(&s->armv7m), "num-irq", s->exp_numirq + 32);
69
+
203
- /* In real hardware the initial Secure VTOR is set from the INITSVTOR0
70
if (is_a64(env)) {
204
- * register in the IoT Kit System Control Register block, and the
71
*pc = env->pc;
205
- * initial value of that is in turn specifiable by the FPGA that
72
- flags = rebuild_hflags_a64(env, current_el, fp_el, mmu_idx);
206
- * instantiates the IoT Kit. In QEMU we don't implement this wrinkle,
73
if (cpu_isar_feature(aa64_bti, env_archcpu(env))) {
207
- * and simply set the CPU's init-svtor to the IoT Kit default value.
74
flags = FIELD_DP32(flags, TBFLAG_A64, BTYPE, env->btype);
208
- */
75
}
209
- qdev_prop_set_uint32(DEVICE(&s->armv7m), "init-svtor", 0x10000000);
76
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
210
- object_property_set_link(OBJECT(&s->armv7m), OBJECT(&s->container),
77
*pc = env->regs[15];
211
- "memory", &err);
78
212
- if (err) {
79
if (arm_feature(env, ARM_FEATURE_M)) {
213
- error_propagate(errp, err);
80
- flags = rebuild_hflags_m32(env, fp_el, mmu_idx);
214
- return;
81
-
215
- }
82
if (arm_feature(env, ARM_FEATURE_M_SECURITY) &&
216
- object_property_set_link(OBJECT(&s->armv7m), OBJECT(s), "idau", &err);
83
FIELD_EX32(env->v7m.fpccr[M_REG_S], V7M_FPCCR, S)
217
- if (err) {
84
!= env->v7m.secure) {
218
- error_propagate(errp, err);
85
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
219
- return;
86
flags = FIELD_DP32(flags, TBFLAG_A32, LSPACT, 1);
220
- }
87
}
221
- object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err);
88
} else {
222
- if (err) {
89
- flags = rebuild_hflags_a32(env, fp_el, mmu_idx);
223
- error_propagate(errp, err);
90
-
224
- return;
91
/*
225
+ for (i = 0; i < info->num_cpus; i++) {
92
* Note that XSCALE_CPAR shares bits with VECSTRIDE.
226
+ DeviceState *cpudev = DEVICE(&s->armv7m[i]);
93
* Note that VECLEN+VECSTRIDE are RES0 for M-profile.
227
+ Object *cpuobj = OBJECT(&s->armv7m[i]);
228
+ int j;
229
+ char *gpioname;
230
+
231
+ qdev_prop_set_uint32(cpudev, "num-irq", s->exp_numirq + 32);
232
+ /*
233
+ * In real hardware the initial Secure VTOR is set from the INITSVTOR0
234
+ * register in the IoT Kit System Control Register block, and the
235
+ * initial value of that is in turn specifiable by the FPGA that
236
+ * instantiates the IoT Kit. In QEMU we don't implement this wrinkle,
237
+ * and simply set the CPU's init-svtor to the IoT Kit default value.
238
+ * In SSE-200 the situation is similar, except that the default value
239
+ * is a reset-time signal input. Typically a board using the SSE-200
240
+ * will have a system control processor whose boot firmware initializes
241
+ * the INITSVTOR* registers before powering up the CPUs in any case,
242
+ * so the hardware's default value doesn't matter. QEMU doesn't emulate
243
+ * the control processor, so instead we behave in the way that the
244
+ * firmware does. All boards currently known about have firmware that
245
+ * sets the INITSVTOR0 and INITSVTOR1 registers to 0x10000000, like the
246
+ * IoTKit default. We can make this more configurable if necessary.
247
+ */
248
+ qdev_prop_set_uint32(cpudev, "init-svtor", 0x10000000);
249
+ /*
250
+ * Start all CPUs except CPU0 powered down. In real hardware it is
251
+ * a configurable property of the SSE-200 which CPUs start powered up
252
+ * (via the CPUWAIT0_RST and CPUWAIT1_RST parameters), but since all
253
+ * the boards we care about start CPU0 and leave CPU1 powered off,
254
+ * we hard-code that for now. We can add QOM properties for this
255
+ * later if necessary.
256
+ */
257
+ if (i > 0) {
258
+ object_property_set_bool(cpuobj, true, "start-powered-off", &err);
259
+ if (err) {
260
+ error_propagate(errp, err);
261
+ return;
262
+ }
263
+ }
264
+ object_property_set_link(cpuobj, OBJECT(&s->container), "memory", &err);
265
+ if (err) {
266
+ error_propagate(errp, err);
267
+ return;
268
+ }
269
+ object_property_set_link(cpuobj, OBJECT(s), "idau", &err);
270
+ if (err) {
271
+ error_propagate(errp, err);
272
+ return;
273
+ }
274
+ object_property_set_bool(cpuobj, true, "realized", &err);
275
+ if (err) {
276
+ error_propagate(errp, err);
277
+ return;
278
+ }
279
+
280
+ /* Connect EXP_IRQ/EXP_CPUn_IRQ GPIOs to the NVIC's lines 32 and up */
281
+ s->exp_irqs[i] = g_new(qemu_irq, s->exp_numirq);
282
+ for (j = 0; j < s->exp_numirq; j++) {
283
+ s->exp_irqs[i][j] = qdev_get_gpio_in(cpudev, i + 32);
284
+ }
285
+ if (i == 0) {
286
+ gpioname = g_strdup("EXP_IRQ");
287
+ } else {
288
+ gpioname = g_strdup_printf("EXP_CPU%d_IRQ", i);
289
+ }
290
+ qdev_init_gpio_in_named_with_opaque(dev, armsse_exp_irq,
291
+ s->exp_irqs[i],
292
+ gpioname, s->exp_numirq);
293
+ g_free(gpioname);
294
}
295
296
- /* Connect our EXP_IRQ GPIOs to the NVIC's lines 32 and up. */
297
- s->exp_irqs = g_new(qemu_irq, s->exp_numirq);
298
- for (i = 0; i < s->exp_numirq; i++) {
299
- s->exp_irqs[i] = qdev_get_gpio_in(DEVICE(&s->armv7m), i + 32);
300
+ /* Wire up the splitters that connect common IRQs to all CPUs */
301
+ if (info->num_cpus > 1) {
302
+ for (i = 0; i < ARRAY_SIZE(s->cpu_irq_splitter); i++) {
303
+ if (irq_is_common[i]) {
304
+ Object *splitter = OBJECT(&s->cpu_irq_splitter[i]);
305
+ DeviceState *devs = DEVICE(splitter);
306
+ int cpunum;
307
+
308
+ object_property_set_int(splitter, info->num_cpus,
309
+ "num-lines", &err);
310
+ if (err) {
311
+ error_propagate(errp, err);
312
+ return;
313
+ }
314
+ object_property_set_bool(splitter, true, "realized", &err);
315
+ if (err) {
316
+ error_propagate(errp, err);
317
+ return;
318
+ }
319
+ for (cpunum = 0; cpunum < info->num_cpus; cpunum++) {
320
+ DeviceState *cpudev = DEVICE(&s->armv7m[cpunum]);
321
+
322
+ qdev_connect_gpio_out(devs, cpunum,
323
+ qdev_get_gpio_in(cpudev, i));
324
+ }
325
+ }
326
+ }
327
}
328
- qdev_init_gpio_in_named(dev, armsse_exp_irq, "EXP_IRQ", s->exp_numirq);
329
330
/* Set up the big aliases first */
331
make_alias(s, &s->alias1, "alias 1", 0x10000000, 0x10000000, 0x00000000);
332
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
333
return;
334
}
335
qdev_connect_gpio_out(DEVICE(&s->mpc_irq_orgate), 0,
336
- qdev_get_gpio_in(DEVICE(&s->armv7m), 9));
337
+ armsse_get_common_irq_in(s, 9));
338
339
/* Devices behind APB PPC0:
340
* 0x40000000: timer0
341
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
342
return;
343
}
344
sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer0), 0,
345
- qdev_get_gpio_in(DEVICE(&s->armv7m), 3));
346
+ armsse_get_common_irq_in(s, 3));
347
mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer0), 0);
348
object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[0]", &err);
349
if (err) {
350
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
351
return;
352
}
353
sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer1), 0,
354
- qdev_get_gpio_in(DEVICE(&s->armv7m), 4));
355
+ armsse_get_common_irq_in(s, 4));
356
mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer1), 0);
357
object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[1]", &err);
358
if (err) {
359
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
360
return;
361
}
362
sysbus_connect_irq(SYS_BUS_DEVICE(&s->dualtimer), 0,
363
- qdev_get_gpio_in(DEVICE(&s->armv7m), 5));
364
+ armsse_get_common_irq_in(s, 5));
365
mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dualtimer), 0);
366
object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[2]", &err);
367
if (err) {
368
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
369
return;
370
}
371
qdev_connect_gpio_out(DEVICE(&s->ppc_irq_orgate), 0,
372
- qdev_get_gpio_in(DEVICE(&s->armv7m), 10));
373
+ armsse_get_common_irq_in(s, 10));
374
375
/* 0x40010000 .. 0x4001ffff: private CPU region: unused in IoTKit */
376
377
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
378
return;
379
}
380
sysbus_connect_irq(SYS_BUS_DEVICE(&s->s32ktimer), 0,
381
- qdev_get_gpio_in(DEVICE(&s->armv7m), 2));
382
+ armsse_get_common_irq_in(s, 2));
383
mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->s32ktimer), 0);
384
object_property_set_link(OBJECT(&s->apb_ppc1), OBJECT(mr), "port[0]", &err);
385
if (err) {
386
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
387
return;
388
}
389
sysbus_connect_irq(SYS_BUS_DEVICE(&s->nswatchdog), 0,
390
- qdev_get_gpio_in(DEVICE(&s->armv7m), 1));
391
+ armsse_get_common_irq_in(s, 1));
392
sysbus_mmio_map(SYS_BUS_DEVICE(&s->nswatchdog), 0, 0x40081000);
393
394
qdev_prop_set_uint32(DEVICE(&s->swatchdog), "wdogclk-frq", s->mainclk_frq);
395
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
396
qdev_pass_gpios(dev_secctl, dev, "mscexp_clear");
397
qdev_pass_gpios(dev_secctl, dev, "mscexp_ns");
398
qdev_connect_gpio_out_named(dev_secctl, "msc_irq", 0,
399
- qdev_get_gpio_in(DEVICE(&s->armv7m), 11));
400
+ armsse_get_common_irq_in(s, 11));
401
402
/*
403
* Expose our container region to the board model; this corresponds
94
--
404
--
95
2.20.1
405
2.20.1
96
406
97
407
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
Give each CPU its own container memory region. This is necessary
2
for two reasons:
3
* some devices are instantiated one per CPU and the CPU sees only
4
its own device
5
* since a memory region can only be put into one container, we must
6
give each armv7m object a different MemoryRegion as its 'memory'
7
property, or a dual-CPU configuration will assert on realize when
8
the second armv7m object tries to put the MR into a container when
9
it is already in the first armv7m object's container
2
10
3
As we are going to add more core-specific fields, add a 'cpu'
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
structure and move the ARMCPU field there as 'core'.
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20190121185118.18550-13-peter.maydell@linaro.org
14
---
15
include/hw/arm/armsse.h | 10 ++++++++++
16
hw/arm/armsse.c | 22 ++++++++++++++++++++--
17
2 files changed, 30 insertions(+), 2 deletions(-)
5
18
6
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
19
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Message-id: 20191019234715.25750-7-f4bug@amsat.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
include/hw/arm/bcm2836.h | 4 +++-
12
hw/arm/bcm2836.c | 26 ++++++++++++++------------
13
2 files changed, 17 insertions(+), 13 deletions(-)
14
15
diff --git a/include/hw/arm/bcm2836.h b/include/hw/arm/bcm2836.h
16
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/arm/bcm2836.h
21
--- a/include/hw/arm/armsse.h
18
+++ b/include/hw/arm/bcm2836.h
22
+++ b/include/hw/arm/armsse.h
19
@@ -XXX,XX +XXX,XX @@ typedef struct BCM283XState {
23
@@ -XXX,XX +XXX,XX @@ typedef struct ARMSSE {
20
char *cpu_type;
24
IoTKitSysCtl sysctl;
21
uint32_t enabled_cpus;
25
IoTKitSysCtl sysinfo;
22
26
23
- ARMCPU cpus[BCM283X_NCPUS];
27
+ /*
24
+ struct {
28
+ * 'container' holds all devices seen by all CPUs.
25
+ ARMCPU core;
29
+ * 'cpu_container[i]' is the view that CPU i has: this has the
26
+ } cpu[BCM283X_NCPUS];
30
+ * per-CPU devices of that CPU, plus as the background 'container'
27
BCM2836ControlState control;
31
+ * (or an alias of it, since we can only use it directly once).
28
BCM2835PeripheralState peripherals;
32
+ * container_alias[i] is the alias of 'container' used by CPU i+1;
29
} BCM283XState;
33
+ * CPU 0 can use 'container' directly.
30
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
34
+ */
35
MemoryRegion container;
36
+ MemoryRegion container_alias[SSE_MAX_CPUS - 1];
37
+ MemoryRegion cpu_container[SSE_MAX_CPUS];
38
MemoryRegion alias1;
39
MemoryRegion alias2;
40
MemoryRegion alias3;
41
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
31
index XXXXXXX..XXXXXXX 100644
42
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/arm/bcm2836.c
43
--- a/hw/arm/armsse.c
33
+++ b/hw/arm/bcm2836.c
44
+++ b/hw/arm/armsse.c
34
@@ -XXX,XX +XXX,XX @@ static void bcm2836_init(Object *obj)
45
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
35
int n;
46
qdev_prop_set_string(DEVICE(&s->armv7m[i]), "cpu-type",
36
47
ARM_CPU_TYPE_NAME("cortex-m33"));
37
for (n = 0; n < BCM283X_NCPUS; n++) {
48
g_free(name);
38
- object_initialize_child(obj, "cpu[*]", &s->cpus[n], sizeof(s->cpus[n]),
49
+ name = g_strdup_printf("arm-sse-cpu-container%d", i);
39
- info->cpu_type, &error_abort, NULL);
50
+ memory_region_init(&s->cpu_container[i], obj, name, UINT64_MAX);
40
+ object_initialize_child(obj, "cpu[*]", &s->cpu[n].core,
51
+ g_free(name);
41
+ sizeof(s->cpu[n].core), info->cpu_type,
52
+ if (i > 0) {
42
+ &error_abort, NULL);
53
+ name = g_strdup_printf("arm-sse-container-alias%d", i);
54
+ memory_region_init_alias(&s->container_alias[i - 1], obj,
55
+ name, &s->container, 0, UINT64_MAX);
56
+ g_free(name);
57
+ }
43
}
58
}
44
59
45
sysbus_init_child_obj(obj, "control", &s->control, sizeof(s->control),
60
sysbus_init_child_obj(obj, "secctl", &s->secctl, sizeof(s->secctl),
46
@@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
61
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
47
62
* 0x50000000..0x5fffffff alias of 0x40000000..0x4fffffff
48
for (n = 0; n < BCM283X_NCPUS; n++) {
63
*/
49
/* TODO: this should be converted to a property of ARM_CPU */
64
50
- s->cpus[n].mp_affinity = (info->clusterid << 8) | n;
65
- memory_region_add_subregion_overlap(&s->container, 0, s->board_memory, -1);
51
+ s->cpu[n].core.mp_affinity = (info->clusterid << 8) | n;
66
+ memory_region_add_subregion_overlap(&s->container, 0, s->board_memory, -2);
52
67
53
/* set periphbase/CBAR value for CPU-local registers */
68
for (i = 0; i < info->num_cpus; i++) {
54
- object_property_set_int(OBJECT(&s->cpus[n]),
69
DeviceState *cpudev = DEVICE(&s->armv7m[i]);
55
+ object_property_set_int(OBJECT(&s->cpu[n].core),
70
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
56
info->peri_base,
71
return;
57
"reset-cbar", &err);
72
}
58
if (err) {
59
@@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
60
}
73
}
61
74
- object_property_set_link(cpuobj, OBJECT(&s->container), "memory", &err);
62
/* start powered off if not enabled */
75
+
63
- object_property_set_bool(OBJECT(&s->cpus[n]), n >= s->enabled_cpus,
76
+ if (i > 0) {
64
+ object_property_set_bool(OBJECT(&s->cpu[n].core), n >= s->enabled_cpus,
77
+ memory_region_add_subregion_overlap(&s->cpu_container[i], 0,
65
"start-powered-off", &err);
78
+ &s->container_alias[i - 1], -1);
79
+ } else {
80
+ memory_region_add_subregion_overlap(&s->cpu_container[i], 0,
81
+ &s->container, -1);
82
+ }
83
+ object_property_set_link(cpuobj, OBJECT(&s->cpu_container[i]),
84
+ "memory", &err);
66
if (err) {
85
if (err) {
67
error_propagate(errp, err);
86
error_propagate(errp, err);
68
return;
87
return;
69
}
70
71
- object_property_set_bool(OBJECT(&s->cpus[n]), true, "realized", &err);
72
+ object_property_set_bool(OBJECT(&s->cpu[n].core), true,
73
+ "realized", &err);
74
if (err) {
75
error_propagate(errp, err);
76
return;
77
@@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
78
79
/* Connect irq/fiq outputs from the interrupt controller. */
80
qdev_connect_gpio_out_named(DEVICE(&s->control), "irq", n,
81
- qdev_get_gpio_in(DEVICE(&s->cpus[n]), ARM_CPU_IRQ));
82
+ qdev_get_gpio_in(DEVICE(&s->cpu[n].core), ARM_CPU_IRQ));
83
qdev_connect_gpio_out_named(DEVICE(&s->control), "fiq", n,
84
- qdev_get_gpio_in(DEVICE(&s->cpus[n]), ARM_CPU_FIQ));
85
+ qdev_get_gpio_in(DEVICE(&s->cpu[n].core), ARM_CPU_FIQ));
86
87
/* Connect timers from the CPU to the interrupt controller */
88
- qdev_connect_gpio_out(DEVICE(&s->cpus[n]), GTIMER_PHYS,
89
+ qdev_connect_gpio_out(DEVICE(&s->cpu[n].core), GTIMER_PHYS,
90
qdev_get_gpio_in_named(DEVICE(&s->control), "cntpnsirq", n));
91
- qdev_connect_gpio_out(DEVICE(&s->cpus[n]), GTIMER_VIRT,
92
+ qdev_connect_gpio_out(DEVICE(&s->cpu[n].core), GTIMER_VIRT,
93
qdev_get_gpio_in_named(DEVICE(&s->control), "cntvirq", n));
94
- qdev_connect_gpio_out(DEVICE(&s->cpus[n]), GTIMER_HYP,
95
+ qdev_connect_gpio_out(DEVICE(&s->cpu[n].core), GTIMER_HYP,
96
qdev_get_gpio_in_named(DEVICE(&s->control), "cnthpirq", n));
97
- qdev_connect_gpio_out(DEVICE(&s->cpus[n]), GTIMER_SEC,
98
+ qdev_connect_gpio_out(DEVICE(&s->cpu[n].core), GTIMER_SEC,
99
qdev_get_gpio_in_named(DEVICE(&s->control), "cntpsirq", n));
100
}
101
}
102
--
88
--
103
2.20.1
89
2.20.1
104
90
105
91
diff view generated by jsdifflib
1
Switch the fsl_etsec code away from bottom-half based ptimers to
1
Create a cluster object to hold each CPU in the SSE. They are
2
the new transaction-based ptimer API. This just requires adding
2
logically distinct and may be configured differently (for instance
3
begin/commit calls around the various places that modify the ptimer
3
one may not have an FPU where the other does).
4
state, and using the new ptimer_init() function to create the timer.
5
4
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Message-id: 20190121185118.18550-14-peter.maydell@linaro.org
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
Message-id: 20191017132122.4402-2-peter.maydell@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
8
---
13
hw/net/fsl_etsec/etsec.h | 1 -
9
include/hw/arm/armsse.h | 2 ++
14
hw/net/fsl_etsec/etsec.c | 9 +++++----
10
hw/arm/armsse.c | 31 ++++++++++++++++++++++++++++---
15
2 files changed, 5 insertions(+), 5 deletions(-)
11
2 files changed, 30 insertions(+), 3 deletions(-)
16
12
17
diff --git a/hw/net/fsl_etsec/etsec.h b/hw/net/fsl_etsec/etsec.h
13
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
18
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/net/fsl_etsec/etsec.h
15
--- a/include/hw/arm/armsse.h
20
+++ b/hw/net/fsl_etsec/etsec.h
16
+++ b/include/hw/arm/armsse.h
21
@@ -XXX,XX +XXX,XX @@ typedef struct eTSEC {
17
@@ -XXX,XX +XXX,XX @@
22
uint16_t phy_control;
18
#include "hw/misc/iotkit-sysinfo.h"
23
19
#include "hw/or-irq.h"
24
/* Polling */
20
#include "hw/core/split-irq.h"
25
- QEMUBH *bh;
21
+#include "hw/cpu/cluster.h"
26
struct ptimer_state *ptimer;
22
27
23
#define TYPE_ARMSSE "arm-sse"
28
/* Whether we should flush the rx queue when buffer becomes available. */
24
#define ARMSSE(obj) OBJECT_CHECK(ARMSSE, (obj), TYPE_ARMSSE)
29
diff --git a/hw/net/fsl_etsec/etsec.c b/hw/net/fsl_etsec/etsec.c
25
@@ -XXX,XX +XXX,XX @@ typedef struct ARMSSE {
26
27
/*< public >*/
28
ARMv7MState armv7m[SSE_MAX_CPUS];
29
+ CPUClusterState cluster[SSE_MAX_CPUS];
30
IoTKitSecCtl secctl;
31
TZPPC apb_ppc0;
32
TZPPC apb_ppc1;
33
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
30
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/net/fsl_etsec/etsec.c
35
--- a/hw/arm/armsse.c
32
+++ b/hw/net/fsl_etsec/etsec.c
36
+++ b/hw/arm/armsse.c
33
@@ -XXX,XX +XXX,XX @@
37
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
34
#include "etsec.h"
38
memory_region_init(&s->container, obj, "armsse-container", UINT64_MAX);
35
#include "registers.h"
39
36
#include "qemu/log.h"
40
for (i = 0; i < info->num_cpus; i++) {
37
-#include "qemu/main-loop.h"
41
- char *name = g_strdup_printf("armv7m%d", i);
38
#include "qemu/module.h"
42
- sysbus_init_child_obj(obj, name, &s->armv7m[i], sizeof(s->armv7m),
39
43
- TYPE_ARMV7M);
40
/* #define HEX_DUMP */
44
+ /*
41
@@ -XXX,XX +XXX,XX @@ static void write_dmactrl(eTSEC *etsec,
45
+ * We put each CPU in its own cluster as they are logically
42
46
+ * distinct and may be configured differently.
43
if (!(value & DMACTRL_WOP)) {
47
+ */
44
/* Start polling */
48
+ char *name;
45
+ ptimer_transaction_begin(etsec->ptimer);
49
+
46
ptimer_stop(etsec->ptimer);
50
+ name = g_strdup_printf("cluster%d", i);
47
ptimer_set_count(etsec->ptimer, 1);
51
+ object_initialize_child(obj, name, &s->cluster[i],
48
ptimer_run(etsec->ptimer, 1);
52
+ sizeof(s->cluster[i]), TYPE_CPU_CLUSTER,
49
+ ptimer_transaction_commit(etsec->ptimer);
53
+ &error_abort, NULL);
50
}
54
+ qdev_prop_set_uint32(DEVICE(&s->cluster[i]), "cluster-id", i);
51
}
55
+ g_free(name);
52
56
+
53
@@ -XXX,XX +XXX,XX @@ static void etsec_realize(DeviceState *dev, Error **errp)
57
+ name = g_strdup_printf("armv7m%d", i);
54
object_get_typename(OBJECT(dev)), dev->id, etsec);
58
+ sysbus_init_child_obj(OBJECT(&s->cluster[i]), name,
55
qemu_format_nic_info_str(qemu_get_queue(etsec->nic), etsec->conf.macaddr.a);
59
+ &s->armv7m[i], sizeof(s->armv7m), TYPE_ARMV7M);
56
60
qdev_prop_set_string(DEVICE(&s->armv7m[i]), "cpu-type",
57
-
61
ARM_CPU_TYPE_NAME("cortex-m33"));
58
- etsec->bh = qemu_bh_new(etsec_timer_hit, etsec);
62
g_free(name);
59
- etsec->ptimer = ptimer_init_with_bh(etsec->bh, PTIMER_POLICY_DEFAULT);
63
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
60
+ etsec->ptimer = ptimer_init(etsec_timer_hit, etsec, PTIMER_POLICY_DEFAULT);
64
error_propagate(errp, err);
61
+ ptimer_transaction_begin(etsec->ptimer);
65
return;
62
ptimer_set_freq(etsec->ptimer, 100);
66
}
63
+ ptimer_transaction_commit(etsec->ptimer);
67
+ /*
64
}
68
+ * The cluster must be realized after the armv7m container, as
65
69
+ * the container's CPU object is only created on realize, and the
66
static void etsec_instance_init(Object *obj)
70
+ * CPU must exist and have been parented into the cluster before
71
+ * the cluster is realized.
72
+ */
73
+ object_property_set_bool(OBJECT(&s->cluster[i]),
74
+ true, "realized", &err);
75
+ if (err) {
76
+ error_propagate(errp, err);
77
+ return;
78
+ }
79
80
/* Connect EXP_IRQ/EXP_CPUn_IRQ GPIOs to the NVIC's lines 32 and up */
81
s->exp_irqs[i] = g_new(qemu_irq, s->exp_numirq);
67
--
82
--
68
2.20.1
83
2.20.1
69
84
70
85
diff view generated by jsdifflib
1
Switch the grlib_gptimer code away from bottom-half based ptimers to
1
The SYS_VERSION and SYS_CONFIG register values differ between the
2
the new transaction-based ptimer API. This just requires adding
2
IoTKit and SSE-200. Make them configurable via QOM properties rather
3
begin/commit calls around the various places that modify the ptimer
3
than hard-coded, and set them appropriately in the ARMSSE code that
4
state, and using the new ptimer_init() function to create the timer.
4
instantiates the IOTKIT_SYSINFO device.
5
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Message-id: 20190121185118.18550-15-peter.maydell@linaro.org
9
Message-id: 20191021134357.14266-3-peter.maydell@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
9
---
12
hw/timer/grlib_gptimer.c | 28 ++++++++++++++++++++++++----
10
include/hw/misc/iotkit-sysinfo.h | 6 ++++
13
1 file changed, 24 insertions(+), 4 deletions(-)
11
hw/arm/armsse.c | 51 ++++++++++++++++++++++++++++++++
12
hw/misc/iotkit-sysinfo.c | 15 ++++++++--
13
3 files changed, 70 insertions(+), 2 deletions(-)
14
14
15
diff --git a/hw/timer/grlib_gptimer.c b/hw/timer/grlib_gptimer.c
15
diff --git a/include/hw/misc/iotkit-sysinfo.h b/include/hw/misc/iotkit-sysinfo.h
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/timer/grlib_gptimer.c
17
--- a/include/hw/misc/iotkit-sysinfo.h
18
+++ b/hw/timer/grlib_gptimer.c
18
+++ b/include/hw/misc/iotkit-sysinfo.h
19
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@
20
#include "hw/irq.h"
20
* Arm IoTKit and documented in
21
#include "hw/ptimer.h"
21
* http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
22
#include "hw/qdev-properties.h"
22
* QEMU interface:
23
-#include "qemu/main-loop.h"
23
+ * + QOM property "SYS_VERSION": value to use for SYS_VERSION register
24
#include "qemu/module.h"
24
+ * + QOM property "SYS_CONFIG": value to use for SYS_CONFIG register
25
25
* + sysbus MMIO region 0: the system information register bank
26
#include "trace.h"
26
*/
27
@@ -XXX,XX +XXX,XX @@ typedef struct GPTimer GPTimer;
27
28
typedef struct GPTimerUnit GPTimerUnit;
28
@@ -XXX,XX +XXX,XX @@ typedef struct IoTKitSysInfo {
29
29
30
struct GPTimer {
30
/*< public >*/
31
- QEMUBH *bh;
31
MemoryRegion iomem;
32
struct ptimer_state *ptimer;
32
+
33
33
+ /* Properties */
34
qemu_irq irq;
34
+ uint32_t sys_version;
35
@@ -XXX,XX +XXX,XX @@ struct GPTimerUnit {
35
+ uint32_t sys_config;
36
uint32_t config;
36
} IoTKitSysInfo;
37
38
#endif
39
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/hw/arm/armsse.c
42
+++ b/hw/arm/armsse.c
43
@@ -XXX,XX +XXX,XX @@
44
#include "hw/arm/armsse.h"
45
#include "hw/arm/arm.h"
46
47
+/* Format of the System Information block SYS_CONFIG register */
48
+typedef enum SysConfigFormat {
49
+ IoTKitFormat,
50
+ SSE200Format,
51
+} SysConfigFormat;
52
+
53
struct ARMSSEInfo {
54
const char *name;
55
int sram_banks;
56
int num_cpus;
57
+ uint32_t sys_version;
58
+ SysConfigFormat sys_config_format;
37
};
59
};
38
60
39
+static void grlib_gptimer_tx_begin(GPTimer *timer)
61
static const ARMSSEInfo armsse_variants[] = {
62
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
63
.name = TYPE_IOTKIT,
64
.sram_banks = 1,
65
.num_cpus = 1,
66
+ .sys_version = 0x41743,
67
+ .sys_config_format = IoTKitFormat,
68
},
69
};
70
71
+static uint32_t armsse_sys_config_value(ARMSSE *s, const ARMSSEInfo *info)
40
+{
72
+{
41
+ ptimer_transaction_begin(timer->ptimer);
73
+ /* Return the SYS_CONFIG value for this SSE */
74
+ uint32_t sys_config;
75
+
76
+ switch (info->sys_config_format) {
77
+ case IoTKitFormat:
78
+ sys_config = 0;
79
+ sys_config = deposit32(sys_config, 0, 4, info->sram_banks);
80
+ sys_config = deposit32(sys_config, 4, 4, s->sram_addr_width - 12);
81
+ break;
82
+ case SSE200Format:
83
+ sys_config = 0;
84
+ sys_config = deposit32(sys_config, 0, 4, info->sram_banks);
85
+ sys_config = deposit32(sys_config, 4, 5, s->sram_addr_width);
86
+ sys_config = deposit32(sys_config, 24, 4, 2);
87
+ if (info->num_cpus > 1) {
88
+ sys_config = deposit32(sys_config, 10, 1, 1);
89
+ sys_config = deposit32(sys_config, 20, 4, info->sram_banks - 1);
90
+ sys_config = deposit32(sys_config, 28, 4, 2);
91
+ }
92
+ break;
93
+ default:
94
+ g_assert_not_reached();
95
+ }
96
+ return sys_config;
42
+}
97
+}
43
+
98
+
44
+static void grlib_gptimer_tx_commit(GPTimer *timer)
99
/* Clock frequency in HZ of the 32KHz "slow clock" */
45
+{
100
#define S32KCLK (32 * 1000)
46
+ ptimer_transaction_commit(timer->ptimer);
101
47
+}
102
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
103
qdev_get_gpio_in_named(dev_apb_ppc1,
104
"cfg_sec_resp", 0));
105
106
+ object_property_set_int(OBJECT(&s->sysinfo), info->sys_version,
107
+ "SYS_VERSION", &err);
108
+ if (err) {
109
+ error_propagate(errp, err);
110
+ return;
111
+ }
112
+ object_property_set_int(OBJECT(&s->sysinfo),
113
+ armsse_sys_config_value(s, info),
114
+ "SYS_CONFIG", &err);
115
+ if (err) {
116
+ error_propagate(errp, err);
117
+ return;
118
+ }
119
object_property_set_bool(OBJECT(&s->sysinfo), true, "realized", &err);
120
if (err) {
121
error_propagate(errp, err);
122
diff --git a/hw/misc/iotkit-sysinfo.c b/hw/misc/iotkit-sysinfo.c
123
index XXXXXXX..XXXXXXX 100644
124
--- a/hw/misc/iotkit-sysinfo.c
125
+++ b/hw/misc/iotkit-sysinfo.c
126
@@ -XXX,XX +XXX,XX @@ static const int sysinfo_id[] = {
127
static uint64_t iotkit_sysinfo_read(void *opaque, hwaddr offset,
128
unsigned size)
129
{
130
+ IoTKitSysInfo *s = IOTKIT_SYSINFO(opaque);
131
uint64_t r;
132
133
switch (offset) {
134
case A_SYS_VERSION:
135
- r = 0x41743;
136
+ r = s->sys_version;
137
break;
138
139
case A_SYS_CONFIG:
140
- r = 0x31;
141
+ r = s->sys_config;
142
break;
143
case A_PID4 ... A_CID3:
144
r = sysinfo_id[(offset - A_PID4) / 4];
145
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps iotkit_sysinfo_ops = {
146
.valid.max_access_size = 4,
147
};
148
149
+static Property iotkit_sysinfo_props[] = {
150
+ DEFINE_PROP_UINT32("SYS_VERSION", IoTKitSysInfo, sys_version, 0),
151
+ DEFINE_PROP_UINT32("SYS_CONFIG", IoTKitSysInfo, sys_config, 0),
152
+ DEFINE_PROP_END_OF_LIST()
153
+};
48
+
154
+
49
+/* Must be called within grlib_gptimer_tx_begin/commit block */
155
static void iotkit_sysinfo_init(Object *obj)
50
static void grlib_gptimer_enable(GPTimer *timer)
51
{
156
{
52
assert(timer != NULL);
157
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
53
@@ -XXX,XX +XXX,XX @@ static void grlib_gptimer_enable(GPTimer *timer)
158
@@ -XXX,XX +XXX,XX @@ static void iotkit_sysinfo_init(Object *obj)
54
ptimer_run(timer->ptimer, 1);
159
160
static void iotkit_sysinfo_class_init(ObjectClass *klass, void *data)
161
{
162
+ DeviceClass *dc = DEVICE_CLASS(klass);
163
+
164
/*
165
* This device has no guest-modifiable state and so it
166
* does not need a reset function or VMState.
167
*/
168
+
169
+ dc->props = iotkit_sysinfo_props;
55
}
170
}
56
171
57
+/* Must be called within grlib_gptimer_tx_begin/commit block */
172
static const TypeInfo iotkit_sysinfo_info = {
58
static void grlib_gptimer_restart(GPTimer *timer)
59
{
60
assert(timer != NULL);
61
@@ -XXX,XX +XXX,XX @@ static void grlib_gptimer_set_scaler(GPTimerUnit *unit, uint32_t scaler)
62
trace_grlib_gptimer_set_scaler(scaler, value);
63
64
for (i = 0; i < unit->nr_timers; i++) {
65
+ ptimer_transaction_begin(unit->timers[i].ptimer);
66
ptimer_set_freq(unit->timers[i].ptimer, value);
67
+ ptimer_transaction_commit(unit->timers[i].ptimer);
68
}
69
}
70
71
@@ -XXX,XX +XXX,XX @@ static void grlib_gptimer_write(void *opaque, hwaddr addr,
72
switch (timer_addr) {
73
case COUNTER_OFFSET:
74
trace_grlib_gptimer_writel(id, addr, value);
75
+ grlib_gptimer_tx_begin(&unit->timers[id]);
76
unit->timers[id].counter = value;
77
grlib_gptimer_enable(&unit->timers[id]);
78
+ grlib_gptimer_tx_commit(&unit->timers[id]);
79
return;
80
81
case COUNTER_RELOAD_OFFSET:
82
@@ -XXX,XX +XXX,XX @@ static void grlib_gptimer_write(void *opaque, hwaddr addr,
83
/* gptimer_restart calls gptimer_enable, so if "enable" and "load"
84
bits are present, we just have to call restart. */
85
86
+ grlib_gptimer_tx_begin(&unit->timers[id]);
87
if (value & GPTIMER_LOAD) {
88
grlib_gptimer_restart(&unit->timers[id]);
89
} else if (value & GPTIMER_ENABLE) {
90
@@ -XXX,XX +XXX,XX @@ static void grlib_gptimer_write(void *opaque, hwaddr addr,
91
value &= ~(GPTIMER_LOAD & GPTIMER_DEBUG_HALT);
92
93
unit->timers[id].config = value;
94
+ grlib_gptimer_tx_commit(&unit->timers[id]);
95
return;
96
97
default:
98
@@ -XXX,XX +XXX,XX @@ static void grlib_gptimer_reset(DeviceState *d)
99
timer->counter = 0;
100
timer->reload = 0;
101
timer->config = 0;
102
+ ptimer_transaction_begin(timer->ptimer);
103
ptimer_stop(timer->ptimer);
104
ptimer_set_count(timer->ptimer, 0);
105
ptimer_set_freq(timer->ptimer, unit->freq_hz);
106
+ ptimer_transaction_commit(timer->ptimer);
107
}
108
}
109
110
@@ -XXX,XX +XXX,XX @@ static void grlib_gptimer_realize(DeviceState *dev, Error **errp)
111
GPTimer *timer = &unit->timers[i];
112
113
timer->unit = unit;
114
- timer->bh = qemu_bh_new(grlib_gptimer_hit, timer);
115
- timer->ptimer = ptimer_init_with_bh(timer->bh, PTIMER_POLICY_DEFAULT);
116
+ timer->ptimer = ptimer_init(grlib_gptimer_hit, timer,
117
+ PTIMER_POLICY_DEFAULT);
118
timer->id = i;
119
120
/* One IRQ line for each timer */
121
sysbus_init_irq(sbd, &timer->irq);
122
123
+ ptimer_transaction_begin(timer->ptimer);
124
ptimer_set_freq(timer->ptimer, unit->freq_hz);
125
+ ptimer_transaction_commit(timer->ptimer);
126
}
127
128
memory_region_init_io(&unit->iomem, OBJECT(unit), &grlib_gptimer_ops,
129
--
173
--
130
2.20.1
174
2.20.1
131
175
132
176
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
1
The SSE-200 has two Message Handling Units (MHUs), which sit behind
2
the APB PPC0. Wire up some unimplemented-device stubs for these,
3
since we don't yet implement a real model of this device.
2
4
3
kvm_arm_create_scratch_host_vcpu() takes a struct kvm_vcpu_init
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
parameter. Rather than just using it as an output parameter to
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
pass back the preferred target, use it also as an input parameter,
7
Message-id: 20190121185118.18550-16-peter.maydell@linaro.org
6
allowing a caller to pass a selected target if they wish and to
8
---
7
also pass cpu features. If the caller doesn't want to select a
9
include/hw/arm/armsse.h | 3 +++
8
target they can pass -1 for the target which indicates they want
10
hw/arm/armsse.c | 41 +++++++++++++++++++++++++++++++++++++++++
9
to use the preferred target and have it passed back like before.
11
2 files changed, 44 insertions(+)
10
12
11
Signed-off-by: Andrew Jones <drjones@redhat.com>
13
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Reviewed-by: Eric Auger <eric.auger@redhat.com>
14
Tested-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
15
Reviewed-by: Beata Michalska <beata.michalska@linaro.org>
16
Message-id: 20191024121808.9612-8-drjones@redhat.com
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
19
target/arm/kvm.c | 20 +++++++++++++++-----
20
target/arm/kvm32.c | 6 +++++-
21
target/arm/kvm64.c | 6 +++++-
22
3 files changed, 25 insertions(+), 7 deletions(-)
23
24
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
25
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/kvm.c
15
--- a/include/hw/arm/armsse.h
27
+++ b/target/arm/kvm.c
16
+++ b/include/hw/arm/armsse.h
28
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_create_scratch_host_vcpu(const uint32_t *cpus_to_try,
17
@@ -XXX,XX +XXX,XX @@
29
int *fdarray,
18
#include "hw/watchdog/cmsdk-apb-watchdog.h"
30
struct kvm_vcpu_init *init)
19
#include "hw/misc/iotkit-sysctl.h"
31
{
20
#include "hw/misc/iotkit-sysinfo.h"
32
- int ret, kvmfd = -1, vmfd = -1, cpufd = -1;
21
+#include "hw/misc/unimp.h"
33
+ int ret = 0, kvmfd = -1, vmfd = -1, cpufd = -1;
22
#include "hw/or-irq.h"
34
23
#include "hw/core/split-irq.h"
35
kvmfd = qemu_open("/dev/kvm", O_RDWR);
24
#include "hw/cpu/cluster.h"
36
if (kvmfd < 0) {
25
@@ -XXX,XX +XXX,XX @@ typedef struct ARMSSE {
37
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_create_scratch_host_vcpu(const uint32_t *cpus_to_try,
26
IoTKitSysCtl sysctl;
38
goto finish;
27
IoTKitSysCtl sysinfo;
28
29
+ UnimplementedDeviceState mhu[2];
30
+
31
/*
32
* 'container' holds all devices seen by all CPUs.
33
* 'cpu_container[i]' is the view that CPU i has: this has the
34
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/hw/arm/armsse.c
37
+++ b/hw/arm/armsse.c
38
@@ -XXX,XX +XXX,XX @@ struct ARMSSEInfo {
39
int num_cpus;
40
uint32_t sys_version;
41
SysConfigFormat sys_config_format;
42
+ bool has_mhus;
43
};
44
45
static const ARMSSEInfo armsse_variants[] = {
46
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
47
.num_cpus = 1,
48
.sys_version = 0x41743,
49
.sys_config_format = IoTKitFormat,
50
+ .has_mhus = false,
51
},
52
};
53
54
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
55
sizeof(s->sysctl), TYPE_IOTKIT_SYSCTL);
56
sysbus_init_child_obj(obj, "armsse-sysinfo", &s->sysinfo,
57
sizeof(s->sysinfo), TYPE_IOTKIT_SYSINFO);
58
+ if (info->has_mhus) {
59
+ sysbus_init_child_obj(obj, "mhu0", &s->mhu[0], sizeof(s->mhu[0]),
60
+ TYPE_UNIMPLEMENTED_DEVICE);
61
+ sysbus_init_child_obj(obj, "mhu1", &s->mhu[1], sizeof(s->mhu[1]),
62
+ TYPE_UNIMPLEMENTED_DEVICE);
63
+ }
64
object_initialize_child(obj, "nmi-orgate", &s->nmi_orgate,
65
sizeof(s->nmi_orgate), TYPE_OR_IRQ,
66
&error_abort, NULL);
67
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
68
* 0x40000000: timer0
69
* 0x40001000: timer1
70
* 0x40002000: dual timer
71
+ * 0x40003000: MHU0 (SSE-200 only)
72
+ * 0x40004000: MHU1 (SSE-200 only)
73
* We must configure and realize each downstream device and connect
74
* it to the appropriate PPC port; then we can realize the PPC and
75
* map its upstream ends to the right place in the container.
76
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
77
return;
39
}
78
}
40
79
41
- ret = ioctl(vmfd, KVM_ARM_PREFERRED_TARGET, init);
80
+ if (info->has_mhus) {
42
+ if (init->target == -1) {
81
+ for (i = 0; i < ARRAY_SIZE(s->mhu); i++) {
43
+ struct kvm_vcpu_init preferred;
82
+ char *name = g_strdup_printf("MHU%d", i);
83
+ char *port = g_strdup_printf("port[%d]", i + 3);
44
+
84
+
45
+ ret = ioctl(vmfd, KVM_ARM_PREFERRED_TARGET, &preferred);
85
+ qdev_prop_set_string(DEVICE(&s->mhu[i]), "name", name);
46
+ if (!ret) {
86
+ qdev_prop_set_uint64(DEVICE(&s->mhu[i]), "size", 0x1000);
47
+ init->target = preferred.target;
87
+ object_property_set_bool(OBJECT(&s->mhu[i]), true,
88
+ "realized", &err);
89
+ if (err) {
90
+ error_propagate(errp, err);
91
+ return;
92
+ }
93
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mhu[i]), 0);
94
+ object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr),
95
+ port, &err);
96
+ if (err) {
97
+ error_propagate(errp, err);
98
+ return;
99
+ }
100
+ g_free(name);
101
+ g_free(port);
48
+ }
102
+ }
49
+ }
103
+ }
50
if (ret >= 0) {
51
ret = ioctl(cpufd, KVM_ARM_VCPU_INIT, init);
52
if (ret < 0) {
53
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_create_scratch_host_vcpu(const uint32_t *cpus_to_try,
54
* creating one kind of guest CPU which is its preferred
55
* CPU type.
56
*/
57
+ struct kvm_vcpu_init try;
58
+
104
+
59
while (*cpus_to_try != QEMU_KVM_ARM_TARGET_NONE) {
105
object_property_set_bool(OBJECT(&s->apb_ppc0), true, "realized", &err);
60
- init->target = *cpus_to_try++;
106
if (err) {
61
- memset(init->features, 0, sizeof(init->features));
107
error_propagate(errp, err);
62
- ret = ioctl(cpufd, KVM_ARM_VCPU_INIT, init);
108
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
63
+ try.target = *cpus_to_try++;
109
memory_region_add_subregion(&s->container, 0x40001000, mr);
64
+ memcpy(try.features, init->features, sizeof(init->features));
110
mr = sysbus_mmio_get_region(sbd_apb_ppc0, 2);
65
+ ret = ioctl(cpufd, KVM_ARM_VCPU_INIT, &try);
111
memory_region_add_subregion(&s->container, 0x40002000, mr);
66
if (ret >= 0) {
112
+ if (info->has_mhus) {
67
break;
113
+ mr = sysbus_mmio_get_region(sbd_apb_ppc0, 3);
68
}
114
+ memory_region_add_subregion(&s->container, 0x40003000, mr);
69
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_create_scratch_host_vcpu(const uint32_t *cpus_to_try,
115
+ mr = sysbus_mmio_get_region(sbd_apb_ppc0, 4);
70
if (ret < 0) {
116
+ memory_region_add_subregion(&s->container, 0x40004000, mr);
71
goto err;
117
+ }
72
}
118
for (i = 0; i < IOTS_APB_PPC0_NUM_PORTS; i++) {
73
+ init->target = try.target;
119
qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_nonsec", i,
74
} else {
120
qdev_get_gpio_in_named(dev_apb_ppc0,
75
/* Treat a NULL cpus_to_try argument the same as an empty
76
* list, which means we will fail the call since this must
77
diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c
78
index XXXXXXX..XXXXXXX 100644
79
--- a/target/arm/kvm32.c
80
+++ b/target/arm/kvm32.c
81
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
82
QEMU_KVM_ARM_TARGET_CORTEX_A15,
83
QEMU_KVM_ARM_TARGET_NONE
84
};
85
- struct kvm_vcpu_init init;
86
+ /*
87
+ * target = -1 informs kvm_arm_create_scratch_host_vcpu()
88
+ * to use the preferred target
89
+ */
90
+ struct kvm_vcpu_init init = { .target = -1, };
91
92
if (!kvm_arm_create_scratch_host_vcpu(cpus_to_try, fdarray, &init)) {
93
return false;
94
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
95
index XXXXXXX..XXXXXXX 100644
96
--- a/target/arm/kvm64.c
97
+++ b/target/arm/kvm64.c
98
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
99
KVM_ARM_TARGET_CORTEX_A57,
100
QEMU_KVM_ARM_TARGET_NONE
101
};
102
- struct kvm_vcpu_init init;
103
+ /*
104
+ * target = -1 informs kvm_arm_create_scratch_host_vcpu()
105
+ * to use the preferred target
106
+ */
107
+ struct kvm_vcpu_init init = { .target = -1, };
108
109
if (!kvm_arm_create_scratch_host_vcpu(cpus_to_try, fdarray, &init)) {
110
return false;
111
--
121
--
112
2.20.1
122
2.20.1
113
123
114
124
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Add unimplemented-device stubs for the various Power Policy Unit
2
devices that the SSE-200 has.
2
3
3
Set TBFLAG_ANY.BE_DATA in rebuild_hflags_common_32 and
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
rebuild_hflags_a64 instead of rebuild_hflags_common, where we do
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
not need to re-test is_a64() nor re-compute the various inputs.
6
Message-id: 20190121185118.18550-17-peter.maydell@linaro.org
7
---
8
include/hw/arm/armsse.h | 11 ++++++++
9
hw/arm/armsse.c | 58 +++++++++++++++++++++++++++++++++++++++++
10
2 files changed, 69 insertions(+)
6
11
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
12
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20191023150057.25731-5-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/cpu.h | 49 +++++++++++++++++++++++++++------------------
13
target/arm/helper.c | 16 +++++++++++----
14
2 files changed, 42 insertions(+), 23 deletions(-)
15
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu.h
14
--- a/include/hw/arm/armsse.h
19
+++ b/target/arm/cpu.h
15
+++ b/include/hw/arm/armsse.h
20
@@ -XXX,XX +XXX,XX @@ static inline uint64_t arm_sctlr(CPUARMState *env, int el)
16
@@ -XXX,XX +XXX,XX @@
17
18
#define SSE_MAX_CPUS 2
19
20
+/* These define what each PPU in the ppu[] index is for */
21
+#define CPU0CORE_PPU 0
22
+#define CPU1CORE_PPU 1
23
+#define DBG_PPU 2
24
+#define RAM0_PPU 3
25
+#define RAM1_PPU 4
26
+#define RAM2_PPU 5
27
+#define RAM3_PPU 6
28
+#define NUM_PPUS 7
29
+
30
typedef struct ARMSSE {
31
/*< private >*/
32
SysBusDevice parent_obj;
33
@@ -XXX,XX +XXX,XX @@ typedef struct ARMSSE {
34
IoTKitSysCtl sysinfo;
35
36
UnimplementedDeviceState mhu[2];
37
+ UnimplementedDeviceState ppu[NUM_PPUS];
38
39
/*
40
* 'container' holds all devices seen by all CPUs.
41
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
42
index XXXXXXX..XXXXXXX 100644
43
--- a/hw/arm/armsse.c
44
+++ b/hw/arm/armsse.c
45
@@ -XXX,XX +XXX,XX @@ struct ARMSSEInfo {
46
uint32_t sys_version;
47
SysConfigFormat sys_config_format;
48
bool has_mhus;
49
+ bool has_ppus;
50
};
51
52
static const ARMSSEInfo armsse_variants[] = {
53
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
54
.sys_version = 0x41743,
55
.sys_config_format = IoTKitFormat,
56
.has_mhus = false,
57
+ .has_ppus = false,
58
},
59
};
60
61
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
62
sysbus_init_child_obj(obj, "mhu1", &s->mhu[1], sizeof(s->mhu[1]),
63
TYPE_UNIMPLEMENTED_DEVICE);
64
}
65
+ if (info->has_ppus) {
66
+ for (i = 0; i < info->num_cpus; i++) {
67
+ char *name = g_strdup_printf("CPU%dCORE_PPU", i);
68
+ int ppuidx = CPU0CORE_PPU + i;
69
+
70
+ sysbus_init_child_obj(obj, name, &s->ppu[ppuidx],
71
+ sizeof(s->ppu[ppuidx]),
72
+ TYPE_UNIMPLEMENTED_DEVICE);
73
+ g_free(name);
74
+ }
75
+ sysbus_init_child_obj(obj, "DBG_PPU", &s->ppu[DBG_PPU],
76
+ sizeof(s->ppu[DBG_PPU]),
77
+ TYPE_UNIMPLEMENTED_DEVICE);
78
+ for (i = 0; i < info->sram_banks; i++) {
79
+ char *name = g_strdup_printf("RAM%d_PPU", i);
80
+ int ppuidx = RAM0_PPU + i;
81
+
82
+ sysbus_init_child_obj(obj, name, &s->ppu[ppuidx],
83
+ sizeof(s->ppu[ppuidx]),
84
+ TYPE_UNIMPLEMENTED_DEVICE);
85
+ g_free(name);
86
+ }
87
+ }
88
object_initialize_child(obj, "nmi-orgate", &s->nmi_orgate,
89
sizeof(s->nmi_orgate), TYPE_OR_IRQ,
90
&error_abort, NULL);
91
@@ -XXX,XX +XXX,XX @@ static qemu_irq armsse_get_common_irq_in(ARMSSE *s, int irqno)
21
}
92
}
22
}
93
}
23
94
24
+static inline bool arm_cpu_data_is_big_endian_a32(CPUARMState *env,
95
+static void map_ppu(ARMSSE *s, int ppuidx, const char *name, hwaddr addr)
25
+ bool sctlr_b)
26
+{
96
+{
27
+#ifdef CONFIG_USER_ONLY
97
+ /* Map a PPU unimplemented device stub */
28
+ /*
98
+ DeviceState *dev = DEVICE(&s->ppu[ppuidx]);
29
+ * In system mode, BE32 is modelled in line with the
99
+
30
+ * architecture (as word-invariant big-endianness), where loads
100
+ qdev_prop_set_string(dev, "name", name);
31
+ * and stores are done little endian but from addresses which
101
+ qdev_prop_set_uint64(dev, "size", 0x1000);
32
+ * are adjusted by XORing with the appropriate constant. So the
102
+ qdev_init_nofail(dev);
33
+ * endianness to use for the raw data access is not affected by
103
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->ppu[ppuidx]), 0, addr);
34
+ * SCTLR.B.
35
+ * In user mode, however, we model BE32 as byte-invariant
36
+ * big-endianness (because user-only code cannot tell the
37
+ * difference), and so we need to use a data access endianness
38
+ * that depends on SCTLR.B.
39
+ */
40
+ if (sctlr_b) {
41
+ return true;
42
+ }
43
+#endif
44
+ /* In 32bit endianness is determined by looking at CPSR's E bit */
45
+ return env->uncached_cpsr & CPSR_E;
46
+}
104
+}
47
+
105
+
48
+static inline bool arm_cpu_data_is_big_endian_a64(int el, uint64_t sctlr)
106
static void armsse_realize(DeviceState *dev, Error **errp)
49
+{
50
+ return sctlr & (el ? SCTLR_EE : SCTLR_E0E);
51
+}
52
53
/* Return true if the processor is in big-endian mode. */
54
static inline bool arm_cpu_data_is_big_endian(CPUARMState *env)
55
{
107
{
56
- /* In 32bit endianness is determined by looking at CPSR's E bit */
108
ARMSSE *s = ARMSSE(dev);
57
if (!is_a64(env)) {
109
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
58
- return
59
-#ifdef CONFIG_USER_ONLY
60
- /* In system mode, BE32 is modelled in line with the
61
- * architecture (as word-invariant big-endianness), where loads
62
- * and stores are done little endian but from addresses which
63
- * are adjusted by XORing with the appropriate constant. So the
64
- * endianness to use for the raw data access is not affected by
65
- * SCTLR.B.
66
- * In user mode, however, we model BE32 as byte-invariant
67
- * big-endianness (because user-only code cannot tell the
68
- * difference), and so we need to use a data access endianness
69
- * that depends on SCTLR.B.
70
- */
71
- arm_sctlr_b(env) ||
72
-#endif
73
- ((env->uncached_cpsr & CPSR_E) ? 1 : 0);
74
+ return arm_cpu_data_is_big_endian_a32(env, arm_sctlr_b(env));
75
} else {
76
int cur_el = arm_current_el(env);
77
uint64_t sctlr = arm_sctlr(env, cur_el);
78
-
79
- return (sctlr & (cur_el ? SCTLR_EE : SCTLR_E0E)) != 0;
80
+ return arm_cpu_data_is_big_endian_a64(cur_el, sctlr);
81
}
110
}
82
}
111
sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysctl), 0, 0x50021000);
83
112
84
diff --git a/target/arm/helper.c b/target/arm/helper.c
113
+ if (info->has_ppus) {
85
index XXXXXXX..XXXXXXX 100644
114
+ /* CPUnCORE_PPU for each CPU */
86
--- a/target/arm/helper.c
115
+ for (i = 0; i < info->num_cpus; i++) {
87
+++ b/target/arm/helper.c
116
+ char *name = g_strdup_printf("CPU%dCORE_PPU", i);
88
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_common(CPUARMState *env, int fp_el,
89
flags = FIELD_DP32(flags, TBFLAG_ANY, MMUIDX,
90
arm_to_core_mmu_idx(mmu_idx));
91
92
- if (arm_cpu_data_is_big_endian(env)) {
93
- flags = FIELD_DP32(flags, TBFLAG_ANY, BE_DATA, 1);
94
- }
95
if (arm_singlestep_active(env)) {
96
flags = FIELD_DP32(flags, TBFLAG_ANY, SS_ACTIVE, 1);
97
}
98
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_common(CPUARMState *env, int fp_el,
99
static uint32_t rebuild_hflags_common_32(CPUARMState *env, int fp_el,
100
ARMMMUIdx mmu_idx, uint32_t flags)
101
{
102
- flags = FIELD_DP32(flags, TBFLAG_A32, SCTLR_B, arm_sctlr_b(env));
103
+ bool sctlr_b = arm_sctlr_b(env);
104
+
117
+
105
+ if (sctlr_b) {
118
+ map_ppu(s, CPU0CORE_PPU + i, name, 0x50023000 + i * 0x2000);
106
+ flags = FIELD_DP32(flags, TBFLAG_A32, SCTLR_B, 1);
119
+ /*
107
+ }
120
+ * We don't support CPU debug so don't create the
108
+ if (arm_cpu_data_is_big_endian_a32(env, sctlr_b)) {
121
+ * CPU0DEBUG_PPU at 0x50024000 and 0x50026000.
109
+ flags = FIELD_DP32(flags, TBFLAG_ANY, BE_DATA, 1);
122
+ */
110
+ }
123
+ g_free(name);
111
flags = FIELD_DP32(flags, TBFLAG_A32, NS, !access_secure_reg(env));
124
+ }
112
125
+ map_ppu(s, DBG_PPU, "DBG_PPU", 0x50029000);
113
return rebuild_hflags_common(env, fp_el, mmu_idx, flags);
126
+
114
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
127
+ for (i = 0; i < info->sram_banks; i++) {
115
128
+ char *name = g_strdup_printf("RAM%d_PPU", i);
116
sctlr = arm_sctlr(env, el);
129
+
117
130
+ map_ppu(s, RAM0_PPU + i, name, 0x5002a000 + i * 0x1000);
118
+ if (arm_cpu_data_is_big_endian_a64(el, sctlr)) {
131
+ g_free(name);
119
+ flags = FIELD_DP32(flags, TBFLAG_ANY, BE_DATA, 1);
132
+ }
120
+ }
133
+ }
121
+
134
+
122
if (cpu_isar_feature(aa64_pauth, env_archcpu(env))) {
135
/* This OR gate wires together outputs from the secure watchdogs to NMI */
123
/*
136
object_property_set_int(OBJECT(&s->nmi_orgate), 2, "num-lines", &err);
124
* In order to save space in flags, we record only whether
137
if (err) {
125
--
138
--
126
2.20.1
139
2.20.1
127
140
128
141
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The SSE-200 gives each CPU a register bank to use to control its
2
L1 instruction cache. Put in an unimplemented-device stub for this.
2
3
3
Create a function to compute the values of the TBFLAG_A64 bits
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
that will be cached. For now, the env->hflags variable is not
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
used, and the results are fed back to cpu_get_tb_cpu_state.
6
Message-id: 20190121185118.18550-18-peter.maydell@linaro.org
7
---
8
include/hw/arm/armsse.h | 1 +
9
hw/arm/armsse.c | 39 ++++++++++++++++++++++++++++++++++++++-
10
2 files changed, 39 insertions(+), 1 deletion(-)
6
11
7
Note that not all BTI related flags are cached, so we have to
12
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
8
test the BTI feature twice -- once for those bits moved out to
9
rebuild_hflags_a64 and once for those bits that remain in
10
cpu_get_tb_cpu_state.
11
12
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20191023150057.25731-3-richard.henderson@linaro.org
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
17
target/arm/helper.c | 131 +++++++++++++++++++++++---------------------
18
1 file changed, 69 insertions(+), 62 deletions(-)
19
20
diff --git a/target/arm/helper.c b/target/arm/helper.c
21
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/helper.c
14
--- a/include/hw/arm/armsse.h
23
+++ b/target/arm/helper.c
15
+++ b/include/hw/arm/armsse.h
24
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_common(CPUARMState *env, int fp_el,
16
@@ -XXX,XX +XXX,XX @@ typedef struct ARMSSE {
25
return flags;
17
26
}
18
UnimplementedDeviceState mhu[2];
27
19
UnimplementedDeviceState ppu[NUM_PPUS];
28
+static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
20
+ UnimplementedDeviceState cachectrl[SSE_MAX_CPUS];
29
+ ARMMMUIdx mmu_idx)
21
30
+{
22
/*
31
+ ARMMMUIdx stage1 = stage_1_mmu_idx(mmu_idx);
23
* 'container' holds all devices seen by all CPUs.
32
+ ARMVAParameters p0 = aa64_va_parameters_both(env, 0, stage1);
24
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
33
+ uint32_t flags = 0;
25
index XXXXXXX..XXXXXXX 100644
34
+ uint64_t sctlr;
26
--- a/hw/arm/armsse.c
35
+ int tbii, tbid;
27
+++ b/hw/arm/armsse.c
28
@@ -XXX,XX +XXX,XX @@ struct ARMSSEInfo {
29
SysConfigFormat sys_config_format;
30
bool has_mhus;
31
bool has_ppus;
32
+ bool has_cachectrl;
33
};
34
35
static const ARMSSEInfo armsse_variants[] = {
36
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
37
.sys_config_format = IoTKitFormat,
38
.has_mhus = false,
39
.has_ppus = false,
40
+ .has_cachectrl = false,
41
},
42
};
43
44
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
45
g_free(name);
46
}
47
}
48
+ if (info->has_cachectrl) {
49
+ for (i = 0; i < info->num_cpus; i++) {
50
+ char *name = g_strdup_printf("cachectrl%d", i);
36
+
51
+
37
+ flags = FIELD_DP32(flags, TBFLAG_ANY, AARCH64_STATE, 1);
52
+ sysbus_init_child_obj(obj, name, &s->cachectrl[i],
38
+
53
+ sizeof(s->cachectrl[i]),
39
+ /* FIXME: ARMv8.1-VHE S2 translation regime. */
54
+ TYPE_UNIMPLEMENTED_DEVICE);
40
+ if (regime_el(env, stage1) < 2) {
55
+ g_free(name);
41
+ ARMVAParameters p1 = aa64_va_parameters_both(env, -1, stage1);
42
+ tbid = (p1.tbi << 1) | p0.tbi;
43
+ tbii = tbid & ~((p1.tbid << 1) | p0.tbid);
44
+ } else {
45
+ tbid = p0.tbi;
46
+ tbii = tbid & !p0.tbid;
47
+ }
48
+
49
+ flags = FIELD_DP32(flags, TBFLAG_A64, TBII, tbii);
50
+ flags = FIELD_DP32(flags, TBFLAG_A64, TBID, tbid);
51
+
52
+ if (cpu_isar_feature(aa64_sve, env_archcpu(env))) {
53
+ int sve_el = sve_exception_el(env, el);
54
+ uint32_t zcr_len;
55
+
56
+ /*
57
+ * If SVE is disabled, but FP is enabled,
58
+ * then the effective len is 0.
59
+ */
60
+ if (sve_el != 0 && fp_el == 0) {
61
+ zcr_len = 0;
62
+ } else {
63
+ zcr_len = sve_zcr_len_for_el(env, el);
64
+ }
65
+ flags = FIELD_DP32(flags, TBFLAG_A64, SVEEXC_EL, sve_el);
66
+ flags = FIELD_DP32(flags, TBFLAG_A64, ZCR_LEN, zcr_len);
67
+ }
68
+
69
+ sctlr = arm_sctlr(env, el);
70
+
71
+ if (cpu_isar_feature(aa64_pauth, env_archcpu(env))) {
72
+ /*
73
+ * In order to save space in flags, we record only whether
74
+ * pauth is "inactive", meaning all insns are implemented as
75
+ * a nop, or "active" when some action must be performed.
76
+ * The decision of which action to take is left to a helper.
77
+ */
78
+ if (sctlr & (SCTLR_EnIA | SCTLR_EnIB | SCTLR_EnDA | SCTLR_EnDB)) {
79
+ flags = FIELD_DP32(flags, TBFLAG_A64, PAUTH_ACTIVE, 1);
80
+ }
56
+ }
81
+ }
57
+ }
58
object_initialize_child(obj, "nmi-orgate", &s->nmi_orgate,
59
sizeof(s->nmi_orgate), TYPE_OR_IRQ,
60
&error_abort, NULL);
61
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
62
qdev_connect_gpio_out(DEVICE(&s->ppc_irq_orgate), 0,
63
armsse_get_common_irq_in(s, 10));
64
65
- /* 0x40010000 .. 0x4001ffff: private CPU region: unused in IoTKit */
66
+ /*
67
+ * 0x40010000 .. 0x4001ffff (and the 0x5001000... secure-only alias):
68
+ * private per-CPU region (all these devices are SSE-200 only):
69
+ * 0x50010000: L1 icache control registers
70
+ * 0x50011000: CPUSECCTRL (CPU local security control registers)
71
+ * 0x4001f000 and 0x5001f000: CPU_IDENTITY register block
72
+ */
73
+ if (info->has_cachectrl) {
74
+ for (i = 0; i < info->num_cpus; i++) {
75
+ char *name = g_strdup_printf("cachectrl%d", i);
76
+ MemoryRegion *mr;
82
+
77
+
83
+ if (cpu_isar_feature(aa64_bti, env_archcpu(env))) {
78
+ qdev_prop_set_string(DEVICE(&s->cachectrl[i]), "name", name);
84
+ /* Note that SCTLR_EL[23].BT == SCTLR_BT1. */
79
+ g_free(name);
85
+ if (sctlr & (el == 0 ? SCTLR_BT0 : SCTLR_BT1)) {
80
+ qdev_prop_set_uint64(DEVICE(&s->cachectrl[i]), "size", 0x1000);
86
+ flags = FIELD_DP32(flags, TBFLAG_A64, BT, 1);
81
+ object_property_set_bool(OBJECT(&s->cachectrl[i]), true,
82
+ "realized", &err);
83
+ if (err) {
84
+ error_propagate(errp, err);
85
+ return;
86
+ }
87
+
88
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->cachectrl[i]), 0);
89
+ memory_region_add_subregion(&s->cpu_container[i], 0x50010000, mr);
87
+ }
90
+ }
88
+ }
91
+ }
89
+
92
90
+ return rebuild_hflags_common(env, fp_el, mmu_idx, flags);
93
/* 0x40020000 .. 0x4002ffff : ARMSSE system control peripheral region */
91
+}
94
/* Devices behind APB PPC1:
92
+
93
void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
94
target_ulong *cs_base, uint32_t *pflags)
95
{
96
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
97
uint32_t flags = 0;
98
99
if (is_a64(env)) {
100
- ARMCPU *cpu = env_archcpu(env);
101
- uint64_t sctlr;
102
-
103
*pc = env->pc;
104
- flags = FIELD_DP32(flags, TBFLAG_ANY, AARCH64_STATE, 1);
105
-
106
- /* Get control bits for tagged addresses. */
107
- {
108
- ARMMMUIdx stage1 = stage_1_mmu_idx(mmu_idx);
109
- ARMVAParameters p0 = aa64_va_parameters_both(env, 0, stage1);
110
- int tbii, tbid;
111
-
112
- /* FIXME: ARMv8.1-VHE S2 translation regime. */
113
- if (regime_el(env, stage1) < 2) {
114
- ARMVAParameters p1 = aa64_va_parameters_both(env, -1, stage1);
115
- tbid = (p1.tbi << 1) | p0.tbi;
116
- tbii = tbid & ~((p1.tbid << 1) | p0.tbid);
117
- } else {
118
- tbid = p0.tbi;
119
- tbii = tbid & !p0.tbid;
120
- }
121
-
122
- flags = FIELD_DP32(flags, TBFLAG_A64, TBII, tbii);
123
- flags = FIELD_DP32(flags, TBFLAG_A64, TBID, tbid);
124
- }
125
-
126
- if (cpu_isar_feature(aa64_sve, cpu)) {
127
- int sve_el = sve_exception_el(env, current_el);
128
- uint32_t zcr_len;
129
-
130
- /* If SVE is disabled, but FP is enabled,
131
- * then the effective len is 0.
132
- */
133
- if (sve_el != 0 && fp_el == 0) {
134
- zcr_len = 0;
135
- } else {
136
- zcr_len = sve_zcr_len_for_el(env, current_el);
137
- }
138
- flags = FIELD_DP32(flags, TBFLAG_A64, SVEEXC_EL, sve_el);
139
- flags = FIELD_DP32(flags, TBFLAG_A64, ZCR_LEN, zcr_len);
140
- }
141
-
142
- sctlr = arm_sctlr(env, current_el);
143
-
144
- if (cpu_isar_feature(aa64_pauth, cpu)) {
145
- /*
146
- * In order to save space in flags, we record only whether
147
- * pauth is "inactive", meaning all insns are implemented as
148
- * a nop, or "active" when some action must be performed.
149
- * The decision of which action to take is left to a helper.
150
- */
151
- if (sctlr & (SCTLR_EnIA | SCTLR_EnIB | SCTLR_EnDA | SCTLR_EnDB)) {
152
- flags = FIELD_DP32(flags, TBFLAG_A64, PAUTH_ACTIVE, 1);
153
- }
154
- }
155
-
156
- if (cpu_isar_feature(aa64_bti, cpu)) {
157
- /* Note that SCTLR_EL[23].BT == SCTLR_BT1. */
158
- if (sctlr & (current_el == 0 ? SCTLR_BT0 : SCTLR_BT1)) {
159
- flags = FIELD_DP32(flags, TBFLAG_A64, BT, 1);
160
- }
161
+ flags = rebuild_hflags_a64(env, current_el, fp_el, mmu_idx);
162
+ if (cpu_isar_feature(aa64_bti, env_archcpu(env))) {
163
flags = FIELD_DP32(flags, TBFLAG_A64, BTYPE, env->btype);
164
}
165
} else {
166
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
167
flags = FIELD_DP32(flags, TBFLAG_A32,
168
XSCALE_CPAR, env->cp15.c15_cpar);
169
}
170
- }
171
172
- flags = rebuild_hflags_common(env, fp_el, mmu_idx, flags);
173
+ flags = rebuild_hflags_common(env, fp_el, mmu_idx, flags);
174
+ }
175
176
/* The SS_ACTIVE and PSTATE_SS bits correspond to the state machine
177
* states defined in the ARM ARM for software singlestep:
178
--
95
--
179
2.20.1
96
2.20.1
180
97
181
98
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
1
The SSE-200 has a "CPU local security control" register bank; add an
2
unimplemented-device stub for it. (The register bank has only one
3
interesting register, which allows the guest to lock down changes
4
to various CPU registers so they cannot be modified further. We
5
don't support that in our Cortex-M33 model anyway.)
2
6
3
These are the SVE equivalents to kvm_arch_get/put_fpsimd. Note, the
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
swabbing is different than it is for fpsmid because the vector format
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
is a little-endian stream of words.
9
Message-id: 20190121185118.18550-19-peter.maydell@linaro.org
10
---
11
include/hw/arm/armsse.h | 1 +
12
hw/arm/armsse.c | 31 +++++++++++++++++++++++++++++++
13
2 files changed, 32 insertions(+)
6
14
7
Signed-off-by: Andrew Jones <drjones@redhat.com>
15
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Eric Auger <eric.auger@redhat.com>
10
Tested-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
11
Message-id: 20191024121808.9612-6-drjones@redhat.com
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
target/arm/kvm64.c | 185 ++++++++++++++++++++++++++++++++++++++-------
15
1 file changed, 156 insertions(+), 29 deletions(-)
16
17
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
18
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/kvm64.c
17
--- a/include/hw/arm/armsse.h
20
+++ b/target/arm/kvm64.c
18
+++ b/include/hw/arm/armsse.h
21
@@ -XXX,XX +XXX,XX @@ int kvm_arch_destroy_vcpu(CPUState *cs)
19
@@ -XXX,XX +XXX,XX @@ typedef struct ARMSSE {
22
bool kvm_arm_reg_syncs_via_cpreg_list(uint64_t regidx)
20
UnimplementedDeviceState mhu[2];
23
{
21
UnimplementedDeviceState ppu[NUM_PPUS];
24
/* Return true if the regidx is a register we should synchronize
22
UnimplementedDeviceState cachectrl[SSE_MAX_CPUS];
25
- * via the cpreg_tuples array (ie is not a core reg we sync by
23
+ UnimplementedDeviceState cpusecctrl[SSE_MAX_CPUS];
26
- * hand in kvm_arch_get/put_registers())
24
27
+ * via the cpreg_tuples array (ie is not a core or sve reg that
25
/*
28
+ * we sync by hand in kvm_arch_get/put_registers())
26
* 'container' holds all devices seen by all CPUs.
29
*/
27
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
30
switch (regidx & KVM_REG_ARM_COPROC_MASK) {
28
index XXXXXXX..XXXXXXX 100644
31
case KVM_REG_ARM_CORE:
29
--- a/hw/arm/armsse.c
32
+ case KVM_REG_ARM64_SVE:
30
+++ b/hw/arm/armsse.c
33
return false;
31
@@ -XXX,XX +XXX,XX @@ struct ARMSSEInfo {
34
default:
32
bool has_mhus;
35
return true;
33
bool has_ppus;
36
@@ -XXX,XX +XXX,XX @@ int kvm_arm_cpreg_level(uint64_t regidx)
34
bool has_cachectrl;
37
35
+ bool has_cpusecctrl;
38
static int kvm_arch_put_fpsimd(CPUState *cs)
36
};
39
{
37
40
- ARMCPU *cpu = ARM_CPU(cs);
38
static const ARMSSEInfo armsse_variants[] = {
41
- CPUARMState *env = &cpu->env;
39
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
42
+ CPUARMState *env = &ARM_CPU(cs)->env;
40
.has_mhus = false,
43
struct kvm_one_reg reg;
41
.has_ppus = false,
44
- uint32_t fpr;
42
.has_cachectrl = false,
45
int i, ret;
43
+ .has_cpusecctrl = false,
46
44
},
47
for (i = 0; i < 32; i++) {
45
};
48
@@ -XXX,XX +XXX,XX @@ static int kvm_arch_put_fpsimd(CPUState *cs)
46
47
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
48
g_free(name);
49
}
49
}
50
}
50
}
51
51
+ if (info->has_cpusecctrl) {
52
- reg.addr = (uintptr_t)(&fpr);
52
+ for (i = 0; i < info->num_cpus; i++) {
53
- fpr = vfp_get_fpsr(env);
53
+ char *name = g_strdup_printf("cpusecctrl%d", i);
54
- reg.id = AARCH64_SIMD_CTRL_REG(fp_regs.fpsr);
55
- ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
56
- if (ret) {
57
- return ret;
58
+ return 0;
59
+}
60
+
54
+
61
+/*
55
+ sysbus_init_child_obj(obj, name, &s->cpusecctrl[i],
62
+ * SVE registers are encoded in KVM's memory in an endianness-invariant format.
56
+ sizeof(s->cpusecctrl[i]),
63
+ * The byte at offset i from the start of the in-memory representation contains
57
+ TYPE_UNIMPLEMENTED_DEVICE);
64
+ * the bits [(7 + 8 * i) : (8 * i)] of the register value. As this means the
58
+ g_free(name);
65
+ * lowest offsets are stored in the lowest memory addresses, then that nearly
66
+ * matches QEMU's representation, which is to use an array of host-endian
67
+ * uint64_t's, where the lower offsets are at the lower indices. To complete
68
+ * the translation we just need to byte swap the uint64_t's on big-endian hosts.
69
+ */
70
+static uint64_t *sve_bswap64(uint64_t *dst, uint64_t *src, int nr)
71
+{
72
+#ifdef HOST_WORDS_BIGENDIAN
73
+ int i;
74
+
75
+ for (i = 0; i < nr; ++i) {
76
+ dst[i] = bswap64(src[i]);
77
}
78
79
- reg.addr = (uintptr_t)(&fpr);
80
- fpr = vfp_get_fpcr(env);
81
- reg.id = AARCH64_SIMD_CTRL_REG(fp_regs.fpcr);
82
+ return dst;
83
+#else
84
+ return src;
85
+#endif
86
+}
87
+
88
+/*
89
+ * KVM SVE registers come in slices where ZREGs have a slice size of 2048 bits
90
+ * and PREGS and the FFR have a slice size of 256 bits. However we simply hard
91
+ * code the slice index to zero for now as it's unlikely we'll need more than
92
+ * one slice for quite some time.
93
+ */
94
+static int kvm_arch_put_sve(CPUState *cs)
95
+{
96
+ ARMCPU *cpu = ARM_CPU(cs);
97
+ CPUARMState *env = &cpu->env;
98
+ uint64_t tmp[ARM_MAX_VQ * 2];
99
+ uint64_t *r;
100
+ struct kvm_one_reg reg;
101
+ int n, ret;
102
+
103
+ for (n = 0; n < KVM_ARM64_SVE_NUM_ZREGS; ++n) {
104
+ r = sve_bswap64(tmp, &env->vfp.zregs[n].d[0], cpu->sve_max_vq * 2);
105
+ reg.addr = (uintptr_t)r;
106
+ reg.id = KVM_REG_ARM64_SVE_ZREG(n, 0);
107
+ ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
108
+ if (ret) {
109
+ return ret;
110
+ }
59
+ }
111
+ }
60
+ }
61
object_initialize_child(obj, "nmi-orgate", &s->nmi_orgate,
62
sizeof(s->nmi_orgate), TYPE_OR_IRQ,
63
&error_abort, NULL);
64
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
65
memory_region_add_subregion(&s->cpu_container[i], 0x50010000, mr);
66
}
67
}
68
+ if (info->has_cpusecctrl) {
69
+ for (i = 0; i < info->num_cpus; i++) {
70
+ char *name = g_strdup_printf("CPUSECCTRL%d", i);
71
+ MemoryRegion *mr;
112
+
72
+
113
+ for (n = 0; n < KVM_ARM64_SVE_NUM_PREGS; ++n) {
73
+ qdev_prop_set_string(DEVICE(&s->cpusecctrl[i]), "name", name);
114
+ r = sve_bswap64(tmp, r = &env->vfp.pregs[n].p[0],
74
+ g_free(name);
115
+ DIV_ROUND_UP(cpu->sve_max_vq * 2, 8));
75
+ qdev_prop_set_uint64(DEVICE(&s->cpusecctrl[i]), "size", 0x1000);
116
+ reg.addr = (uintptr_t)r;
76
+ object_property_set_bool(OBJECT(&s->cpusecctrl[i]), true,
117
+ reg.id = KVM_REG_ARM64_SVE_PREG(n, 0);
77
+ "realized", &err);
118
+ ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
78
+ if (err) {
119
+ if (ret) {
79
+ error_propagate(errp, err);
120
+ return ret;
80
+ return;
81
+ }
82
+
83
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->cpusecctrl[i]), 0);
84
+ memory_region_add_subregion(&s->cpu_container[i], 0x50011000, mr);
121
+ }
85
+ }
122
+ }
86
+ }
123
+
87
124
+ r = sve_bswap64(tmp, &env->vfp.pregs[FFR_PRED_NUM].p[0],
88
/* 0x40020000 .. 0x4002ffff : ARMSSE system control peripheral region */
125
+ DIV_ROUND_UP(cpu->sve_max_vq * 2, 8));
89
/* Devices behind APB PPC1:
126
+ reg.addr = (uintptr_t)r;
127
+ reg.id = KVM_REG_ARM64_SVE_FFR(0);
128
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
129
if (ret) {
130
return ret;
131
@@ -XXX,XX +XXX,XX @@ int kvm_arch_put_registers(CPUState *cs, int level)
132
{
133
struct kvm_one_reg reg;
134
uint64_t val;
135
+ uint32_t fpr;
136
int i, ret;
137
unsigned int el;
138
139
@@ -XXX,XX +XXX,XX @@ int kvm_arch_put_registers(CPUState *cs, int level)
140
}
141
}
142
143
- ret = kvm_arch_put_fpsimd(cs);
144
+ if (cpu_isar_feature(aa64_sve, cpu)) {
145
+ ret = kvm_arch_put_sve(cs);
146
+ } else {
147
+ ret = kvm_arch_put_fpsimd(cs);
148
+ }
149
+ if (ret) {
150
+ return ret;
151
+ }
152
+
153
+ reg.addr = (uintptr_t)(&fpr);
154
+ fpr = vfp_get_fpsr(env);
155
+ reg.id = AARCH64_SIMD_CTRL_REG(fp_regs.fpsr);
156
+ ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
157
+ if (ret) {
158
+ return ret;
159
+ }
160
+
161
+ reg.addr = (uintptr_t)(&fpr);
162
+ fpr = vfp_get_fpcr(env);
163
+ reg.id = AARCH64_SIMD_CTRL_REG(fp_regs.fpcr);
164
+ ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
165
if (ret) {
166
return ret;
167
}
168
@@ -XXX,XX +XXX,XX @@ int kvm_arch_put_registers(CPUState *cs, int level)
169
170
static int kvm_arch_get_fpsimd(CPUState *cs)
171
{
172
- ARMCPU *cpu = ARM_CPU(cs);
173
- CPUARMState *env = &cpu->env;
174
+ CPUARMState *env = &ARM_CPU(cs)->env;
175
struct kvm_one_reg reg;
176
- uint32_t fpr;
177
int i, ret;
178
179
for (i = 0; i < 32; i++) {
180
@@ -XXX,XX +XXX,XX @@ static int kvm_arch_get_fpsimd(CPUState *cs)
181
}
182
}
183
184
- reg.addr = (uintptr_t)(&fpr);
185
- reg.id = AARCH64_SIMD_CTRL_REG(fp_regs.fpsr);
186
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
187
- if (ret) {
188
- return ret;
189
- }
190
- vfp_set_fpsr(env, fpr);
191
+ return 0;
192
+}
193
194
- reg.addr = (uintptr_t)(&fpr);
195
- reg.id = AARCH64_SIMD_CTRL_REG(fp_regs.fpcr);
196
+/*
197
+ * KVM SVE registers come in slices where ZREGs have a slice size of 2048 bits
198
+ * and PREGS and the FFR have a slice size of 256 bits. However we simply hard
199
+ * code the slice index to zero for now as it's unlikely we'll need more than
200
+ * one slice for quite some time.
201
+ */
202
+static int kvm_arch_get_sve(CPUState *cs)
203
+{
204
+ ARMCPU *cpu = ARM_CPU(cs);
205
+ CPUARMState *env = &cpu->env;
206
+ struct kvm_one_reg reg;
207
+ uint64_t *r;
208
+ int n, ret;
209
+
210
+ for (n = 0; n < KVM_ARM64_SVE_NUM_ZREGS; ++n) {
211
+ r = &env->vfp.zregs[n].d[0];
212
+ reg.addr = (uintptr_t)r;
213
+ reg.id = KVM_REG_ARM64_SVE_ZREG(n, 0);
214
+ ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
215
+ if (ret) {
216
+ return ret;
217
+ }
218
+ sve_bswap64(r, r, cpu->sve_max_vq * 2);
219
+ }
220
+
221
+ for (n = 0; n < KVM_ARM64_SVE_NUM_PREGS; ++n) {
222
+ r = &env->vfp.pregs[n].p[0];
223
+ reg.addr = (uintptr_t)r;
224
+ reg.id = KVM_REG_ARM64_SVE_PREG(n, 0);
225
+ ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
226
+ if (ret) {
227
+ return ret;
228
+ }
229
+ sve_bswap64(r, r, DIV_ROUND_UP(cpu->sve_max_vq * 2, 8));
230
+ }
231
+
232
+ r = &env->vfp.pregs[FFR_PRED_NUM].p[0];
233
+ reg.addr = (uintptr_t)r;
234
+ reg.id = KVM_REG_ARM64_SVE_FFR(0);
235
ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
236
if (ret) {
237
return ret;
238
}
239
- vfp_set_fpcr(env, fpr);
240
+ sve_bswap64(r, r, DIV_ROUND_UP(cpu->sve_max_vq * 2, 8));
241
242
return 0;
243
}
244
@@ -XXX,XX +XXX,XX @@ int kvm_arch_get_registers(CPUState *cs)
245
struct kvm_one_reg reg;
246
uint64_t val;
247
unsigned int el;
248
+ uint32_t fpr;
249
int i, ret;
250
251
ARMCPU *cpu = ARM_CPU(cs);
252
@@ -XXX,XX +XXX,XX @@ int kvm_arch_get_registers(CPUState *cs)
253
env->spsr = env->banked_spsr[i];
254
}
255
256
- ret = kvm_arch_get_fpsimd(cs);
257
+ if (cpu_isar_feature(aa64_sve, cpu)) {
258
+ ret = kvm_arch_get_sve(cs);
259
+ } else {
260
+ ret = kvm_arch_get_fpsimd(cs);
261
+ }
262
if (ret) {
263
return ret;
264
}
265
266
+ reg.addr = (uintptr_t)(&fpr);
267
+ reg.id = AARCH64_SIMD_CTRL_REG(fp_regs.fpsr);
268
+ ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
269
+ if (ret) {
270
+ return ret;
271
+ }
272
+ vfp_set_fpsr(env, fpr);
273
+
274
+ reg.addr = (uintptr_t)(&fpr);
275
+ reg.id = AARCH64_SIMD_CTRL_REG(fp_regs.fpcr);
276
+ ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
277
+ if (ret) {
278
+ return ret;
279
+ }
280
+ vfp_set_fpcr(env, fpr);
281
+
282
ret = kvm_get_vcpu_events(cpu);
283
if (ret) {
284
return ret;
285
--
90
--
286
2.20.1
91
2.20.1
287
92
288
93
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
The SSE-200 has a CPU_IDENTITY register block, which is a set of
2
2
read-only registers. As well as the usual PID/CID registers, there
3
We will soon implement the SYS_timer. This timer is used by Linux
3
is a single CPUID register which indicates whether the CPU is CPU 0
4
in the thermal subsystem, so once available, the subsystem will be
4
or CPU 1. Implement a model of this register block.
5
enabled and poll the temperature sensors. We need to provide the
5
6
minimum required to keep Linux booting.
7
8
Add a dummy thermal sensor returning ~25°C based on:
9
https://github.com/raspberrypi/linux/blob/rpi-5.3.y/drivers/thermal/broadcom/bcm2835_thermal.c
10
11
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
13
Message-id: 20191019234715.25750-2-f4bug@amsat.org
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20190121185118.18550-20-peter.maydell@linaro.org
15
---
9
---
16
hw/misc/Makefile.objs | 1 +
10
hw/misc/Makefile.objs | 1 +
17
include/hw/misc/bcm2835_thermal.h | 27 ++++++
11
include/hw/misc/armsse-cpuid.h | 41 ++++++++++
18
hw/misc/bcm2835_thermal.c | 135 ++++++++++++++++++++++++++++++
12
hw/misc/armsse-cpuid.c | 134 ++++++++++++++++++++++++++++++++
19
3 files changed, 163 insertions(+)
13
MAINTAINERS | 2 +
20
create mode 100644 include/hw/misc/bcm2835_thermal.h
14
default-configs/arm-softmmu.mak | 1 +
21
create mode 100644 hw/misc/bcm2835_thermal.c
15
hw/misc/trace-events | 4 +
16
6 files changed, 183 insertions(+)
17
create mode 100644 include/hw/misc/armsse-cpuid.h
18
create mode 100644 hw/misc/armsse-cpuid.c
22
19
23
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
20
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
24
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
25
--- a/hw/misc/Makefile.objs
22
--- a/hw/misc/Makefile.objs
26
+++ b/hw/misc/Makefile.objs
23
+++ b/hw/misc/Makefile.objs
27
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_OMAP) += omap_tap.o
24
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_TZ_PPC) += tz-ppc.o
28
common-obj-$(CONFIG_RASPI) += bcm2835_mbox.o
25
obj-$(CONFIG_IOTKIT_SECCTL) += iotkit-secctl.o
29
common-obj-$(CONFIG_RASPI) += bcm2835_property.o
26
obj-$(CONFIG_IOTKIT_SYSCTL) += iotkit-sysctl.o
30
common-obj-$(CONFIG_RASPI) += bcm2835_rng.o
27
obj-$(CONFIG_IOTKIT_SYSINFO) += iotkit-sysinfo.o
31
+common-obj-$(CONFIG_RASPI) += bcm2835_thermal.o
28
+obj-$(CONFIG_ARMSSE_CPUID) += armsse-cpuid.o
32
common-obj-$(CONFIG_SLAVIO) += slavio_misc.o
29
33
common-obj-$(CONFIG_ZYNQ) += zynq_slcr.o
30
obj-$(CONFIG_PVPANIC) += pvpanic.o
34
common-obj-$(CONFIG_ZYNQ) += zynq-xadc.o
31
obj-$(CONFIG_AUX) += auxbus.o
35
diff --git a/include/hw/misc/bcm2835_thermal.h b/include/hw/misc/bcm2835_thermal.h
32
diff --git a/include/hw/misc/armsse-cpuid.h b/include/hw/misc/armsse-cpuid.h
36
new file mode 100644
33
new file mode 100644
37
index XXXXXXX..XXXXXXX
34
index XXXXXXX..XXXXXXX
38
--- /dev/null
35
--- /dev/null
39
+++ b/include/hw/misc/bcm2835_thermal.h
36
+++ b/include/hw/misc/armsse-cpuid.h
40
@@ -XXX,XX +XXX,XX @@
37
@@ -XXX,XX +XXX,XX @@
41
+/*
38
+/*
42
+ * BCM2835 dummy thermal sensor
39
+ * ARM SSE-200 CPU_IDENTITY register block
43
+ *
40
+ *
44
+ * Copyright (C) 2019 Philippe Mathieu-Daudé <f4bug@amsat.org>
41
+ * Copyright (c) 2019 Linaro Limited
45
+ *
42
+ * Written by Peter Maydell
46
+ * SPDX-License-Identifier: GPL-2.0-or-later
43
+ *
47
+ */
44
+ * This program is free software; you can redistribute it and/or modify
48
+
45
+ * it under the terms of the GNU General Public License version 2 or
49
+#ifndef HW_MISC_BCM2835_THERMAL_H
46
+ * (at your option) any later version.
50
+#define HW_MISC_BCM2835_THERMAL_H
47
+ */
48
+
49
+/*
50
+ * This is a model of the "CPU_IDENTITY" register block which is part of the
51
+ * Arm SSE-200 and documented in
52
+ * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
53
+ *
54
+ * QEMU interface:
55
+ * + QOM property "CPUID": the value to use for the CPUID register
56
+ * + sysbus MMIO region 0: the system information register bank
57
+ */
58
+
59
+#ifndef HW_MISC_ARMSSE_CPUID_H
60
+#define HW_MISC_ARMSSE_CPUID_H
51
+
61
+
52
+#include "hw/sysbus.h"
62
+#include "hw/sysbus.h"
53
+
63
+
54
+#define TYPE_BCM2835_THERMAL "bcm2835-thermal"
64
+#define TYPE_ARMSSE_CPUID "armsse-cpuid"
55
+
65
+#define ARMSSE_CPUID(obj) OBJECT_CHECK(ARMSSECPUID, (obj), TYPE_ARMSSE_CPUID)
56
+#define BCM2835_THERMAL(obj) \
66
+
57
+ OBJECT_CHECK(Bcm2835ThermalState, (obj), TYPE_BCM2835_THERMAL)
67
+typedef struct ARMSSECPUID {
58
+
59
+typedef struct {
60
+ /*< private >*/
68
+ /*< private >*/
61
+ SysBusDevice parent_obj;
69
+ SysBusDevice parent_obj;
70
+
62
+ /*< public >*/
71
+ /*< public >*/
63
+ MemoryRegion iomem;
72
+ MemoryRegion iomem;
64
+ uint32_t ctl;
73
+
65
+} Bcm2835ThermalState;
74
+ /* Properties */
75
+ uint32_t cpuid;
76
+} ARMSSECPUID;
66
+
77
+
67
+#endif
78
+#endif
68
diff --git a/hw/misc/bcm2835_thermal.c b/hw/misc/bcm2835_thermal.c
79
diff --git a/hw/misc/armsse-cpuid.c b/hw/misc/armsse-cpuid.c
69
new file mode 100644
80
new file mode 100644
70
index XXXXXXX..XXXXXXX
81
index XXXXXXX..XXXXXXX
71
--- /dev/null
82
--- /dev/null
72
+++ b/hw/misc/bcm2835_thermal.c
83
+++ b/hw/misc/armsse-cpuid.c
73
@@ -XXX,XX +XXX,XX @@
84
@@ -XXX,XX +XXX,XX @@
74
+/*
85
+/*
75
+ * BCM2835 dummy thermal sensor
86
+ * ARM SSE-200 CPU_IDENTITY register block
76
+ *
87
+ *
77
+ * Copyright (C) 2019 Philippe Mathieu-Daudé <f4bug@amsat.org>
88
+ * Copyright (c) 2019 Linaro Limited
78
+ *
89
+ * Written by Peter Maydell
79
+ * SPDX-License-Identifier: GPL-2.0-or-later
90
+ *
91
+ * This program is free software; you can redistribute it and/or modify
92
+ * it under the terms of the GNU General Public License version 2 or
93
+ * (at your option) any later version.
94
+ */
95
+
96
+/*
97
+ * This is a model of the "CPU_IDENTITY" register block which is part of the
98
+ * Arm SSE-200 and documented in
99
+ * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
100
+ *
101
+ * It consists of one read-only CPUID register (set by QOM property), plus the
102
+ * usual ID registers.
80
+ */
103
+ */
81
+
104
+
82
+#include "qemu/osdep.h"
105
+#include "qemu/osdep.h"
83
+#include "qemu/log.h"
106
+#include "qemu/log.h"
107
+#include "trace.h"
84
+#include "qapi/error.h"
108
+#include "qapi/error.h"
85
+#include "hw/misc/bcm2835_thermal.h"
109
+#include "sysemu/sysemu.h"
110
+#include "hw/sysbus.h"
86
+#include "hw/registerfields.h"
111
+#include "hw/registerfields.h"
87
+#include "migration/vmstate.h"
112
+#include "hw/misc/armsse-cpuid.h"
88
+
113
+
89
+REG32(CTL, 0)
114
+REG32(CPUID, 0x0)
90
+FIELD(CTL, POWER_DOWN, 0, 1)
115
+REG32(PID4, 0xfd0)
91
+FIELD(CTL, RESET, 1, 1)
116
+REG32(PID5, 0xfd4)
92
+FIELD(CTL, BANDGAP_CTRL, 2, 3)
117
+REG32(PID6, 0xfd8)
93
+FIELD(CTL, INTERRUPT_ENABLE, 5, 1)
118
+REG32(PID7, 0xfdc)
94
+FIELD(CTL, DIRECT, 6, 1)
119
+REG32(PID0, 0xfe0)
95
+FIELD(CTL, INTERRUPT_CLEAR, 7, 1)
120
+REG32(PID1, 0xfe4)
96
+FIELD(CTL, HOLD, 8, 10)
121
+REG32(PID2, 0xfe8)
97
+FIELD(CTL, RESET_DELAY, 18, 8)
122
+REG32(PID3, 0xfec)
98
+FIELD(CTL, REGULATOR_ENABLE, 26, 1)
123
+REG32(CID0, 0xff0)
99
+
124
+REG32(CID1, 0xff4)
100
+REG32(STAT, 4)
125
+REG32(CID2, 0xff8)
101
+FIELD(STAT, DATA, 0, 10)
126
+REG32(CID3, 0xffc)
102
+FIELD(STAT, VALID, 10, 1)
127
+
103
+FIELD(STAT, INTERRUPT, 11, 1)
128
+/* PID/CID values */
104
+
129
+static const int sysinfo_id[] = {
105
+#define THERMAL_OFFSET_C 412
130
+ 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
106
+#define THERMAL_COEFF (-0.538f)
131
+ 0x58, 0xb8, 0x0b, 0x00, /* PID0..PID3 */
107
+
132
+ 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
108
+static uint16_t bcm2835_thermal_temp2adc(int temp_C)
133
+};
109
+{
134
+
110
+ return (temp_C - THERMAL_OFFSET_C) / THERMAL_COEFF;
135
+static uint64_t armsse_cpuid_read(void *opaque, hwaddr offset,
111
+}
136
+ unsigned size)
112
+
137
+{
113
+static uint64_t bcm2835_thermal_read(void *opaque, hwaddr addr, unsigned size)
138
+ ARMSSECPUID *s = ARMSSE_CPUID(opaque);
114
+{
139
+ uint64_t r;
115
+ Bcm2835ThermalState *s = BCM2835_THERMAL(opaque);
140
+
116
+ uint32_t val = 0;
141
+ switch (offset) {
117
+
142
+ case A_CPUID:
118
+ switch (addr) {
143
+ r = s->cpuid;
119
+ case A_CTL:
120
+ val = s->ctl;
121
+ break;
144
+ break;
122
+ case A_STAT:
145
+ case A_PID4 ... A_CID3:
123
+ /* Temperature is constantly 25°C. */
146
+ r = sysinfo_id[(offset - A_PID4) / 4];
124
+ val = FIELD_DP32(bcm2835_thermal_temp2adc(25), STAT, VALID, true);
125
+ break;
147
+ break;
126
+ default:
148
+ default:
127
+ /* MemoryRegionOps are aligned, so this can not happen. */
149
+ qemu_log_mask(LOG_GUEST_ERROR,
128
+ g_assert_not_reached();
150
+ "SSE CPU_IDENTITY read: bad offset 0x%x\n", (int)offset);
151
+ r = 0;
152
+ break;
129
+ }
153
+ }
130
+ return val;
154
+ trace_armsse_cpuid_read(offset, r, size);
131
+}
155
+ return r;
132
+
156
+}
133
+static void bcm2835_thermal_write(void *opaque, hwaddr addr,
157
+
134
+ uint64_t value, unsigned size)
158
+static void armsse_cpuid_write(void *opaque, hwaddr offset,
135
+{
159
+ uint64_t value, unsigned size)
136
+ Bcm2835ThermalState *s = BCM2835_THERMAL(opaque);
160
+{
137
+
161
+ trace_armsse_cpuid_write(offset, value, size);
138
+ switch (addr) {
162
+
139
+ case A_CTL:
163
+ qemu_log_mask(LOG_GUEST_ERROR,
140
+ s->ctl = value;
164
+ "SSE CPU_IDENTITY: write to RO offset 0x%x\n", (int)offset);
141
+ break;
165
+}
142
+ case A_STAT:
166
+
143
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: write 0x%" PRIx64
167
+static const MemoryRegionOps armsse_cpuid_ops = {
144
+ " to 0x%" HWADDR_PRIx "\n",
168
+ .read = armsse_cpuid_read,
145
+ __func__, value, addr);
169
+ .write = armsse_cpuid_write,
146
+ break;
170
+ .endianness = DEVICE_LITTLE_ENDIAN,
147
+ default:
171
+ /* byte/halfword accesses are just zero-padded on reads and writes */
148
+ /* MemoryRegionOps are aligned, so this can not happen. */
172
+ .impl.min_access_size = 4,
149
+ g_assert_not_reached();
150
+ }
151
+}
152
+
153
+static const MemoryRegionOps bcm2835_thermal_ops = {
154
+ .read = bcm2835_thermal_read,
155
+ .write = bcm2835_thermal_write,
156
+ .impl.max_access_size = 4,
173
+ .impl.max_access_size = 4,
157
+ .valid.min_access_size = 4,
174
+ .valid.min_access_size = 1,
158
+ .endianness = DEVICE_NATIVE_ENDIAN,
175
+ .valid.max_access_size = 4,
159
+};
176
+};
160
+
177
+
161
+static void bcm2835_thermal_reset(DeviceState *dev)
178
+static Property armsse_cpuid_props[] = {
162
+{
179
+ DEFINE_PROP_UINT32("CPUID", ARMSSECPUID, cpuid, 0),
163
+ Bcm2835ThermalState *s = BCM2835_THERMAL(dev);
180
+ DEFINE_PROP_END_OF_LIST()
164
+
181
+};
165
+ s->ctl = 0;
182
+
166
+}
183
+static void armsse_cpuid_init(Object *obj)
167
+
184
+{
168
+static void bcm2835_thermal_realize(DeviceState *dev, Error **errp)
185
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
169
+{
186
+ ARMSSECPUID *s = ARMSSE_CPUID(obj);
170
+ Bcm2835ThermalState *s = BCM2835_THERMAL(dev);
187
+
171
+
188
+ memory_region_init_io(&s->iomem, obj, &armsse_cpuid_ops,
172
+ memory_region_init_io(&s->iomem, OBJECT(s), &bcm2835_thermal_ops,
189
+ s, "armsse-cpuid", 0x1000);
173
+ s, TYPE_BCM2835_THERMAL, 8);
190
+ sysbus_init_mmio(sbd, &s->iomem);
174
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
191
+}
175
+}
192
+
176
+
193
+static void armsse_cpuid_class_init(ObjectClass *klass, void *data)
177
+static const VMStateDescription bcm2835_thermal_vmstate = {
178
+ .name = "bcm2835_thermal",
179
+ .version_id = 1,
180
+ .minimum_version_id = 1,
181
+ .fields = (VMStateField[]) {
182
+ VMSTATE_UINT32(ctl, Bcm2835ThermalState),
183
+ VMSTATE_END_OF_LIST()
184
+ }
185
+};
186
+
187
+static void bcm2835_thermal_class_init(ObjectClass *klass, void *data)
188
+{
194
+{
189
+ DeviceClass *dc = DEVICE_CLASS(klass);
195
+ DeviceClass *dc = DEVICE_CLASS(klass);
190
+
196
+
191
+ dc->realize = bcm2835_thermal_realize;
197
+ /*
192
+ dc->reset = bcm2835_thermal_reset;
198
+ * This device has no guest-modifiable state and so it
193
+ dc->vmsd = &bcm2835_thermal_vmstate;
199
+ * does not need a reset function or VMState.
194
+}
200
+ */
195
+
201
+
196
+static const TypeInfo bcm2835_thermal_info = {
202
+ dc->props = armsse_cpuid_props;
197
+ .name = TYPE_BCM2835_THERMAL,
203
+}
204
+
205
+static const TypeInfo armsse_cpuid_info = {
206
+ .name = TYPE_ARMSSE_CPUID,
198
+ .parent = TYPE_SYS_BUS_DEVICE,
207
+ .parent = TYPE_SYS_BUS_DEVICE,
199
+ .instance_size = sizeof(Bcm2835ThermalState),
208
+ .instance_size = sizeof(ARMSSECPUID),
200
+ .class_init = bcm2835_thermal_class_init,
209
+ .instance_init = armsse_cpuid_init,
201
+};
210
+ .class_init = armsse_cpuid_class_init,
202
+
211
+};
203
+static void bcm2835_thermal_register_types(void)
212
+
204
+{
213
+static void armsse_cpuid_register_types(void)
205
+ type_register_static(&bcm2835_thermal_info);
214
+{
206
+}
215
+ type_register_static(&armsse_cpuid_info);
207
+
216
+}
208
+type_init(bcm2835_thermal_register_types)
217
+
218
+type_init(armsse_cpuid_register_types);
219
diff --git a/MAINTAINERS b/MAINTAINERS
220
index XXXXXXX..XXXXXXX 100644
221
--- a/MAINTAINERS
222
+++ b/MAINTAINERS
223
@@ -XXX,XX +XXX,XX @@ F: hw/misc/iotkit-sysctl.c
224
F: include/hw/misc/iotkit-sysctl.h
225
F: hw/misc/iotkit-sysinfo.c
226
F: include/hw/misc/iotkit-sysinfo.h
227
+F: hw/misc/armsse-cpuid.c
228
+F: include/hw/misc/armsse-cpuid.h
229
230
Musicpal
231
M: Jan Kiszka <jan.kiszka@web.de>
232
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
233
index XXXXXXX..XXXXXXX 100644
234
--- a/default-configs/arm-softmmu.mak
235
+++ b/default-configs/arm-softmmu.mak
236
@@ -XXX,XX +XXX,XX @@ CONFIG_ARMSSE=y
237
CONFIG_IOTKIT_SECCTL=y
238
CONFIG_IOTKIT_SYSCTL=y
239
CONFIG_IOTKIT_SYSINFO=y
240
+CONFIG_ARMSSE_CPUID=y
241
242
CONFIG_VERSATILE=y
243
CONFIG_VERSATILE_PCI=y
244
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
245
index XXXXXXX..XXXXXXX 100644
246
--- a/hw/misc/trace-events
247
+++ b/hw/misc/trace-events
248
@@ -XXX,XX +XXX,XX @@ iotkit_sysinfo_write(uint64_t offset, uint64_t data, unsigned size) "IoTKit SysI
249
iotkit_sysctl_read(uint64_t offset, uint64_t data, unsigned size) "IoTKit SysCtl read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
250
iotkit_sysctl_write(uint64_t offset, uint64_t data, unsigned size) "IoTKit SysCtl write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
251
iotkit_sysctl_reset(void) "IoTKit SysCtl: reset"
252
+
253
+# hw/misc/armsse-cpuid.c
254
+armsse_cpuid_read(uint64_t offset, uint64_t data, unsigned size) "SSE-200 CPU_IDENTITY read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
255
+armsse_cpuid_write(uint64_t offset, uint64_t data, unsigned size) "SSE-200 CPU_IDENTITY write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
209
--
256
--
210
2.20.1
257
2.20.1
211
258
212
259
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Instantiate a copy of the CPU_IDENTITY register block for each CPU
2
in an SSE-200.
2
3
3
Create a function to compute the values of the TBFLAG_ANY bits
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
that will be cached. For now, the env->hflags variable is not
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
used, and the results are fed back to cpu_get_tb_cpu_state.
6
Message-id: 20190121185118.18550-21-peter.maydell@linaro.org
7
---
8
include/hw/arm/armsse.h | 3 +++
9
hw/arm/armsse.c | 28 ++++++++++++++++++++++++++++
10
2 files changed, 31 insertions(+)
6
11
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
12
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20191023150057.25731-2-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/cpu.h | 29 ++++++++++++++++++-----------
13
target/arm/helper.c | 26 +++++++++++++++++++-------
14
2 files changed, 37 insertions(+), 18 deletions(-)
15
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu.h
14
--- a/include/hw/arm/armsse.h
19
+++ b/target/arm/cpu.h
15
+++ b/include/hw/arm/armsse.h
20
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
16
@@ -XXX,XX +XXX,XX @@
21
uint32_t pstate;
17
#include "hw/watchdog/cmsdk-apb-watchdog.h"
22
uint32_t aarch64; /* 1 if CPU is in aarch64 state; inverse of PSTATE.nRW */
18
#include "hw/misc/iotkit-sysctl.h"
23
19
#include "hw/misc/iotkit-sysinfo.h"
24
+ /* Cached TBFLAGS state. See below for which bits are included. */
20
+#include "hw/misc/armsse-cpuid.h"
25
+ uint32_t hflags;
21
#include "hw/misc/unimp.h"
22
#include "hw/or-irq.h"
23
#include "hw/core/split-irq.h"
24
@@ -XXX,XX +XXX,XX @@ typedef struct ARMSSE {
25
UnimplementedDeviceState cachectrl[SSE_MAX_CPUS];
26
UnimplementedDeviceState cpusecctrl[SSE_MAX_CPUS];
27
28
+ ARMSSECPUID cpuid[SSE_MAX_CPUS];
26
+
29
+
27
/* Frequently accessed CPSR bits are stored separately for efficiency.
30
/*
28
This contains all the other bits. Use cpsr_{read,write} to access
31
* 'container' holds all devices seen by all CPUs.
29
the whole CPSR. */
32
* 'cpu_container[i]' is the view that CPU i has: this has the
30
@@ -XXX,XX +XXX,XX @@ typedef ARMCPU ArchCPU;
33
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
31
32
#include "exec/cpu-all.h"
33
34
-/* Bit usage in the TB flags field: bit 31 indicates whether we are
35
+/*
36
+ * Bit usage in the TB flags field: bit 31 indicates whether we are
37
* in 32 or 64 bit mode. The meaning of the other bits depends on that.
38
* We put flags which are shared between 32 and 64 bit mode at the top
39
* of the word, and flags which apply to only one mode at the bottom.
40
+ *
41
+ * Unless otherwise noted, these bits are cached in env->hflags.
42
*/
43
FIELD(TBFLAG_ANY, AARCH64_STATE, 31, 1)
44
FIELD(TBFLAG_ANY, MMUIDX, 28, 3)
45
FIELD(TBFLAG_ANY, SS_ACTIVE, 27, 1)
46
-FIELD(TBFLAG_ANY, PSTATE_SS, 26, 1)
47
+FIELD(TBFLAG_ANY, PSTATE_SS, 26, 1) /* Not cached. */
48
/* Target EL if we take a floating-point-disabled exception */
49
FIELD(TBFLAG_ANY, FPEXC_EL, 24, 2)
50
FIELD(TBFLAG_ANY, BE_DATA, 23, 1)
51
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_ANY, BE_DATA, 23, 1)
52
FIELD(TBFLAG_ANY, DEBUG_TARGET_EL, 21, 2)
53
54
/* Bit usage when in AArch32 state: */
55
-FIELD(TBFLAG_A32, THUMB, 0, 1)
56
-FIELD(TBFLAG_A32, VECLEN, 1, 3)
57
-FIELD(TBFLAG_A32, VECSTRIDE, 4, 2)
58
+FIELD(TBFLAG_A32, THUMB, 0, 1) /* Not cached. */
59
+FIELD(TBFLAG_A32, VECLEN, 1, 3) /* Not cached. */
60
+FIELD(TBFLAG_A32, VECSTRIDE, 4, 2) /* Not cached. */
61
/*
62
* We store the bottom two bits of the CPAR as TB flags and handle
63
* checks on the other bits at runtime. This shares the same bits as
64
* VECSTRIDE, which is OK as no XScale CPU has VFP.
65
+ * Not cached, because VECLEN+VECSTRIDE are not cached.
66
*/
67
FIELD(TBFLAG_A32, XSCALE_CPAR, 4, 2)
68
/*
69
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_A32, XSCALE_CPAR, 4, 2)
70
* the same thing as the current security state of the processor!
71
*/
72
FIELD(TBFLAG_A32, NS, 6, 1)
73
-FIELD(TBFLAG_A32, VFPEN, 7, 1)
74
-FIELD(TBFLAG_A32, CONDEXEC, 8, 8)
75
+FIELD(TBFLAG_A32, VFPEN, 7, 1) /* Not cached. */
76
+FIELD(TBFLAG_A32, CONDEXEC, 8, 8) /* Not cached. */
77
FIELD(TBFLAG_A32, SCTLR_B, 16, 1)
78
/* For M profile only, set if FPCCR.LSPACT is set */
79
-FIELD(TBFLAG_A32, LSPACT, 18, 1)
80
+FIELD(TBFLAG_A32, LSPACT, 18, 1) /* Not cached. */
81
/* For M profile only, set if we must create a new FP context */
82
-FIELD(TBFLAG_A32, NEW_FP_CTXT_NEEDED, 19, 1)
83
+FIELD(TBFLAG_A32, NEW_FP_CTXT_NEEDED, 19, 1) /* Not cached. */
84
/* For M profile only, set if FPCCR.S does not match current security state */
85
-FIELD(TBFLAG_A32, FPCCR_S_WRONG, 20, 1)
86
+FIELD(TBFLAG_A32, FPCCR_S_WRONG, 20, 1) /* Not cached. */
87
/* For M profile only, Handler (ie not Thread) mode */
88
FIELD(TBFLAG_A32, HANDLER, 21, 1)
89
/* For M profile only, whether we should generate stack-limit checks */
90
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_A64, SVEEXC_EL, 2, 2)
91
FIELD(TBFLAG_A64, ZCR_LEN, 4, 4)
92
FIELD(TBFLAG_A64, PAUTH_ACTIVE, 8, 1)
93
FIELD(TBFLAG_A64, BT, 9, 1)
94
-FIELD(TBFLAG_A64, BTYPE, 10, 2)
95
+FIELD(TBFLAG_A64, BTYPE, 10, 2) /* Not cached. */
96
FIELD(TBFLAG_A64, TBID, 12, 2)
97
98
static inline bool bswap_code(bool sctlr_b)
99
diff --git a/target/arm/helper.c b/target/arm/helper.c
100
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
101
--- a/target/arm/helper.c
35
--- a/hw/arm/armsse.c
102
+++ b/target/arm/helper.c
36
+++ b/hw/arm/armsse.c
103
@@ -XXX,XX +XXX,XX @@ ARMMMUIdx arm_stage1_mmu_idx(CPUARMState *env)
37
@@ -XXX,XX +XXX,XX @@ struct ARMSSEInfo {
104
}
38
bool has_ppus;
105
#endif
39
bool has_cachectrl;
106
40
bool has_cpusecctrl;
107
+static uint32_t rebuild_hflags_common(CPUARMState *env, int fp_el,
41
+ bool has_cpuid;
108
+ ARMMMUIdx mmu_idx, uint32_t flags)
42
};
109
+{
43
110
+ flags = FIELD_DP32(flags, TBFLAG_ANY, FPEXC_EL, fp_el);
44
static const ARMSSEInfo armsse_variants[] = {
111
+ flags = FIELD_DP32(flags, TBFLAG_ANY, MMUIDX,
45
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
112
+ arm_to_core_mmu_idx(mmu_idx));
46
.has_ppus = false,
113
+
47
.has_cachectrl = false,
114
+ if (arm_cpu_data_is_big_endian(env)) {
48
.has_cpusecctrl = false,
115
+ flags = FIELD_DP32(flags, TBFLAG_ANY, BE_DATA, 1);
49
+ .has_cpuid = false,
116
+ }
50
},
117
+ if (arm_singlestep_active(env)) {
51
};
118
+ flags = FIELD_DP32(flags, TBFLAG_ANY, SS_ACTIVE, 1);
52
119
+ }
53
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
120
+ return flags;
54
g_free(name);
121
+}
122
+
123
void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
124
target_ulong *cs_base, uint32_t *pflags)
125
{
126
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
127
}
55
}
128
}
56
}
129
57
+ if (info->has_cpuid) {
130
- flags = FIELD_DP32(flags, TBFLAG_ANY, MMUIDX, arm_to_core_mmu_idx(mmu_idx));
58
+ for (i = 0; i < info->num_cpus; i++) {
131
+ flags = rebuild_hflags_common(env, fp_el, mmu_idx, flags);
59
+ char *name = g_strdup_printf("cpuid%d", i);
132
60
+
133
/* The SS_ACTIVE and PSTATE_SS bits correspond to the state machine
61
+ sysbus_init_child_obj(obj, name, &s->cpuid[i],
134
* states defined in the ARM ARM for software singlestep:
62
+ sizeof(s->cpuid[i]),
135
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
63
+ TYPE_ARMSSE_CPUID);
136
* 0 x Inactive (the TB flag for SS is always 0)
64
+ g_free(name);
137
* 1 0 Active-pending
65
+ }
138
* 1 1 Active-not-pending
66
+ }
139
+ * SS_ACTIVE is set in hflags; PSTATE_SS is computed every TB.
67
object_initialize_child(obj, "nmi-orgate", &s->nmi_orgate,
140
*/
68
sizeof(s->nmi_orgate), TYPE_OR_IRQ,
141
- if (arm_singlestep_active(env)) {
69
&error_abort, NULL);
142
- flags = FIELD_DP32(flags, TBFLAG_ANY, SS_ACTIVE, 1);
70
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
143
+ if (FIELD_EX32(flags, TBFLAG_ANY, SS_ACTIVE)) {
71
memory_region_add_subregion(&s->cpu_container[i], 0x50011000, mr);
144
if (is_a64(env)) {
145
if (env->pstate & PSTATE_SS) {
146
flags = FIELD_DP32(flags, TBFLAG_ANY, PSTATE_SS, 1);
147
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
148
}
149
}
72
}
150
}
73
}
151
- if (arm_cpu_data_is_big_endian(env)) {
74
+ if (info->has_cpuid) {
152
- flags = FIELD_DP32(flags, TBFLAG_ANY, BE_DATA, 1);
75
+ for (i = 0; i < info->num_cpus; i++) {
153
- }
76
+ MemoryRegion *mr;
154
- flags = FIELD_DP32(flags, TBFLAG_ANY, FPEXC_EL, fp_el);
77
+
155
78
+ qdev_prop_set_uint32(DEVICE(&s->cpuid[i]), "CPUID", i);
156
if (arm_v7m_is_handler_mode(env)) {
79
+ object_property_set_bool(OBJECT(&s->cpuid[i]), true,
157
flags = FIELD_DP32(flags, TBFLAG_A32, HANDLER, 1);
80
+ "realized", &err);
81
+ if (err) {
82
+ error_propagate(errp, err);
83
+ return;
84
+ }
85
+
86
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->cpuid[i]), 0);
87
+ memory_region_add_subregion(&s->cpu_container[i], 0x4001F000, mr);
88
+ }
89
+ }
90
91
/* 0x40020000 .. 0x4002ffff : ARMSSE system control peripheral region */
92
/* Devices behind APB PPC1:
158
--
93
--
159
2.20.1
94
2.20.1
160
95
161
96
diff view generated by jsdifflib
1
Switch the xilinx_axidma code away from bottom-half based ptimers to
1
Add a model of the SSE-200, now we have put in all
2
the new transaction-based ptimer API. This just requires adding
2
the code that lets us make it different from the IoTKit.
3
begin/commit calls around the various places that modify the ptimer
4
state, and using the new ptimer_init() function to create the timer.
5
3
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
Message-id: 20190121185118.18550-22-peter.maydell@linaro.org
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
Message-id: 20191017132122.4402-4-peter.maydell@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
7
---
13
hw/dma/xilinx_axidma.c | 9 +++++----
8
include/hw/arm/armsse.h | 19 ++++++++++++++++---
14
1 file changed, 5 insertions(+), 4 deletions(-)
9
hw/arm/armsse.c | 12 ++++++++++++
10
2 files changed, 28 insertions(+), 3 deletions(-)
15
11
16
diff --git a/hw/dma/xilinx_axidma.c b/hw/dma/xilinx_axidma.c
12
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
17
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/dma/xilinx_axidma.c
14
--- a/include/hw/arm/armsse.h
19
+++ b/hw/dma/xilinx_axidma.c
15
+++ b/include/hw/arm/armsse.h
20
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@
21
#include "hw/ptimer.h"
17
/*
22
#include "hw/qdev-properties.h"
18
- * ARM SSE (Subsystems for Embedded): IoTKit
23
#include "qemu/log.h"
19
+ * ARM SSE (Subsystems for Embedded): IoTKit, SSE-200
24
-#include "qemu/main-loop.h"
20
*
25
#include "qemu/module.h"
21
* Copyright (c) 2018 Linaro Limited
26
22
* Written by Peter Maydell
27
#include "hw/stream.h"
23
@@ -XXX,XX +XXX,XX @@
28
@@ -XXX,XX +XXX,XX @@ enum {
24
/*
25
* This is a model of the Arm "Subsystems for Embedded" family of
26
* hardware, which include the IoT Kit and the SSE-050, SSE-100 and
27
- * SSE-200. Currently we model only the Arm IoT Kit which is documented in
28
+ * SSE-200. Currently we model:
29
+ * - the Arm IoT Kit which is documented in
30
* http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
31
- * It contains:
32
+ * - the SSE-200 which is documented in
33
+ * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
34
+ *
35
+ * The IoTKit contains:
36
* a Cortex-M33
37
* the IDAU
38
* some timers and watchdogs
39
@@ -XXX,XX +XXX,XX @@
40
* a security controller
41
* a bus fabric which arranges that some parts of the address
42
* space are secure and non-secure aliases of each other
43
+ * The SSE-200 additionally contains:
44
+ * a second Cortex-M33
45
+ * two Message Handling Units (MHUs)
46
+ * an optional CryptoCell (which we do not model)
47
+ * more SRAM banks with associated MPCs
48
+ * multiple Power Policy Units (PPUs)
49
+ * a control interface for an icache for each CPU
50
+ * per-CPU identity and control register blocks
51
*
52
* QEMU interface:
53
* + QOM property "memory" is a MemoryRegion containing the devices provided
54
@@ -XXX,XX +XXX,XX @@
55
* them via the ARMSSE base class, so they have no IOTKIT() etc macros.
56
*/
57
#define TYPE_IOTKIT "iotkit"
58
+#define TYPE_SSE200 "sse-200"
59
60
/* We have an IRQ splitter and an OR gate input for each external PPC
61
* and the 2 internal PPCs
62
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
63
index XXXXXXX..XXXXXXX 100644
64
--- a/hw/arm/armsse.c
65
+++ b/hw/arm/armsse.c
66
@@ -XXX,XX +XXX,XX @@ static const ARMSSEInfo armsse_variants[] = {
67
.has_cpusecctrl = false,
68
.has_cpuid = false,
69
},
70
+ {
71
+ .name = TYPE_SSE200,
72
+ .sram_banks = 4,
73
+ .num_cpus = 2,
74
+ .sys_version = 0x22041743,
75
+ .sys_config_format = SSE200Format,
76
+ .has_mhus = true,
77
+ .has_ppus = true,
78
+ .has_cachectrl = true,
79
+ .has_cpusecctrl = true,
80
+ .has_cpuid = true,
81
+ },
29
};
82
};
30
83
31
struct Stream {
84
static uint32_t armsse_sys_config_value(ARMSSE *s, const ARMSSEInfo *info)
32
- QEMUBH *bh;
33
ptimer_state *ptimer;
34
qemu_irq irq;
35
36
@@ -XXX,XX +XXX,XX @@ static void stream_complete(struct Stream *s)
37
unsigned int comp_delay;
38
39
/* Start the delayed timer. */
40
+ ptimer_transaction_begin(s->ptimer);
41
comp_delay = s->regs[R_DMACR] >> 24;
42
if (comp_delay) {
43
ptimer_stop(s->ptimer);
44
@@ -XXX,XX +XXX,XX @@ static void stream_complete(struct Stream *s)
45
s->regs[R_DMASR] |= DMASR_IOC_IRQ;
46
stream_reload_complete_cnt(s);
47
}
48
+ ptimer_transaction_commit(s->ptimer);
49
}
50
51
static void stream_process_mem2s(struct Stream *s, StreamSlave *tx_data_dev,
52
@@ -XXX,XX +XXX,XX @@ static void xilinx_axidma_realize(DeviceState *dev, Error **errp)
53
struct Stream *st = &s->streams[i];
54
55
st->nr = i;
56
- st->bh = qemu_bh_new(timer_hit, st);
57
- st->ptimer = ptimer_init_with_bh(st->bh, PTIMER_POLICY_DEFAULT);
58
+ st->ptimer = ptimer_init(timer_hit, st, PTIMER_POLICY_DEFAULT);
59
+ ptimer_transaction_begin(st->ptimer);
60
ptimer_set_freq(st->ptimer, s->freqhz);
61
+ ptimer_transaction_commit(st->ptimer);
62
}
63
return;
64
65
--
85
--
66
2.20.1
86
2.20.1
67
87
68
88
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
In preparation for adding support for the AN521 MPS2 image, we need
2
to handle wiring up the MPS2 device interrupt lines to both CPUs in
3
the SSE-200, rather than just the one that the IoTKit has.
2
4
3
Continue setting, but not relying upon, env->hflags.
5
Abstract out a "connect to the IoTKit interrupt line" function
6
and make it connect to a splitter which feeds both sets of inputs
7
for the SSE-200 case.
4
8
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20191023150057.25731-21-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20190121185118.18550-23-peter.maydell@linaro.org
9
---
12
---
10
target/arm/m_helper.c | 6 ++++++
13
hw/arm/mps2-tz.c | 79 ++++++++++++++++++++++++++++++++++++------------
11
target/arm/translate.c | 5 ++++-
14
1 file changed, 59 insertions(+), 20 deletions(-)
12
2 files changed, 10 insertions(+), 1 deletion(-)
13
15
14
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
16
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
15
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/m_helper.c
18
--- a/hw/arm/mps2-tz.c
17
+++ b/target/arm/m_helper.c
19
+++ b/hw/arm/mps2-tz.c
18
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_bxns)(CPUARMState *env, uint32_t dest)
20
@@ -XXX,XX +XXX,XX @@
19
switch_v7m_security_state(env, dest & 1);
21
#include "net/net.h"
20
env->thumb = 1;
22
#include "hw/core/split-irq.h"
21
env->regs[15] = dest & ~1;
23
22
+ arm_rebuild_hflags(env);
24
+#define MPS2TZ_NUMIRQ 92
25
+
26
typedef enum MPS2TZFPGAType {
27
FPGA_AN505,
28
+ FPGA_AN521,
29
} MPS2TZFPGAType;
30
31
typedef struct {
32
@@ -XXX,XX +XXX,XX @@ typedef struct {
33
SplitIRQ sec_resp_splitter;
34
qemu_or_irq uart_irq_orgate;
35
DeviceState *lan9118;
36
+ SplitIRQ cpu_irq_splitter[MPS2TZ_NUMIRQ];
37
} MPS2TZMachineState;
38
39
#define TYPE_MPS2TZ_MACHINE "mps2tz"
40
@@ -XXX,XX +XXX,XX @@ static void make_ram_alias(MemoryRegion *mr, const char *name,
41
memory_region_add_subregion(get_system_memory(), base, mr);
23
}
42
}
24
43
25
void HELPER(v7m_blxns)(CPUARMState *env, uint32_t dest)
44
+static qemu_irq get_sse_irq_in(MPS2TZMachineState *mms, int irqno)
26
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_blxns)(CPUARMState *env, uint32_t dest)
45
+{
27
switch_v7m_security_state(env, 0);
46
+ /* Return a qemu_irq which will signal IRQ n to all CPUs in the SSE. */
28
env->thumb = 1;
47
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
29
env->regs[15] = dest;
48
+
30
+ arm_rebuild_hflags(env);
49
+ assert(irqno < MPS2TZ_NUMIRQ);
50
+
51
+ switch (mmc->fpga_type) {
52
+ case FPGA_AN505:
53
+ return qdev_get_gpio_in_named(DEVICE(&mms->iotkit), "EXP_IRQ", irqno);
54
+ case FPGA_AN521:
55
+ return qdev_get_gpio_in(DEVICE(&mms->cpu_irq_splitter[irqno]), 0);
56
+ default:
57
+ g_assert_not_reached();
58
+ }
59
+}
60
+
61
/* Most of the devices in the AN505 FPGA image sit behind
62
* Peripheral Protection Controllers. These data structures
63
* define the layout of which devices sit behind which PPCs.
64
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
65
int txirqno = i * 2 + 1;
66
int combirqno = i + 10;
67
SysBusDevice *s;
68
- DeviceState *iotkitdev = DEVICE(&mms->iotkit);
69
DeviceState *orgate_dev = DEVICE(&mms->uart_irq_orgate);
70
71
sysbus_init_child_obj(OBJECT(mms), name, uart, sizeof(mms->uart[0]),
72
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
73
qdev_prop_set_uint32(DEVICE(uart), "pclk-frq", SYSCLK_FRQ);
74
object_property_set_bool(OBJECT(uart), true, "realized", &error_fatal);
75
s = SYS_BUS_DEVICE(uart);
76
- sysbus_connect_irq(s, 0, qdev_get_gpio_in_named(iotkitdev,
77
- "EXP_IRQ", txirqno));
78
- sysbus_connect_irq(s, 1, qdev_get_gpio_in_named(iotkitdev,
79
- "EXP_IRQ", rxirqno));
80
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, txirqno));
81
+ sysbus_connect_irq(s, 1, get_sse_irq_in(mms, rxirqno));
82
sysbus_connect_irq(s, 2, qdev_get_gpio_in(orgate_dev, i * 2));
83
sysbus_connect_irq(s, 3, qdev_get_gpio_in(orgate_dev, i * 2 + 1));
84
- sysbus_connect_irq(s, 4, qdev_get_gpio_in_named(iotkitdev,
85
- "EXP_IRQ", combirqno));
86
+ sysbus_connect_irq(s, 4, get_sse_irq_in(mms, combirqno));
87
return sysbus_mmio_get_region(SYS_BUS_DEVICE(uart), 0);
31
}
88
}
32
89
33
static uint32_t *get_v7m_sp_ptr(CPUARMState *env, bool secure, bool threadmode,
90
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
34
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
91
const char *name, hwaddr size)
35
env->regs[14] = lr;
92
{
36
env->regs[15] = addr & 0xfffffffe;
93
SysBusDevice *s;
37
env->thumb = addr & 1;
94
- DeviceState *iotkitdev = DEVICE(&mms->iotkit);
38
+ arm_rebuild_hflags(env);
95
NICInfo *nd = &nd_table[0];
96
97
/* In hardware this is a LAN9220; the LAN9118 is software compatible
98
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
99
qdev_init_nofail(mms->lan9118);
100
101
s = SYS_BUS_DEVICE(mms->lan9118);
102
- sysbus_connect_irq(s, 0, qdev_get_gpio_in_named(iotkitdev, "EXP_IRQ", 16));
103
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, 16));
104
return sysbus_mmio_get_region(s, 0);
39
}
105
}
40
106
41
static void v7m_update_fpccr(CPUARMState *env, uint32_t frameptr,
107
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_dma(MPS2TZMachineState *mms, void *opaque,
42
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
108
43
109
s = SYS_BUS_DEVICE(dma);
44
/* Otherwise, we have a successful exception exit. */
110
/* Wire up DMACINTR, DMACINTERR, DMACINTTC */
45
arm_clear_exclusive(env);
111
- sysbus_connect_irq(s, 0, qdev_get_gpio_in_named(iotkitdev,
46
+ arm_rebuild_hflags(env);
112
- "EXP_IRQ", 58 + i * 3));
47
qemu_log_mask(CPU_LOG_INT, "...successful exception return\n");
113
- sysbus_connect_irq(s, 1, qdev_get_gpio_in_named(iotkitdev,
114
- "EXP_IRQ", 56 + i * 3));
115
- sysbus_connect_irq(s, 2, qdev_get_gpio_in_named(iotkitdev,
116
- "EXP_IRQ", 57 + i * 3));
117
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, 58 + i * 3));
118
+ sysbus_connect_irq(s, 1, get_sse_irq_in(mms, 56 + i * 3));
119
+ sysbus_connect_irq(s, 2, get_sse_irq_in(mms, 57 + i * 3));
120
121
g_free(mscname);
122
return sysbus_mmio_get_region(s, 0);
123
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_spi(MPS2TZMachineState *mms, void *opaque,
124
*/
125
PL022State *spi = opaque;
126
int i = spi - &mms->spi[0];
127
- DeviceState *iotkitdev = DEVICE(&mms->iotkit);
128
SysBusDevice *s;
129
130
sysbus_init_child_obj(OBJECT(mms), name, spi, sizeof(mms->spi[0]),
131
TYPE_PL022);
132
object_property_set_bool(OBJECT(spi), true, "realized", &error_fatal);
133
s = SYS_BUS_DEVICE(spi);
134
- sysbus_connect_irq(s, 0,
135
- qdev_get_gpio_in_named(iotkitdev, "EXP_IRQ", 51 + i));
136
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, 51 + i));
137
return sysbus_mmio_get_region(s, 0);
48
}
138
}
49
139
50
@@ -XXX,XX +XXX,XX @@ static bool do_v7m_function_return(ARMCPU *cpu)
140
static void mps2tz_common_init(MachineState *machine)
51
xpsr_write(env, 0, XPSR_IT);
52
env->thumb = newpc & 1;
53
env->regs[15] = newpc & ~1;
54
+ arm_rebuild_hflags(env);
55
56
qemu_log_mask(CPU_LOG_INT, "...function return successful\n");
57
return true;
58
@@ -XXX,XX +XXX,XX @@ static bool v7m_handle_execute_nsc(ARMCPU *cpu)
59
switch_v7m_security_state(env, true);
60
xpsr_write(env, 0, XPSR_IT);
61
env->regs[15] += 4;
62
+ arm_rebuild_hflags(env);
63
return true;
64
65
gen_invep:
66
diff --git a/target/arm/translate.c b/target/arm/translate.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/target/arm/translate.c
69
+++ b/target/arm/translate.c
70
@@ -XXX,XX +XXX,XX @@ static bool trans_MRS_v7m(DisasContext *s, arg_MRS_v7m *a)
71
72
static bool trans_MSR_v7m(DisasContext *s, arg_MSR_v7m *a)
73
{
141
{
74
- TCGv_i32 addr, reg;
142
MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine);
75
+ TCGv_i32 addr, reg, el;
143
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
76
144
MachineClass *mc = MACHINE_GET_CLASS(machine);
77
if (!arm_dc_feature(s, ARM_FEATURE_M)) {
145
MemoryRegion *system_memory = get_system_memory();
78
return false;
146
DeviceState *iotkitdev;
79
@@ -XXX,XX +XXX,XX @@ static bool trans_MSR_v7m(DisasContext *s, arg_MSR_v7m *a)
147
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
80
gen_helper_v7m_msr(cpu_env, addr, reg);
148
iotkitdev = DEVICE(&mms->iotkit);
81
tcg_temp_free_i32(addr);
149
object_property_set_link(OBJECT(&mms->iotkit), OBJECT(system_memory),
82
tcg_temp_free_i32(reg);
150
"memory", &error_abort);
83
+ el = tcg_const_i32(s->current_el);
151
- qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", 92);
84
+ gen_helper_rebuild_hflags_m32(cpu_env, el);
152
+ qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", MPS2TZ_NUMIRQ);
85
+ tcg_temp_free_i32(el);
153
qdev_prop_set_uint32(iotkitdev, "MAINCLK", SYSCLK_FRQ);
86
gen_lookup_tb(s);
154
object_property_set_bool(OBJECT(&mms->iotkit), true, "realized",
87
return true;
155
&error_fatal);
88
}
156
157
+ /*
158
+ * The AN521 needs us to create splitters to feed the IRQ inputs
159
+ * for each CPU in the SSE-200 from each device in the board.
160
+ */
161
+ if (mmc->fpga_type == FPGA_AN521) {
162
+ for (i = 0; i < MPS2TZ_NUMIRQ; i++) {
163
+ char *name = g_strdup_printf("mps2-irq-splitter%d", i);
164
+ SplitIRQ *splitter = &mms->cpu_irq_splitter[i];
165
+
166
+ object_initialize_child(OBJECT(machine), name,
167
+ splitter, sizeof(*splitter),
168
+ TYPE_SPLIT_IRQ, &error_fatal, NULL);
169
+ g_free(name);
170
+
171
+ object_property_set_int(OBJECT(splitter), 2, "num-lines",
172
+ &error_fatal);
173
+ object_property_set_bool(OBJECT(splitter), true, "realized",
174
+ &error_fatal);
175
+ qdev_connect_gpio_out(DEVICE(splitter), 0,
176
+ qdev_get_gpio_in_named(DEVICE(&mms->iotkit),
177
+ "EXP_IRQ", i));
178
+ qdev_connect_gpio_out(DEVICE(splitter), 1,
179
+ qdev_get_gpio_in_named(DEVICE(&mms->iotkit),
180
+ "EXP_CPU1_IRQ", i));
181
+ }
182
+ }
183
+
184
/* The sec_resp_cfg output from the IoTKit must be split into multiple
185
* lines, one for each of the PPCs we create here, plus one per MSC.
186
*/
187
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
188
object_property_set_bool(OBJECT(&mms->uart_irq_orgate), true,
189
"realized", &error_fatal);
190
qdev_connect_gpio_out(DEVICE(&mms->uart_irq_orgate), 0,
191
- qdev_get_gpio_in_named(iotkitdev, "EXP_IRQ", 15));
192
+ get_sse_irq_in(mms, 15));
193
194
/* Most of the devices in the FPGA are behind Peripheral Protection
195
* Controllers. The required order for initializing things is:
89
--
196
--
90
2.20.1
197
2.20.1
91
198
92
199
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Add a model of the MPS2 FPGA image described in Application Note
2
AN521. This is identical to the AN505 image, except that it uses
3
the SSE-200 rather than the IoTKit and so has two Cortex-M33 CPUs.
2
4
3
Create a function to compute the values of the TBFLAG_ANY bits
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
that will be cached, and are used by A-profile.
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20190121185118.18550-24-peter.maydell@linaro.org
8
---
9
hw/arm/mps2-tz.c | 38 ++++++++++++++++++++++++++++++++++++--
10
1 file changed, 36 insertions(+), 2 deletions(-)
5
11
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
12
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20191023150057.25731-9-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/helper.c | 20 ++++++++++++--------
12
1 file changed, 12 insertions(+), 8 deletions(-)
13
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
14
--- a/hw/arm/mps2-tz.c
17
+++ b/target/arm/helper.c
15
+++ b/hw/arm/mps2-tz.c
18
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_m32(CPUARMState *env, int fp_el,
16
@@ -XXX,XX +XXX,XX @@
19
return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags);
17
* as seen by the guest depend significantly on the FPGA image.
18
* This source file covers the following FPGA images, for TrustZone cores:
19
* "mps2-an505" -- Cortex-M33 as documented in ARM Application Note AN505
20
+ * "mps2-an521" -- Dual Cortex-M33 as documented in Application Note AN521
21
*
22
* Links to the TRM for the board itself and to the various Application
23
* Notes which document the FPGA images can be found here:
24
@@ -XXX,XX +XXX,XX @@
25
* http://infocenter.arm.com/help/topic/com.arm.doc.100112_0200_06_en/versatile_express_cortex_m_prototyping_systems_v2m_mps2_and_v2m_mps2plus_technical_reference_100112_0200_06_en.pdf
26
* Application Note AN505:
27
* http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
28
+ * Application Note AN521:
29
+ * http://infocenter.arm.com/help/topic/com.arm.doc.dai0521c/index.html
30
*
31
* The AN505 defers to the Cortex-M33 processor ARMv8M IoT Kit FVP User Guide
32
* (ARM ECM0601256) for the details of some of the device layout:
33
* http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
34
+ * Similarly, the AN521 uses the SSE-200, and the SSE-200 TRM defines
35
+ * most of the device layout:
36
+ * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
37
+ *
38
*/
39
40
#include "qemu/osdep.h"
41
@@ -XXX,XX +XXX,XX @@ typedef struct {
42
MachineClass parent;
43
MPS2TZFPGAType fpga_type;
44
uint32_t scc_id;
45
+ const char *armsse_type;
46
} MPS2TZMachineClass;
47
48
typedef struct {
49
@@ -XXX,XX +XXX,XX @@ typedef struct {
50
51
#define TYPE_MPS2TZ_MACHINE "mps2tz"
52
#define TYPE_MPS2TZ_AN505_MACHINE MACHINE_TYPE_NAME("mps2-an505")
53
+#define TYPE_MPS2TZ_AN521_MACHINE MACHINE_TYPE_NAME("mps2-an521")
54
55
#define MPS2TZ_MACHINE(obj) \
56
OBJECT_CHECK(MPS2TZMachineState, obj, TYPE_MPS2TZ_MACHINE)
57
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
58
}
59
60
sysbus_init_child_obj(OBJECT(machine), "iotkit", &mms->iotkit,
61
- sizeof(mms->iotkit), TYPE_IOTKIT);
62
+ sizeof(mms->iotkit), mmc->armsse_type);
63
iotkitdev = DEVICE(&mms->iotkit);
64
object_property_set_link(OBJECT(&mms->iotkit), OBJECT(system_memory),
65
"memory", &error_abort);
66
@@ -XXX,XX +XXX,XX @@ static void mps2tz_class_init(ObjectClass *oc, void *data)
67
IDAUInterfaceClass *iic = IDAU_INTERFACE_CLASS(oc);
68
69
mc->init = mps2tz_common_init;
70
- mc->max_cpus = 1;
71
iic->check = mps2_tz_idau_check;
20
}
72
}
21
73
22
+static uint32_t rebuild_hflags_aprofile(CPUARMState *env)
74
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
23
+{
75
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_CLASS(oc);
24
+ int flags = 0;
76
25
+
77
mc->desc = "ARM MPS2 with AN505 FPGA image for Cortex-M33";
26
+ flags = FIELD_DP32(flags, TBFLAG_ANY, DEBUG_TARGET_EL,
78
+ mc->default_cpus = 1;
27
+ arm_debug_target_el(env));
79
+ mc->min_cpus = mc->default_cpus;
28
+ return flags;
80
+ mc->max_cpus = mc->default_cpus;
81
mmc->fpga_type = FPGA_AN505;
82
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
83
mmc->scc_id = 0x41045050;
84
+ mmc->armsse_type = TYPE_IOTKIT;
29
+}
85
+}
30
+
86
+
31
static uint32_t rebuild_hflags_a32(CPUARMState *env, int fp_el,
87
+static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
32
ARMMMUIdx mmu_idx)
88
+{
89
+ MachineClass *mc = MACHINE_CLASS(oc);
90
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_CLASS(oc);
91
+
92
+ mc->desc = "ARM MPS2 with AN521 FPGA image for dual Cortex-M33";
93
+ mc->default_cpus = 2;
94
+ mc->min_cpus = mc->default_cpus;
95
+ mc->max_cpus = mc->default_cpus;
96
+ mmc->fpga_type = FPGA_AN521;
97
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
98
+ mmc->scc_id = 0x41045210;
99
+ mmc->armsse_type = TYPE_SSE200;
100
}
101
102
static const TypeInfo mps2tz_info = {
103
@@ -XXX,XX +XXX,XX @@ static const TypeInfo mps2tz_an505_info = {
104
.class_init = mps2tz_an505_class_init,
105
};
106
107
+static const TypeInfo mps2tz_an521_info = {
108
+ .name = TYPE_MPS2TZ_AN521_MACHINE,
109
+ .parent = TYPE_MPS2TZ_MACHINE,
110
+ .class_init = mps2tz_an521_class_init,
111
+};
112
+
113
static void mps2tz_machine_init(void)
33
{
114
{
34
- return rebuild_hflags_common_32(env, fp_el, mmu_idx, 0);
115
type_register_static(&mps2tz_info);
35
+ uint32_t flags = rebuild_hflags_aprofile(env);
116
type_register_static(&mps2tz_an505_info);
36
+ return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags);
117
+ type_register_static(&mps2tz_an521_info);
37
}
118
}
38
119
39
static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
120
type_init(mps2tz_machine_init);
40
ARMMMUIdx mmu_idx)
41
{
42
+ uint32_t flags = rebuild_hflags_aprofile(env);
43
ARMMMUIdx stage1 = stage_1_mmu_idx(mmu_idx);
44
ARMVAParameters p0 = aa64_va_parameters_both(env, 0, stage1);
45
- uint32_t flags = 0;
46
uint64_t sctlr;
47
int tbii, tbid;
48
49
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
50
}
51
}
52
53
- if (!arm_feature(env, ARM_FEATURE_M)) {
54
- int target_el = arm_debug_target_el(env);
55
-
56
- flags = FIELD_DP32(flags, TBFLAG_ANY, DEBUG_TARGET_EL, target_el);
57
- }
58
-
59
*pflags = flags;
60
*cs_base = 0;
61
}
62
--
121
--
63
2.20.1
122
2.20.1
64
123
65
124
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The "system instructions" and "system register move" subcategories
2
of "branches, exception generating and system instructions" for A64
3
only apply if bits [23:22] are zero; other values are currently
4
unallocated. Correctly UNDEF these unallocated encodings.
2
5
3
Hoist the computation of some TBFLAG_A32 bits that only apply to
6
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
4
M-profile under a single test for ARM_FEATURE_M.
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
9
Message-id: 20190125182626.9221-2-peter.maydell@linaro.org
10
---
11
target/arm/translate-a64.c | 6 +++++-
12
1 file changed, 5 insertions(+), 1 deletion(-)
5
13
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
14
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20191023150057.25731-7-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/helper.c | 49 +++++++++++++++++++++------------------------
12
1 file changed, 23 insertions(+), 26 deletions(-)
13
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
16
--- a/target/arm/translate-a64.c
17
+++ b/target/arm/helper.c
17
+++ b/target/arm/translate-a64.c
18
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
18
@@ -XXX,XX +XXX,XX @@ static void disas_b_exc_sys(DisasContext *s, uint32_t insn)
19
19
break;
20
if (arm_feature(env, ARM_FEATURE_M)) {
20
case 0x6a: /* Exception generation / System */
21
flags = rebuild_hflags_m32(env, fp_el, mmu_idx);
21
if (insn & (1 << 24)) {
22
+
22
- disas_system(s, insn);
23
+ if (arm_feature(env, ARM_FEATURE_M_SECURITY) &&
23
+ if (extract32(insn, 22, 2) == 0) {
24
+ FIELD_EX32(env->v7m.fpccr[M_REG_S], V7M_FPCCR, S)
24
+ disas_system(s, insn);
25
+ != env->v7m.secure) {
25
+ } else {
26
+ flags = FIELD_DP32(flags, TBFLAG_A32, FPCCR_S_WRONG, 1);
26
+ unallocated_encoding(s);
27
+ }
28
+
29
+ if ((env->v7m.fpccr[env->v7m.secure] & R_V7M_FPCCR_ASPEN_MASK) &&
30
+ (!(env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK) ||
31
+ (env->v7m.secure &&
32
+ !(env->v7m.control[M_REG_S] & R_V7M_CONTROL_SFPA_MASK)))) {
33
+ /*
34
+ * ASPEN is set, but FPCA/SFPA indicate that there is no
35
+ * active FP context; we must create a new FP context before
36
+ * executing any FP insn.
37
+ */
38
+ flags = FIELD_DP32(flags, TBFLAG_A32, NEW_FP_CTXT_NEEDED, 1);
39
+ }
40
+
41
+ bool is_secure = env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_S_MASK;
42
+ if (env->v7m.fpccr[is_secure] & R_V7M_FPCCR_LSPACT_MASK) {
43
+ flags = FIELD_DP32(flags, TBFLAG_A32, LSPACT, 1);
44
+ }
27
+ }
45
} else {
28
} else {
46
flags = rebuild_hflags_common_32(env, fp_el, mmu_idx, 0);
29
disas_exc(s, insn);
47
}
30
}
48
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
49
}
50
}
51
52
- if (arm_feature(env, ARM_FEATURE_M_SECURITY) &&
53
- FIELD_EX32(env->v7m.fpccr[M_REG_S], V7M_FPCCR, S) != env->v7m.secure) {
54
- flags = FIELD_DP32(flags, TBFLAG_A32, FPCCR_S_WRONG, 1);
55
- }
56
-
57
- if (arm_feature(env, ARM_FEATURE_M) &&
58
- (env->v7m.fpccr[env->v7m.secure] & R_V7M_FPCCR_ASPEN_MASK) &&
59
- (!(env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK) ||
60
- (env->v7m.secure &&
61
- !(env->v7m.control[M_REG_S] & R_V7M_CONTROL_SFPA_MASK)))) {
62
- /*
63
- * ASPEN is set, but FPCA/SFPA indicate that there is no active
64
- * FP context; we must create a new FP context before executing
65
- * any FP insn.
66
- */
67
- flags = FIELD_DP32(flags, TBFLAG_A32, NEW_FP_CTXT_NEEDED, 1);
68
- }
69
-
70
- if (arm_feature(env, ARM_FEATURE_M)) {
71
- bool is_secure = env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_S_MASK;
72
-
73
- if (env->v7m.fpccr[is_secure] & R_V7M_FPCCR_LSPACT_MASK) {
74
- flags = FIELD_DP32(flags, TBFLAG_A32, LSPACT, 1);
75
- }
76
- }
77
-
78
if (!arm_feature(env, ARM_FEATURE_M)) {
79
int target_el = arm_debug_target_el(env);
80
81
--
31
--
82
2.20.1
32
2.20.1
83
33
84
34
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The PRFM prefetch insn in the load/store with imm9 encodings
2
requires idx field 0b00; we were underdecoding this by
3
only checking !is_unpriv (which is equivalent to idx != 2).
4
Correctly UNDEF the unallocated encodings where idx == 0b01
5
and 0b11 as well as 0b10.
2
6
3
This is the payoff.
7
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
10
Message-id: 20190125182626.9221-3-peter.maydell@linaro.org
11
---
12
target/arm/translate-a64.c | 2 +-
13
1 file changed, 1 insertion(+), 1 deletion(-)
4
14
5
From perf record -g data of ubuntu 18 boot and shutdown:
15
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
6
7
BEFORE:
8
9
- 23.02% 2.82% qemu-system-aar [.] helper_lookup_tb_ptr
10
- 20.22% helper_lookup_tb_ptr
11
+ 10.05% tb_htable_lookup
12
- 9.13% cpu_get_tb_cpu_state
13
3.20% aa64_va_parameters_both
14
0.55% fp_exception_el
15
16
- 11.66% 4.74% qemu-system-aar [.] cpu_get_tb_cpu_state
17
- 6.96% cpu_get_tb_cpu_state
18
3.63% aa64_va_parameters_both
19
0.60% fp_exception_el
20
0.53% sve_exception_el
21
22
AFTER:
23
24
- 16.40% 3.40% qemu-system-aar [.] helper_lookup_tb_ptr
25
- 13.03% helper_lookup_tb_ptr
26
+ 11.19% tb_htable_lookup
27
0.55% cpu_get_tb_cpu_state
28
29
0.98% 0.71% qemu-system-aar [.] cpu_get_tb_cpu_state
30
31
0.87% 0.24% qemu-system-aar [.] rebuild_hflags_a64
32
33
Before, helper_lookup_tb_ptr is the second hottest function in the
34
application, consuming almost a quarter of the runtime. Within the
35
entire execution, cpu_get_tb_cpu_state consumes about 12%.
36
37
After, helper_lookup_tb_ptr has dropped to the fourth hottest function,
38
with consumption dropping to a sixth of the runtime. Within the
39
entire execution, cpu_get_tb_cpu_state has dropped below 1%, and the
40
supporting function to rebuild hflags also consumes about 1%.
41
42
Assertions are retained for --enable-debug-tcg.
43
44
Tested-by: Alex Bennée <alex.bennee@linaro.org>
45
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
46
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
47
Message-id: 20191023150057.25731-25-richard.henderson@linaro.org
48
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
49
---
50
target/arm/helper.c | 9 ++++++---
51
1 file changed, 6 insertions(+), 3 deletions(-)
52
53
diff --git a/target/arm/helper.c b/target/arm/helper.c
54
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
55
--- a/target/arm/helper.c
17
--- a/target/arm/translate-a64.c
56
+++ b/target/arm/helper.c
18
+++ b/target/arm/translate-a64.c
57
@@ -XXX,XX +XXX,XX @@ void HELPER(rebuild_hflags_a64)(CPUARMState *env, int el)
19
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn,
58
void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
20
} else {
59
target_ulong *cs_base, uint32_t *pflags)
21
if (size == 3 && opc == 2) {
60
{
22
/* PRFM - prefetch */
61
- uint32_t flags, pstate_for_ss;
23
- if (is_unpriv) {
62
+ uint32_t flags = env->hflags;
24
+ if (idx != 0) {
63
+ uint32_t pstate_for_ss;
25
unallocated_encoding(s);
64
26
return;
65
*cs_base = 0;
27
}
66
- flags = rebuild_hflags_internal(env);
67
+#ifdef CONFIG_DEBUG_TCG
68
+ assert(flags == rebuild_hflags_internal(env));
69
+#endif
70
71
- if (is_a64(env)) {
72
+ if (FIELD_EX32(flags, TBFLAG_ANY, AARCH64_STATE)) {
73
*pc = env->pc;
74
if (cpu_isar_feature(aa64_bti, env_archcpu(env))) {
75
flags = FIELD_DP32(flags, TBFLAG_A64, BTYPE, env->btype);
76
--
28
--
77
2.20.1
29
2.20.1
78
30
79
31
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
1
In the AdvSIMD load/store multiple structures encodings,
2
the non-post-indexed case should have zeroes in [20:16]
3
(which is the Rm field for the post-indexed case).
4
Correctly UNDEF the currently unallocated encodings which
5
have non-zeroes in those bits.
2
6
3
Enable SVE in the KVM guest when the 'max' cpu type is configured
7
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
4
and KVM supports it. KVM SVE requires use of the new finalize
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
vcpu ioctl, so we add that now too. For starters SVE can only be
9
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
6
turned on or off, getting all vector lengths the host CPU supports
10
Message-id: 20190125182626.9221-4-peter.maydell@linaro.org
7
when on. We'll add the other SVE CPU properties in later patches.
11
---
12
target/arm/translate-a64.c | 7 ++++++-
13
1 file changed, 6 insertions(+), 1 deletion(-)
8
14
9
Signed-off-by: Andrew Jones <drjones@redhat.com>
15
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Eric Auger <eric.auger@redhat.com>
12
Tested-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
13
Reviewed-by: Beata Michalska <beata.michalska@linaro.org>
14
Message-id: 20191024121808.9612-7-drjones@redhat.com
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
17
target/arm/kvm_arm.h | 27 +++++++++++++++++++++++++++
18
target/arm/cpu64.c | 17 ++++++++++++++---
19
target/arm/kvm.c | 5 +++++
20
target/arm/kvm64.c | 20 +++++++++++++++++++-
21
tests/arm-cpu-features.c | 4 ++++
22
5 files changed, 69 insertions(+), 4 deletions(-)
23
24
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
25
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/kvm_arm.h
17
--- a/target/arm/translate-a64.c
27
+++ b/target/arm/kvm_arm.h
18
+++ b/target/arm/translate-a64.c
28
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
29
*/
30
int kvm_arm_vcpu_init(CPUState *cs);
31
32
+/**
33
+ * kvm_arm_vcpu_finalize
34
+ * @cs: CPUState
35
+ * @feature: int
36
+ *
37
+ * Finalizes the configuration of the specified VCPU feature by
38
+ * invoking the KVM_ARM_VCPU_FINALIZE ioctl. Features requiring
39
+ * this are documented in the "KVM_ARM_VCPU_FINALIZE" section of
40
+ * KVM's API documentation.
41
+ *
42
+ * Returns: 0 if success else < 0 error code
43
+ */
44
+int kvm_arm_vcpu_finalize(CPUState *cs, int feature);
45
+
46
/**
47
* kvm_arm_register_device:
48
* @mr: memory region for this device
49
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_aarch32_supported(CPUState *cs);
50
*/
51
bool kvm_arm_pmu_supported(CPUState *cs);
52
53
+/**
54
+ * bool kvm_arm_sve_supported:
55
+ * @cs: CPUState
56
+ *
57
+ * Returns true if the KVM VCPU can enable SVE and false otherwise.
58
+ */
59
+bool kvm_arm_sve_supported(CPUState *cs);
60
+
61
/**
62
* kvm_arm_get_max_vm_ipa_size - Returns the number of bits in the
63
* IPA address space supported by KVM
64
@@ -XXX,XX +XXX,XX @@ static inline bool kvm_arm_pmu_supported(CPUState *cs)
65
return false;
66
}
67
68
+static inline bool kvm_arm_sve_supported(CPUState *cs)
69
+{
70
+ return false;
71
+}
72
+
73
static inline int kvm_arm_get_max_vm_ipa_size(MachineState *ms)
74
{
20
{
75
return -ENOENT;
21
int rt = extract32(insn, 0, 5);
76
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
22
int rn = extract32(insn, 5, 5);
77
index XXXXXXX..XXXXXXX 100644
23
+ int rm = extract32(insn, 16, 5);
78
--- a/target/arm/cpu64.c
24
int size = extract32(insn, 10, 2);
79
+++ b/target/arm/cpu64.c
25
int opcode = extract32(insn, 12, 4);
80
@@ -XXX,XX +XXX,XX @@ static void cpu_arm_set_sve(Object *obj, Visitor *v, const char *name,
26
bool is_store = !extract32(insn, 22, 1);
27
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
81
return;
28
return;
82
}
29
}
83
30
84
+ if (value && kvm_enabled() && !kvm_arm_sve_supported(CPU(cpu))) {
31
+ if (!is_postidx && rm != 0) {
85
+ error_setg(errp, "'sve' feature not supported by KVM on this host");
32
+ unallocated_encoding(s);
86
+ return;
33
+ return;
87
+ }
34
+ }
88
+
35
+
89
t = cpu->isar.id_aa64pfr0;
36
/* From the shared decode logic */
90
t = FIELD_DP64(t, ID_AA64PFR0, SVE, value);
37
switch (opcode) {
91
cpu->isar.id_aa64pfr0 = t;
38
case 0x0:
92
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
39
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
93
{
94
ARMCPU *cpu = ARM_CPU(obj);
95
uint32_t vq;
96
+ uint64_t t;
97
98
if (kvm_enabled()) {
99
kvm_arm_set_cpu_features_from_host(cpu);
100
+ if (kvm_arm_sve_supported(CPU(cpu))) {
101
+ t = cpu->isar.id_aa64pfr0;
102
+ t = FIELD_DP64(t, ID_AA64PFR0, SVE, 1);
103
+ cpu->isar.id_aa64pfr0 = t;
104
+ }
105
} else {
106
- uint64_t t;
107
uint32_t u;
108
aarch64_a57_initfn(obj);
109
110
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
111
112
object_property_add(obj, "sve-max-vq", "uint32", cpu_max_get_sve_max_vq,
113
cpu_max_set_sve_max_vq, NULL, NULL, &error_fatal);
114
- object_property_add(obj, "sve", "bool", cpu_arm_get_sve,
115
- cpu_arm_set_sve, NULL, NULL, &error_fatal);
116
117
for (vq = 1; vq <= ARM_MAX_VQ; ++vq) {
118
char name[8];
119
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
120
cpu_arm_set_sve_vq, NULL, NULL, &error_fatal);
121
}
122
}
40
}
123
+
41
124
+ object_property_add(obj, "sve", "bool", cpu_arm_get_sve,
42
if (is_postidx) {
125
+ cpu_arm_set_sve, NULL, NULL, &error_fatal);
43
- int rm = extract32(insn, 16, 5);
126
}
44
if (rm == 31) {
127
45
tcg_gen_mov_i64(tcg_rn, tcg_addr);
128
struct ARMCPUInfo {
46
} else {
129
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
130
index XXXXXXX..XXXXXXX 100644
131
--- a/target/arm/kvm.c
132
+++ b/target/arm/kvm.c
133
@@ -XXX,XX +XXX,XX @@ int kvm_arm_vcpu_init(CPUState *cs)
134
return kvm_vcpu_ioctl(cs, KVM_ARM_VCPU_INIT, &init);
135
}
136
137
+int kvm_arm_vcpu_finalize(CPUState *cs, int feature)
138
+{
139
+ return kvm_vcpu_ioctl(cs, KVM_ARM_VCPU_FINALIZE, &feature);
140
+}
141
+
142
void kvm_arm_init_serror_injection(CPUState *cs)
143
{
144
cap_has_inject_serror_esr = kvm_check_extension(cs->kvm_state,
145
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
146
index XXXXXXX..XXXXXXX 100644
147
--- a/target/arm/kvm64.c
148
+++ b/target/arm/kvm64.c
149
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_aarch32_supported(CPUState *cpu)
150
return kvm_check_extension(s, KVM_CAP_ARM_EL1_32BIT);
151
}
152
153
+bool kvm_arm_sve_supported(CPUState *cpu)
154
+{
155
+ KVMState *s = KVM_STATE(current_machine->accelerator);
156
+
157
+ return kvm_check_extension(s, KVM_CAP_ARM_SVE);
158
+}
159
+
160
#define ARM_CPU_ID_MPIDR 3, 0, 0, 0, 5
161
162
int kvm_arch_init_vcpu(CPUState *cs)
163
@@ -XXX,XX +XXX,XX @@ int kvm_arch_init_vcpu(CPUState *cs)
164
cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_EL1_32BIT;
165
}
166
if (!kvm_check_extension(cs->kvm_state, KVM_CAP_ARM_PMU_V3)) {
167
- cpu->has_pmu = false;
168
+ cpu->has_pmu = false;
169
}
170
if (cpu->has_pmu) {
171
cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_PMU_V3;
172
} else {
173
unset_feature(&env->features, ARM_FEATURE_PMU);
174
}
175
+ if (cpu_isar_feature(aa64_sve, cpu)) {
176
+ assert(kvm_arm_sve_supported(cs));
177
+ cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_SVE;
178
+ }
179
180
/* Do KVM_ARM_VCPU_INIT ioctl */
181
ret = kvm_arm_vcpu_init(cs);
182
@@ -XXX,XX +XXX,XX @@ int kvm_arch_init_vcpu(CPUState *cs)
183
return ret;
184
}
185
186
+ if (cpu_isar_feature(aa64_sve, cpu)) {
187
+ ret = kvm_arm_vcpu_finalize(cs, KVM_ARM_VCPU_SVE);
188
+ if (ret) {
189
+ return ret;
190
+ }
191
+ }
192
+
193
/*
194
* When KVM is in use, PSCI is emulated in-kernel and not by qemu.
195
* Currently KVM has its own idea about MPIDR assignment, so we
196
diff --git a/tests/arm-cpu-features.c b/tests/arm-cpu-features.c
197
index XXXXXXX..XXXXXXX 100644
198
--- a/tests/arm-cpu-features.c
199
+++ b/tests/arm-cpu-features.c
200
@@ -XXX,XX +XXX,XX @@ static void test_query_cpu_model_expansion_kvm(const void *data)
201
assert_has_feature(qts, "host", "aarch64");
202
assert_has_feature(qts, "host", "pmu");
203
204
+ assert_has_feature(qts, "max", "sve");
205
+
206
assert_error(qts, "cortex-a15",
207
"We cannot guarantee the CPU type 'cortex-a15' works "
208
"with KVM on this host", NULL);
209
} else {
210
assert_has_not_feature(qts, "host", "aarch64");
211
assert_has_not_feature(qts, "host", "pmu");
212
+
213
+ assert_has_not_feature(qts, "max", "sve");
214
}
215
216
qtest_quit(qts);
217
--
47
--
218
2.20.1
48
2.20.1
219
49
220
50
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
In the AdvSIMD load/store single structure encodings, the
2
non-post-indexed case should have zeroes in [20:16] (which is the
3
Rm field for the post-indexed case). Bit 31 must also be zero
4
(a check we got right in ldst_multiple but not here). Correctly
5
UNDEF these unallocated encodings.
2
6
3
Connect the recently added SYS_timer.
7
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
4
Now U-Boot does not hang anymore polling a free running counter
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
stuck at 0.
9
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
6
This timer is also used by the Linux kernel thermal subsystem.
10
Message-id: 20190125182626.9221-5-peter.maydell@linaro.org
11
---
12
target/arm/translate-a64.c | 11 ++++++++++-
13
1 file changed, 10 insertions(+), 1 deletion(-)
7
14
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
15
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
9
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Message-id: 20191019234715.25750-5-f4bug@amsat.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
include/hw/arm/bcm2835_peripherals.h | 3 ++-
14
hw/arm/bcm2835_peripherals.c | 17 ++++++++++++++++-
15
2 files changed, 18 insertions(+), 2 deletions(-)
16
17
diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h
18
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/arm/bcm2835_peripherals.h
17
--- a/target/arm/translate-a64.c
20
+++ b/include/hw/arm/bcm2835_peripherals.h
18
+++ b/target/arm/translate-a64.c
21
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
22
#include "hw/sd/sdhci.h"
20
{
23
#include "hw/sd/bcm2835_sdhost.h"
21
int rt = extract32(insn, 0, 5);
24
#include "hw/gpio/bcm2835_gpio.h"
22
int rn = extract32(insn, 5, 5);
25
+#include "hw/timer/bcm2835_systmr.h"
23
+ int rm = extract32(insn, 16, 5);
26
#include "hw/misc/unimp.h"
24
int size = extract32(insn, 10, 2);
27
25
int S = extract32(insn, 12, 1);
28
#define TYPE_BCM2835_PERIPHERALS "bcm2835-peripherals"
26
int opc = extract32(insn, 13, 3);
29
@@ -XXX,XX +XXX,XX @@ typedef struct BCM2835PeripheralState {
27
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
30
MemoryRegion ram_alias[4];
28
int ebytes, xs;
31
qemu_irq irq, fiq;
29
TCGv_i64 tcg_addr, tcg_rn, tcg_ebytes;
32
30
33
- UnimplementedDeviceState systmr;
31
+ if (extract32(insn, 31, 1)) {
34
+ BCM2835SystemTimerState systmr;
32
+ unallocated_encoding(s);
35
UnimplementedDeviceState armtmr;
36
UnimplementedDeviceState cprman;
37
UnimplementedDeviceState a2w;
38
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/hw/arm/bcm2835_peripherals.c
41
+++ b/hw/arm/bcm2835_peripherals.c
42
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_init(Object *obj)
43
/* Interrupt Controller */
44
sysbus_init_child_obj(obj, "ic", &s->ic, sizeof(s->ic), TYPE_BCM2835_IC);
45
46
+ /* SYS Timer */
47
+ sysbus_init_child_obj(obj, "systimer", &s->systmr, sizeof(s->systmr),
48
+ TYPE_BCM2835_SYSTIMER);
49
+
50
/* UART0 */
51
sysbus_init_child_obj(obj, "uart0", &s->uart0, sizeof(s->uart0),
52
TYPE_PL011);
53
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
54
sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->ic), 0));
55
sysbus_pass_irq(SYS_BUS_DEVICE(s), SYS_BUS_DEVICE(&s->ic));
56
57
+ /* Sys Timer */
58
+ object_property_set_bool(OBJECT(&s->systmr), true, "realized", &err);
59
+ if (err) {
60
+ error_propagate(errp, err);
61
+ return;
33
+ return;
62
+ }
34
+ }
63
+ memory_region_add_subregion(&s->peri_mr, ST_OFFSET,
35
+ if (!is_postidx && rm != 0) {
64
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->systmr), 0));
36
+ unallocated_encoding(s);
65
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->systmr), 0,
37
+ return;
66
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_ARM_IRQ,
38
+ }
67
+ INTERRUPT_ARM_TIMER));
68
+
39
+
69
/* UART0 */
40
switch (scale) {
70
qdev_prop_set_chr(DEVICE(&s->uart0), "chardev", serial_hd(0));
41
case 3:
71
object_property_set_bool(OBJECT(&s->uart0), true, "realized", &err);
42
if (!is_load || S) {
72
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
43
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
73
}
44
}
74
45
75
create_unimp(s, &s->armtmr, "bcm2835-sp804", ARMCTRL_TIMER0_1_OFFSET, 0x40);
46
if (is_postidx) {
76
- create_unimp(s, &s->systmr, "bcm2835-systimer", ST_OFFSET, 0x20);
47
- int rm = extract32(insn, 16, 5);
77
create_unimp(s, &s->cprman, "bcm2835-cprman", CPRMAN_OFFSET, 0x1000);
48
if (rm == 31) {
78
create_unimp(s, &s->a2w, "bcm2835-a2w", A2W_OFFSET, 0x1000);
49
tcg_gen_mov_i64(tcg_rn, tcg_addr);
79
create_unimp(s, &s->i2s, "bcm2835-i2s", I2S_OFFSET, 0x100);
50
} else {
80
--
51
--
81
2.20.1
52
2.20.1
82
53
83
54
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
In the "add/subtract (extended register)" encoding group, the "opt"
2
field in bits [23:22] must be zero. Correctly UNDEF the unallocated
3
encodings where this field is not zero.
2
4
3
write_secondary_boot() is used in SMP configurations where the
5
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
4
CPU address space might not be the main System Bus.
5
The rom_add_blob_fixed_as() function allow us to specify an
6
address space. Use it to write each boot blob in the corresponding
7
CPU address space.
8
9
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
11
Message-id: 20191019234715.25750-15-f4bug@amsat.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
8
Message-id: 20190125182626.9221-6-peter.maydell@linaro.org
13
---
9
---
14
hw/arm/highbank.c | 3 ++-
10
target/arm/translate-a64.c | 3 ++-
15
1 file changed, 2 insertions(+), 1 deletion(-)
11
1 file changed, 2 insertions(+), 1 deletion(-)
16
12
17
diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
13
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
18
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/highbank.c
15
--- a/target/arm/translate-a64.c
20
+++ b/hw/arm/highbank.c
16
+++ b/target/arm/translate-a64.c
21
@@ -XXX,XX +XXX,XX @@ static void hb_write_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
17
@@ -XXX,XX +XXX,XX @@ static void disas_add_sub_ext_reg(DisasContext *s, uint32_t insn)
22
for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
18
int imm3 = extract32(insn, 10, 3);
23
smpboot[n] = tswap32(smpboot[n]);
19
int option = extract32(insn, 13, 3);
20
int rm = extract32(insn, 16, 5);
21
+ int opt = extract32(insn, 22, 2);
22
bool setflags = extract32(insn, 29, 1);
23
bool sub_op = extract32(insn, 30, 1);
24
bool sf = extract32(insn, 31, 1);
25
@@ -XXX,XX +XXX,XX @@ static void disas_add_sub_ext_reg(DisasContext *s, uint32_t insn)
26
TCGv_i64 tcg_rd;
27
TCGv_i64 tcg_result;
28
29
- if (imm3 > 4) {
30
+ if (imm3 > 4 || opt != 0) {
31
unallocated_encoding(s);
32
return;
24
}
33
}
25
- rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot), SMP_BOOT_ADDR);
26
+ rom_add_blob_fixed_as("smpboot", smpboot, sizeof(smpboot), SMP_BOOT_ADDR,
27
+ arm_boot_address_space(cpu, info));
28
}
29
30
static void hb_reset_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
31
--
34
--
32
2.20.1
35
2.20.1
33
36
34
37
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
1
In the encoding groups
2
* floating-point data-processing (1 source)
3
* floating-point data-processing (2 source)
4
* floating-point data-processing (3 source)
5
* floating-point immediate
6
* floating-point compare
7
* floating-ponit conditional compare
8
* floating-point conditional select
2
9
3
Extend the SVE vq map initialization and validation with KVM's
10
bit 31 is M and bit 29 is S (and bit 30 is 0, already checked at
4
supported vector lengths when KVM is enabled. In order to determine
11
this point in the decode). None of these groups allocate any
5
and select supported lengths we add two new KVM functions for getting
12
encoding for M=1 or S=1. We checked this in disas_fp_compare(),
6
and setting the KVM_REG_ARM64_SVE_VLS pseudo-register.
13
disas_fp_ccomp() and disas_fp_csel(), but missed it in disas_fp_1src(),
14
disas_fp_2src(), disas_fp_3src() and disas_fp_imm().
7
15
8
This patch has been co-authored with Richard Henderson, who reworked
16
We also missed that in the fp immediate encoding the imm5 field
9
the target/arm/cpu64.c changes in order to push all the validation and
17
must be all zeroes.
10
auto-enabling/disabling steps into the finalizer, resulting in a nice
11
LOC reduction.
12
18
13
Signed-off-by: Andrew Jones <drjones@redhat.com>
19
Correctly UNDEF the unallocated encodings here.
14
Reviewed-by: Eric Auger <eric.auger@redhat.com>
20
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
16
Tested-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
17
Message-id: 20191024121808.9612-9-drjones@redhat.com
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
24
Message-id: 20190125182626.9221-7-peter.maydell@linaro.org
19
---
25
---
20
target/arm/kvm_arm.h | 12 +++
26
target/arm/translate-a64.c | 22 +++++++++++++++++++++-
21
target/arm/cpu64.c | 176 ++++++++++++++++++++++++++++----------
27
1 file changed, 21 insertions(+), 1 deletion(-)
22
target/arm/kvm64.c | 100 +++++++++++++++++++++-
23
tests/arm-cpu-features.c | 106 ++++++++++++++++++++++-
24
docs/arm-cpu-features.rst | 45 +++++++---
25
5 files changed, 381 insertions(+), 58 deletions(-)
26
28
27
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
29
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
28
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/kvm_arm.h
31
--- a/target/arm/translate-a64.c
30
+++ b/target/arm/kvm_arm.h
32
+++ b/target/arm/translate-a64.c
31
@@ -XXX,XX +XXX,XX @@ typedef struct ARMHostCPUFeatures {
33
@@ -XXX,XX +XXX,XX @@ static void handle_fp_fcvt(DisasContext *s, int opcode,
32
*/
34
*/
33
bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf);
35
static void disas_fp_1src(DisasContext *s, uint32_t insn)
34
35
+/**
36
+ * kvm_arm_sve_get_vls:
37
+ * @cs: CPUState
38
+ * @map: bitmap to fill in
39
+ *
40
+ * Get all the SVE vector lengths supported by the KVM host, setting
41
+ * the bits corresponding to their length in quadwords minus one
42
+ * (vq - 1) in @map up to ARM_MAX_VQ.
43
+ */
44
+void kvm_arm_sve_get_vls(CPUState *cs, unsigned long *map);
45
+
46
/**
47
* kvm_arm_set_cpu_features_from_host:
48
* @cpu: ARMCPU to set the features for
49
@@ -XXX,XX +XXX,XX @@ static inline int kvm_arm_vgic_probe(void)
50
static inline void kvm_arm_pmu_set_irq(CPUState *cs, int irq) {}
51
static inline void kvm_arm_pmu_init(CPUState *cs) {}
52
53
+static inline void kvm_arm_sve_get_vls(CPUState *cs, unsigned long *map) {}
54
#endif
55
56
static inline const char *gic_class_name(void)
57
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
58
index XXXXXXX..XXXXXXX 100644
59
--- a/target/arm/cpu64.c
60
+++ b/target/arm/cpu64.c
61
@@ -XXX,XX +XXX,XX @@ void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp)
62
* any of the above. Finally, if SVE is not disabled, then at least one
63
* vector length must be enabled.
64
*/
65
+ DECLARE_BITMAP(kvm_supported, ARM_MAX_VQ);
66
DECLARE_BITMAP(tmp, ARM_MAX_VQ);
67
uint32_t vq, max_vq = 0;
68
69
+ /* Collect the set of vector lengths supported by KVM. */
70
+ bitmap_zero(kvm_supported, ARM_MAX_VQ);
71
+ if (kvm_enabled() && kvm_arm_sve_supported(CPU(cpu))) {
72
+ kvm_arm_sve_get_vls(CPU(cpu), kvm_supported);
73
+ } else if (kvm_enabled()) {
74
+ assert(!cpu_isar_feature(aa64_sve, cpu));
75
+ }
76
+
77
/*
78
* Process explicit sve<N> properties.
79
* From the properties, sve_vq_map<N> implies sve_vq_init<N>.
80
@@ -XXX,XX +XXX,XX @@ void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp)
81
return;
82
}
83
84
- /* Propagate enabled bits down through required powers-of-two. */
85
- for (vq = pow2floor(max_vq); vq >= 1; vq >>= 1) {
86
- if (!test_bit(vq - 1, cpu->sve_vq_init)) {
87
- set_bit(vq - 1, cpu->sve_vq_map);
88
+ if (kvm_enabled()) {
89
+ /*
90
+ * For KVM we have to automatically enable all supported unitialized
91
+ * lengths, even when the smaller lengths are not all powers-of-two.
92
+ */
93
+ bitmap_andnot(tmp, kvm_supported, cpu->sve_vq_init, max_vq);
94
+ bitmap_or(cpu->sve_vq_map, cpu->sve_vq_map, tmp, max_vq);
95
+ } else {
96
+ /* Propagate enabled bits down through required powers-of-two. */
97
+ for (vq = pow2floor(max_vq); vq >= 1; vq >>= 1) {
98
+ if (!test_bit(vq - 1, cpu->sve_vq_init)) {
99
+ set_bit(vq - 1, cpu->sve_vq_map);
100
+ }
101
}
102
}
103
} else if (cpu->sve_max_vq == 0) {
104
@@ -XXX,XX +XXX,XX @@ void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp)
105
return;
106
}
107
108
- /* Disabling a power-of-two disables all larger lengths. */
109
- if (test_bit(0, cpu->sve_vq_init)) {
110
- error_setg(errp, "cannot disable sve128");
111
- error_append_hint(errp, "Disabling sve128 results in all vector "
112
- "lengths being disabled.\n");
113
- error_append_hint(errp, "With SVE enabled, at least one vector "
114
- "length must be enabled.\n");
115
- return;
116
- }
117
- for (vq = 2; vq <= ARM_MAX_VQ; vq <<= 1) {
118
- if (test_bit(vq - 1, cpu->sve_vq_init)) {
119
- break;
120
+ if (kvm_enabled()) {
121
+ /* Disabling a supported length disables all larger lengths. */
122
+ for (vq = 1; vq <= ARM_MAX_VQ; ++vq) {
123
+ if (test_bit(vq - 1, cpu->sve_vq_init) &&
124
+ test_bit(vq - 1, kvm_supported)) {
125
+ break;
126
+ }
127
}
128
+ max_vq = vq <= ARM_MAX_VQ ? vq - 1 : ARM_MAX_VQ;
129
+ bitmap_andnot(cpu->sve_vq_map, kvm_supported,
130
+ cpu->sve_vq_init, max_vq);
131
+ if (max_vq == 0 || bitmap_empty(cpu->sve_vq_map, max_vq)) {
132
+ error_setg(errp, "cannot disable sve%d", vq * 128);
133
+ error_append_hint(errp, "Disabling sve%d results in all "
134
+ "vector lengths being disabled.\n",
135
+ vq * 128);
136
+ error_append_hint(errp, "With SVE enabled, at least one "
137
+ "vector length must be enabled.\n");
138
+ return;
139
+ }
140
+ } else {
141
+ /* Disabling a power-of-two disables all larger lengths. */
142
+ if (test_bit(0, cpu->sve_vq_init)) {
143
+ error_setg(errp, "cannot disable sve128");
144
+ error_append_hint(errp, "Disabling sve128 results in all "
145
+ "vector lengths being disabled.\n");
146
+ error_append_hint(errp, "With SVE enabled, at least one "
147
+ "vector length must be enabled.\n");
148
+ return;
149
+ }
150
+ for (vq = 2; vq <= ARM_MAX_VQ; vq <<= 1) {
151
+ if (test_bit(vq - 1, cpu->sve_vq_init)) {
152
+ break;
153
+ }
154
+ }
155
+ max_vq = vq <= ARM_MAX_VQ ? vq - 1 : ARM_MAX_VQ;
156
+ bitmap_complement(cpu->sve_vq_map, cpu->sve_vq_init, max_vq);
157
}
158
- max_vq = vq <= ARM_MAX_VQ ? vq - 1 : ARM_MAX_VQ;
159
160
- bitmap_complement(cpu->sve_vq_map, cpu->sve_vq_init, max_vq);
161
max_vq = find_last_bit(cpu->sve_vq_map, max_vq) + 1;
162
}
163
164
@@ -XXX,XX +XXX,XX @@ void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp)
165
assert(max_vq != 0);
166
bitmap_clear(cpu->sve_vq_map, max_vq, ARM_MAX_VQ - max_vq);
167
168
- /* Ensure all required powers-of-two are enabled. */
169
- for (vq = pow2floor(max_vq); vq >= 1; vq >>= 1) {
170
- if (!test_bit(vq - 1, cpu->sve_vq_map)) {
171
- error_setg(errp, "cannot disable sve%d", vq * 128);
172
- error_append_hint(errp, "sve%d is required as it "
173
- "is a power-of-two length smaller than "
174
- "the maximum, sve%d\n",
175
- vq * 128, max_vq * 128);
176
+ if (kvm_enabled()) {
177
+ /* Ensure the set of lengths matches what KVM supports. */
178
+ bitmap_xor(tmp, cpu->sve_vq_map, kvm_supported, max_vq);
179
+ if (!bitmap_empty(tmp, max_vq)) {
180
+ vq = find_last_bit(tmp, max_vq) + 1;
181
+ if (test_bit(vq - 1, cpu->sve_vq_map)) {
182
+ if (cpu->sve_max_vq) {
183
+ error_setg(errp, "cannot set sve-max-vq=%d",
184
+ cpu->sve_max_vq);
185
+ error_append_hint(errp, "This KVM host does not support "
186
+ "the vector length %d-bits.\n",
187
+ vq * 128);
188
+ error_append_hint(errp, "It may not be possible to use "
189
+ "sve-max-vq with this KVM host. Try "
190
+ "using only sve<N> properties.\n");
191
+ } else {
192
+ error_setg(errp, "cannot enable sve%d", vq * 128);
193
+ error_append_hint(errp, "This KVM host does not support "
194
+ "the vector length %d-bits.\n",
195
+ vq * 128);
196
+ }
197
+ } else {
198
+ error_setg(errp, "cannot disable sve%d", vq * 128);
199
+ error_append_hint(errp, "The KVM host requires all "
200
+ "supported vector lengths smaller "
201
+ "than %d bits to also be enabled.\n",
202
+ max_vq * 128);
203
+ }
204
return;
205
}
206
+ } else {
207
+ /* Ensure all required powers-of-two are enabled. */
208
+ for (vq = pow2floor(max_vq); vq >= 1; vq >>= 1) {
209
+ if (!test_bit(vq - 1, cpu->sve_vq_map)) {
210
+ error_setg(errp, "cannot disable sve%d", vq * 128);
211
+ error_append_hint(errp, "sve%d is required as it "
212
+ "is a power-of-two length smaller than "
213
+ "the maximum, sve%d\n",
214
+ vq * 128, max_vq * 128);
215
+ return;
216
+ }
217
+ }
218
}
219
220
/*
221
@@ -XXX,XX +XXX,XX @@ static void cpu_max_set_sve_max_vq(Object *obj, Visitor *v, const char *name,
222
{
36
{
223
ARMCPU *cpu = ARM_CPU(obj);
37
+ int mos = extract32(insn, 29, 3);
224
Error *err = NULL;
38
int type = extract32(insn, 22, 2);
225
+ uint32_t max_vq;
39
int opcode = extract32(insn, 15, 6);
226
40
int rn = extract32(insn, 5, 5);
227
- visit_type_uint32(v, name, &cpu->sve_max_vq, &err);
41
int rd = extract32(insn, 0, 5);
228
-
42
229
- if (!err && (cpu->sve_max_vq == 0 || cpu->sve_max_vq > ARM_MAX_VQ)) {
43
+ if (mos) {
230
- error_setg(&err, "unsupported SVE vector length");
44
+ unallocated_encoding(s);
231
- error_append_hint(&err, "Valid sve-max-vq in range [1-%d]\n",
232
- ARM_MAX_VQ);
233
+ visit_type_uint32(v, name, &max_vq, &err);
234
+ if (err) {
235
+ error_propagate(errp, err);
236
+ return;
237
}
238
- error_propagate(errp, err);
239
+
240
+ if (kvm_enabled() && !kvm_arm_sve_supported(CPU(cpu))) {
241
+ error_setg(errp, "cannot set sve-max-vq");
242
+ error_append_hint(errp, "SVE not supported by KVM on this host\n");
243
+ return;
45
+ return;
244
+ }
46
+ }
245
+
47
+
246
+ if (max_vq == 0 || max_vq > ARM_MAX_VQ) {
48
switch (opcode) {
247
+ error_setg(errp, "unsupported SVE vector length");
49
case 0x4: case 0x5: case 0x7:
248
+ error_append_hint(errp, "Valid sve-max-vq in range [1-%d]\n",
50
{
249
+ ARM_MAX_VQ);
51
@@ -XXX,XX +XXX,XX @@ static void handle_fp_2src_half(DisasContext *s, int opcode,
52
*/
53
static void disas_fp_2src(DisasContext *s, uint32_t insn)
54
{
55
+ int mos = extract32(insn, 29, 3);
56
int type = extract32(insn, 22, 2);
57
int rd = extract32(insn, 0, 5);
58
int rn = extract32(insn, 5, 5);
59
int rm = extract32(insn, 16, 5);
60
int opcode = extract32(insn, 12, 4);
61
62
- if (opcode > 8) {
63
+ if (opcode > 8 || mos) {
64
unallocated_encoding(s);
65
return;
66
}
67
@@ -XXX,XX +XXX,XX @@ static void handle_fp_3src_half(DisasContext *s, bool o0, bool o1,
68
*/
69
static void disas_fp_3src(DisasContext *s, uint32_t insn)
70
{
71
+ int mos = extract32(insn, 29, 3);
72
int type = extract32(insn, 22, 2);
73
int rd = extract32(insn, 0, 5);
74
int rn = extract32(insn, 5, 5);
75
@@ -XXX,XX +XXX,XX @@ static void disas_fp_3src(DisasContext *s, uint32_t insn)
76
bool o0 = extract32(insn, 15, 1);
77
bool o1 = extract32(insn, 21, 1);
78
79
+ if (mos) {
80
+ unallocated_encoding(s);
250
+ return;
81
+ return;
251
+ }
82
+ }
252
+
83
+
253
+ cpu->sve_max_vq = max_vq;
84
switch (type) {
254
}
85
case 0:
255
86
if (!fp_access_check(s)) {
256
static void cpu_arm_get_sve_vq(Object *obj, Visitor *v, const char *name,
87
@@ -XXX,XX +XXX,XX @@ uint64_t vfp_expand_imm(int size, uint8_t imm8)
257
@@ -XXX,XX +XXX,XX @@ static void cpu_arm_set_sve_vq(Object *obj, Visitor *v, const char *name,
88
static void disas_fp_imm(DisasContext *s, uint32_t insn)
258
return;
89
{
259
}
90
int rd = extract32(insn, 0, 5);
260
91
+ int imm5 = extract32(insn, 5, 5);
261
+ if (value && kvm_enabled() && !kvm_arm_sve_supported(CPU(cpu))) {
92
int imm8 = extract32(insn, 13, 8);
262
+ error_setg(errp, "cannot enable %s", name);
93
int type = extract32(insn, 22, 2);
263
+ error_append_hint(errp, "SVE not supported by KVM on this host\n");
94
+ int mos = extract32(insn, 29, 3);
95
uint64_t imm;
96
TCGv_i64 tcg_res;
97
TCGMemOp sz;
98
99
+ if (mos || imm5) {
100
+ unallocated_encoding(s);
264
+ return;
101
+ return;
265
+ }
102
+ }
266
+
103
+
267
if (value) {
104
switch (type) {
268
set_bit(vq - 1, cpu->sve_vq_map);
105
case 0:
269
} else {
106
sz = MO_32;
270
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
271
cpu->ctr = 0x80038003; /* 32 byte I and D cacheline size, VIPT icache */
272
cpu->dcz_blocksize = 7; /* 512 bytes */
273
#endif
274
-
275
- object_property_add(obj, "sve-max-vq", "uint32", cpu_max_get_sve_max_vq,
276
- cpu_max_set_sve_max_vq, NULL, NULL, &error_fatal);
277
-
278
- for (vq = 1; vq <= ARM_MAX_VQ; ++vq) {
279
- char name[8];
280
- sprintf(name, "sve%d", vq * 128);
281
- object_property_add(obj, name, "bool", cpu_arm_get_sve_vq,
282
- cpu_arm_set_sve_vq, NULL, NULL, &error_fatal);
283
- }
284
}
285
286
object_property_add(obj, "sve", "bool", cpu_arm_get_sve,
287
cpu_arm_set_sve, NULL, NULL, &error_fatal);
288
+ object_property_add(obj, "sve-max-vq", "uint32", cpu_max_get_sve_max_vq,
289
+ cpu_max_set_sve_max_vq, NULL, NULL, &error_fatal);
290
+
291
+ for (vq = 1; vq <= ARM_MAX_VQ; ++vq) {
292
+ char name[8];
293
+ sprintf(name, "sve%d", vq * 128);
294
+ object_property_add(obj, name, "bool", cpu_arm_get_sve_vq,
295
+ cpu_arm_set_sve_vq, NULL, NULL, &error_fatal);
296
+ }
297
}
298
299
struct ARMCPUInfo {
300
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
301
index XXXXXXX..XXXXXXX 100644
302
--- a/target/arm/kvm64.c
303
+++ b/target/arm/kvm64.c
304
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_sve_supported(CPUState *cpu)
305
return kvm_check_extension(s, KVM_CAP_ARM_SVE);
306
}
307
308
+QEMU_BUILD_BUG_ON(KVM_ARM64_SVE_VQ_MIN != 1);
309
+
310
+void kvm_arm_sve_get_vls(CPUState *cs, unsigned long *map)
311
+{
312
+ /* Only call this function if kvm_arm_sve_supported() returns true. */
313
+ static uint64_t vls[KVM_ARM64_SVE_VLS_WORDS];
314
+ static bool probed;
315
+ uint32_t vq = 0;
316
+ int i, j;
317
+
318
+ bitmap_clear(map, 0, ARM_MAX_VQ);
319
+
320
+ /*
321
+ * KVM ensures all host CPUs support the same set of vector lengths.
322
+ * So we only need to create the scratch VCPUs once and then cache
323
+ * the results.
324
+ */
325
+ if (!probed) {
326
+ struct kvm_vcpu_init init = {
327
+ .target = -1,
328
+ .features[0] = (1 << KVM_ARM_VCPU_SVE),
329
+ };
330
+ struct kvm_one_reg reg = {
331
+ .id = KVM_REG_ARM64_SVE_VLS,
332
+ .addr = (uint64_t)&vls[0],
333
+ };
334
+ int fdarray[3], ret;
335
+
336
+ probed = true;
337
+
338
+ if (!kvm_arm_create_scratch_host_vcpu(NULL, fdarray, &init)) {
339
+ error_report("failed to create scratch VCPU with SVE enabled");
340
+ abort();
341
+ }
342
+ ret = ioctl(fdarray[2], KVM_GET_ONE_REG, &reg);
343
+ kvm_arm_destroy_scratch_host_vcpu(fdarray);
344
+ if (ret) {
345
+ error_report("failed to get KVM_REG_ARM64_SVE_VLS: %s",
346
+ strerror(errno));
347
+ abort();
348
+ }
349
+
350
+ for (i = KVM_ARM64_SVE_VLS_WORDS - 1; i >= 0; --i) {
351
+ if (vls[i]) {
352
+ vq = 64 - clz64(vls[i]) + i * 64;
353
+ break;
354
+ }
355
+ }
356
+ if (vq > ARM_MAX_VQ) {
357
+ warn_report("KVM supports vector lengths larger than "
358
+ "QEMU can enable");
359
+ }
360
+ }
361
+
362
+ for (i = 0; i < KVM_ARM64_SVE_VLS_WORDS; ++i) {
363
+ if (!vls[i]) {
364
+ continue;
365
+ }
366
+ for (j = 1; j <= 64; ++j) {
367
+ vq = j + i * 64;
368
+ if (vq > ARM_MAX_VQ) {
369
+ return;
370
+ }
371
+ if (vls[i] & (1UL << (j - 1))) {
372
+ set_bit(vq - 1, map);
373
+ }
374
+ }
375
+ }
376
+}
377
+
378
+static int kvm_arm_sve_set_vls(CPUState *cs)
379
+{
380
+ uint64_t vls[KVM_ARM64_SVE_VLS_WORDS] = {0};
381
+ struct kvm_one_reg reg = {
382
+ .id = KVM_REG_ARM64_SVE_VLS,
383
+ .addr = (uint64_t)&vls[0],
384
+ };
385
+ ARMCPU *cpu = ARM_CPU(cs);
386
+ uint32_t vq;
387
+ int i, j;
388
+
389
+ assert(cpu->sve_max_vq <= KVM_ARM64_SVE_VQ_MAX);
390
+
391
+ for (vq = 1; vq <= cpu->sve_max_vq; ++vq) {
392
+ if (test_bit(vq - 1, cpu->sve_vq_map)) {
393
+ i = (vq - 1) / 64;
394
+ j = (vq - 1) % 64;
395
+ vls[i] |= 1UL << j;
396
+ }
397
+ }
398
+
399
+ return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
400
+}
401
+
402
#define ARM_CPU_ID_MPIDR 3, 0, 0, 0, 5
403
404
int kvm_arch_init_vcpu(CPUState *cs)
405
@@ -XXX,XX +XXX,XX @@ int kvm_arch_init_vcpu(CPUState *cs)
406
407
if (cpu->kvm_target == QEMU_KVM_ARM_TARGET_NONE ||
408
!object_dynamic_cast(OBJECT(cpu), TYPE_AARCH64_CPU)) {
409
- fprintf(stderr, "KVM is not supported for this guest CPU type\n");
410
+ error_report("KVM is not supported for this guest CPU type");
411
return -EINVAL;
412
}
413
414
@@ -XXX,XX +XXX,XX @@ int kvm_arch_init_vcpu(CPUState *cs)
415
}
416
417
if (cpu_isar_feature(aa64_sve, cpu)) {
418
+ ret = kvm_arm_sve_set_vls(cs);
419
+ if (ret) {
420
+ return ret;
421
+ }
422
ret = kvm_arm_vcpu_finalize(cs, KVM_ARM_VCPU_SVE);
423
if (ret) {
424
return ret;
425
diff --git a/tests/arm-cpu-features.c b/tests/arm-cpu-features.c
426
index XXXXXXX..XXXXXXX 100644
427
--- a/tests/arm-cpu-features.c
428
+++ b/tests/arm-cpu-features.c
429
@@ -XXX,XX +XXX,XX @@ static QDict *resp_get_props(QDict *resp)
430
return qdict;
431
}
432
433
+static bool resp_get_feature(QDict *resp, const char *feature)
434
+{
435
+ QDict *props;
436
+
437
+ g_assert(resp);
438
+ g_assert(resp_has_props(resp));
439
+ props = resp_get_props(resp);
440
+ g_assert(qdict_get(props, feature));
441
+ return qdict_get_bool(props, feature);
442
+}
443
+
444
#define assert_has_feature(qts, cpu_type, feature) \
445
({ \
446
QDict *_resp = do_query_no_props(qts, cpu_type); \
447
@@ -XXX,XX +XXX,XX @@ static void sve_tests_sve_off(const void *data)
448
qtest_quit(qts);
449
}
450
451
+static void sve_tests_sve_off_kvm(const void *data)
452
+{
453
+ QTestState *qts;
454
+
455
+ qts = qtest_init(MACHINE "-accel kvm -cpu max,sve=off");
456
+
457
+ /*
458
+ * We don't know if this host supports SVE so we don't
459
+ * attempt to test enabling anything. We only test that
460
+ * everything is disabled (as it should be with sve=off)
461
+ * and that using sve<N>=off to explicitly disable vector
462
+ * lengths is OK too.
463
+ */
464
+ assert_sve_vls(qts, "max", 0, NULL);
465
+ assert_sve_vls(qts, "max", 0, "{ 'sve128': false }");
466
+
467
+ qtest_quit(qts);
468
+}
469
+
470
static void test_query_cpu_model_expansion(const void *data)
471
{
472
QTestState *qts;
473
@@ -XXX,XX +XXX,XX @@ static void test_query_cpu_model_expansion_kvm(const void *data)
474
qts = qtest_init(MACHINE "-accel kvm -cpu host");
475
476
if (g_str_equal(qtest_get_arch(), "aarch64")) {
477
+ bool kvm_supports_sve;
478
+ char max_name[8], name[8];
479
+ uint32_t max_vq, vq;
480
+ uint64_t vls;
481
+ QDict *resp;
482
+ char *error;
483
+
484
assert_has_feature(qts, "host", "aarch64");
485
assert_has_feature(qts, "host", "pmu");
486
487
- assert_has_feature(qts, "max", "sve");
488
-
489
assert_error(qts, "cortex-a15",
490
"We cannot guarantee the CPU type 'cortex-a15' works "
491
"with KVM on this host", NULL);
492
+
493
+ assert_has_feature(qts, "max", "sve");
494
+ resp = do_query_no_props(qts, "max");
495
+ kvm_supports_sve = resp_get_feature(resp, "sve");
496
+ vls = resp_get_sve_vls(resp);
497
+ qobject_unref(resp);
498
+
499
+ if (kvm_supports_sve) {
500
+ g_assert(vls != 0);
501
+ max_vq = 64 - __builtin_clzll(vls);
502
+ sprintf(max_name, "sve%d", max_vq * 128);
503
+
504
+ /* Enabling a supported length is of course fine. */
505
+ assert_sve_vls(qts, "max", vls, "{ %s: true }", max_name);
506
+
507
+ /* Get the next supported length smaller than max-vq. */
508
+ vq = 64 - __builtin_clzll(vls & ~BIT_ULL(max_vq - 1));
509
+ if (vq) {
510
+ /*
511
+ * We have at least one length smaller than max-vq,
512
+ * so we can disable max-vq.
513
+ */
514
+ assert_sve_vls(qts, "max", (vls & ~BIT_ULL(max_vq - 1)),
515
+ "{ %s: false }", max_name);
516
+
517
+ /*
518
+ * Smaller, supported vector lengths cannot be disabled
519
+ * unless all larger, supported vector lengths are also
520
+ * disabled.
521
+ */
522
+ sprintf(name, "sve%d", vq * 128);
523
+ error = g_strdup_printf("cannot disable %s", name);
524
+ assert_error(qts, "max", error,
525
+ "{ %s: true, %s: false }",
526
+ max_name, name);
527
+ g_free(error);
528
+ }
529
+
530
+ /*
531
+ * The smallest, supported vector length is required, because
532
+ * we need at least one vector length enabled.
533
+ */
534
+ vq = __builtin_ffsll(vls);
535
+ sprintf(name, "sve%d", vq * 128);
536
+ error = g_strdup_printf("cannot disable %s", name);
537
+ assert_error(qts, "max", error, "{ %s: false }", name);
538
+ g_free(error);
539
+
540
+ /* Get an unsupported length. */
541
+ for (vq = 1; vq <= max_vq; ++vq) {
542
+ if (!(vls & BIT_ULL(vq - 1))) {
543
+ break;
544
+ }
545
+ }
546
+ if (vq <= SVE_MAX_VQ) {
547
+ sprintf(name, "sve%d", vq * 128);
548
+ error = g_strdup_printf("cannot enable %s", name);
549
+ assert_error(qts, "max", error, "{ %s: true }", name);
550
+ g_free(error);
551
+ }
552
+ } else {
553
+ g_assert(vls == 0);
554
+ }
555
} else {
556
assert_has_not_feature(qts, "host", "aarch64");
557
assert_has_not_feature(qts, "host", "pmu");
558
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
559
if (kvm_available) {
560
qtest_add_data_func("/arm/kvm/query-cpu-model-expansion",
561
NULL, test_query_cpu_model_expansion_kvm);
562
+ if (g_str_equal(qtest_get_arch(), "aarch64")) {
563
+ qtest_add_data_func("/arm/kvm/query-cpu-model-expansion/sve-off",
564
+ NULL, sve_tests_sve_off_kvm);
565
+ }
566
}
567
568
return g_test_run();
569
diff --git a/docs/arm-cpu-features.rst b/docs/arm-cpu-features.rst
570
index XXXXXXX..XXXXXXX 100644
571
--- a/docs/arm-cpu-features.rst
572
+++ b/docs/arm-cpu-features.rst
573
@@ -XXX,XX +XXX,XX @@ SVE CPU Property Dependencies and Constraints
574
575
1) At least one vector length must be enabled when `sve` is enabled.
576
577
- 2) If a vector length `N` is enabled, then all power-of-two vector
578
- lengths smaller than `N` must also be enabled. E.g. if `sve512`
579
- is enabled, then the 128-bit and 256-bit vector lengths must also
580
- be enabled.
581
+ 2) If a vector length `N` is enabled, then, when KVM is enabled, all
582
+ smaller, host supported vector lengths must also be enabled. If
583
+ KVM is not enabled, then only all the smaller, power-of-two vector
584
+ lengths must be enabled. E.g. with KVM if the host supports all
585
+ vector lengths up to 512-bits (128, 256, 384, 512), then if `sve512`
586
+ is enabled, the 128-bit vector length, 256-bit vector length, and
587
+ 384-bit vector length must also be enabled. Without KVM, the 384-bit
588
+ vector length would not be required.
589
+
590
+ 3) If KVM is enabled then only vector lengths that the host CPU type
591
+ support may be enabled. If SVE is not supported by the host, then
592
+ no `sve*` properties may be enabled.
593
594
SVE CPU Property Parsing Semantics
595
----------------------------------
596
@@ -XXX,XX +XXX,XX @@ SVE CPU Property Parsing Semantics
597
an error is generated.
598
599
2) If SVE is enabled (`sve=on`), but no `sve<N>` CPU properties are
600
- provided, then all supported vector lengths are enabled, including
601
- the non-power-of-two lengths.
602
+ provided, then all supported vector lengths are enabled, which when
603
+ KVM is not in use means including the non-power-of-two lengths, and,
604
+ when KVM is in use, it means all vector lengths supported by the host
605
+ processor.
606
607
3) If SVE is enabled, then an error is generated when attempting to
608
disable the last enabled vector length (see constraint (1) of "SVE
609
@@ -XXX,XX +XXX,XX @@ SVE CPU Property Parsing Semantics
610
has been explicitly disabled, then an error is generated (see
611
constraint (2) of "SVE CPU Property Dependencies and Constraints").
612
613
- 5) If one or more `sve<N>` CPU properties are set `off`, but no `sve<N>`,
614
+ 5) When KVM is enabled, if the host does not support SVE, then an error
615
+ is generated when attempting to enable any `sve*` properties (see
616
+ constraint (3) of "SVE CPU Property Dependencies and Constraints").
617
+
618
+ 6) When KVM is enabled, if the host does support SVE, then an error is
619
+ generated when attempting to enable any vector lengths not supported
620
+ by the host (see constraint (3) of "SVE CPU Property Dependencies and
621
+ Constraints").
622
+
623
+ 7) If one or more `sve<N>` CPU properties are set `off`, but no `sve<N>`,
624
CPU properties are set `on`, then the specified vector lengths are
625
disabled but the default for any unspecified lengths remains enabled.
626
- Disabling a power-of-two vector length also disables all vector
627
- lengths larger than the power-of-two length (see constraint (2) of
628
- "SVE CPU Property Dependencies and Constraints").
629
+ When KVM is not enabled, disabling a power-of-two vector length also
630
+ disables all vector lengths larger than the power-of-two length.
631
+ When KVM is enabled, then disabling any supported vector length also
632
+ disables all larger vector lengths (see constraint (2) of "SVE CPU
633
+ Property Dependencies and Constraints").
634
635
- 6) If one or more `sve<N>` CPU properties are set to `on`, then they
636
+ 8) If one or more `sve<N>` CPU properties are set to `on`, then they
637
are enabled and all unspecified lengths default to disabled, except
638
for the required lengths per constraint (2) of "SVE CPU Property
639
Dependencies and Constraints", which will even be auto-enabled if
640
they were not explicitly enabled.
641
642
- 7) If SVE was disabled (`sve=off`), allowing all vector lengths to be
643
+ 9) If SVE was disabled (`sve=off`), allowing all vector lengths to be
644
explicitly disabled (i.e. avoiding the error specified in (3) of
645
"SVE CPU Property Parsing Semantics"), then if later an `sve=on` is
646
provided an error will be generated. To avoid this error, one must
647
--
107
--
648
2.20.1
108
2.20.1
649
109
650
110
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
In the AdvSIMD scalar x indexed element and vector x indexed element
2
encoding group, the SDOT and UDOT instructions are vector only,
3
and their opcode is unallocated in the scalar group. Correctly
4
UNDEF this unallocated encoding.
2
5
3
Begin setting, but not relying upon, env->hflags.
6
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
9
Message-id: 20190125182626.9221-8-peter.maydell@linaro.org
10
---
11
target/arm/translate-a64.c | 2 +-
12
1 file changed, 1 insertion(+), 1 deletion(-)
4
13
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
14
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20191023150057.25731-17-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
linux-user/syscall.c | 1 +
11
target/arm/cpu.c | 1 +
12
target/arm/helper-a64.c | 3 +++
13
target/arm/helper.c | 2 ++
14
target/arm/machine.c | 1 +
15
target/arm/op_helper.c | 1 +
16
6 files changed, 9 insertions(+)
17
18
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
19
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
20
--- a/linux-user/syscall.c
16
--- a/target/arm/translate-a64.c
21
+++ b/linux-user/syscall.c
17
+++ b/target/arm/translate-a64.c
22
@@ -XXX,XX +XXX,XX @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
18
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
23
aarch64_sve_narrow_vq(env, vq);
19
break;
24
}
20
case 0x0e: /* SDOT */
25
env->vfp.zcr_el[1] = vq - 1;
21
case 0x1e: /* UDOT */
26
+ arm_rebuild_hflags(env);
22
- if (size != MO_32 || !dc_isar_feature(aa64_dp, s)) {
27
ret = vq * 16;
23
+ if (is_scalar || size != MO_32 || !dc_isar_feature(aa64_dp, s)) {
28
}
24
unallocated_encoding(s);
29
return ret;
25
return;
30
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/cpu.c
33
+++ b/target/arm/cpu.c
34
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
35
36
hw_breakpoint_update_all(cpu);
37
hw_watchpoint_update_all(cpu);
38
+ arm_rebuild_hflags(env);
39
}
40
41
bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
42
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/helper-a64.c
45
+++ b/target/arm/helper-a64.c
46
@@ -XXX,XX +XXX,XX @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
47
} else {
48
env->regs[15] = new_pc & ~0x3;
49
}
26
}
50
+ helper_rebuild_hflags_a32(env, new_el);
51
qemu_log_mask(CPU_LOG_INT, "Exception return from AArch64 EL%d to "
52
"AArch32 EL%d PC 0x%" PRIx32 "\n",
53
cur_el, new_el, env->regs[15]);
54
@@ -XXX,XX +XXX,XX @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
55
}
56
aarch64_restore_sp(env, new_el);
57
env->pc = new_pc;
58
+ helper_rebuild_hflags_a64(env, new_el);
59
qemu_log_mask(CPU_LOG_INT, "Exception return from AArch64 EL%d to "
60
"AArch64 EL%d PC 0x%" PRIx64 "\n",
61
cur_el, new_el, env->pc);
62
}
63
+
64
/*
65
* Note that cur_el can never be 0. If new_el is 0, then
66
* el0_a64 is return_to_aa64, else el0_a64 is ignored.
67
diff --git a/target/arm/helper.c b/target/arm/helper.c
68
index XXXXXXX..XXXXXXX 100644
69
--- a/target/arm/helper.c
70
+++ b/target/arm/helper.c
71
@@ -XXX,XX +XXX,XX @@ static void take_aarch32_exception(CPUARMState *env, int new_mode,
72
env->regs[14] = env->regs[15] + offset;
73
}
74
env->regs[15] = newpc;
75
+ arm_rebuild_hflags(env);
76
}
77
78
static void arm_cpu_do_interrupt_aarch32_hyp(CPUState *cs)
79
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
80
pstate_write(env, PSTATE_DAIF | new_mode);
81
env->aarch64 = 1;
82
aarch64_restore_sp(env, new_el);
83
+ helper_rebuild_hflags_a64(env, new_el);
84
85
env->pc = addr;
86
87
diff --git a/target/arm/machine.c b/target/arm/machine.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/target/arm/machine.c
90
+++ b/target/arm/machine.c
91
@@ -XXX,XX +XXX,XX @@ static int cpu_post_load(void *opaque, int version_id)
92
if (!kvm_enabled()) {
93
pmu_op_finish(&cpu->env);
94
}
95
+ arm_rebuild_hflags(&cpu->env);
96
97
return 0;
98
}
99
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
100
index XXXXXXX..XXXXXXX 100644
101
--- a/target/arm/op_helper.c
102
+++ b/target/arm/op_helper.c
103
@@ -XXX,XX +XXX,XX @@ void HELPER(cpsr_write_eret)(CPUARMState *env, uint32_t val)
104
* state. Do the masking now.
105
*/
106
env->regs[15] &= (env->thumb ? ~1 : ~3);
107
+ arm_rebuild_hflags(env);
108
109
qemu_mutex_lock_iothread();
110
arm_call_el_change_hook(env_archcpu(env));
111
--
27
--
112
2.20.1
28
2.20.1
113
29
114
30
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The tcg_register_iommu_notifier() code has a GArray of
2
TCGIOMMUNotifier structs which it has registered by passing
3
memory_region_register_iommu_notifier() a pointer to the embedded
4
IOMMUNotifier field. Unfortunately, if we need to enlarge the
5
array via g_array_set_size() this can cause a realloc(), which
6
invalidates the pointer that memory_region_register_iommu_notifier()
7
put into the MemoryRegion's iommu_notify list. This can result
8
in segfaults.
2
9
3
Avoid calling arm_current_el() twice.
10
Switch the GArray to holding pointers to the TCGIOMMUNotifier
11
structs, so that we can individually allocate and free them.
4
12
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
13
Cc: qemu-stable@nongnu.org
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
14
Fixes: 1f871c5e6b0f30644a60a ("exec.c: Handle IOMMUs in address_space_translate_for_iotlb()")
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20191023150057.25731-14-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20190128174241.5860-1-peter.maydell@linaro.org
10
---
18
---
11
target/arm/internals.h | 9 +++++++++
19
exec.c | 10 ++++++----
12
target/arm/helper.c | 12 +++++++-----
20
1 file changed, 6 insertions(+), 4 deletions(-)
13
2 files changed, 16 insertions(+), 5 deletions(-)
14
21
15
diff --git a/target/arm/internals.h b/target/arm/internals.h
22
diff --git a/exec.c b/exec.c
16
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/internals.h
24
--- a/exec.c
18
+++ b/target/arm/internals.h
25
+++ b/exec.c
19
@@ -XXX,XX +XXX,XX @@ void arm_cpu_update_virq(ARMCPU *cpu);
26
@@ -XXX,XX +XXX,XX @@ static void tcg_register_iommu_notifier(CPUState *cpu,
20
*/
27
int i;
21
void arm_cpu_update_vfiq(ARMCPU *cpu);
28
22
29
for (i = 0; i < cpu->iommu_notifiers->len; i++) {
23
+/**
30
- notifier = &g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier, i);
24
+ * arm_mmu_idx_el:
31
+ notifier = g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier *, i);
25
+ * @env: The cpu environment
32
if (notifier->mr == mr && notifier->iommu_idx == iommu_idx) {
26
+ * @el: The EL to use.
33
break;
27
+ *
34
}
28
+ * Return the full ARMMMUIdx for the translation regime for EL.
35
@@ -XXX,XX +XXX,XX @@ static void tcg_register_iommu_notifier(CPUState *cpu,
29
+ */
36
if (i == cpu->iommu_notifiers->len) {
30
+ARMMMUIdx arm_mmu_idx_el(CPUARMState *env, int el);
37
/* Not found, add a new entry at the end of the array */
31
+
38
cpu->iommu_notifiers = g_array_set_size(cpu->iommu_notifiers, i + 1);
32
/**
39
- notifier = &g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier, i);
33
* arm_mmu_idx:
40
+ notifier = g_new0(TCGIOMMUNotifier, 1);
34
* @env: The cpu environment
41
+ g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier *, i) = notifier;
35
diff --git a/target/arm/helper.c b/target/arm/helper.c
42
36
index XXXXXXX..XXXXXXX 100644
43
notifier->mr = mr;
37
--- a/target/arm/helper.c
44
notifier->iommu_idx = iommu_idx;
38
+++ b/target/arm/helper.c
45
@@ -XXX,XX +XXX,XX @@ static void tcg_iommu_free_notifier_list(CPUState *cpu)
39
@@ -XXX,XX +XXX,XX @@ ARMMMUIdx arm_v7m_mmu_idx_for_secstate(CPUARMState *env, bool secstate)
46
TCGIOMMUNotifier *notifier;
47
48
for (i = 0; i < cpu->iommu_notifiers->len; i++) {
49
- notifier = &g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier, i);
50
+ notifier = g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier *, i);
51
memory_region_unregister_iommu_notifier(notifier->mr, &notifier->n);
52
+ g_free(notifier);
53
}
54
g_array_free(cpu->iommu_notifiers, true);
40
}
55
}
56
@@ -XXX,XX +XXX,XX @@ void cpu_exec_realizefn(CPUState *cpu, Error **errp)
57
vmstate_register(NULL, cpu->cpu_index, cc->vmsd, cpu);
58
}
59
60
- cpu->iommu_notifiers = g_array_new(false, true, sizeof(TCGIOMMUNotifier));
61
+ cpu->iommu_notifiers = g_array_new(false, true, sizeof(TCGIOMMUNotifier *));
41
#endif
62
#endif
42
43
-ARMMMUIdx arm_mmu_idx(CPUARMState *env)
44
+ARMMMUIdx arm_mmu_idx_el(CPUARMState *env, int el)
45
{
46
- int el;
47
-
48
if (arm_feature(env, ARM_FEATURE_M)) {
49
return arm_v7m_mmu_idx_for_secstate(env, env->v7m.secure);
50
}
51
52
- el = arm_current_el(env);
53
if (el < 2 && arm_is_secure_below_el3(env)) {
54
return ARMMMUIdx_S1SE0 + el;
55
} else {
56
@@ -XXX,XX +XXX,XX @@ ARMMMUIdx arm_mmu_idx(CPUARMState *env)
57
}
58
}
63
}
59
64
60
+ARMMMUIdx arm_mmu_idx(CPUARMState *env)
61
+{
62
+ return arm_mmu_idx_el(env, arm_current_el(env));
63
+}
64
+
65
int cpu_mmu_index(CPUARMState *env, bool ifetch)
66
{
67
return arm_to_core_mmu_idx(arm_mmu_idx(env));
68
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_internal(CPUARMState *env)
69
{
70
int el = arm_current_el(env);
71
int fp_el = fp_exception_el(env, el);
72
- ARMMMUIdx mmu_idx = arm_mmu_idx(env);
73
+ ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el);
74
75
if (is_a64(env)) {
76
return rebuild_hflags_a64(env, el, fp_el, mmu_idx);
77
--
65
--
78
2.20.1
66
2.20.1
79
67
80
68
diff view generated by jsdifflib
1
From: Cédric Le Goater <clg@kaod.org>
1
The FCMLA (by element) instruction exists in the
2
"vector x indexed element" encoding group, but not in
3
the "scalar x indexed element" group. Correctly UNDEF
4
the unallocated encodings.
2
5
3
The property names of AST2600 GPIO 1.8V model are one character bigger
6
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
4
than the names of the other ASPEED GPIO model. Increase the string
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
buffer size by one and be more strict on the expected pattern of the
8
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
6
property name.
9
Message-id: 20190129140411.682-2-peter.maydell@linaro.org
10
---
11
target/arm/translate-a64.c | 2 +-
12
1 file changed, 1 insertion(+), 1 deletion(-)
7
13
8
This fixes the QOM test of the ast2600-evb machine under :
14
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
9
10
Apple LLVM version 10.0.0 (clang-1000.10.44.4)
11
Target: x86_64-apple-darwin17.7.0
12
Thread model: posix
13
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
14
15
Cc: Rashmica Gupta <rashmica.g@gmail.com>
16
Fixes: 36d737ee82b2 ("hw/gpio: Add in AST2600 specific implementation")
17
Signed-off-by: Cédric Le Goater <clg@kaod.org>
18
Message-id: 20191023130455.1347-2-clg@kaod.org
19
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
---
22
hw/gpio/aspeed_gpio.c | 8 ++++----
23
1 file changed, 4 insertions(+), 4 deletions(-)
24
25
diff --git a/hw/gpio/aspeed_gpio.c b/hw/gpio/aspeed_gpio.c
26
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/gpio/aspeed_gpio.c
16
--- a/target/arm/translate-a64.c
28
+++ b/hw/gpio/aspeed_gpio.c
17
+++ b/target/arm/translate-a64.c
29
@@ -XXX,XX +XXX,XX @@ static void aspeed_gpio_get_pin(Object *obj, Visitor *v, const char *name,
18
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
30
{
19
case 0x13: /* FCMLA #90 */
31
int pin = 0xfff;
20
case 0x15: /* FCMLA #180 */
32
bool level = true;
21
case 0x17: /* FCMLA #270 */
33
- char group[3];
22
- if (!dc_isar_feature(aa64_fcma, s)) {
34
+ char group[4];
23
+ if (is_scalar || !dc_isar_feature(aa64_fcma, s)) {
35
AspeedGPIOState *s = ASPEED_GPIO(obj);
24
unallocated_encoding(s);
36
int set_idx, group_idx = 0;
37
38
if (sscanf(name, "gpio%2[A-Z]%1d", group, &pin) != 2) {
39
/* 1.8V gpio */
40
- if (sscanf(name, "gpio%3s%1d", group, &pin) != 2) {
41
+ if (sscanf(name, "gpio%3[18A-E]%1d", group, &pin) != 2) {
42
error_setg(errp, "%s: error reading %s", __func__, name);
43
return;
44
}
45
@@ -XXX,XX +XXX,XX @@ static void aspeed_gpio_set_pin(Object *obj, Visitor *v, const char *name,
46
Error *local_err = NULL;
47
bool level;
48
int pin = 0xfff;
49
- char group[3];
50
+ char group[4];
51
AspeedGPIOState *s = ASPEED_GPIO(obj);
52
int set_idx, group_idx = 0;
53
54
@@ -XXX,XX +XXX,XX @@ static void aspeed_gpio_set_pin(Object *obj, Visitor *v, const char *name,
55
}
56
if (sscanf(name, "gpio%2[A-Z]%1d", group, &pin) != 2) {
57
/* 1.8V gpio */
58
- if (sscanf(name, "gpio%3s%1d", group, &pin) != 2) {
59
+ if (sscanf(name, "gpio%3[18A-E]%1d", group, &pin) != 2) {
60
error_setg(errp, "%s: error reading %s", __func__, name);
61
return;
25
return;
62
}
26
}
63
--
27
--
64
2.20.1
28
2.20.1
65
29
66
30
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Create a function to compute the values of the TBFLAG_A32 bits
4
that will be cached, and are used by all profiles.
5
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20191023150057.25731-4-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/helper.c | 16 +++++++++++-----
12
1 file changed, 11 insertions(+), 5 deletions(-)
13
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
17
+++ b/target/arm/helper.c
18
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_common(CPUARMState *env, int fp_el,
19
return flags;
20
}
21
22
+static uint32_t rebuild_hflags_common_32(CPUARMState *env, int fp_el,
23
+ ARMMMUIdx mmu_idx, uint32_t flags)
24
+{
25
+ flags = FIELD_DP32(flags, TBFLAG_A32, SCTLR_B, arm_sctlr_b(env));
26
+ flags = FIELD_DP32(flags, TBFLAG_A32, NS, !access_secure_reg(env));
27
+
28
+ return rebuild_hflags_common(env, fp_el, mmu_idx, flags);
29
+}
30
+
31
static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
32
ARMMMUIdx mmu_idx)
33
{
34
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
35
ARMMMUIdx mmu_idx = arm_mmu_idx(env);
36
int current_el = arm_current_el(env);
37
int fp_el = fp_exception_el(env, current_el);
38
- uint32_t flags = 0;
39
+ uint32_t flags;
40
41
if (is_a64(env)) {
42
*pc = env->pc;
43
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
44
}
45
} else {
46
*pc = env->regs[15];
47
+ flags = rebuild_hflags_common_32(env, fp_el, mmu_idx, 0);
48
flags = FIELD_DP32(flags, TBFLAG_A32, THUMB, env->thumb);
49
flags = FIELD_DP32(flags, TBFLAG_A32, VECLEN, env->vfp.vec_len);
50
flags = FIELD_DP32(flags, TBFLAG_A32, VECSTRIDE, env->vfp.vec_stride);
51
flags = FIELD_DP32(flags, TBFLAG_A32, CONDEXEC, env->condexec_bits);
52
- flags = FIELD_DP32(flags, TBFLAG_A32, SCTLR_B, arm_sctlr_b(env));
53
- flags = FIELD_DP32(flags, TBFLAG_A32, NS, !access_secure_reg(env));
54
if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)
55
|| arm_el_is_aa64(env, 1) || arm_feature(env, ARM_FEATURE_M)) {
56
flags = FIELD_DP32(flags, TBFLAG_A32, VFPEN, 1);
57
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
58
flags = FIELD_DP32(flags, TBFLAG_A32,
59
XSCALE_CPAR, env->cp15.c15_cpar);
60
}
61
-
62
- flags = rebuild_hflags_common(env, fp_el, mmu_idx, flags);
63
}
64
65
/* The SS_ACTIVE and PSTATE_SS bits correspond to the state machine
66
--
67
2.20.1
68
69
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
In disas_simd_indexed(), for the case of "complex fp", each indexable
2
element is a complex pair, so the total size is twice that indicated
3
in the 'size' field in the encoding. We were trying to do this
4
"double the size" operation with a left shift by 1, but this is
5
incorrect because the 'size' field is a MO_8/MO_16/MO_32/MO_64
6
value, and doubling the size should be done by a simple increment.
2
7
3
By performing this store early, we avoid having to save and restore
8
This meant we were mishandling FCMLA (by element) of values where
4
the register holding the address around any function calls.
9
the real and imaginary parts are 32-bit floats, and would incorrectly
10
UNDEF this encoding. (No other insns take this code path, and for
11
16-bit floats it happens that 1 << 1 and 1 + 1 are both the same).
5
12
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
13
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20191023150057.25731-15-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
16
Message-id: 20190129140411.682-3-peter.maydell@linaro.org
10
---
17
---
11
target/arm/helper.c | 2 +-
18
target/arm/translate-a64.c | 2 +-
12
1 file changed, 1 insertion(+), 1 deletion(-)
19
1 file changed, 1 insertion(+), 1 deletion(-)
13
20
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
21
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
15
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
23
--- a/target/arm/translate-a64.c
17
+++ b/target/arm/helper.c
24
+++ b/target/arm/translate-a64.c
18
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
25
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
19
{
26
20
uint32_t flags, pstate_for_ss;
27
case 2: /* complex fp */
21
28
/* Each indexable element is a complex pair. */
22
+ *cs_base = 0;
29
- size <<= 1;
23
flags = rebuild_hflags_internal(env);
30
+ size += 1;
24
31
switch (size) {
25
if (is_a64(env)) {
32
case MO_32:
26
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
33
if (h && !is_q) {
27
}
28
29
*pflags = flags;
30
- *cs_base = 0;
31
}
32
33
#ifdef TARGET_AARCH64
34
--
34
--
35
2.20.1
35
2.20.1
36
36
37
37
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Aaron Lindsay OS <aaron@os.amperecomputing.com>
2
2
3
Create a function to compute the values of the TBFLAG_A32 bits
3
Whenever we notice that a counter overflow has occurred, send an
4
that will be cached, and are used by M-profile.
4
interrupt. This is made more reliable with the addition of a timer in a
5
follow-on commit.
5
6
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Signed-off-by: Aaron Lindsay <aaron@os.amperecomputing.com>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20191023150057.25731-6-richard.henderson@linaro.org
9
Message-id: 20190124162401.5111-2-aaron@os.amperecomputing.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
---
11
target/arm/helper.c | 45 ++++++++++++++++++++++++++++++---------------
12
target/arm/helper.c | 61 +++++++++++++++++++++++++++++++++++++--------
12
1 file changed, 30 insertions(+), 15 deletions(-)
13
1 file changed, 51 insertions(+), 10 deletions(-)
13
14
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
17
--- a/target/arm/helper.c
17
+++ b/target/arm/helper.c
18
+++ b/target/arm/helper.c
18
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_common_32(CPUARMState *env, int fp_el,
19
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v6_cp_reginfo[] = {
19
return rebuild_hflags_common(env, fp_el, mmu_idx, flags);
20
/* Definitions for the PMU registers */
21
#define PMCRN_MASK 0xf800
22
#define PMCRN_SHIFT 11
23
+#define PMCRLC 0x40
24
#define PMCRDP 0x10
25
#define PMCRD 0x8
26
#define PMCRC 0x4
27
@@ -XXX,XX +XXX,XX @@ static bool pmu_counter_enabled(CPUARMState *env, uint8_t counter)
28
return enabled && !prohibited && !filtered;
20
}
29
}
21
30
22
+static uint32_t rebuild_hflags_m32(CPUARMState *env, int fp_el,
31
+static void pmu_update_irq(CPUARMState *env)
23
+ ARMMMUIdx mmu_idx)
24
+{
32
+{
25
+ uint32_t flags = 0;
33
+ ARMCPU *cpu = arm_env_get_cpu(env);
26
+
34
+ qemu_set_irq(cpu->pmu_interrupt, (env->cp15.c9_pmcr & PMCRE) &&
27
+ if (arm_v7m_is_handler_mode(env)) {
35
+ (env->cp15.c9_pminten & env->cp15.c9_pmovsr));
28
+ flags = FIELD_DP32(flags, TBFLAG_A32, HANDLER, 1);
29
+ }
30
+
31
+ /*
32
+ * v8M always applies stack limit checks unless CCR.STKOFHFNMIGN
33
+ * is suppressing them because the requested execution priority
34
+ * is less than 0.
35
+ */
36
+ if (arm_feature(env, ARM_FEATURE_V8) &&
37
+ !((mmu_idx & ARM_MMU_IDX_M_NEGPRI) &&
38
+ (env->v7m.ccr[env->v7m.secure] & R_V7M_CCR_STKOFHFNMIGN_MASK))) {
39
+ flags = FIELD_DP32(flags, TBFLAG_A32, STACKCHECK, 1);
40
+ }
41
+
42
+ return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags);
43
+}
36
+}
44
+
37
+
45
static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
38
/*
46
ARMMMUIdx mmu_idx)
39
* Ensure c15_ccnt is the guest-visible count so that operations such as
47
{
40
* enabling/disabling the counter or filtering, modifying the count itself,
48
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
41
@@ -XXX,XX +XXX,XX @@ void pmccntr_op_start(CPUARMState *env)
42
eff_cycles /= 64;
49
}
43
}
50
} else {
44
51
*pc = env->regs[15];
45
- env->cp15.c15_ccnt = eff_cycles - env->cp15.c15_ccnt_delta;
52
- flags = rebuild_hflags_common_32(env, fp_el, mmu_idx, 0);
46
+ uint64_t new_pmccntr = eff_cycles - env->cp15.c15_ccnt_delta;
53
+
47
+
54
+ if (arm_feature(env, ARM_FEATURE_M)) {
48
+ uint64_t overflow_mask = env->cp15.c9_pmcr & PMCRLC ? \
55
+ flags = rebuild_hflags_m32(env, fp_el, mmu_idx);
49
+ 1ull << 63 : 1ull << 31;
56
+ } else {
50
+ if (env->cp15.c15_ccnt & ~new_pmccntr & overflow_mask) {
57
+ flags = rebuild_hflags_common_32(env, fp_el, mmu_idx, 0);
51
+ env->cp15.c9_pmovsr |= (1 << 31);
52
+ pmu_update_irq(env);
58
+ }
53
+ }
59
+
54
+
60
flags = FIELD_DP32(flags, TBFLAG_A32, THUMB, env->thumb);
55
+ env->cp15.c15_ccnt = new_pmccntr;
61
flags = FIELD_DP32(flags, TBFLAG_A32, VECLEN, env->vfp.vec_len);
56
}
62
flags = FIELD_DP32(flags, TBFLAG_A32, VECSTRIDE, env->vfp.vec_stride);
57
env->cp15.c15_ccnt_delta = cycles;
63
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
58
}
59
@@ -XXX,XX +XXX,XX @@ static void pmevcntr_op_start(CPUARMState *env, uint8_t counter)
60
}
61
62
if (pmu_counter_enabled(env, counter)) {
63
- env->cp15.c14_pmevcntr[counter] =
64
- count - env->cp15.c14_pmevcntr_delta[counter];
65
+ uint32_t new_pmevcntr = count - env->cp15.c14_pmevcntr_delta[counter];
66
+
67
+ if (env->cp15.c14_pmevcntr[counter] & ~new_pmevcntr & INT32_MIN) {
68
+ env->cp15.c9_pmovsr |= (1 << counter);
69
+ pmu_update_irq(env);
70
+ }
71
+ env->cp15.c14_pmevcntr[counter] = new_pmevcntr;
72
}
73
env->cp15.c14_pmevcntr_delta[counter] = count;
74
}
75
@@ -XXX,XX +XXX,XX @@ static void pmswinc_write(CPUARMState *env, const ARMCPRegInfo *ri,
76
/* counter is SW_INCR */
77
(env->cp15.c14_pmevtyper[i] & PMXEVTYPER_EVTCOUNT) == 0x0) {
78
pmevcntr_op_start(env, i);
79
- env->cp15.c14_pmevcntr[i]++;
80
+
81
+ /*
82
+ * Detect if this write causes an overflow since we can't predict
83
+ * PMSWINC overflows like we can for other events
84
+ */
85
+ uint32_t new_pmswinc = env->cp15.c14_pmevcntr[i] + 1;
86
+
87
+ if (env->cp15.c14_pmevcntr[i] & ~new_pmswinc & INT32_MIN) {
88
+ env->cp15.c9_pmovsr |= (1 << i);
89
+ pmu_update_irq(env);
90
+ }
91
+
92
+ env->cp15.c14_pmevcntr[i] = new_pmswinc;
93
+
94
pmevcntr_op_finish(env, i);
64
}
95
}
65
}
96
}
66
97
@@ -XXX,XX +XXX,XX @@ static void pmovsr_write(CPUARMState *env, const ARMCPRegInfo *ri,
67
- if (arm_v7m_is_handler_mode(env)) {
98
{
68
- flags = FIELD_DP32(flags, TBFLAG_A32, HANDLER, 1);
99
value &= pmu_counter_mask(env);
69
- }
100
env->cp15.c9_pmovsr &= ~value;
70
-
101
+ pmu_update_irq(env);
71
- /* v8M always applies stack limit checks unless CCR.STKOFHFNMIGN is
102
}
72
- * suppressing them because the requested execution priority is less than 0.
103
73
- */
104
static void pmovsset_write(CPUARMState *env, const ARMCPRegInfo *ri,
74
- if (arm_feature(env, ARM_FEATURE_V8) &&
105
@@ -XXX,XX +XXX,XX @@ static void pmovsset_write(CPUARMState *env, const ARMCPRegInfo *ri,
75
- arm_feature(env, ARM_FEATURE_M) &&
106
{
76
- !((mmu_idx & ARM_MMU_IDX_M_NEGPRI) &&
107
value &= pmu_counter_mask(env);
77
- (env->v7m.ccr[env->v7m.secure] & R_V7M_CCR_STKOFHFNMIGN_MASK))) {
108
env->cp15.c9_pmovsr |= value;
78
- flags = FIELD_DP32(flags, TBFLAG_A32, STACKCHECK, 1);
109
+ pmu_update_irq(env);
79
- }
110
}
80
-
111
81
if (arm_feature(env, ARM_FEATURE_M_SECURITY) &&
112
static void pmevtyper_write(CPUARMState *env, const ARMCPRegInfo *ri,
82
FIELD_EX32(env->v7m.fpccr[M_REG_S], V7M_FPCCR, S) != env->v7m.secure) {
113
@@ -XXX,XX +XXX,XX @@ static void pmintenset_write(CPUARMState *env, const ARMCPRegInfo *ri,
83
flags = FIELD_DP32(flags, TBFLAG_A32, FPCCR_S_WRONG, 1);
114
/* We have no event counters so only the C bit can be changed */
115
value &= pmu_counter_mask(env);
116
env->cp15.c9_pminten |= value;
117
+ pmu_update_irq(env);
118
}
119
120
static void pmintenclr_write(CPUARMState *env, const ARMCPRegInfo *ri,
121
@@ -XXX,XX +XXX,XX @@ static void pmintenclr_write(CPUARMState *env, const ARMCPRegInfo *ri,
122
{
123
value &= pmu_counter_mask(env);
124
env->cp15.c9_pminten &= ~value;
125
+ pmu_update_irq(env);
126
}
127
128
static void vbar_write(CPUARMState *env, const ARMCPRegInfo *ri,
129
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
130
.fieldoffset = offsetof(CPUARMState, cp15.c9_pmcnten),
131
.writefn = pmcntenclr_write },
132
{ .name = "PMOVSR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 3,
133
- .access = PL0_RW,
134
+ .access = PL0_RW, .type = ARM_CP_IO,
135
.fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pmovsr),
136
.accessfn = pmreg_access,
137
.writefn = pmovsr_write,
138
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
139
{ .name = "PMOVSCLR_EL0", .state = ARM_CP_STATE_AA64,
140
.opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 3,
141
.access = PL0_RW, .accessfn = pmreg_access,
142
- .type = ARM_CP_ALIAS,
143
+ .type = ARM_CP_ALIAS | ARM_CP_IO,
144
.fieldoffset = offsetof(CPUARMState, cp15.c9_pmovsr),
145
.writefn = pmovsr_write,
146
.raw_writefn = raw_write },
147
{ .name = "PMSWINC", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 4,
148
- .access = PL0_W, .accessfn = pmreg_access_swinc, .type = ARM_CP_NO_RAW,
149
+ .access = PL0_W, .accessfn = pmreg_access_swinc,
150
+ .type = ARM_CP_NO_RAW | ARM_CP_IO,
151
.writefn = pmswinc_write },
152
{ .name = "PMSWINC_EL0", .state = ARM_CP_STATE_AA64,
153
.opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 4,
154
- .access = PL0_W, .accessfn = pmreg_access_swinc, .type = ARM_CP_NO_RAW,
155
+ .access = PL0_W, .accessfn = pmreg_access_swinc,
156
+ .type = ARM_CP_NO_RAW | ARM_CP_IO,
157
.writefn = pmswinc_write },
158
{ .name = "PMSELR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 5,
159
.access = PL0_RW, .type = ARM_CP_ALIAS,
160
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo pmovsset_cp_reginfo[] = {
161
/* PMOVSSET is not implemented in v7 before v7ve */
162
{ .name = "PMOVSSET", .cp = 15, .opc1 = 0, .crn = 9, .crm = 14, .opc2 = 3,
163
.access = PL0_RW, .accessfn = pmreg_access,
164
- .type = ARM_CP_ALIAS,
165
+ .type = ARM_CP_ALIAS | ARM_CP_IO,
166
.fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pmovsr),
167
.writefn = pmovsset_write,
168
.raw_writefn = raw_write },
169
{ .name = "PMOVSSET_EL0", .state = ARM_CP_STATE_AA64,
170
.opc0 = 3, .opc1 = 3, .crn = 9, .crm = 14, .opc2 = 3,
171
.access = PL0_RW, .accessfn = pmreg_access,
172
- .type = ARM_CP_ALIAS,
173
+ .type = ARM_CP_ALIAS | ARM_CP_IO,
174
.fieldoffset = offsetof(CPUARMState, cp15.c9_pmovsr),
175
.writefn = pmovsset_write,
176
.raw_writefn = raw_write },
84
--
177
--
85
2.20.1
178
2.20.1
86
179
87
180
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Currently a trivial wrapper for rebuild_hflags_common_32.
4
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20191023150057.25731-8-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
target/arm/helper.c | 8 +++++++-
11
1 file changed, 7 insertions(+), 1 deletion(-)
12
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.c
16
+++ b/target/arm/helper.c
17
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_m32(CPUARMState *env, int fp_el,
18
return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags);
19
}
20
21
+static uint32_t rebuild_hflags_a32(CPUARMState *env, int fp_el,
22
+ ARMMMUIdx mmu_idx)
23
+{
24
+ return rebuild_hflags_common_32(env, fp_el, mmu_idx, 0);
25
+}
26
+
27
static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
28
ARMMMUIdx mmu_idx)
29
{
30
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
31
flags = FIELD_DP32(flags, TBFLAG_A32, LSPACT, 1);
32
}
33
} else {
34
- flags = rebuild_hflags_common_32(env, fp_el, mmu_idx, 0);
35
+ flags = rebuild_hflags_a32(env, fp_el, mmu_idx);
36
}
37
38
flags = FIELD_DP32(flags, TBFLAG_A32, THUMB, env->thumb);
39
--
40
2.20.1
41
42
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
We do not need to compute any of these values for M-profile.
4
Further, XSCALE_CPAR overlaps VECSTRIDE so obviously the two
5
sets must be mutually exclusive.
6
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20191023150057.25731-10-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/helper.c | 21 ++++++++++++++-------
13
1 file changed, 14 insertions(+), 7 deletions(-)
14
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.c
18
+++ b/target/arm/helper.c
19
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
20
}
21
} else {
22
flags = rebuild_hflags_a32(env, fp_el, mmu_idx);
23
+
24
+ /*
25
+ * Note that XSCALE_CPAR shares bits with VECSTRIDE.
26
+ * Note that VECLEN+VECSTRIDE are RES0 for M-profile.
27
+ */
28
+ if (arm_feature(env, ARM_FEATURE_XSCALE)) {
29
+ flags = FIELD_DP32(flags, TBFLAG_A32,
30
+ XSCALE_CPAR, env->cp15.c15_cpar);
31
+ } else {
32
+ flags = FIELD_DP32(flags, TBFLAG_A32, VECLEN,
33
+ env->vfp.vec_len);
34
+ flags = FIELD_DP32(flags, TBFLAG_A32, VECSTRIDE,
35
+ env->vfp.vec_stride);
36
+ }
37
}
38
39
flags = FIELD_DP32(flags, TBFLAG_A32, THUMB, env->thumb);
40
- flags = FIELD_DP32(flags, TBFLAG_A32, VECLEN, env->vfp.vec_len);
41
- flags = FIELD_DP32(flags, TBFLAG_A32, VECSTRIDE, env->vfp.vec_stride);
42
flags = FIELD_DP32(flags, TBFLAG_A32, CONDEXEC, env->condexec_bits);
43
if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)
44
|| arm_el_is_aa64(env, 1) || arm_feature(env, ARM_FEATURE_M)) {
45
flags = FIELD_DP32(flags, TBFLAG_A32, VFPEN, 1);
46
}
47
- /* Note that XSCALE_CPAR shares bits with VECSTRIDE */
48
- if (arm_feature(env, ARM_FEATURE_XSCALE)) {
49
- flags = FIELD_DP32(flags, TBFLAG_A32,
50
- XSCALE_CPAR, env->cp15.c15_cpar);
51
- }
52
}
53
54
/* The SS_ACTIVE and PSTATE_SS bits correspond to the state machine
55
--
56
2.20.1
57
58
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Hoist the variable load for PSTATE into the existing test vs is_a64.
4
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20191023150057.25731-11-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
target/arm/helper.c | 20 ++++++++------------
11
1 file changed, 8 insertions(+), 12 deletions(-)
12
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.c
16
+++ b/target/arm/helper.c
17
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
18
ARMMMUIdx mmu_idx = arm_mmu_idx(env);
19
int current_el = arm_current_el(env);
20
int fp_el = fp_exception_el(env, current_el);
21
- uint32_t flags;
22
+ uint32_t flags, pstate_for_ss;
23
24
if (is_a64(env)) {
25
*pc = env->pc;
26
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
27
if (cpu_isar_feature(aa64_bti, env_archcpu(env))) {
28
flags = FIELD_DP32(flags, TBFLAG_A64, BTYPE, env->btype);
29
}
30
+ pstate_for_ss = env->pstate;
31
} else {
32
*pc = env->regs[15];
33
34
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
35
|| arm_el_is_aa64(env, 1) || arm_feature(env, ARM_FEATURE_M)) {
36
flags = FIELD_DP32(flags, TBFLAG_A32, VFPEN, 1);
37
}
38
+ pstate_for_ss = env->uncached_cpsr;
39
}
40
41
- /* The SS_ACTIVE and PSTATE_SS bits correspond to the state machine
42
+ /*
43
+ * The SS_ACTIVE and PSTATE_SS bits correspond to the state machine
44
* states defined in the ARM ARM for software singlestep:
45
* SS_ACTIVE PSTATE.SS State
46
* 0 x Inactive (the TB flag for SS is always 0)
47
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
48
* 1 1 Active-not-pending
49
* SS_ACTIVE is set in hflags; PSTATE_SS is computed every TB.
50
*/
51
- if (FIELD_EX32(flags, TBFLAG_ANY, SS_ACTIVE)) {
52
- if (is_a64(env)) {
53
- if (env->pstate & PSTATE_SS) {
54
- flags = FIELD_DP32(flags, TBFLAG_ANY, PSTATE_SS, 1);
55
- }
56
- } else {
57
- if (env->uncached_cpsr & PSTATE_SS) {
58
- flags = FIELD_DP32(flags, TBFLAG_ANY, PSTATE_SS, 1);
59
- }
60
- }
61
+ if (FIELD_EX32(flags, TBFLAG_ANY, SS_ACTIVE) &&
62
+ (pstate_for_ss & PSTATE_SS)) {
63
+ flags = FIELD_DP32(flags, TBFLAG_ANY, PSTATE_SS, 1);
64
}
65
66
*pflags = flags;
67
--
68
2.20.1
69
70
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
1
From: Aaron Lindsay OS <aaron@os.amperecomputing.com>
2
2
3
Introduce cpu properties to give fine control over SVE vector lengths.
3
Make PMU overflow interrupts more accurate by using a timer to predict
4
We introduce a property for each valid length up to the current
4
when they will overflow rather than waiting for an event to occur which
5
maximum supported, which is 2048-bits. The properties are named, e.g.
5
allows us to otherwise check them.
6
sve128, sve256, sve384, sve512, ..., where the number is the number of
6
7
bits. See the updates to docs/arm-cpu-features.rst for a description
7
Signed-off-by: Aaron Lindsay <aaron@os.amperecomputing.com>
8
of the semantics and for example uses.
9
10
Note, as sve-max-vq is still present and we'd like to be able to
11
support qmp_query_cpu_model_expansion with guests launched with e.g.
12
-cpu max,sve-max-vq=8 on their command lines, then we do allow
13
sve-max-vq and sve<N> properties to be provided at the same time, but
14
this is not recommended, and is why sve-max-vq is not mentioned in the
15
document. If sve-max-vq is provided then it enables all lengths smaller
16
than and including the max and disables all lengths larger. It also has
17
the side-effect that no larger lengths may be enabled and that the max
18
itself cannot be disabled. Smaller non-power-of-two lengths may,
19
however, be disabled, e.g. -cpu max,sve-max-vq=4,sve384=off provides a
20
guest the vector lengths 128, 256, and 512 bits.
21
22
This patch has been co-authored with Richard Henderson, who reworked
23
the target/arm/cpu64.c changes in order to push all the validation and
24
auto-enabling/disabling steps into the finalizer, resulting in a nice
25
LOC reduction.
26
27
Signed-off-by: Andrew Jones <drjones@redhat.com>
28
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
29
Reviewed-by: Eric Auger <eric.auger@redhat.com>
9
Message-id: 20190124162401.5111-3-aaron@os.amperecomputing.com
30
Tested-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
31
Reviewed-by: Beata Michalska <beata.michalska@linaro.org>
32
Message-id: 20191024121808.9612-5-drjones@redhat.com
33
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
34
---
11
---
35
include/qemu/bitops.h | 1 +
12
target/arm/cpu.h | 10 +++++++
36
target/arm/cpu.h | 19 ++++
13
target/arm/cpu.c | 12 ++++++++
37
target/arm/cpu.c | 19 ++++
14
target/arm/helper.c | 72 +++++++++++++++++++++++++++++++++++++++++++--
38
target/arm/cpu64.c | 192 ++++++++++++++++++++++++++++++++++++-
15
3 files changed, 92 insertions(+), 2 deletions(-)
39
target/arm/helper.c | 10 +-
16
40
target/arm/monitor.c | 12 +++
41
tests/arm-cpu-features.c | 194 ++++++++++++++++++++++++++++++++++++++
42
docs/arm-cpu-features.rst | 168 +++++++++++++++++++++++++++++++--
43
8 files changed, 606 insertions(+), 9 deletions(-)
44
45
diff --git a/include/qemu/bitops.h b/include/qemu/bitops.h
46
index XXXXXXX..XXXXXXX 100644
47
--- a/include/qemu/bitops.h
48
+++ b/include/qemu/bitops.h
49
@@ -XXX,XX +XXX,XX @@
50
#define BITS_PER_LONG (sizeof (unsigned long) * BITS_PER_BYTE)
51
52
#define BIT(nr) (1UL << (nr))
53
+#define BIT_ULL(nr) (1ULL << (nr))
54
#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
55
#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
56
#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
57
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
58
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
59
--- a/target/arm/cpu.h
19
--- a/target/arm/cpu.h
60
+++ b/target/arm/cpu.h
20
+++ b/target/arm/cpu.h
61
@@ -XXX,XX +XXX,XX @@ typedef struct {
62
63
#ifdef TARGET_AARCH64
64
# define ARM_MAX_VQ 16
65
+void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp);
66
+uint32_t arm_cpu_vq_map_next_smaller(ARMCPU *cpu, uint32_t vq);
67
#else
68
# define ARM_MAX_VQ 1
69
+static inline void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp) { }
70
+static inline uint32_t arm_cpu_vq_map_next_smaller(ARMCPU *cpu, uint32_t vq)
71
+{ return 0; }
72
#endif
73
74
typedef struct ARMVectorReg {
75
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
21
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
76
22
77
/* Used to set the maximum vector length the cpu will support. */
23
/* Timers used by the generic (architected) timer */
78
uint32_t sve_max_vq;
24
QEMUTimer *gt_timer[NUM_GTIMERS];
79
+
80
+ /*
25
+ /*
81
+ * In sve_vq_map each set bit is a supported vector length of
26
+ * Timer used by the PMU. Its state is restored after migration by
82
+ * (bit-number + 1) * 16 bytes, i.e. each bit number + 1 is the vector
27
+ * pmu_op_finish() - it does not need other handling during migration
83
+ * length in quadwords.
84
+ *
85
+ * While processing properties during initialization, corresponding
86
+ * sve_vq_init bits are set for bits in sve_vq_map that have been
87
+ * set by properties.
88
+ */
28
+ */
89
+ DECLARE_BITMAP(sve_vq_map, ARM_MAX_VQ);
29
+ QEMUTimer *pmu_timer;
90
+ DECLARE_BITMAP(sve_vq_init, ARM_MAX_VQ);
30
/* GPIO outputs for generic timer */
91
};
31
qemu_irq gt_timer_outputs[NUM_GTIMERS];
92
32
/* GPIO output for GICv3 maintenance interrupt signal */
93
void arm_cpu_post_init(Object *obj);
33
@@ -XXX,XX +XXX,XX @@ void pmccntr_op_finish(CPUARMState *env);
94
@@ -XXX,XX +XXX,XX @@ static inline int arm_feature(CPUARMState *env, int feature)
34
void pmu_op_start(CPUARMState *env);
95
return (env->features & (1ULL << feature)) != 0;
35
void pmu_op_finish(CPUARMState *env);
96
}
36
97
37
+/*
98
+void arm_cpu_finalize_features(ARMCPU *cpu, Error **errp);
38
+ * Called when a PMU counter is due to overflow
99
+
39
+ */
100
#if !defined(CONFIG_USER_ONLY)
40
+void arm_pmu_timer_cb(void *opaque);
101
/* Return true if exception levels below EL3 are in secure state,
41
+
102
* or would be following an exception return to that level.
42
/**
43
* Functions to register as EL change hooks for PMU mode filtering
44
*/
103
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
45
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
104
index XXXXXXX..XXXXXXX 100644
46
index XXXXXXX..XXXXXXX 100644
105
--- a/target/arm/cpu.c
47
--- a/target/arm/cpu.c
106
+++ b/target/arm/cpu.c
48
+++ b/target/arm/cpu.c
107
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_finalizefn(Object *obj)
49
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_finalizefn(Object *obj)
108
#endif
50
QLIST_REMOVE(hook, node);
109
}
51
g_free(hook);
110
52
}
111
+void arm_cpu_finalize_features(ARMCPU *cpu, Error **errp)
53
+#ifndef CONFIG_USER_ONLY
112
+{
54
+ if (cpu->pmu_timer) {
113
+ Error *local_err = NULL;
55
+ timer_del(cpu->pmu_timer);
114
+
56
+ timer_deinit(cpu->pmu_timer);
115
+ if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
57
+ timer_free(cpu->pmu_timer);
116
+ arm_cpu_sve_finalize(cpu, &local_err);
117
+ if (local_err != NULL) {
118
+ error_propagate(errp, local_err);
119
+ return;
120
+ }
121
+ }
58
+ }
122
+}
59
+#endif
123
+
60
}
61
124
static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
62
static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
125
{
126
CPUState *cs = CPU(dev);
127
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
63
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
128
return;
64
arm_register_pre_el_change_hook(cpu, &pmu_pre_el_change, 0);
129
}
65
arm_register_el_change_hook(cpu, &pmu_post_el_change, 0);
130
66
}
131
+ arm_cpu_finalize_features(cpu, &local_err);
67
+
132
+ if (local_err != NULL) {
68
+#ifndef CONFIG_USER_ONLY
133
+ error_propagate(errp, local_err);
69
+ cpu->pmu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, arm_pmu_timer_cb,
134
+ return;
70
+ cpu);
135
+ }
71
+#endif
136
+
72
} else {
137
if (arm_feature(env, ARM_FEATURE_AARCH64) &&
73
cpu->id_aa64dfr0 &= ~0xf00;
138
cpu->has_vfp != cpu->has_neon) {
74
cpu->pmceid0 = 0;
139
/*
140
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
141
index XXXXXXX..XXXXXXX 100644
142
--- a/target/arm/cpu64.c
143
+++ b/target/arm/cpu64.c
144
@@ -XXX,XX +XXX,XX @@ static void aarch64_a72_initfn(Object *obj)
145
define_arm_cp_regs(cpu, cortex_a72_a57_a53_cp_reginfo);
146
}
147
148
+void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp)
149
+{
150
+ /*
151
+ * If any vector lengths are explicitly enabled with sve<N> properties,
152
+ * then all other lengths are implicitly disabled. If sve-max-vq is
153
+ * specified then it is the same as explicitly enabling all lengths
154
+ * up to and including the specified maximum, which means all larger
155
+ * lengths will be implicitly disabled. If no sve<N> properties
156
+ * are enabled and sve-max-vq is not specified, then all lengths not
157
+ * explicitly disabled will be enabled. Additionally, all power-of-two
158
+ * vector lengths less than the maximum enabled length will be
159
+ * automatically enabled and all vector lengths larger than the largest
160
+ * disabled power-of-two vector length will be automatically disabled.
161
+ * Errors are generated if the user provided input that interferes with
162
+ * any of the above. Finally, if SVE is not disabled, then at least one
163
+ * vector length must be enabled.
164
+ */
165
+ DECLARE_BITMAP(tmp, ARM_MAX_VQ);
166
+ uint32_t vq, max_vq = 0;
167
+
168
+ /*
169
+ * Process explicit sve<N> properties.
170
+ * From the properties, sve_vq_map<N> implies sve_vq_init<N>.
171
+ * Check first for any sve<N> enabled.
172
+ */
173
+ if (!bitmap_empty(cpu->sve_vq_map, ARM_MAX_VQ)) {
174
+ max_vq = find_last_bit(cpu->sve_vq_map, ARM_MAX_VQ) + 1;
175
+
176
+ if (cpu->sve_max_vq && max_vq > cpu->sve_max_vq) {
177
+ error_setg(errp, "cannot enable sve%d", max_vq * 128);
178
+ error_append_hint(errp, "sve%d is larger than the maximum vector "
179
+ "length, sve-max-vq=%d (%d bits)\n",
180
+ max_vq * 128, cpu->sve_max_vq,
181
+ cpu->sve_max_vq * 128);
182
+ return;
183
+ }
184
+
185
+ /* Propagate enabled bits down through required powers-of-two. */
186
+ for (vq = pow2floor(max_vq); vq >= 1; vq >>= 1) {
187
+ if (!test_bit(vq - 1, cpu->sve_vq_init)) {
188
+ set_bit(vq - 1, cpu->sve_vq_map);
189
+ }
190
+ }
191
+ } else if (cpu->sve_max_vq == 0) {
192
+ /*
193
+ * No explicit bits enabled, and no implicit bits from sve-max-vq.
194
+ */
195
+ if (!cpu_isar_feature(aa64_sve, cpu)) {
196
+ /* SVE is disabled and so are all vector lengths. Good. */
197
+ return;
198
+ }
199
+
200
+ /* Disabling a power-of-two disables all larger lengths. */
201
+ if (test_bit(0, cpu->sve_vq_init)) {
202
+ error_setg(errp, "cannot disable sve128");
203
+ error_append_hint(errp, "Disabling sve128 results in all vector "
204
+ "lengths being disabled.\n");
205
+ error_append_hint(errp, "With SVE enabled, at least one vector "
206
+ "length must be enabled.\n");
207
+ return;
208
+ }
209
+ for (vq = 2; vq <= ARM_MAX_VQ; vq <<= 1) {
210
+ if (test_bit(vq - 1, cpu->sve_vq_init)) {
211
+ break;
212
+ }
213
+ }
214
+ max_vq = vq <= ARM_MAX_VQ ? vq - 1 : ARM_MAX_VQ;
215
+
216
+ bitmap_complement(cpu->sve_vq_map, cpu->sve_vq_init, max_vq);
217
+ max_vq = find_last_bit(cpu->sve_vq_map, max_vq) + 1;
218
+ }
219
+
220
+ /*
221
+ * Process the sve-max-vq property.
222
+ * Note that we know from the above that no bit above
223
+ * sve-max-vq is currently set.
224
+ */
225
+ if (cpu->sve_max_vq != 0) {
226
+ max_vq = cpu->sve_max_vq;
227
+
228
+ if (!test_bit(max_vq - 1, cpu->sve_vq_map) &&
229
+ test_bit(max_vq - 1, cpu->sve_vq_init)) {
230
+ error_setg(errp, "cannot disable sve%d", max_vq * 128);
231
+ error_append_hint(errp, "The maximum vector length must be "
232
+ "enabled, sve-max-vq=%d (%d bits)\n",
233
+ max_vq, max_vq * 128);
234
+ return;
235
+ }
236
+
237
+ /* Set all bits not explicitly set within sve-max-vq. */
238
+ bitmap_complement(tmp, cpu->sve_vq_init, max_vq);
239
+ bitmap_or(cpu->sve_vq_map, cpu->sve_vq_map, tmp, max_vq);
240
+ }
241
+
242
+ /*
243
+ * We should know what max-vq is now. Also, as we're done
244
+ * manipulating sve-vq-map, we ensure any bits above max-vq
245
+ * are clear, just in case anybody looks.
246
+ */
247
+ assert(max_vq != 0);
248
+ bitmap_clear(cpu->sve_vq_map, max_vq, ARM_MAX_VQ - max_vq);
249
+
250
+ /* Ensure all required powers-of-two are enabled. */
251
+ for (vq = pow2floor(max_vq); vq >= 1; vq >>= 1) {
252
+ if (!test_bit(vq - 1, cpu->sve_vq_map)) {
253
+ error_setg(errp, "cannot disable sve%d", vq * 128);
254
+ error_append_hint(errp, "sve%d is required as it "
255
+ "is a power-of-two length smaller than "
256
+ "the maximum, sve%d\n",
257
+ vq * 128, max_vq * 128);
258
+ return;
259
+ }
260
+ }
261
+
262
+ /*
263
+ * Now that we validated all our vector lengths, the only question
264
+ * left to answer is if we even want SVE at all.
265
+ */
266
+ if (!cpu_isar_feature(aa64_sve, cpu)) {
267
+ error_setg(errp, "cannot enable sve%d", max_vq * 128);
268
+ error_append_hint(errp, "SVE must be enabled to enable vector "
269
+ "lengths.\n");
270
+ error_append_hint(errp, "Add sve=on to the CPU property list.\n");
271
+ return;
272
+ }
273
+
274
+ /* From now on sve_max_vq is the actual maximum supported length. */
275
+ cpu->sve_max_vq = max_vq;
276
+}
277
+
278
+uint32_t arm_cpu_vq_map_next_smaller(ARMCPU *cpu, uint32_t vq)
279
+{
280
+ uint32_t bitnum;
281
+
282
+ /*
283
+ * We allow vq == ARM_MAX_VQ + 1 to be input because the caller may want
284
+ * to find the maximum vq enabled, which may be ARM_MAX_VQ, but this
285
+ * function always returns the next smaller than the input.
286
+ */
287
+ assert(vq && vq <= ARM_MAX_VQ + 1);
288
+
289
+ bitnum = find_last_bit(cpu->sve_vq_map, vq - 1);
290
+ return bitnum == vq - 1 ? 0 : bitnum + 1;
291
+}
292
+
293
static void cpu_max_get_sve_max_vq(Object *obj, Visitor *v, const char *name,
294
void *opaque, Error **errp)
295
{
296
@@ -XXX,XX +XXX,XX @@ static void cpu_max_set_sve_max_vq(Object *obj, Visitor *v, const char *name,
297
error_propagate(errp, err);
298
}
299
300
+static void cpu_arm_get_sve_vq(Object *obj, Visitor *v, const char *name,
301
+ void *opaque, Error **errp)
302
+{
303
+ ARMCPU *cpu = ARM_CPU(obj);
304
+ uint32_t vq = atoi(&name[3]) / 128;
305
+ bool value;
306
+
307
+ /* All vector lengths are disabled when SVE is off. */
308
+ if (!cpu_isar_feature(aa64_sve, cpu)) {
309
+ value = false;
310
+ } else {
311
+ value = test_bit(vq - 1, cpu->sve_vq_map);
312
+ }
313
+ visit_type_bool(v, name, &value, errp);
314
+}
315
+
316
+static void cpu_arm_set_sve_vq(Object *obj, Visitor *v, const char *name,
317
+ void *opaque, Error **errp)
318
+{
319
+ ARMCPU *cpu = ARM_CPU(obj);
320
+ uint32_t vq = atoi(&name[3]) / 128;
321
+ Error *err = NULL;
322
+ bool value;
323
+
324
+ visit_type_bool(v, name, &value, &err);
325
+ if (err) {
326
+ error_propagate(errp, err);
327
+ return;
328
+ }
329
+
330
+ if (value) {
331
+ set_bit(vq - 1, cpu->sve_vq_map);
332
+ } else {
333
+ clear_bit(vq - 1, cpu->sve_vq_map);
334
+ }
335
+ set_bit(vq - 1, cpu->sve_vq_init);
336
+}
337
+
338
static void cpu_arm_get_sve(Object *obj, Visitor *v, const char *name,
339
void *opaque, Error **errp)
340
{
341
@@ -XXX,XX +XXX,XX @@ static void cpu_arm_set_sve(Object *obj, Visitor *v, const char *name,
342
static void aarch64_max_initfn(Object *obj)
343
{
344
ARMCPU *cpu = ARM_CPU(obj);
345
+ uint32_t vq;
346
347
if (kvm_enabled()) {
348
kvm_arm_set_cpu_features_from_host(cpu);
349
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
350
cpu->dcz_blocksize = 7; /* 512 bytes */
351
#endif
352
353
- cpu->sve_max_vq = ARM_MAX_VQ;
354
object_property_add(obj, "sve-max-vq", "uint32", cpu_max_get_sve_max_vq,
355
cpu_max_set_sve_max_vq, NULL, NULL, &error_fatal);
356
object_property_add(obj, "sve", "bool", cpu_arm_get_sve,
357
cpu_arm_set_sve, NULL, NULL, &error_fatal);
358
+
359
+ for (vq = 1; vq <= ARM_MAX_VQ; ++vq) {
360
+ char name[8];
361
+ sprintf(name, "sve%d", vq * 128);
362
+ object_property_add(obj, name, "bool", cpu_arm_get_sve_vq,
363
+ cpu_arm_set_sve_vq, NULL, NULL, &error_fatal);
364
+ }
365
}
366
}
367
368
diff --git a/target/arm/helper.c b/target/arm/helper.c
75
diff --git a/target/arm/helper.c b/target/arm/helper.c
369
index XXXXXXX..XXXXXXX 100644
76
index XXXXXXX..XXXXXXX 100644
370
--- a/target/arm/helper.c
77
--- a/target/arm/helper.c
371
+++ b/target/arm/helper.c
78
+++ b/target/arm/helper.c
372
@@ -XXX,XX +XXX,XX @@ int sve_exception_el(CPUARMState *env, int el)
79
@@ -XXX,XX +XXX,XX @@ typedef struct pm_event {
80
* counters hold a difference from the return value from this function
81
*/
82
uint64_t (*get_count)(CPUARMState *);
83
+ /*
84
+ * Return how many nanoseconds it will take (at a minimum) for count events
85
+ * to occur. A negative value indicates the counter will never overflow, or
86
+ * that the counter has otherwise arranged for the overflow bit to be set
87
+ * and the PMU interrupt to be raised on overflow.
88
+ */
89
+ int64_t (*ns_per_count)(uint64_t);
90
} pm_event;
91
92
static bool event_always_supported(CPUARMState *env)
93
@@ -XXX,XX +XXX,XX @@ static uint64_t swinc_get_count(CPUARMState *env)
373
return 0;
94
return 0;
374
}
95
}
375
96
376
+static uint32_t sve_zcr_get_valid_len(ARMCPU *cpu, uint32_t start_len)
97
+static int64_t swinc_ns_per(uint64_t ignored)
377
+{
98
+{
378
+ uint32_t start_vq = (start_len & 0xf) + 1;
99
+ return -1;
379
+
380
+ return arm_cpu_vq_map_next_smaller(cpu, start_vq + 1) - 1;
381
+}
100
+}
382
+
101
+
383
/*
102
/*
384
* Given that SVE is enabled, return the vector length for EL.
103
* Return the underlying cycle count for the PMU cycle counters. If we're in
385
*/
104
* usermode, simply return 0.
386
@@ -XXX,XX +XXX,XX @@ uint32_t sve_zcr_len_for_el(CPUARMState *env, int el)
105
@@ -XXX,XX +XXX,XX @@ static uint64_t cycles_get_count(CPUARMState *env)
387
if (arm_feature(env, ARM_FEATURE_EL3)) {
106
}
388
zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[3]);
107
389
}
108
#ifndef CONFIG_USER_ONLY
390
- return zcr_len;
109
+static int64_t cycles_ns_per(uint64_t cycles)
391
+
110
+{
392
+ return sve_zcr_get_valid_len(cpu, zcr_len);
111
+ return (ARM_CPU_FREQ / NANOSECONDS_PER_SECOND) * cycles;
393
}
112
+}
394
113
+
395
static void zcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
114
static bool instructions_supported(CPUARMState *env)
396
diff --git a/target/arm/monitor.c b/target/arm/monitor.c
115
{
397
index XXXXXXX..XXXXXXX 100644
116
return use_icount == 1 /* Precise instruction counting */;
398
--- a/target/arm/monitor.c
117
@@ -XXX,XX +XXX,XX @@ static uint64_t instructions_get_count(CPUARMState *env)
399
+++ b/target/arm/monitor.c
118
{
400
@@ -XXX,XX +XXX,XX @@ GICCapabilityList *qmp_query_gic_capabilities(Error **errp)
119
return (uint64_t)cpu_get_icount_raw();
401
return head;
120
}
402
}
121
+
403
122
+static int64_t instructions_ns_per(uint64_t icount)
404
+QEMU_BUILD_BUG_ON(ARM_MAX_VQ > 16);
123
+{
405
+
124
+ return cpu_icount_to_ns((int64_t)icount);
406
/*
125
+}
407
* These are cpu model features we want to advertise. The order here
126
#endif
408
* matters as this is the order in which qmp_query_cpu_model_expansion
127
409
@@ -XXX,XX +XXX,XX @@ GICCapabilityList *qmp_query_gic_capabilities(Error **errp)
128
static const pm_event pm_events[] = {
410
*/
129
{ .number = 0x000, /* SW_INCR */
411
static const char *cpu_model_advertised_features[] = {
130
.supported = event_always_supported,
412
"aarch64", "pmu", "sve",
131
.get_count = swinc_get_count,
413
+ "sve128", "sve256", "sve384", "sve512",
132
+ .ns_per_count = swinc_ns_per,
414
+ "sve640", "sve768", "sve896", "sve1024", "sve1152", "sve1280",
133
},
415
+ "sve1408", "sve1536", "sve1664", "sve1792", "sve1920", "sve2048",
134
#ifndef CONFIG_USER_ONLY
416
NULL
135
{ .number = 0x008, /* INST_RETIRED, Instruction architecturally executed */
136
.supported = instructions_supported,
137
.get_count = instructions_get_count,
138
+ .ns_per_count = instructions_ns_per,
139
},
140
{ .number = 0x011, /* CPU_CYCLES, Cycle */
141
.supported = event_always_supported,
142
.get_count = cycles_get_count,
143
+ .ns_per_count = cycles_ns_per,
144
}
145
#endif
417
};
146
};
418
147
@@ -XXX,XX +XXX,XX @@ void pmccntr_op_start(CPUARMState *env)
419
@@ -XXX,XX +XXX,XX @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
148
void pmccntr_op_finish(CPUARMState *env)
420
if (!err) {
149
{
421
visit_check_struct(visitor, &err);
150
if (pmu_counter_enabled(env, 31)) {
151
- uint64_t prev_cycles = env->cp15.c15_ccnt_delta;
152
+#ifndef CONFIG_USER_ONLY
153
+ /* Calculate when the counter will next overflow */
154
+ uint64_t remaining_cycles = -env->cp15.c15_ccnt;
155
+ if (!(env->cp15.c9_pmcr & PMCRLC)) {
156
+ remaining_cycles = (uint32_t)remaining_cycles;
157
+ }
158
+ int64_t overflow_in = cycles_ns_per(remaining_cycles);
159
160
+ if (overflow_in > 0) {
161
+ int64_t overflow_at = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
162
+ overflow_in;
163
+ ARMCPU *cpu = arm_env_get_cpu(env);
164
+ timer_mod_anticipate_ns(cpu->pmu_timer, overflow_at);
165
+ }
166
+#endif
167
+
168
+ uint64_t prev_cycles = env->cp15.c15_ccnt_delta;
169
if (env->cp15.c9_pmcr & PMCRD) {
170
/* Increment once every 64 processor clock cycles */
171
prev_cycles /= 64;
422
}
172
}
423
+ if (!err) {
173
-
424
+ arm_cpu_finalize_features(ARM_CPU(obj), &err);
174
env->cp15.c15_ccnt_delta = prev_cycles - env->cp15.c15_ccnt;
175
}
176
}
177
@@ -XXX,XX +XXX,XX @@ static void pmevcntr_op_start(CPUARMState *env, uint8_t counter)
178
static void pmevcntr_op_finish(CPUARMState *env, uint8_t counter)
179
{
180
if (pmu_counter_enabled(env, counter)) {
181
+#ifndef CONFIG_USER_ONLY
182
+ uint16_t event = env->cp15.c14_pmevtyper[counter] & PMXEVTYPER_EVTCOUNT;
183
+ uint16_t event_idx = supported_event_map[event];
184
+ uint64_t delta = UINT32_MAX -
185
+ (uint32_t)env->cp15.c14_pmevcntr[counter] + 1;
186
+ int64_t overflow_in = pm_events[event_idx].ns_per_count(delta);
187
+
188
+ if (overflow_in > 0) {
189
+ int64_t overflow_at = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
190
+ overflow_in;
191
+ ARMCPU *cpu = arm_env_get_cpu(env);
192
+ timer_mod_anticipate_ns(cpu->pmu_timer, overflow_at);
425
+ }
193
+ }
426
visit_end_struct(visitor, NULL);
194
+#endif
427
visit_free(visitor);
195
+
428
if (err) {
196
env->cp15.c14_pmevcntr_delta[counter] -=
429
@@ -XXX,XX +XXX,XX @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
197
env->cp15.c14_pmevcntr[counter];
430
error_propagate(errp, err);
198
}
431
return NULL;
199
@@ -XXX,XX +XXX,XX @@ void pmu_post_el_change(ARMCPU *cpu, void *ignored)
432
}
200
pmu_op_finish(&cpu->env);
433
+ } else {
201
}
434
+ Error *err = NULL;
202
435
+ arm_cpu_finalize_features(ARM_CPU(obj), &err);
203
+void arm_pmu_timer_cb(void *opaque)
436
+ assert(err == NULL);
204
+{
437
}
205
+ ARMCPU *cpu = opaque;
438
206
+
439
expansion_info = g_new0(CpuModelExpansionInfo, 1);
440
diff --git a/tests/arm-cpu-features.c b/tests/arm-cpu-features.c
441
index XXXXXXX..XXXXXXX 100644
442
--- a/tests/arm-cpu-features.c
443
+++ b/tests/arm-cpu-features.c
444
@@ -XXX,XX +XXX,XX @@
445
* See the COPYING file in the top-level directory.
446
*/
447
#include "qemu/osdep.h"
448
+#include "qemu/bitops.h"
449
#include "libqtest.h"
450
#include "qapi/qmp/qdict.h"
451
#include "qapi/qmp/qjson.h"
452
453
+/*
454
+ * We expect the SVE max-vq to be 16. Also it must be <= 64
455
+ * for our test code, otherwise 'vls' can't just be a uint64_t.
456
+ */
457
+#define SVE_MAX_VQ 16
458
+
459
#define MACHINE "-machine virt,gic-version=max "
460
#define QUERY_HEAD "{ 'execute': 'query-cpu-model-expansion', " \
461
"'arguments': { 'type': 'full', "
462
@@ -XXX,XX +XXX,XX @@ static void assert_bad_props(QTestState *qts, const char *cpu_type)
463
qobject_unref(resp);
464
}
465
466
+static uint64_t resp_get_sve_vls(QDict *resp)
467
+{
468
+ QDict *props;
469
+ const QDictEntry *e;
470
+ uint64_t vls = 0;
471
+ int n = 0;
472
+
473
+ g_assert(resp);
474
+ g_assert(resp_has_props(resp));
475
+
476
+ props = resp_get_props(resp);
477
+
478
+ for (e = qdict_first(props); e; e = qdict_next(props, e)) {
479
+ if (strlen(e->key) > 3 && !strncmp(e->key, "sve", 3) &&
480
+ g_ascii_isdigit(e->key[3])) {
481
+ char *endptr;
482
+ int bits;
483
+
484
+ bits = g_ascii_strtoll(&e->key[3], &endptr, 10);
485
+ if (!bits || *endptr != '\0') {
486
+ continue;
487
+ }
488
+
489
+ if (qdict_get_bool(props, e->key)) {
490
+ vls |= BIT_ULL((bits / 128) - 1);
491
+ }
492
+ ++n;
493
+ }
494
+ }
495
+
496
+ g_assert(n == SVE_MAX_VQ);
497
+
498
+ return vls;
499
+}
500
+
501
+#define assert_sve_vls(qts, cpu_type, expected_vls, fmt, ...) \
502
+({ \
503
+ QDict *_resp = do_query(qts, cpu_type, fmt, ##__VA_ARGS__); \
504
+ g_assert(_resp); \
505
+ g_assert(resp_has_props(_resp)); \
506
+ g_assert(resp_get_sve_vls(_resp) == expected_vls); \
507
+ qobject_unref(_resp); \
508
+})
509
+
510
+static void sve_tests_default(QTestState *qts, const char *cpu_type)
511
+{
512
+ /*
207
+ /*
513
+ * With no sve-max-vq or sve<N> properties on the command line
208
+ * Update all the counter values based on the current underlying counts,
514
+ * the default is to have all vector lengths enabled. This also
209
+ * triggering interrupts to be raised, if necessary. pmu_op_finish() also
515
+ * tests that 'sve' is 'on' by default.
210
+ * has the effect of setting the cpu->pmu_timer to the next earliest time a
211
+ * counter may expire.
516
+ */
212
+ */
517
+ assert_sve_vls(qts, cpu_type, BIT_ULL(SVE_MAX_VQ) - 1, NULL);
213
+ pmu_op_start(&cpu->env);
518
+
214
+ pmu_op_finish(&cpu->env);
519
+ /* With SVE off, all vector lengths should also be off. */
215
+}
520
+ assert_sve_vls(qts, cpu_type, 0, "{ 'sve': false }");
216
+
521
+
217
static void pmcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
522
+ /* With SVE on, we must have at least one vector length enabled. */
218
uint64_t value)
523
+ assert_error(qts, cpu_type, "cannot disable sve128", "{ 'sve128': false }");
219
{
524
+
525
+ /* Basic enable/disable tests. */
526
+ assert_sve_vls(qts, cpu_type, 0x7, "{ 'sve384': true }");
527
+ assert_sve_vls(qts, cpu_type, ((BIT_ULL(SVE_MAX_VQ) - 1) & ~BIT_ULL(2)),
528
+ "{ 'sve384': false }");
529
+
530
+ /*
531
+ * ---------------------------------------------------------------------
532
+ * power-of-two(vq) all-power- can can
533
+ * of-two(< vq) enable disable
534
+ * ---------------------------------------------------------------------
535
+ * vq < max_vq no MUST* yes yes
536
+ * vq < max_vq yes MUST* yes no
537
+ * ---------------------------------------------------------------------
538
+ * vq == max_vq n/a MUST* yes** yes**
539
+ * ---------------------------------------------------------------------
540
+ * vq > max_vq n/a no no yes
541
+ * vq > max_vq n/a yes yes yes
542
+ * ---------------------------------------------------------------------
543
+ *
544
+ * [*] "MUST" means this requirement must already be satisfied,
545
+ * otherwise 'max_vq' couldn't itself be enabled.
546
+ *
547
+ * [**] Not testable with the QMP interface, only with the command line.
548
+ */
549
+
550
+ /* max_vq := 8 */
551
+ assert_sve_vls(qts, cpu_type, 0x8b, "{ 'sve1024': true }");
552
+
553
+ /* max_vq := 8, vq < max_vq, !power-of-two(vq) */
554
+ assert_sve_vls(qts, cpu_type, 0x8f,
555
+ "{ 'sve1024': true, 'sve384': true }");
556
+ assert_sve_vls(qts, cpu_type, 0x8b,
557
+ "{ 'sve1024': true, 'sve384': false }");
558
+
559
+ /* max_vq := 8, vq < max_vq, power-of-two(vq) */
560
+ assert_sve_vls(qts, cpu_type, 0x8b,
561
+ "{ 'sve1024': true, 'sve256': true }");
562
+ assert_error(qts, cpu_type, "cannot disable sve256",
563
+ "{ 'sve1024': true, 'sve256': false }");
564
+
565
+ /* max_vq := 3, vq > max_vq, !all-power-of-two(< vq) */
566
+ assert_error(qts, cpu_type, "cannot disable sve512",
567
+ "{ 'sve384': true, 'sve512': false, 'sve640': true }");
568
+
569
+ /*
570
+ * We can disable power-of-two vector lengths when all larger lengths
571
+ * are also disabled. We only need to disable the power-of-two length,
572
+ * as all non-enabled larger lengths will then be auto-disabled.
573
+ */
574
+ assert_sve_vls(qts, cpu_type, 0x7, "{ 'sve512': false }");
575
+
576
+ /* max_vq := 3, vq > max_vq, all-power-of-two(< vq) */
577
+ assert_sve_vls(qts, cpu_type, 0x1f,
578
+ "{ 'sve384': true, 'sve512': true, 'sve640': true }");
579
+ assert_sve_vls(qts, cpu_type, 0xf,
580
+ "{ 'sve384': true, 'sve512': true, 'sve640': false }");
581
+}
582
+
583
+static void sve_tests_sve_max_vq_8(const void *data)
584
+{
585
+ QTestState *qts;
586
+
587
+ qts = qtest_init(MACHINE "-cpu max,sve-max-vq=8");
588
+
589
+ assert_sve_vls(qts, "max", BIT_ULL(8) - 1, NULL);
590
+
591
+ /*
592
+ * Disabling the max-vq set by sve-max-vq is not allowed, but
593
+ * of course enabling it is OK.
594
+ */
595
+ assert_error(qts, "max", "cannot disable sve1024", "{ 'sve1024': false }");
596
+ assert_sve_vls(qts, "max", 0xff, "{ 'sve1024': true }");
597
+
598
+ /*
599
+ * Enabling anything larger than max-vq set by sve-max-vq is not
600
+ * allowed, but of course disabling everything larger is OK.
601
+ */
602
+ assert_error(qts, "max", "cannot enable sve1152", "{ 'sve1152': true }");
603
+ assert_sve_vls(qts, "max", 0xff, "{ 'sve1152': false }");
604
+
605
+ /*
606
+ * We can enable/disable non power-of-two lengths smaller than the
607
+ * max-vq set by sve-max-vq, but, while we can enable power-of-two
608
+ * lengths, we can't disable them.
609
+ */
610
+ assert_sve_vls(qts, "max", 0xff, "{ 'sve384': true }");
611
+ assert_sve_vls(qts, "max", 0xfb, "{ 'sve384': false }");
612
+ assert_sve_vls(qts, "max", 0xff, "{ 'sve256': true }");
613
+ assert_error(qts, "max", "cannot disable sve256", "{ 'sve256': false }");
614
+
615
+ qtest_quit(qts);
616
+}
617
+
618
+static void sve_tests_sve_off(const void *data)
619
+{
620
+ QTestState *qts;
621
+
622
+ qts = qtest_init(MACHINE "-cpu max,sve=off");
623
+
624
+ /* SVE is off, so the map should be empty. */
625
+ assert_sve_vls(qts, "max", 0, NULL);
626
+
627
+ /* The map stays empty even if we turn lengths off. */
628
+ assert_sve_vls(qts, "max", 0, "{ 'sve128': false }");
629
+
630
+ /* It's an error to enable lengths when SVE is off. */
631
+ assert_error(qts, "max", "cannot enable sve128", "{ 'sve128': true }");
632
+
633
+ /* With SVE re-enabled we should get all vector lengths enabled. */
634
+ assert_sve_vls(qts, "max", BIT_ULL(SVE_MAX_VQ) - 1, "{ 'sve': true }");
635
+
636
+ /* Or enable SVE with just specific vector lengths. */
637
+ assert_sve_vls(qts, "max", 0x3,
638
+ "{ 'sve': true, 'sve128': true, 'sve256': true }");
639
+
640
+ qtest_quit(qts);
641
+}
642
+
643
static void test_query_cpu_model_expansion(const void *data)
644
{
645
QTestState *qts;
646
@@ -XXX,XX +XXX,XX @@ static void test_query_cpu_model_expansion(const void *data)
647
if (g_str_equal(qtest_get_arch(), "aarch64")) {
648
assert_has_feature(qts, "max", "aarch64");
649
assert_has_feature(qts, "max", "sve");
650
+ assert_has_feature(qts, "max", "sve128");
651
assert_has_feature(qts, "cortex-a57", "pmu");
652
assert_has_feature(qts, "cortex-a57", "aarch64");
653
654
+ sve_tests_default(qts, "max");
655
+
656
/* Test that features that depend on KVM generate errors without. */
657
assert_error(qts, "max",
658
"'aarch64' feature cannot be disabled "
659
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
660
qtest_add_data_func("/arm/query-cpu-model-expansion",
661
NULL, test_query_cpu_model_expansion);
662
663
+ if (g_str_equal(qtest_get_arch(), "aarch64")) {
664
+ qtest_add_data_func("/arm/max/query-cpu-model-expansion/sve-max-vq-8",
665
+ NULL, sve_tests_sve_max_vq_8);
666
+ qtest_add_data_func("/arm/max/query-cpu-model-expansion/sve-off",
667
+ NULL, sve_tests_sve_off);
668
+ }
669
+
670
if (kvm_available) {
671
qtest_add_data_func("/arm/kvm/query-cpu-model-expansion",
672
NULL, test_query_cpu_model_expansion_kvm);
673
diff --git a/docs/arm-cpu-features.rst b/docs/arm-cpu-features.rst
674
index XXXXXXX..XXXXXXX 100644
675
--- a/docs/arm-cpu-features.rst
676
+++ b/docs/arm-cpu-features.rst
677
@@ -XXX,XX +XXX,XX @@ block in the script for usage) is used to issue the QMP commands.
678
(QEMU) query-cpu-model-expansion type=full model={"name":"max"}
679
{ "return": {
680
"model": { "name": "max", "props": {
681
- "pmu": true, "aarch64": true
682
+ "sve1664": true, "pmu": true, "sve1792": true, "sve1920": true,
683
+ "sve128": true, "aarch64": true, "sve1024": true, "sve": true,
684
+ "sve640": true, "sve768": true, "sve1408": true, "sve256": true,
685
+ "sve1152": true, "sve512": true, "sve384": true, "sve1536": true,
686
+ "sve896": true, "sve1280": true, "sve2048": true
687
}}}}
688
689
-We see that the `max` CPU type has the `pmu` and `aarch64` CPU features.
690
-We also see that the CPU features are enabled, as they are all `true`.
691
+We see that the `max` CPU type has the `pmu`, `aarch64`, `sve`, and many
692
+`sve<N>` CPU features. We also see that all the CPU features are
693
+enabled, as they are all `true`. (The `sve<N>` CPU features are all
694
+optional SVE vector lengths (see "SVE CPU Properties"). While with TCG
695
+all SVE vector lengths can be supported, when KVM is in use it's more
696
+likely that only a few lengths will be supported, if SVE is supported at
697
+all.)
698
699
(2) Let's try to disable the PMU::
700
701
(QEMU) query-cpu-model-expansion type=full model={"name":"max","props":{"pmu":false}}
702
{ "return": {
703
"model": { "name": "max", "props": {
704
- "pmu": false, "aarch64": true
705
+ "sve1664": true, "pmu": false, "sve1792": true, "sve1920": true,
706
+ "sve128": true, "aarch64": true, "sve1024": true, "sve": true,
707
+ "sve640": true, "sve768": true, "sve1408": true, "sve256": true,
708
+ "sve1152": true, "sve512": true, "sve384": true, "sve1536": true,
709
+ "sve896": true, "sve1280": true, "sve2048": true
710
}}}}
711
712
We see it worked, as `pmu` is now `false`.
713
@@ -XXX,XX +XXX,XX @@ We see it worked, as `pmu` is now `false`.
714
It looks like this feature is limited to a configuration we do not
715
currently have.
716
717
-(4) Let's try probing CPU features for the Cortex-A15 CPU type::
718
+(4) Let's disable `sve` and see what happens to all the optional SVE
719
+ vector lengths::
720
+
721
+ (QEMU) query-cpu-model-expansion type=full model={"name":"max","props":{"sve":false}}
722
+ { "return": {
723
+ "model": { "name": "max", "props": {
724
+ "sve1664": false, "pmu": true, "sve1792": false, "sve1920": false,
725
+ "sve128": false, "aarch64": true, "sve1024": false, "sve": false,
726
+ "sve640": false, "sve768": false, "sve1408": false, "sve256": false,
727
+ "sve1152": false, "sve512": false, "sve384": false, "sve1536": false,
728
+ "sve896": false, "sve1280": false, "sve2048": false
729
+ }}}}
730
+
731
+As expected they are now all `false`.
732
+
733
+(5) Let's try probing CPU features for the Cortex-A15 CPU type::
734
735
(QEMU) query-cpu-model-expansion type=full model={"name":"cortex-a15"}
736
{"return": {"model": {"name": "cortex-a15", "props": {"pmu": true}}}}
737
@@ -XXX,XX +XXX,XX @@ After determining which CPU features are available and supported for a
738
given CPU type, then they may be selectively enabled or disabled on the
739
QEMU command line with that CPU type::
740
741
- $ qemu-system-aarch64 -M virt -cpu max,pmu=off
742
+ $ qemu-system-aarch64 -M virt -cpu max,pmu=off,sve=on,sve128=on,sve256=on
743
744
-The example above disables the PMU for the `max` CPU type.
745
+The example above disables the PMU and enables the first two SVE vector
746
+lengths for the `max` CPU type. Note, the `sve=on` isn't actually
747
+necessary, because, as we observed above with our probe of the `max` CPU
748
+type, `sve` is already on by default. Also, based on our probe of
749
+defaults, it would seem we need to disable many SVE vector lengths, rather
750
+than only enabling the two we want. This isn't the case, because, as
751
+disabling many SVE vector lengths would be quite verbose, the `sve<N>` CPU
752
+properties have special semantics (see "SVE CPU Property Parsing
753
+Semantics").
754
+
755
+SVE CPU Properties
756
+==================
757
+
758
+There are two types of SVE CPU properties: `sve` and `sve<N>`. The first
759
+is used to enable or disable the entire SVE feature, just as the `pmu`
760
+CPU property completely enables or disables the PMU. The second type
761
+is used to enable or disable specific vector lengths, where `N` is the
762
+number of bits of the length. The `sve<N>` CPU properties have special
763
+dependencies and constraints, see "SVE CPU Property Dependencies and
764
+Constraints" below. Additionally, as we want all supported vector lengths
765
+to be enabled by default, then, in order to avoid overly verbose command
766
+lines (command lines full of `sve<N>=off`, for all `N` not wanted), we
767
+provide the parsing semantics listed in "SVE CPU Property Parsing
768
+Semantics".
769
+
770
+SVE CPU Property Dependencies and Constraints
771
+---------------------------------------------
772
+
773
+ 1) At least one vector length must be enabled when `sve` is enabled.
774
+
775
+ 2) If a vector length `N` is enabled, then all power-of-two vector
776
+ lengths smaller than `N` must also be enabled. E.g. if `sve512`
777
+ is enabled, then the 128-bit and 256-bit vector lengths must also
778
+ be enabled.
779
+
780
+SVE CPU Property Parsing Semantics
781
+----------------------------------
782
+
783
+ 1) If SVE is disabled (`sve=off`), then which SVE vector lengths
784
+ are enabled or disabled is irrelevant to the guest, as the entire
785
+ SVE feature is disabled and that disables all vector lengths for
786
+ the guest. However QEMU will still track any `sve<N>` CPU
787
+ properties provided by the user. If later an `sve=on` is provided,
788
+ then the guest will get only the enabled lengths. If no `sve=on`
789
+ is provided and there are explicitly enabled vector lengths, then
790
+ an error is generated.
791
+
792
+ 2) If SVE is enabled (`sve=on`), but no `sve<N>` CPU properties are
793
+ provided, then all supported vector lengths are enabled, including
794
+ the non-power-of-two lengths.
795
+
796
+ 3) If SVE is enabled, then an error is generated when attempting to
797
+ disable the last enabled vector length (see constraint (1) of "SVE
798
+ CPU Property Dependencies and Constraints").
799
+
800
+ 4) If one or more vector lengths have been explicitly enabled and at
801
+ at least one of the dependency lengths of the maximum enabled length
802
+ has been explicitly disabled, then an error is generated (see
803
+ constraint (2) of "SVE CPU Property Dependencies and Constraints").
804
+
805
+ 5) If one or more `sve<N>` CPU properties are set `off`, but no `sve<N>`,
806
+ CPU properties are set `on`, then the specified vector lengths are
807
+ disabled but the default for any unspecified lengths remains enabled.
808
+ Disabling a power-of-two vector length also disables all vector
809
+ lengths larger than the power-of-two length (see constraint (2) of
810
+ "SVE CPU Property Dependencies and Constraints").
811
+
812
+ 6) If one or more `sve<N>` CPU properties are set to `on`, then they
813
+ are enabled and all unspecified lengths default to disabled, except
814
+ for the required lengths per constraint (2) of "SVE CPU Property
815
+ Dependencies and Constraints", which will even be auto-enabled if
816
+ they were not explicitly enabled.
817
+
818
+ 7) If SVE was disabled (`sve=off`), allowing all vector lengths to be
819
+ explicitly disabled (i.e. avoiding the error specified in (3) of
820
+ "SVE CPU Property Parsing Semantics"), then if later an `sve=on` is
821
+ provided an error will be generated. To avoid this error, one must
822
+ enable at least one vector length prior to enabling SVE.
823
+
824
+SVE CPU Property Examples
825
+-------------------------
826
+
827
+ 1) Disable SVE::
828
+
829
+ $ qemu-system-aarch64 -M virt -cpu max,sve=off
830
+
831
+ 2) Implicitly enable all vector lengths for the `max` CPU type::
832
+
833
+ $ qemu-system-aarch64 -M virt -cpu max
834
+
835
+ 3) Only enable the 128-bit vector length::
836
+
837
+ $ qemu-system-aarch64 -M virt -cpu max,sve128=on
838
+
839
+ 4) Disable the 512-bit vector length and all larger vector lengths,
840
+ since 512 is a power-of-two. This results in all the smaller,
841
+ uninitialized lengths (128, 256, and 384) defaulting to enabled::
842
+
843
+ $ qemu-system-aarch64 -M virt -cpu max,sve512=off
844
+
845
+ 5) Enable the 128-bit, 256-bit, and 512-bit vector lengths::
846
+
847
+ $ qemu-system-aarch64 -M virt -cpu max,sve128=on,sve256=on,sve512=on
848
+
849
+ 6) The same as (5), but since the 128-bit and 256-bit vector
850
+ lengths are required for the 512-bit vector length to be enabled,
851
+ then allow them to be auto-enabled::
852
+
853
+ $ qemu-system-aarch64 -M virt -cpu max,sve512=on
854
+
855
+ 7) Do the same as (6), but by first disabling SVE and then re-enabling it::
856
+
857
+ $ qemu-system-aarch64 -M virt -cpu max,sve=off,sve512=on,sve=on
858
+
859
+ 8) Force errors regarding the last vector length::
860
+
861
+ $ qemu-system-aarch64 -M virt -cpu max,sve128=off
862
+ $ qemu-system-aarch64 -M virt -cpu max,sve=off,sve128=off,sve=on
863
+
864
+SVE CPU Property Recommendations
865
+--------------------------------
866
+
867
+The examples in "SVE CPU Property Examples" exhibit many ways to select
868
+vector lengths which developers may find useful in order to avoid overly
869
+verbose command lines. However, the recommended way to select vector
870
+lengths is to explicitly enable each desired length. Therefore only
871
+example's (1), (3), and (5) exhibit recommended uses of the properties.
872
873
--
220
--
874
2.20.1
221
2.20.1
875
222
876
223
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Continue setting, but not relying upon, env->hflags.
3
These bits become writable with the ARMv8.3-PAuth extension.
4
4
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20191023150057.25731-20-richard.henderson@linaro.org
6
Message-id: 20190129143511.12311-1-richard.henderson@linaro.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
9
---
9
target/arm/helper.c | 10 ++++++++++
10
target/arm/helper.c | 6 ++++++
10
1 file changed, 10 insertions(+)
11
1 file changed, 6 insertions(+)
11
12
12
diff --git a/target/arm/helper.c b/target/arm/helper.c
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
13
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/helper.c
15
--- a/target/arm/helper.c
15
+++ b/target/arm/helper.c
16
+++ b/target/arm/helper.c
16
@@ -XXX,XX +XXX,XX @@ static void sctlr_write(CPUARMState *env, const ARMCPRegInfo *ri,
17
@@ -XXX,XX +XXX,XX @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
17
/* ??? Lots of these bits are not implemented. */
18
if (cpu_isar_feature(aa64_lor, cpu)) {
18
/* This may enable/disable the MMU, so do a TLB flush. */
19
valid_mask |= SCR_TLOR;
19
tlb_flush(CPU(cpu));
20
}
20
+
21
+ if (cpu_isar_feature(aa64_pauth, cpu)) {
21
+ if (ri->type & ARM_CP_SUPPRESS_TB_END) {
22
+ valid_mask |= SCR_API | SCR_APK;
22
+ /*
23
+ * Normally we would always end the TB on an SCTLR write; see the
24
+ * comment in ARMCPRegInfo sctlr initialization below for why Xscale
25
+ * is special. Setting ARM_CP_SUPPRESS_TB_END also stops the rebuild
26
+ * of hflags from the translator, so do it here.
27
+ */
28
+ arm_rebuild_hflags(env);
29
+ }
23
+ }
30
}
24
31
25
/* Clear all-context RES0 bits. */
32
static CPAccessResult fpexc32_access(CPUARMState *env, const ARMCPRegInfo *ri,
26
value &= valid_mask;
27
@@ -XXX,XX +XXX,XX @@ static void hcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
28
if (cpu_isar_feature(aa64_lor, cpu)) {
29
valid_mask |= HCR_TLOR;
30
}
31
+ if (cpu_isar_feature(aa64_pauth, cpu)) {
32
+ valid_mask |= HCR_API | HCR_APK;
33
+ }
34
35
/* Clear RES0 bits. */
36
value &= valid_mask;
33
--
37
--
34
2.20.1
38
2.20.1
35
39
36
40
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
1
From: Julia Suvorova <jusual@mail.ru>
2
2
3
Allow cpu 'host' to enable SVE when it's available, unless the
3
Until now, the set_pc logic was unclear, which raised questions about
4
user chooses to disable it with the added 'sve=off' cpu property.
4
whether it should be used directly, applying a value to PC or adding
5
Also give the user the ability to select vector lengths with the
5
additional checks, for example, set the Thumb bit in Arm cpu. Let's set
6
sve<N> properties. We don't adopt 'max' cpu's other sve property,
6
the set_pc logic for “Configure the PC, as was done in the ELF file”
7
sve-max-vq, because that property is difficult to use with KVM.
7
and implement synchronize_with_tb hook for preserving PC to cpu_tb_exec.
8
That property assumes all vector lengths in the range from 1 up
9
to and including the specified maximum length are supported, but
10
there may be optional lengths not supported by the host in that
11
range. With KVM one must be more specific when enabling vector
12
lengths.
13
8
14
Signed-off-by: Andrew Jones <drjones@redhat.com>
9
Signed-off-by: Julia Suvorova <jusual@mail.ru>
15
Reviewed-by: Eric Auger <eric.auger@redhat.com>
10
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20190129121817.7109-1-jusual@mail.ru
17
Tested-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
18
Message-id: 20191024121808.9612-10-drjones@redhat.com
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
---
14
---
21
target/arm/cpu.h | 2 ++
15
include/qom/cpu.h | 16 ++++++++++++++--
22
target/arm/cpu.c | 3 +++
16
hw/arm/boot.c | 4 ----
23
target/arm/cpu64.c | 33 +++++++++++++++++----------------
17
target/arm/arm-powerctl.c | 3 ---
24
target/arm/kvm64.c | 14 +++++++++++++-
18
target/arm/cpu.c | 26 +++++++++++++++++++++++++-
25
tests/arm-cpu-features.c | 23 +++++++++++------------
19
target/arm/cpu64.c | 15 ---------------
26
docs/arm-cpu-features.rst | 19 ++++++++++++-------
20
5 files changed, 39 insertions(+), 25 deletions(-)
27
6 files changed, 58 insertions(+), 36 deletions(-)
28
21
29
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
22
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
30
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/cpu.h
24
--- a/include/qom/cpu.h
32
+++ b/target/arm/cpu.h
25
+++ b/include/qom/cpu.h
33
@@ -XXX,XX +XXX,XX @@ int aarch64_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
26
@@ -XXX,XX +XXX,XX @@ struct TranslationBlock;
34
void aarch64_sve_narrow_vq(CPUARMState *env, unsigned vq);
27
* @get_arch_id: Callback for getting architecture-dependent CPU ID.
35
void aarch64_sve_change_el(CPUARMState *env, int old_el,
28
* @get_paging_enabled: Callback for inquiring whether paging is enabled.
36
int new_el, bool el0_a64);
29
* @get_memory_mapping: Callback for obtaining the memory mappings.
37
+void aarch64_add_sve_properties(Object *obj);
30
- * @set_pc: Callback for setting the Program Counter register.
38
#else
31
+ * @set_pc: Callback for setting the Program Counter register. This
39
static inline void aarch64_sve_narrow_vq(CPUARMState *env, unsigned vq) { }
32
+ * should have the semantics used by the target architecture when
40
static inline void aarch64_sve_change_el(CPUARMState *env, int o,
33
+ * setting the PC from a source such as an ELF file entry point;
41
int n, bool a)
34
+ * for example on Arm it will also set the Thumb mode bit based
42
{ }
35
+ * on the least significant bit of the new PC value.
43
+static inline void aarch64_add_sve_properties(Object *obj) { }
36
+ * If the target behaviour here is anything other than "set
44
#endif
37
+ * the PC register to the value passed in" then the target must
45
38
+ * also implement the synchronize_from_tb hook.
46
#if !defined(CONFIG_TCG)
39
* @synchronize_from_tb: Callback for synchronizing state from a TCG
40
- * #TranslationBlock.
41
+ * #TranslationBlock. This is called when we abandon execution
42
+ * of a TB before starting it, and must set all parts of the CPU
43
+ * state which the previous TB in the chain may not have updated.
44
+ * This always includes at least the program counter; some targets
45
+ * will need to do more. If this hook is not implemented then the
46
+ * default is to call @set_pc(tb->pc).
47
* @handle_mmu_fault: Callback for handling an MMU fault.
48
* @get_phys_page_debug: Callback for obtaining a physical address.
49
* @get_phys_page_attrs_debug: Callback for obtaining a physical address and the
50
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
51
index XXXXXXX..XXXXXXX 100644
52
--- a/hw/arm/boot.c
53
+++ b/hw/arm/boot.c
54
@@ -XXX,XX +XXX,XX @@ static void do_cpu_reset(void *opaque)
55
g_assert_not_reached();
56
}
57
58
- if (!env->aarch64) {
59
- env->thumb = info->entry & 1;
60
- entry &= 0xfffffffe;
61
- }
62
cpu_set_pc(cs, entry);
63
} else {
64
/* If we are booting Linux then we need to check whether we are
65
diff --git a/target/arm/arm-powerctl.c b/target/arm/arm-powerctl.c
66
index XXXXXXX..XXXXXXX 100644
67
--- a/target/arm/arm-powerctl.c
68
+++ b/target/arm/arm-powerctl.c
69
@@ -XXX,XX +XXX,XX @@ static void arm_set_cpu_on_async_work(CPUState *target_cpu_state,
70
71
if (info->target_aa64) {
72
target_cpu->env.xregs[0] = info->context_id;
73
- target_cpu->env.thumb = false;
74
} else {
75
target_cpu->env.regs[0] = info->context_id;
76
- target_cpu->env.thumb = info->entry & 1;
77
- info->entry &= 0xfffffffe;
78
}
79
80
/* Start the new CPU at the requested address */
47
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
81
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
48
index XXXXXXX..XXXXXXX 100644
82
index XXXXXXX..XXXXXXX 100644
49
--- a/target/arm/cpu.c
83
--- a/target/arm/cpu.c
50
+++ b/target/arm/cpu.c
84
+++ b/target/arm/cpu.c
51
@@ -XXX,XX +XXX,XX @@ static void arm_host_initfn(Object *obj)
85
@@ -XXX,XX +XXX,XX @@
52
ARMCPU *cpu = ARM_CPU(obj);
86
static void arm_cpu_set_pc(CPUState *cs, vaddr value)
53
87
{
54
kvm_arm_set_cpu_features_from_host(cpu);
88
ARMCPU *cpu = ARM_CPU(cs);
55
+ if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
89
+ CPUARMState *env = &cpu->env;
56
+ aarch64_add_sve_properties(obj);
90
91
- cpu->env.regs[15] = value;
92
+ if (is_a64(env)) {
93
+ env->pc = value;
94
+ env->thumb = 0;
95
+ } else {
96
+ env->regs[15] = value & ~1;
97
+ env->thumb = value & 1;
57
+ }
98
+ }
58
arm_cpu_post_init(obj);
99
+}
100
+
101
+static void arm_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
102
+{
103
+ ARMCPU *cpu = ARM_CPU(cs);
104
+ CPUARMState *env = &cpu->env;
105
+
106
+ /*
107
+ * It's OK to look at env for the current mode here, because it's
108
+ * never possible for an AArch64 TB to chain to an AArch32 TB.
109
+ */
110
+ if (is_a64(env)) {
111
+ env->pc = tb->pc;
112
+ } else {
113
+ env->regs[15] = tb->pc;
114
+ }
59
}
115
}
60
116
117
static bool arm_cpu_has_work(CPUState *cs)
118
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
119
cc->cpu_exec_interrupt = arm_cpu_exec_interrupt;
120
cc->dump_state = arm_cpu_dump_state;
121
cc->set_pc = arm_cpu_set_pc;
122
+ cc->synchronize_from_tb = arm_cpu_synchronize_from_tb;
123
cc->gdb_read_register = arm_cpu_gdb_read_register;
124
cc->gdb_write_register = arm_cpu_gdb_write_register;
125
#ifdef CONFIG_USER_ONLY
61
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
126
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
62
index XXXXXXX..XXXXXXX 100644
127
index XXXXXXX..XXXXXXX 100644
63
--- a/target/arm/cpu64.c
128
--- a/target/arm/cpu64.c
64
+++ b/target/arm/cpu64.c
129
+++ b/target/arm/cpu64.c
65
@@ -XXX,XX +XXX,XX @@ static void cpu_arm_set_sve(Object *obj, Visitor *v, const char *name,
130
@@ -XXX,XX +XXX,XX @@ static void aarch64_cpu_finalizefn(Object *obj)
66
cpu->isar.id_aa64pfr0 = t;
131
{
67
}
132
}
68
133
69
+void aarch64_add_sve_properties(Object *obj)
134
-static void aarch64_cpu_set_pc(CPUState *cs, vaddr value)
70
+{
135
-{
71
+ uint32_t vq;
136
- ARMCPU *cpu = ARM_CPU(cs);
72
+
137
- /* It's OK to look at env for the current mode here, because it's
73
+ object_property_add(obj, "sve", "bool", cpu_arm_get_sve,
138
- * never possible for an AArch64 TB to chain to an AArch32 TB.
74
+ cpu_arm_set_sve, NULL, NULL, &error_fatal);
139
- * (Otherwise we would need to use synchronize_from_tb instead.)
75
+
140
- */
76
+ for (vq = 1; vq <= ARM_MAX_VQ; ++vq) {
141
- if (is_a64(&cpu->env)) {
77
+ char name[8];
142
- cpu->env.pc = value;
78
+ sprintf(name, "sve%d", vq * 128);
143
- } else {
79
+ object_property_add(obj, name, "bool", cpu_arm_get_sve_vq,
144
- cpu->env.regs[15] = value;
80
+ cpu_arm_set_sve_vq, NULL, NULL, &error_fatal);
145
- }
81
+ }
146
-}
82
+}
147
-
83
+
148
static gchar *aarch64_gdb_arch_name(CPUState *cs)
84
/* -cpu max: if KVM is enabled, like -cpu host (best possible with this host);
85
* otherwise, a CPU with as many features enabled as our emulation supports.
86
* The version of '-cpu max' for qemu-system-arm is defined in cpu.c;
87
@@ -XXX,XX +XXX,XX @@ static void cpu_arm_set_sve(Object *obj, Visitor *v, const char *name,
88
static void aarch64_max_initfn(Object *obj)
89
{
149
{
90
ARMCPU *cpu = ARM_CPU(obj);
150
return g_strdup("aarch64");
91
- uint32_t vq;
151
@@ -XXX,XX +XXX,XX @@ static void aarch64_cpu_class_init(ObjectClass *oc, void *data)
92
- uint64_t t;
152
CPUClass *cc = CPU_CLASS(oc);
93
153
94
if (kvm_enabled()) {
154
cc->cpu_exec_interrupt = arm_cpu_exec_interrupt;
95
kvm_arm_set_cpu_features_from_host(cpu);
155
- cc->set_pc = aarch64_cpu_set_pc;
96
- if (kvm_arm_sve_supported(CPU(cpu))) {
156
cc->gdb_read_register = aarch64_cpu_gdb_read_register;
97
- t = cpu->isar.id_aa64pfr0;
157
cc->gdb_write_register = aarch64_cpu_gdb_write_register;
98
- t = FIELD_DP64(t, ID_AA64PFR0, SVE, 1);
158
cc->gdb_num_core_regs = 34;
99
- cpu->isar.id_aa64pfr0 = t;
100
- }
101
} else {
102
+ uint64_t t;
103
uint32_t u;
104
aarch64_a57_initfn(obj);
105
106
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
107
#endif
108
}
109
110
- object_property_add(obj, "sve", "bool", cpu_arm_get_sve,
111
- cpu_arm_set_sve, NULL, NULL, &error_fatal);
112
+ aarch64_add_sve_properties(obj);
113
object_property_add(obj, "sve-max-vq", "uint32", cpu_max_get_sve_max_vq,
114
cpu_max_set_sve_max_vq, NULL, NULL, &error_fatal);
115
-
116
- for (vq = 1; vq <= ARM_MAX_VQ; ++vq) {
117
- char name[8];
118
- sprintf(name, "sve%d", vq * 128);
119
- object_property_add(obj, name, "bool", cpu_arm_get_sve_vq,
120
- cpu_arm_set_sve_vq, NULL, NULL, &error_fatal);
121
- }
122
}
123
124
struct ARMCPUInfo {
125
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
126
index XXXXXXX..XXXXXXX 100644
127
--- a/target/arm/kvm64.c
128
+++ b/target/arm/kvm64.c
129
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
130
* and then query that CPU for the relevant ID registers.
131
*/
132
int fdarray[3];
133
+ bool sve_supported;
134
uint64_t features = 0;
135
+ uint64_t t;
136
int err;
137
138
/* Old kernels may not know about the PREFERRED_TARGET ioctl: however
139
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
140
ARM64_SYS_REG(3, 0, 0, 3, 2));
141
}
142
143
+ sve_supported = ioctl(fdarray[0], KVM_CHECK_EXTENSION, KVM_CAP_ARM_SVE) > 0;
144
+
145
kvm_arm_destroy_scratch_host_vcpu(fdarray);
146
147
if (err < 0) {
148
return false;
149
}
150
151
- /* We can assume any KVM supporting CPU is at least a v8
152
+ /* Add feature bits that can't appear until after VCPU init. */
153
+ if (sve_supported) {
154
+ t = ahcf->isar.id_aa64pfr0;
155
+ t = FIELD_DP64(t, ID_AA64PFR0, SVE, 1);
156
+ ahcf->isar.id_aa64pfr0 = t;
157
+ }
158
+
159
+ /*
160
+ * We can assume any KVM supporting CPU is at least a v8
161
* with VFPv4+Neon; this in turn implies most of the other
162
* feature bits.
163
*/
164
diff --git a/tests/arm-cpu-features.c b/tests/arm-cpu-features.c
165
index XXXXXXX..XXXXXXX 100644
166
--- a/tests/arm-cpu-features.c
167
+++ b/tests/arm-cpu-features.c
168
@@ -XXX,XX +XXX,XX @@ static void sve_tests_sve_off_kvm(const void *data)
169
{
170
QTestState *qts;
171
172
- qts = qtest_init(MACHINE "-accel kvm -cpu max,sve=off");
173
+ qts = qtest_init(MACHINE "-accel kvm -cpu host,sve=off");
174
175
/*
176
* We don't know if this host supports SVE so we don't
177
@@ -XXX,XX +XXX,XX @@ static void sve_tests_sve_off_kvm(const void *data)
178
* and that using sve<N>=off to explicitly disable vector
179
* lengths is OK too.
180
*/
181
- assert_sve_vls(qts, "max", 0, NULL);
182
- assert_sve_vls(qts, "max", 0, "{ 'sve128': false }");
183
+ assert_sve_vls(qts, "host", 0, NULL);
184
+ assert_sve_vls(qts, "host", 0, "{ 'sve128': false }");
185
186
qtest_quit(qts);
187
}
188
@@ -XXX,XX +XXX,XX @@ static void test_query_cpu_model_expansion_kvm(const void *data)
189
"We cannot guarantee the CPU type 'cortex-a15' works "
190
"with KVM on this host", NULL);
191
192
- assert_has_feature(qts, "max", "sve");
193
- resp = do_query_no_props(qts, "max");
194
+ assert_has_feature(qts, "host", "sve");
195
+ resp = do_query_no_props(qts, "host");
196
kvm_supports_sve = resp_get_feature(resp, "sve");
197
vls = resp_get_sve_vls(resp);
198
qobject_unref(resp);
199
@@ -XXX,XX +XXX,XX @@ static void test_query_cpu_model_expansion_kvm(const void *data)
200
sprintf(max_name, "sve%d", max_vq * 128);
201
202
/* Enabling a supported length is of course fine. */
203
- assert_sve_vls(qts, "max", vls, "{ %s: true }", max_name);
204
+ assert_sve_vls(qts, "host", vls, "{ %s: true }", max_name);
205
206
/* Get the next supported length smaller than max-vq. */
207
vq = 64 - __builtin_clzll(vls & ~BIT_ULL(max_vq - 1));
208
@@ -XXX,XX +XXX,XX @@ static void test_query_cpu_model_expansion_kvm(const void *data)
209
* We have at least one length smaller than max-vq,
210
* so we can disable max-vq.
211
*/
212
- assert_sve_vls(qts, "max", (vls & ~BIT_ULL(max_vq - 1)),
213
+ assert_sve_vls(qts, "host", (vls & ~BIT_ULL(max_vq - 1)),
214
"{ %s: false }", max_name);
215
216
/*
217
@@ -XXX,XX +XXX,XX @@ static void test_query_cpu_model_expansion_kvm(const void *data)
218
*/
219
sprintf(name, "sve%d", vq * 128);
220
error = g_strdup_printf("cannot disable %s", name);
221
- assert_error(qts, "max", error,
222
+ assert_error(qts, "host", error,
223
"{ %s: true, %s: false }",
224
max_name, name);
225
g_free(error);
226
@@ -XXX,XX +XXX,XX @@ static void test_query_cpu_model_expansion_kvm(const void *data)
227
vq = __builtin_ffsll(vls);
228
sprintf(name, "sve%d", vq * 128);
229
error = g_strdup_printf("cannot disable %s", name);
230
- assert_error(qts, "max", error, "{ %s: false }", name);
231
+ assert_error(qts, "host", error, "{ %s: false }", name);
232
g_free(error);
233
234
/* Get an unsupported length. */
235
@@ -XXX,XX +XXX,XX @@ static void test_query_cpu_model_expansion_kvm(const void *data)
236
if (vq <= SVE_MAX_VQ) {
237
sprintf(name, "sve%d", vq * 128);
238
error = g_strdup_printf("cannot enable %s", name);
239
- assert_error(qts, "max", error, "{ %s: true }", name);
240
+ assert_error(qts, "host", error, "{ %s: true }", name);
241
g_free(error);
242
}
243
} else {
244
@@ -XXX,XX +XXX,XX @@ static void test_query_cpu_model_expansion_kvm(const void *data)
245
} else {
246
assert_has_not_feature(qts, "host", "aarch64");
247
assert_has_not_feature(qts, "host", "pmu");
248
-
249
- assert_has_not_feature(qts, "max", "sve");
250
+ assert_has_not_feature(qts, "host", "sve");
251
}
252
253
qtest_quit(qts);
254
diff --git a/docs/arm-cpu-features.rst b/docs/arm-cpu-features.rst
255
index XXXXXXX..XXXXXXX 100644
256
--- a/docs/arm-cpu-features.rst
257
+++ b/docs/arm-cpu-features.rst
258
@@ -XXX,XX +XXX,XX @@ SVE CPU Property Examples
259
260
$ qemu-system-aarch64 -M virt -cpu max
261
262
- 3) Only enable the 128-bit vector length::
263
+ 3) When KVM is enabled, implicitly enable all host CPU supported vector
264
+ lengths with the `host` CPU type::
265
+
266
+ $ qemu-system-aarch64 -M virt,accel=kvm -cpu host
267
+
268
+ 4) Only enable the 128-bit vector length::
269
270
$ qemu-system-aarch64 -M virt -cpu max,sve128=on
271
272
- 4) Disable the 512-bit vector length and all larger vector lengths,
273
+ 5) Disable the 512-bit vector length and all larger vector lengths,
274
since 512 is a power-of-two. This results in all the smaller,
275
uninitialized lengths (128, 256, and 384) defaulting to enabled::
276
277
$ qemu-system-aarch64 -M virt -cpu max,sve512=off
278
279
- 5) Enable the 128-bit, 256-bit, and 512-bit vector lengths::
280
+ 6) Enable the 128-bit, 256-bit, and 512-bit vector lengths::
281
282
$ qemu-system-aarch64 -M virt -cpu max,sve128=on,sve256=on,sve512=on
283
284
- 6) The same as (5), but since the 128-bit and 256-bit vector
285
+ 7) The same as (6), but since the 128-bit and 256-bit vector
286
lengths are required for the 512-bit vector length to be enabled,
287
then allow them to be auto-enabled::
288
289
$ qemu-system-aarch64 -M virt -cpu max,sve512=on
290
291
- 7) Do the same as (6), but by first disabling SVE and then re-enabling it::
292
+ 8) Do the same as (7), but by first disabling SVE and then re-enabling it::
293
294
$ qemu-system-aarch64 -M virt -cpu max,sve=off,sve512=on,sve=on
295
296
- 8) Force errors regarding the last vector length::
297
+ 9) Force errors regarding the last vector length::
298
299
$ qemu-system-aarch64 -M virt -cpu max,sve128=off
300
$ qemu-system-aarch64 -M virt -cpu max,sve=off,sve128=off,sve=on
301
@@ -XXX,XX +XXX,XX @@ The examples in "SVE CPU Property Examples" exhibit many ways to select
302
vector lengths which developers may find useful in order to avoid overly
303
verbose command lines. However, the recommended way to select vector
304
lengths is to explicitly enable each desired length. Therefore only
305
-example's (1), (3), and (5) exhibit recommended uses of the properties.
306
+example's (1), (4), and (6) exhibit recommended uses of the properties.
307
308
--
159
--
309
2.20.1
160
2.20.1
310
161
311
162
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Since 97a28b0eeac14 ("target/arm: Allow VFP and Neon to be disabled via
3
Drop the pac properties. This approach cannot work as written
4
a CPU property") we can disable the 'max' cpu model's VFP and neon
4
because the properties are applied before arm_cpu_reset, which
5
features, but there's no way to disable SVE. Add the 'sve=on|off'
5
zeros SCTLR_EL1 (amongst everything else).
6
property to give it that flexibility. We also rename
7
cpu_max_get/set_sve_vq to cpu_max_get/set_sve_max_vq in order for them
8
to follow the typical *_get/set_<property-name> pattern.
9
6
10
Signed-off-by: Andrew Jones <drjones@redhat.com>
7
We can re-introduce the properties if they turn out to be useful.
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
But since linux 5.0 enables all of the keys, they may not be.
12
Reviewed-by: Eric Auger <eric.auger@redhat.com>
9
13
Tested-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
10
Fixes: 1ae9cfbd470
14
Reviewed-by: Beata Michalska <beata.michalska@linaro.org>
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20191024121808.9612-4-drjones@redhat.com
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
14
---
18
target/arm/cpu.c | 3 ++-
15
target/arm/cpu.c | 3 +++
19
target/arm/cpu64.c | 52 ++++++++++++++++++++++++++++++++++------
16
target/arm/cpu64.c | 60 ----------------------------------------------
20
target/arm/monitor.c | 2 +-
17
2 files changed, 3 insertions(+), 60 deletions(-)
21
tests/arm-cpu-features.c | 1 +
22
4 files changed, 49 insertions(+), 9 deletions(-)
23
18
24
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
19
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
25
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/cpu.c
21
--- a/target/arm/cpu.c
27
+++ b/target/arm/cpu.c
22
+++ b/target/arm/cpu.c
28
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
23
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
29
env->cp15.cpacr_el1 = deposit64(env->cp15.cpacr_el1, 16, 2, 3);
24
env->pstate = PSTATE_MODE_EL0t;
30
env->cp15.cptr_el[3] |= CPTR_EZ;
25
/* Userspace expects access to DC ZVA, CTL_EL0 and the cache ops */
31
/* with maximum vector length */
26
env->cp15.sctlr_el[1] |= SCTLR_UCT | SCTLR_UCI | SCTLR_DZE;
32
- env->vfp.zcr_el[1] = cpu->sve_max_vq - 1;
27
+ /* Enable all PAC keys. */
33
+ env->vfp.zcr_el[1] = cpu_isar_feature(aa64_sve, cpu) ?
28
+ env->cp15.sctlr_el[1] |= (SCTLR_EnIA | SCTLR_EnIB |
34
+ cpu->sve_max_vq - 1 : 0;
29
+ SCTLR_EnDA | SCTLR_EnDB);
35
env->vfp.zcr_el[2] = env->vfp.zcr_el[1];
30
/* Enable all PAC instructions */
36
env->vfp.zcr_el[3] = env->vfp.zcr_el[1];
31
env->cp15.hcr_el2 |= HCR_API;
37
/*
32
env->cp15.scr_el3 |= SCR_API;
38
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
33
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
39
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
40
--- a/target/arm/cpu64.c
35
--- a/target/arm/cpu64.c
41
+++ b/target/arm/cpu64.c
36
+++ b/target/arm/cpu64.c
42
@@ -XXX,XX +XXX,XX @@ static void aarch64_a72_initfn(Object *obj)
43
define_arm_cp_regs(cpu, cortex_a72_a57_a53_cp_reginfo);
44
}
45
46
-static void cpu_max_get_sve_vq(Object *obj, Visitor *v, const char *name,
47
- void *opaque, Error **errp)
48
+static void cpu_max_get_sve_max_vq(Object *obj, Visitor *v, const char *name,
49
+ void *opaque, Error **errp)
50
{
51
ARMCPU *cpu = ARM_CPU(obj);
52
- visit_type_uint32(v, name, &cpu->sve_max_vq, errp);
53
+ uint32_t value;
54
+
55
+ /* All vector lengths are disabled when SVE is off. */
56
+ if (!cpu_isar_feature(aa64_sve, cpu)) {
57
+ value = 0;
58
+ } else {
59
+ value = cpu->sve_max_vq;
60
+ }
61
+ visit_type_uint32(v, name, &value, errp);
62
}
63
64
-static void cpu_max_set_sve_vq(Object *obj, Visitor *v, const char *name,
65
- void *opaque, Error **errp)
66
+static void cpu_max_set_sve_max_vq(Object *obj, Visitor *v, const char *name,
67
+ void *opaque, Error **errp)
68
{
69
ARMCPU *cpu = ARM_CPU(obj);
70
Error *err = NULL;
71
@@ -XXX,XX +XXX,XX @@ static void cpu_max_set_sve_vq(Object *obj, Visitor *v, const char *name,
37
@@ -XXX,XX +XXX,XX @@ static void cpu_max_set_sve_vq(Object *obj, Visitor *v, const char *name,
72
error_propagate(errp, err);
38
error_propagate(errp, err);
73
}
39
}
74
40
75
+static void cpu_arm_get_sve(Object *obj, Visitor *v, const char *name,
41
-#ifdef CONFIG_USER_ONLY
76
+ void *opaque, Error **errp)
42
-static void cpu_max_get_packey(Object *obj, Visitor *v, const char *name,
77
+{
43
- void *opaque, Error **errp)
78
+ ARMCPU *cpu = ARM_CPU(obj);
44
-{
79
+ bool value = cpu_isar_feature(aa64_sve, cpu);
45
- ARMCPU *cpu = ARM_CPU(obj);
80
+
46
- const uint64_t *bit = opaque;
81
+ visit_type_bool(v, name, &value, errp);
47
- bool enabled = (cpu->env.cp15.sctlr_el[1] & *bit) != 0;
82
+}
48
-
83
+
49
- visit_type_bool(v, name, &enabled, errp);
84
+static void cpu_arm_set_sve(Object *obj, Visitor *v, const char *name,
50
-}
85
+ void *opaque, Error **errp)
51
-
86
+{
52
-static void cpu_max_set_packey(Object *obj, Visitor *v, const char *name,
87
+ ARMCPU *cpu = ARM_CPU(obj);
53
- void *opaque, Error **errp)
88
+ Error *err = NULL;
54
-{
89
+ bool value;
55
- ARMCPU *cpu = ARM_CPU(obj);
90
+ uint64_t t;
56
- Error *err = NULL;
91
+
57
- const uint64_t *bit = opaque;
92
+ visit_type_bool(v, name, &value, &err);
58
- bool enabled;
93
+ if (err) {
59
-
94
+ error_propagate(errp, err);
60
- visit_type_bool(v, name, &enabled, errp);
95
+ return;
61
-
96
+ }
62
- if (!err) {
97
+
63
- if (enabled) {
98
+ t = cpu->isar.id_aa64pfr0;
64
- cpu->env.cp15.sctlr_el[1] |= *bit;
99
+ t = FIELD_DP64(t, ID_AA64PFR0, SVE, value);
65
- } else {
100
+ cpu->isar.id_aa64pfr0 = t;
66
- cpu->env.cp15.sctlr_el[1] &= ~*bit;
101
+}
67
- }
102
+
68
- }
69
- error_propagate(errp, err);
70
-}
71
-#endif
72
-
103
/* -cpu max: if KVM is enabled, like -cpu host (best possible with this host);
73
/* -cpu max: if KVM is enabled, like -cpu host (best possible with this host);
104
* otherwise, a CPU with as many features enabled as our emulation supports.
74
* otherwise, a CPU with as many features enabled as our emulation supports.
105
* The version of '-cpu max' for qemu-system-arm is defined in cpu.c;
75
* The version of '-cpu max' for qemu-system-arm is defined in cpu.c;
106
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
76
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
77
*/
78
cpu->ctr = 0x80038003; /* 32 byte I and D cacheline size, VIPT icache */
79
cpu->dcz_blocksize = 7; /* 512 bytes */
80
-
81
- /*
82
- * Note that Linux will enable enable all of the keys at once.
83
- * But doing it this way will allow experimentation beyond that.
84
- */
85
- {
86
- static const uint64_t apia_bit = SCTLR_EnIA;
87
- static const uint64_t apib_bit = SCTLR_EnIB;
88
- static const uint64_t apda_bit = SCTLR_EnDA;
89
- static const uint64_t apdb_bit = SCTLR_EnDB;
90
-
91
- object_property_add(obj, "apia", "bool", cpu_max_get_packey,
92
- cpu_max_set_packey, NULL,
93
- (void *)&apia_bit, &error_fatal);
94
- object_property_add(obj, "apib", "bool", cpu_max_get_packey,
95
- cpu_max_set_packey, NULL,
96
- (void *)&apib_bit, &error_fatal);
97
- object_property_add(obj, "apda", "bool", cpu_max_get_packey,
98
- cpu_max_set_packey, NULL,
99
- (void *)&apda_bit, &error_fatal);
100
- object_property_add(obj, "apdb", "bool", cpu_max_get_packey,
101
- cpu_max_set_packey, NULL,
102
- (void *)&apdb_bit, &error_fatal);
103
-
104
- /* Enable all PAC keys by default. */
105
- cpu->env.cp15.sctlr_el[1] |= SCTLR_EnIA | SCTLR_EnIB;
106
- cpu->env.cp15.sctlr_el[1] |= SCTLR_EnDA | SCTLR_EnDB;
107
- }
107
#endif
108
#endif
108
109
109
cpu->sve_max_vq = ARM_MAX_VQ;
110
cpu->sve_max_vq = ARM_MAX_VQ;
110
- object_property_add(obj, "sve-max-vq", "uint32", cpu_max_get_sve_vq,
111
- cpu_max_set_sve_vq, NULL, NULL, &error_fatal);
112
+ object_property_add(obj, "sve-max-vq", "uint32", cpu_max_get_sve_max_vq,
113
+ cpu_max_set_sve_max_vq, NULL, NULL, &error_fatal);
114
+ object_property_add(obj, "sve", "bool", cpu_arm_get_sve,
115
+ cpu_arm_set_sve, NULL, NULL, &error_fatal);
116
}
117
}
118
119
diff --git a/target/arm/monitor.c b/target/arm/monitor.c
120
index XXXXXXX..XXXXXXX 100644
121
--- a/target/arm/monitor.c
122
+++ b/target/arm/monitor.c
123
@@ -XXX,XX +XXX,XX @@ GICCapabilityList *qmp_query_gic_capabilities(Error **errp)
124
* then the order that considers those dependencies must be used.
125
*/
126
static const char *cpu_model_advertised_features[] = {
127
- "aarch64", "pmu",
128
+ "aarch64", "pmu", "sve",
129
NULL
130
};
131
132
diff --git a/tests/arm-cpu-features.c b/tests/arm-cpu-features.c
133
index XXXXXXX..XXXXXXX 100644
134
--- a/tests/arm-cpu-features.c
135
+++ b/tests/arm-cpu-features.c
136
@@ -XXX,XX +XXX,XX @@ static void test_query_cpu_model_expansion(const void *data)
137
138
if (g_str_equal(qtest_get_arch(), "aarch64")) {
139
assert_has_feature(qts, "max", "aarch64");
140
+ assert_has_feature(qts, "max", "sve");
141
assert_has_feature(qts, "cortex-a57", "pmu");
142
assert_has_feature(qts, "cortex-a57", "aarch64");
143
144
--
111
--
145
2.20.1
112
2.20.1
146
113
147
114
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This functions are given the mode and el state of the cpu
4
and writes the computed value to env->hflags.
5
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20191023150057.25731-16-richard.henderson@linaro.org
4
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
6
---
11
target/arm/helper.h | 4 ++++
7
linux-user/elfload.c | 9 +++++++++
12
target/arm/helper.c | 24 ++++++++++++++++++++++++
8
1 file changed, 9 insertions(+)
13
2 files changed, 28 insertions(+)
14
9
15
diff --git a/target/arm/helper.h b/target/arm/helper.h
10
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
16
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.h
12
--- a/linux-user/elfload.c
18
+++ b/target/arm/helper.h
13
+++ b/linux-user/elfload.c
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_4(msr_banked, void, env, i32, i32, i32)
14
@@ -XXX,XX +XXX,XX @@ enum {
20
DEF_HELPER_2(get_user_reg, i32, env, i32)
15
ARM_HWCAP_A64_ASIMDDP = 1 << 20,
21
DEF_HELPER_3(set_user_reg, void, env, i32, i32)
16
ARM_HWCAP_A64_SHA512 = 1 << 21,
22
17
ARM_HWCAP_A64_SVE = 1 << 22,
23
+DEF_HELPER_FLAGS_2(rebuild_hflags_m32, TCG_CALL_NO_RWG, void, env, int)
18
+ ARM_HWCAP_A64_ASIMDFHM = 1 << 23,
24
+DEF_HELPER_FLAGS_2(rebuild_hflags_a32, TCG_CALL_NO_RWG, void, env, int)
19
+ ARM_HWCAP_A64_DIT = 1 << 24,
25
+DEF_HELPER_FLAGS_2(rebuild_hflags_a64, TCG_CALL_NO_RWG, void, env, int)
20
+ ARM_HWCAP_A64_USCAT = 1 << 25,
26
+
21
+ ARM_HWCAP_A64_ILRCPC = 1 << 26,
27
DEF_HELPER_1(vfp_get_fpscr, i32, env)
22
+ ARM_HWCAP_A64_FLAGM = 1 << 27,
28
DEF_HELPER_2(vfp_set_fpscr, void, env, i32)
23
+ ARM_HWCAP_A64_SSBS = 1 << 28,
29
24
+ ARM_HWCAP_A64_SB = 1 << 29,
30
diff --git a/target/arm/helper.c b/target/arm/helper.c
25
+ ARM_HWCAP_A64_PACA = 1 << 30,
31
index XXXXXXX..XXXXXXX 100644
26
+ ARM_HWCAP_A64_PACG = 1UL << 31,
32
--- a/target/arm/helper.c
27
};
33
+++ b/target/arm/helper.c
28
34
@@ -XXX,XX +XXX,XX @@ void arm_rebuild_hflags(CPUARMState *env)
29
#define ELF_HWCAP get_elf_hwcap()
35
env->hflags = rebuild_hflags_internal(env);
36
}
37
38
+void HELPER(rebuild_hflags_m32)(CPUARMState *env, int el)
39
+{
40
+ int fp_el = fp_exception_el(env, el);
41
+ ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el);
42
+
43
+ env->hflags = rebuild_hflags_m32(env, fp_el, mmu_idx);
44
+}
45
+
46
+void HELPER(rebuild_hflags_a32)(CPUARMState *env, int el)
47
+{
48
+ int fp_el = fp_exception_el(env, el);
49
+ ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el);
50
+
51
+ env->hflags = rebuild_hflags_a32(env, fp_el, mmu_idx);
52
+}
53
+
54
+void HELPER(rebuild_hflags_a64)(CPUARMState *env, int el)
55
+{
56
+ int fp_el = fp_exception_el(env, el);
57
+ ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el);
58
+
59
+ env->hflags = rebuild_hflags_a64(env, el, fp_el, mmu_idx);
60
+}
61
+
62
void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
63
target_ulong *cs_base, uint32_t *pflags)
64
{
65
--
30
--
66
2.20.1
31
2.20.1
67
32
68
33
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Continue setting, but not relying upon, env->hflags.
4
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20191023150057.25731-24-richard.henderson@linaro.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
6
---
10
linux-user/arm/cpu_loop.c | 1 +
7
linux-user/elfload.c | 1 +
11
1 file changed, 1 insertion(+)
8
1 file changed, 1 insertion(+)
12
9
13
diff --git a/linux-user/arm/cpu_loop.c b/linux-user/arm/cpu_loop.c
10
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
14
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
15
--- a/linux-user/arm/cpu_loop.c
12
--- a/linux-user/elfload.c
16
+++ b/linux-user/arm/cpu_loop.c
13
+++ b/linux-user/elfload.c
17
@@ -XXX,XX +XXX,XX @@ void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
14
@@ -XXX,XX +XXX,XX @@ static uint32_t get_elf_hwcap(void)
18
} else {
15
GET_FEATURE_ID(aa64_dp, ARM_HWCAP_A64_ASIMDDP);
19
env->cp15.sctlr_el[1] |= SCTLR_B;
16
GET_FEATURE_ID(aa64_fcma, ARM_HWCAP_A64_FCMA);
20
}
17
GET_FEATURE_ID(aa64_sve, ARM_HWCAP_A64_SVE);
21
+ arm_rebuild_hflags(env);
18
+ GET_FEATURE_ID(aa64_pauth, ARM_HWCAP_A64_PACA | ARM_HWCAP_A64_PACG);
22
#endif
19
23
20
#undef GET_FEATURE_ID
24
ts->stack_base = info->start_stack;
21
25
--
22
--
26
2.20.1
23
2.20.1
27
24
28
25
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Continue setting, but not relying upon, env->hflags.
3
Initialize the keys to a non-zero value on process start.
4
4
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20191023150057.25731-23-richard.henderson@linaro.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
8
---
10
linux-user/aarch64/cpu_loop.c | 1 +
9
linux-user/aarch64/target_syscall.h | 2 ++
11
1 file changed, 1 insertion(+)
10
linux-user/aarch64/cpu_loop.c | 31 +++++++++++++++++++++++++++--
11
2 files changed, 31 insertions(+), 2 deletions(-)
12
12
13
diff --git a/linux-user/aarch64/target_syscall.h b/linux-user/aarch64/target_syscall.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/linux-user/aarch64/target_syscall.h
16
+++ b/linux-user/aarch64/target_syscall.h
17
@@ -XXX,XX +XXX,XX @@ struct target_pt_regs {
18
#define TARGET_PR_SVE_SET_VL 50
19
#define TARGET_PR_SVE_GET_VL 51
20
21
+void arm_init_pauth_key(ARMPACKey *key);
22
+
23
#endif /* AARCH64_TARGET_SYSCALL_H */
13
diff --git a/linux-user/aarch64/cpu_loop.c b/linux-user/aarch64/cpu_loop.c
24
diff --git a/linux-user/aarch64/cpu_loop.c b/linux-user/aarch64/cpu_loop.c
14
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
15
--- a/linux-user/aarch64/cpu_loop.c
26
--- a/linux-user/aarch64/cpu_loop.c
16
+++ b/linux-user/aarch64/cpu_loop.c
27
+++ b/linux-user/aarch64/cpu_loop.c
28
@@ -XXX,XX +XXX,XX @@ void cpu_loop(CPUARMState *env)
29
}
30
}
31
32
+static uint64_t arm_rand64(void)
33
+{
34
+ int shift = 64 - clz64(RAND_MAX);
35
+ int i, n = 64 / shift + (64 % shift != 0);
36
+ uint64_t ret = 0;
37
+
38
+ for (i = 0; i < n; i++) {
39
+ ret = (ret << shift) | rand();
40
+ }
41
+ return ret;
42
+}
43
+
44
+void arm_init_pauth_key(ARMPACKey *key)
45
+{
46
+ key->lo = arm_rand64();
47
+ key->hi = arm_rand64();
48
+}
49
+
50
void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
51
{
52
- CPUState *cpu = ENV_GET_CPU(env);
53
- TaskState *ts = cpu->opaque;
54
+ ARMCPU *cpu = arm_env_get_cpu(env);
55
+ CPUState *cs = CPU(cpu);
56
+ TaskState *ts = cs->opaque;
57
struct image_info *info = ts->info;
58
int i;
59
17
@@ -XXX,XX +XXX,XX @@ void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
60
@@ -XXX,XX +XXX,XX @@ void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
18
for (i = 1; i < 4; ++i) {
19
env->cp15.sctlr_el[i] |= SCTLR_EE;
20
}
61
}
21
+ arm_rebuild_hflags(env);
22
#endif
62
#endif
23
63
24
if (cpu_isar_feature(aa64_pauth, cpu)) {
64
+ if (cpu_isar_feature(aa64_pauth, cpu)) {
65
+ arm_init_pauth_key(&env->apia_key);
66
+ arm_init_pauth_key(&env->apib_key);
67
+ arm_init_pauth_key(&env->apda_key);
68
+ arm_init_pauth_key(&env->apdb_key);
69
+ arm_init_pauth_key(&env->apga_key);
70
+ }
71
+
72
ts->stack_base = info->start_stack;
73
ts->heap_base = info->brk;
74
/* This will be filled in on the first SYS_HEAPINFO call. */
25
--
75
--
26
2.20.1
76
2.20.1
27
77
28
78
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Remi Denis-Courmont <remi.denis.courmont@huawei.com>
2
2
3
There are 3 conditions that each enable this flag. M-profile always
3
Since QEMU does not support the ARMv8.2-LVA, Large Virtual Address,
4
enables; A-profile with EL1 as AA64 always enables. Both of these
4
extension (yet), the VA address space is 48-bits plus a sign bit. User
5
conditions can easily be cached. The final condition relies on the
5
mode can only handle the positive half of the address space, so that
6
FPEXC register which we are not prepared to cache.
6
makes a limit of 48 bits.
7
7
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
(With LVA, it would be 53 and 52 bits respectively.)
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
10
Message-id: 20191023150057.25731-12-richard.henderson@linaro.org
10
The incorrectly large address space conflicts with PAuth instructions,
11
which use bits 48-54 and 56-63 for the pointer authentication code. This
12
also conflicts with (as yet unsupported by QEMU) data tagging and with
13
the ARMv8.5-MTE extension.
14
15
Signed-off-by: Remi Denis-Courmont <remi.denis.courmont@huawei.com>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
18
---
13
target/arm/cpu.h | 2 +-
19
target/arm/cpu.h | 2 +-
14
target/arm/helper.c | 14 ++++++++++----
20
1 file changed, 1 insertion(+), 1 deletion(-)
15
2 files changed, 11 insertions(+), 5 deletions(-)
16
21
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
22
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
18
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/cpu.h
24
--- a/target/arm/cpu.h
20
+++ b/target/arm/cpu.h
25
+++ b/target/arm/cpu.h
21
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_A32, XSCALE_CPAR, 4, 2)
26
@@ -XXX,XX +XXX,XX @@ bool write_cpustate_to_list(ARMCPU *cpu);
22
* the same thing as the current security state of the processor!
27
23
*/
28
#if defined(TARGET_AARCH64)
24
FIELD(TBFLAG_A32, NS, 6, 1)
29
# define TARGET_PHYS_ADDR_SPACE_BITS 48
25
-FIELD(TBFLAG_A32, VFPEN, 7, 1) /* Not cached. */
30
-# define TARGET_VIRT_ADDR_SPACE_BITS 64
26
+FIELD(TBFLAG_A32, VFPEN, 7, 1) /* Partially cached, minus FPEXC. */
31
+# define TARGET_VIRT_ADDR_SPACE_BITS 48
27
FIELD(TBFLAG_A32, CONDEXEC, 8, 8) /* Not cached. */
32
#else
28
FIELD(TBFLAG_A32, SCTLR_B, 16, 1)
33
# define TARGET_PHYS_ADDR_SPACE_BITS 40
29
/* For M profile only, set if FPCCR.LSPACT is set */
34
# define TARGET_VIRT_ADDR_SPACE_BITS 32
30
diff --git a/target/arm/helper.c b/target/arm/helper.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/helper.c
33
+++ b/target/arm/helper.c
34
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_m32(CPUARMState *env, int fp_el,
35
{
36
uint32_t flags = 0;
37
38
+ /* v8M always enables the fpu. */
39
+ flags = FIELD_DP32(flags, TBFLAG_A32, VFPEN, 1);
40
+
41
if (arm_v7m_is_handler_mode(env)) {
42
flags = FIELD_DP32(flags, TBFLAG_A32, HANDLER, 1);
43
}
44
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_a32(CPUARMState *env, int fp_el,
45
ARMMMUIdx mmu_idx)
46
{
47
uint32_t flags = rebuild_hflags_aprofile(env);
48
+
49
+ if (arm_el_is_aa64(env, 1)) {
50
+ flags = FIELD_DP32(flags, TBFLAG_A32, VFPEN, 1);
51
+ }
52
return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags);
53
}
54
55
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
56
flags = FIELD_DP32(flags, TBFLAG_A32, VECSTRIDE,
57
env->vfp.vec_stride);
58
}
59
+ if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) {
60
+ flags = FIELD_DP32(flags, TBFLAG_A32, VFPEN, 1);
61
+ }
62
}
63
64
flags = FIELD_DP32(flags, TBFLAG_A32, THUMB, env->thumb);
65
flags = FIELD_DP32(flags, TBFLAG_A32, CONDEXEC, env->condexec_bits);
66
- if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)
67
- || arm_el_is_aa64(env, 1) || arm_feature(env, ARM_FEATURE_M)) {
68
- flags = FIELD_DP32(flags, TBFLAG_A32, VFPEN, 1);
69
- }
70
pstate_for_ss = env->uncached_cpsr;
71
}
72
73
--
35
--
74
2.20.1
36
2.20.1
75
37
76
38
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Remi Denis-Courmont <remi.denis.courmont@huawei.com>
2
2
3
Continue setting, but not relying upon, env->hflags.
3
A flawed test lead to the instructions always being treated as
4
unallocated encodings.
4
5
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Fixes: https://bugs.launchpad.net/bugs/1813460
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Remi Denis-Courmont <remi.denis.courmont@huawei.com>
7
Message-id: 20191023150057.25731-18-richard.henderson@linaro.org
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
---
10
target/arm/translate-a64.c | 13 +++++++++++--
11
target/arm/translate-a64.c | 2 +-
11
target/arm/translate.c | 28 +++++++++++++++++++++++-----
12
1 file changed, 1 insertion(+), 1 deletion(-)
12
2 files changed, 34 insertions(+), 7 deletions(-)
13
13
14
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
14
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/translate-a64.c
16
--- a/target/arm/translate-a64.c
17
+++ b/target/arm/translate-a64.c
17
+++ b/target/arm/translate-a64.c
18
@@ -XXX,XX +XXX,XX @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
18
@@ -XXX,XX +XXX,XX @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
19
if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
19
if (!dc_isar_feature(aa64_pauth, s)) {
20
/* I/O operations must end the TB here (whether read or write) */
20
goto do_unallocated;
21
s->base.is_jmp = DISAS_UPDATE;
22
- } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
23
- /* We default to ending the TB on a coprocessor register write,
24
+ }
25
+ if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
26
+ /*
27
+ * A write to any coprocessor regiser that ends a TB
28
+ * must rebuild the hflags for the next TB.
29
+ */
30
+ TCGv_i32 tcg_el = tcg_const_i32(s->current_el);
31
+ gen_helper_rebuild_hflags_a64(cpu_env, tcg_el);
32
+ tcg_temp_free_i32(tcg_el);
33
+ /*
34
+ * We default to ending the TB on a coprocessor register write,
35
* but allow this to be suppressed by the register definition
36
* (usually only necessary to work around guest bugs).
37
*/
38
diff --git a/target/arm/translate.c b/target/arm/translate.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/target/arm/translate.c
41
+++ b/target/arm/translate.c
42
@@ -XXX,XX +XXX,XX @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn)
43
ri = get_arm_cp_reginfo(s->cp_regs,
44
ENCODE_CP_REG(cpnum, is64, s->ns, crn, crm, opc1, opc2));
45
if (ri) {
46
+ bool need_exit_tb;
47
+
48
/* Check access permissions */
49
if (!cp_access_ok(s->current_el, ri, isread)) {
50
return 1;
51
@@ -XXX,XX +XXX,XX @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn)
52
}
53
}
21
}
54
22
- if (op3 != 2 || op3 != 3) {
55
- if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
23
+ if ((op3 & ~1) != 2) {
56
- /* I/O operations must end the TB here (whether read or write) */
24
goto do_unallocated;
57
- gen_lookup_tb(s);
58
- } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
59
- /* We default to ending the TB on a coprocessor register write,
60
+ /* I/O operations must end the TB here (whether read or write) */
61
+ need_exit_tb = ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) &&
62
+ (ri->type & ARM_CP_IO));
63
+
64
+ if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
65
+ /*
66
+ * A write to any coprocessor regiser that ends a TB
67
+ * must rebuild the hflags for the next TB.
68
+ */
69
+ TCGv_i32 tcg_el = tcg_const_i32(s->current_el);
70
+ if (arm_dc_feature(s, ARM_FEATURE_M)) {
71
+ gen_helper_rebuild_hflags_m32(cpu_env, tcg_el);
72
+ } else {
73
+ gen_helper_rebuild_hflags_a32(cpu_env, tcg_el);
74
+ }
75
+ tcg_temp_free_i32(tcg_el);
76
+ /*
77
+ * We default to ending the TB on a coprocessor register write,
78
* but allow this to be suppressed by the register definition
79
* (usually only necessary to work around guest bugs).
80
*/
81
+ need_exit_tb = true;
82
+ }
83
+ if (need_exit_tb) {
84
gen_lookup_tb(s);
85
}
25
}
86
26
if (s->pauth_active) {
87
--
27
--
88
2.20.1
28
2.20.1
89
29
90
30
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Steffen Görtz <contrib@steffen-goertz.de>
2
2
3
Add the 64-bit free running timer. Do not model the COMPARE register
3
The nRF51 contains three regions of non-volatile memory (NVM):
4
(no IRQ generated).
4
- CODE (R/W): contains code
5
This timer is used by Linux kernel and recently U-Boot:
5
- FICR (R): Factory information like code size, chip id etc.
6
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/clocksource/bcm2835_timer.c?h=v3.7
6
- UICR (R/W): Changeable configuration data. Lock bits, Code
7
https://github.com/u-boot/u-boot/blob/v2019.07/include/configs/rpi.h#L19
7
protection configuration, Bootloader address, Nordic SoftRadio
8
8
configuration, Firmware configuration.
9
Datasheet used:
9
10
https://www.raspberrypi.org/app/uploads/2012/02/BCM2835-ARM-Peripherals.pdf
10
Read and write access to the memories is managed by the
11
11
Non-volatile memory controller.
12
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
13
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
13
Memory schema:
14
Message-id: 20191019234715.25750-4-f4bug@amsat.org
14
[ CPU ] -+- [ NVM, either FICR, UICR or CODE ]
15
[PMM: squashed in switch to using memset in reset]
15
| |
16
\- [ NVMC ]
17
18
Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
19
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
20
Tested-by: Joel Stanley <joel@jms.id.au>
21
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
22
Message-id: 20190201023357.22596-2-stefanha@redhat.com
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
24
---
18
hw/timer/Makefile.objs | 1 +
25
hw/nvram/Makefile.objs | 1 +
19
include/hw/timer/bcm2835_systmr.h | 33 ++++++
26
include/hw/nvram/nrf51_nvm.h | 64 ++++++
20
hw/timer/bcm2835_systmr.c | 163 ++++++++++++++++++++++++++++++
27
hw/nvram/nrf51_nvm.c | 388 +++++++++++++++++++++++++++++++++++
21
hw/timer/trace-events | 5 +
28
3 files changed, 453 insertions(+)
22
4 files changed, 202 insertions(+)
29
create mode 100644 include/hw/nvram/nrf51_nvm.h
23
create mode 100644 include/hw/timer/bcm2835_systmr.h
30
create mode 100644 hw/nvram/nrf51_nvm.c
24
create mode 100644 hw/timer/bcm2835_systmr.c
31
25
32
diff --git a/hw/nvram/Makefile.objs b/hw/nvram/Makefile.objs
26
diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs
27
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/timer/Makefile.objs
34
--- a/hw/nvram/Makefile.objs
29
+++ b/hw/timer/Makefile.objs
35
+++ b/hw/nvram/Makefile.objs
30
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_SUN4V_RTC) += sun4v-rtc.o
36
@@ -XXX,XX +XXX,XX @@ common-obj-y += fw_cfg.o
31
common-obj-$(CONFIG_CMSDK_APB_TIMER) += cmsdk-apb-timer.o
37
common-obj-y += chrp_nvram.o
32
common-obj-$(CONFIG_CMSDK_APB_DUALTIMER) += cmsdk-apb-dualtimer.o
38
common-obj-$(CONFIG_MAC_NVRAM) += mac_nvram.o
33
common-obj-$(CONFIG_MSF2) += mss-timer.o
39
obj-$(CONFIG_PSERIES) += spapr_nvram.o
34
+common-obj-$(CONFIG_RASPI) += bcm2835_systmr.o
40
+obj-$(CONFIG_NRF51_SOC) += nrf51_nvm.o
35
diff --git a/include/hw/timer/bcm2835_systmr.h b/include/hw/timer/bcm2835_systmr.h
41
diff --git a/include/hw/nvram/nrf51_nvm.h b/include/hw/nvram/nrf51_nvm.h
36
new file mode 100644
42
new file mode 100644
37
index XXXXXXX..XXXXXXX
43
index XXXXXXX..XXXXXXX
38
--- /dev/null
44
--- /dev/null
39
+++ b/include/hw/timer/bcm2835_systmr.h
45
+++ b/include/hw/nvram/nrf51_nvm.h
40
@@ -XXX,XX +XXX,XX @@
46
@@ -XXX,XX +XXX,XX @@
41
+/*
47
+/*
42
+ * BCM2835 SYS timer emulation
48
+ * Nordic Semiconductor nRF51 non-volatile memory
43
+ *
49
+ *
44
+ * Copyright (c) 2019 Philippe Mathieu-Daudé <f4bug@amsat.org>
50
+ * It provides an interface to erase regions in flash memory.
45
+ *
51
+ * Furthermore it provides the user and factory information registers.
46
+ * SPDX-License-Identifier: GPL-2.0-or-later
52
+ *
53
+ * QEMU interface:
54
+ * + sysbus MMIO regions 0: NVMC peripheral registers
55
+ * + sysbus MMIO regions 1: FICR peripheral registers
56
+ * + sysbus MMIO regions 2: UICR peripheral registers
57
+ * + flash-size property: flash size in bytes.
58
+ *
59
+ * Accuracy of the peripheral model:
60
+ * + Code regions (MPU configuration) are disregarded.
61
+ *
62
+ * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
63
+ *
64
+ * This code is licensed under the GPL version 2 or later. See
65
+ * the COPYING file in the top-level directory.
66
+ *
47
+ */
67
+ */
48
+
68
+#ifndef NRF51_NVM_H
49
+#ifndef BCM2835_SYSTIMER_H
69
+#define NRF51_NVM_H
50
+#define BCM2835_SYSTIMER_H
51
+
70
+
52
+#include "hw/sysbus.h"
71
+#include "hw/sysbus.h"
53
+#include "hw/irq.h"
72
+#define TYPE_NRF51_NVM "nrf51_soc.nvm"
54
+
73
+#define NRF51_NVM(obj) OBJECT_CHECK(NRF51NVMState, (obj), TYPE_NRF51_NVM)
55
+#define TYPE_BCM2835_SYSTIMER "bcm2835-sys-timer"
74
+
56
+#define BCM2835_SYSTIMER(obj) \
75
+#define NRF51_UICR_FIXTURE_SIZE 64
57
+ OBJECT_CHECK(BCM2835SystemTimerState, (obj), TYPE_BCM2835_SYSTIMER)
76
+
58
+
77
+#define NRF51_NVMC_SIZE 0x1000
59
+typedef struct {
78
+
60
+ /*< private >*/
79
+#define NRF51_NVMC_READY 0x400
80
+#define NRF51_NVMC_READY_READY 0x01
81
+#define NRF51_NVMC_CONFIG 0x504
82
+#define NRF51_NVMC_CONFIG_MASK 0x03
83
+#define NRF51_NVMC_CONFIG_WEN 0x01
84
+#define NRF51_NVMC_CONFIG_EEN 0x02
85
+#define NRF51_NVMC_ERASEPCR1 0x508
86
+#define NRF51_NVMC_ERASEPCR0 0x510
87
+#define NRF51_NVMC_ERASEALL 0x50C
88
+#define NRF51_NVMC_ERASEUICR 0x514
89
+#define NRF51_NVMC_ERASE 0x01
90
+
91
+#define NRF51_UICR_SIZE 0x100
92
+
93
+typedef struct NRF51NVMState {
61
+ SysBusDevice parent_obj;
94
+ SysBusDevice parent_obj;
62
+
95
+
63
+ /*< public >*/
96
+ MemoryRegion mmio;
64
+ MemoryRegion iomem;
97
+ MemoryRegion ficr;
65
+ qemu_irq irq;
98
+ MemoryRegion uicr;
66
+
99
+ MemoryRegion flash;
67
+ struct {
100
+
68
+ uint32_t status;
101
+ uint32_t uicr_content[NRF51_UICR_FIXTURE_SIZE];
69
+ uint32_t compare[4];
102
+ uint32_t flash_size;
70
+ } reg;
103
+ uint8_t *storage;
71
+} BCM2835SystemTimerState;
104
+
105
+ uint32_t config;
106
+
107
+} NRF51NVMState;
108
+
72
+
109
+
73
+#endif
110
+#endif
74
diff --git a/hw/timer/bcm2835_systmr.c b/hw/timer/bcm2835_systmr.c
111
diff --git a/hw/nvram/nrf51_nvm.c b/hw/nvram/nrf51_nvm.c
75
new file mode 100644
112
new file mode 100644
76
index XXXXXXX..XXXXXXX
113
index XXXXXXX..XXXXXXX
77
--- /dev/null
114
--- /dev/null
78
+++ b/hw/timer/bcm2835_systmr.c
115
+++ b/hw/nvram/nrf51_nvm.c
79
@@ -XXX,XX +XXX,XX @@
116
@@ -XXX,XX +XXX,XX @@
80
+/*
117
+/*
81
+ * BCM2835 SYS timer emulation
118
+ * Nordic Semiconductor nRF51 non-volatile memory
82
+ *
119
+ *
83
+ * Copyright (C) 2019 Philippe Mathieu-Daudé <f4bug@amsat.org>
120
+ * It provides an interface to erase regions in flash memory.
84
+ *
121
+ * Furthermore it provides the user and factory information registers.
85
+ * SPDX-License-Identifier: GPL-2.0-or-later
122
+ *
86
+ *
123
+ * Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.pdf
87
+ * Datasheet: BCM2835 ARM Peripherals (C6357-M-1398)
124
+ *
88
+ * https://www.raspberrypi.org/app/uploads/2012/02/BCM2835-ARM-Peripherals.pdf
125
+ * See nRF51 reference manual and product sheet sections:
89
+ *
126
+ * + Non-Volatile Memory Controller (NVMC)
90
+ * Only the free running 64-bit counter is implemented.
127
+ * + Factory Information Configuration Registers (FICR)
91
+ * The 4 COMPARE registers and the interruption are not implemented.
128
+ * + User Information Configuration Registers (UICR)
129
+ *
130
+ * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
131
+ *
132
+ * This code is licensed under the GPL version 2 or later. See
133
+ * the COPYING file in the top-level directory.
92
+ */
134
+ */
93
+
135
+
94
+#include "qemu/osdep.h"
136
+#include "qemu/osdep.h"
137
+#include "qapi/error.h"
95
+#include "qemu/log.h"
138
+#include "qemu/log.h"
96
+#include "qemu/timer.h"
139
+#include "exec/address-spaces.h"
97
+#include "hw/timer/bcm2835_systmr.h"
140
+#include "hw/arm/nrf51.h"
98
+#include "hw/registerfields.h"
141
+#include "hw/nvram/nrf51_nvm.h"
99
+#include "migration/vmstate.h"
142
+
100
+#include "trace.h"
143
+/*
101
+
144
+ * FICR Registers Assignments
102
+REG32(CTRL_STATUS, 0x00)
145
+ * CODEPAGESIZE 0x010
103
+REG32(COUNTER_LOW, 0x04)
146
+ * CODESIZE 0x014
104
+REG32(COUNTER_HIGH, 0x08)
147
+ * CLENR0 0x028
105
+REG32(COMPARE0, 0x0c)
148
+ * PPFC 0x02C
106
+REG32(COMPARE1, 0x10)
149
+ * NUMRAMBLOCK 0x034
107
+REG32(COMPARE2, 0x14)
150
+ * SIZERAMBLOCKS 0x038
108
+REG32(COMPARE3, 0x18)
151
+ * SIZERAMBLOCK[0] 0x038
109
+
152
+ * SIZERAMBLOCK[1] 0x03C
110
+static void bcm2835_systmr_update_irq(BCM2835SystemTimerState *s)
153
+ * SIZERAMBLOCK[2] 0x040
111
+{
154
+ * SIZERAMBLOCK[3] 0x044
112
+ bool enable = !!s->reg.status;
155
+ * CONFIGID 0x05C
113
+
156
+ * DEVICEID[0] 0x060
114
+ trace_bcm2835_systmr_irq(enable);
157
+ * DEVICEID[1] 0x064
115
+ qemu_set_irq(s->irq, enable);
158
+ * ER[0] 0x080
116
+}
159
+ * ER[1] 0x084
117
+
160
+ * ER[2] 0x088
118
+static void bcm2835_systmr_update_compare(BCM2835SystemTimerState *s,
161
+ * ER[3] 0x08C
119
+ unsigned timer_index)
162
+ * IR[0] 0x090
120
+{
163
+ * IR[1] 0x094
121
+ /* TODO fow now, since neither Linux nor U-boot use these timers. */
164
+ * IR[2] 0x098
122
+ qemu_log_mask(LOG_UNIMP, "COMPARE register %u not implemented\n",
165
+ * IR[3] 0x09C
123
+ timer_index);
166
+ * DEVICEADDRTYPE 0x0A0
124
+}
167
+ * DEVICEADDR[0] 0x0A4
125
+
168
+ * DEVICEADDR[1] 0x0A8
126
+static uint64_t bcm2835_systmr_read(void *opaque, hwaddr offset,
169
+ * OVERRIDEEN 0x0AC
127
+ unsigned size)
170
+ * NRF_1MBIT[0] 0x0B0
128
+{
171
+ * NRF_1MBIT[1] 0x0B4
129
+ BCM2835SystemTimerState *s = BCM2835_SYSTIMER(opaque);
172
+ * NRF_1MBIT[2] 0x0B8
173
+ * NRF_1MBIT[3] 0x0BC
174
+ * NRF_1MBIT[4] 0x0C0
175
+ * BLE_1MBIT[0] 0x0EC
176
+ * BLE_1MBIT[1] 0x0F0
177
+ * BLE_1MBIT[2] 0x0F4
178
+ * BLE_1MBIT[3] 0x0F8
179
+ * BLE_1MBIT[4] 0x0FC
180
+ */
181
+static const uint32_t ficr_content[64] = {
182
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000400,
183
+ 0x00000100, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000002, 0x00002000,
184
+ 0x00002000, 0x00002000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
185
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
186
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000003,
187
+ 0x12345678, 0x9ABCDEF1, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
188
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
189
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
190
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
191
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
192
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
193
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
194
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
195
+};
196
+
197
+static uint64_t ficr_read(void *opaque, hwaddr offset, unsigned int size)
198
+{
199
+ assert(offset < sizeof(ficr_content));
200
+ return ficr_content[offset / 4];
201
+}
202
+
203
+static void ficr_write(void *opaque, hwaddr offset, uint64_t value,
204
+ unsigned int size)
205
+{
206
+ /* Intentionally do nothing */
207
+}
208
+
209
+static const MemoryRegionOps ficr_ops = {
210
+ .read = ficr_read,
211
+ .write = ficr_write,
212
+ .impl.min_access_size = 4,
213
+ .impl.max_access_size = 4,
214
+ .endianness = DEVICE_LITTLE_ENDIAN
215
+};
216
+
217
+/*
218
+ * UICR Registers Assignments
219
+ * CLENR0 0x000
220
+ * RBPCONF 0x004
221
+ * XTALFREQ 0x008
222
+ * FWID 0x010
223
+ * BOOTLOADERADDR 0x014
224
+ * NRFFW[0] 0x014
225
+ * NRFFW[1] 0x018
226
+ * NRFFW[2] 0x01C
227
+ * NRFFW[3] 0x020
228
+ * NRFFW[4] 0x024
229
+ * NRFFW[5] 0x028
230
+ * NRFFW[6] 0x02C
231
+ * NRFFW[7] 0x030
232
+ * NRFFW[8] 0x034
233
+ * NRFFW[9] 0x038
234
+ * NRFFW[10] 0x03C
235
+ * NRFFW[11] 0x040
236
+ * NRFFW[12] 0x044
237
+ * NRFFW[13] 0x048
238
+ * NRFFW[14] 0x04C
239
+ * NRFHW[0] 0x050
240
+ * NRFHW[1] 0x054
241
+ * NRFHW[2] 0x058
242
+ * NRFHW[3] 0x05C
243
+ * NRFHW[4] 0x060
244
+ * NRFHW[5] 0x064
245
+ * NRFHW[6] 0x068
246
+ * NRFHW[7] 0x06C
247
+ * NRFHW[8] 0x070
248
+ * NRFHW[9] 0x074
249
+ * NRFHW[10] 0x078
250
+ * NRFHW[11] 0x07C
251
+ * CUSTOMER[0] 0x080
252
+ * CUSTOMER[1] 0x084
253
+ * CUSTOMER[2] 0x088
254
+ * CUSTOMER[3] 0x08C
255
+ * CUSTOMER[4] 0x090
256
+ * CUSTOMER[5] 0x094
257
+ * CUSTOMER[6] 0x098
258
+ * CUSTOMER[7] 0x09C
259
+ * CUSTOMER[8] 0x0A0
260
+ * CUSTOMER[9] 0x0A4
261
+ * CUSTOMER[10] 0x0A8
262
+ * CUSTOMER[11] 0x0AC
263
+ * CUSTOMER[12] 0x0B0
264
+ * CUSTOMER[13] 0x0B4
265
+ * CUSTOMER[14] 0x0B8
266
+ * CUSTOMER[15] 0x0BC
267
+ * CUSTOMER[16] 0x0C0
268
+ * CUSTOMER[17] 0x0C4
269
+ * CUSTOMER[18] 0x0C8
270
+ * CUSTOMER[19] 0x0CC
271
+ * CUSTOMER[20] 0x0D0
272
+ * CUSTOMER[21] 0x0D4
273
+ * CUSTOMER[22] 0x0D8
274
+ * CUSTOMER[23] 0x0DC
275
+ * CUSTOMER[24] 0x0E0
276
+ * CUSTOMER[25] 0x0E4
277
+ * CUSTOMER[26] 0x0E8
278
+ * CUSTOMER[27] 0x0EC
279
+ * CUSTOMER[28] 0x0F0
280
+ * CUSTOMER[29] 0x0F4
281
+ * CUSTOMER[30] 0x0F8
282
+ * CUSTOMER[31] 0x0FC
283
+ */
284
+
285
+static uint64_t uicr_read(void *opaque, hwaddr offset, unsigned int size)
286
+{
287
+ NRF51NVMState *s = NRF51_NVM(opaque);
288
+
289
+ assert(offset < sizeof(s->uicr_content));
290
+ return s->uicr_content[offset / 4];
291
+}
292
+
293
+static void uicr_write(void *opaque, hwaddr offset, uint64_t value,
294
+ unsigned int size)
295
+{
296
+ NRF51NVMState *s = NRF51_NVM(opaque);
297
+
298
+ assert(offset < sizeof(s->uicr_content));
299
+ s->uicr_content[offset / 4] = value;
300
+}
301
+
302
+static const MemoryRegionOps uicr_ops = {
303
+ .read = uicr_read,
304
+ .write = uicr_write,
305
+ .impl.min_access_size = 4,
306
+ .impl.max_access_size = 4,
307
+ .endianness = DEVICE_LITTLE_ENDIAN
308
+};
309
+
310
+
311
+static uint64_t io_read(void *opaque, hwaddr offset, unsigned int size)
312
+{
313
+ NRF51NVMState *s = NRF51_NVM(opaque);
130
+ uint64_t r = 0;
314
+ uint64_t r = 0;
131
+
315
+
132
+ switch (offset) {
316
+ switch (offset) {
133
+ case A_CTRL_STATUS:
317
+ case NRF51_NVMC_READY:
134
+ r = s->reg.status;
318
+ r = NRF51_NVMC_READY_READY;
135
+ break;
319
+ break;
136
+ case A_COMPARE0 ... A_COMPARE3:
320
+ case NRF51_NVMC_CONFIG:
137
+ r = s->reg.compare[(offset - A_COMPARE0) >> 2];
321
+ r = s->config;
138
+ break;
139
+ case A_COUNTER_LOW:
140
+ case A_COUNTER_HIGH:
141
+ /* Free running counter at 1MHz */
142
+ r = qemu_clock_get_us(QEMU_CLOCK_VIRTUAL);
143
+ r >>= 8 * (offset - A_COUNTER_LOW);
144
+ r &= UINT32_MAX;
145
+ break;
322
+ break;
146
+ default:
323
+ default:
147
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: bad offset 0x%" HWADDR_PRIx "\n",
324
+ qemu_log_mask(LOG_GUEST_ERROR,
148
+ __func__, offset);
325
+ "%s: bad read offset 0x%" HWADDR_PRIx "\n", __func__, offset);
149
+ break;
326
+ break;
150
+ }
327
+ }
151
+ trace_bcm2835_systmr_read(offset, r);
152
+
328
+
153
+ return r;
329
+ return r;
154
+}
330
+}
155
+
331
+
156
+static void bcm2835_systmr_write(void *opaque, hwaddr offset,
332
+static void io_write(void *opaque, hwaddr offset, uint64_t value,
157
+ uint64_t value, unsigned size)
333
+ unsigned int size)
158
+{
334
+{
159
+ BCM2835SystemTimerState *s = BCM2835_SYSTIMER(opaque);
335
+ NRF51NVMState *s = NRF51_NVM(opaque);
160
+
336
+
161
+ trace_bcm2835_systmr_write(offset, value);
162
+ switch (offset) {
337
+ switch (offset) {
163
+ case A_CTRL_STATUS:
338
+ case NRF51_NVMC_CONFIG:
164
+ s->reg.status &= ~value; /* Ack */
339
+ s->config = value & NRF51_NVMC_CONFIG_MASK;
165
+ bcm2835_systmr_update_irq(s);
340
+ break;
166
+ break;
341
+ case NRF51_NVMC_ERASEPCR0:
167
+ case A_COMPARE0 ... A_COMPARE3:
342
+ case NRF51_NVMC_ERASEPCR1:
168
+ s->reg.compare[(offset - A_COMPARE0) >> 2] = value;
343
+ if (s->config & NRF51_NVMC_CONFIG_EEN) {
169
+ bcm2835_systmr_update_compare(s, (offset - A_COMPARE0) >> 2);
344
+ /* Mask in-page sub address */
170
+ break;
345
+ value &= ~(NRF51_PAGE_SIZE - 1);
171
+ case A_COUNTER_LOW:
346
+ if (value <= (s->flash_size - NRF51_PAGE_SIZE)) {
172
+ case A_COUNTER_HIGH:
347
+ memset(s->storage + value, 0xFF, NRF51_PAGE_SIZE);
173
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: read-only ofs 0x%" HWADDR_PRIx "\n",
348
+ memory_region_flush_rom_device(&s->flash, value,
174
+ __func__, offset);
349
+ NRF51_PAGE_SIZE);
175
+ break;
350
+ }
351
+ } else {
352
+ qemu_log_mask(LOG_GUEST_ERROR,
353
+ "%s: Flash erase at 0x%" HWADDR_PRIx" while flash not erasable.\n",
354
+ __func__, offset);
355
+ }
356
+ break;
357
+ case NRF51_NVMC_ERASEALL:
358
+ if (value == NRF51_NVMC_ERASE) {
359
+ if (s->config & NRF51_NVMC_CONFIG_EEN) {
360
+ memset(s->storage, 0xFF, s->flash_size);
361
+ memory_region_flush_rom_device(&s->flash, 0, s->flash_size);
362
+ memset(s->uicr_content, 0xFF, sizeof(s->uicr_content));
363
+ } else {
364
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Flash not erasable.\n",
365
+ __func__);
366
+ }
367
+ }
368
+ break;
369
+ case NRF51_NVMC_ERASEUICR:
370
+ if (value == NRF51_NVMC_ERASE) {
371
+ memset(s->uicr_content, 0xFF, sizeof(s->uicr_content));
372
+ }
373
+ break;
374
+
176
+ default:
375
+ default:
177
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: bad offset 0x%" HWADDR_PRIx "\n",
376
+ qemu_log_mask(LOG_GUEST_ERROR,
178
+ __func__, offset);
377
+ "%s: bad write offset 0x%" HWADDR_PRIx "\n", __func__, offset);
179
+ break;
180
+ }
378
+ }
181
+}
379
+}
182
+
380
+
183
+static const MemoryRegionOps bcm2835_systmr_ops = {
381
+static const MemoryRegionOps io_ops = {
184
+ .read = bcm2835_systmr_read,
382
+ .read = io_read,
185
+ .write = bcm2835_systmr_write,
383
+ .write = io_write,
384
+ .impl.min_access_size = 4,
385
+ .impl.max_access_size = 4,
386
+ .endianness = DEVICE_LITTLE_ENDIAN,
387
+};
388
+
389
+
390
+static void flash_write(void *opaque, hwaddr offset, uint64_t value,
391
+ unsigned int size)
392
+{
393
+ NRF51NVMState *s = NRF51_NVM(opaque);
394
+
395
+ if (s->config & NRF51_NVMC_CONFIG_WEN) {
396
+ uint32_t oldval;
397
+
398
+ assert(offset + size <= s->flash_size);
399
+
400
+ /* NOR Flash only allows bits to be flipped from 1's to 0's on write */
401
+ oldval = ldl_le_p(s->storage + offset);
402
+ oldval &= value;
403
+ stl_le_p(s->storage + offset, oldval);
404
+
405
+ memory_region_flush_rom_device(&s->flash, offset, size);
406
+ } else {
407
+ qemu_log_mask(LOG_GUEST_ERROR,
408
+ "%s: Flash write 0x%" HWADDR_PRIx" while flash not writable.\n",
409
+ __func__, offset);
410
+ }
411
+}
412
+
413
+
414
+
415
+static const MemoryRegionOps flash_ops = {
416
+ .write = flash_write,
417
+ .valid.min_access_size = 4,
418
+ .valid.max_access_size = 4,
186
+ .endianness = DEVICE_LITTLE_ENDIAN,
419
+ .endianness = DEVICE_LITTLE_ENDIAN,
187
+ .impl = {
420
+};
188
+ .min_access_size = 4,
421
+
189
+ .max_access_size = 4,
422
+static void nrf51_nvm_init(Object *obj)
190
+ },
423
+{
191
+};
424
+ NRF51NVMState *s = NRF51_NVM(obj);
192
+
425
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
193
+static void bcm2835_systmr_reset(DeviceState *dev)
426
+
194
+{
427
+ memory_region_init_io(&s->mmio, obj, &io_ops, s, "nrf51_soc.nvmc",
195
+ BCM2835SystemTimerState *s = BCM2835_SYSTIMER(dev);
428
+ NRF51_NVMC_SIZE);
196
+
429
+ sysbus_init_mmio(sbd, &s->mmio);
197
+ memset(&s->reg, 0, sizeof(s->reg));
430
+
198
+}
431
+ memory_region_init_io(&s->ficr, obj, &ficr_ops, s, "nrf51_soc.ficr",
199
+
432
+ sizeof(ficr_content));
200
+static void bcm2835_systmr_realize(DeviceState *dev, Error **errp)
433
+ sysbus_init_mmio(sbd, &s->ficr);
201
+{
434
+
202
+ BCM2835SystemTimerState *s = BCM2835_SYSTIMER(dev);
435
+ memory_region_init_io(&s->uicr, obj, &uicr_ops, s, "nrf51_soc.uicr",
203
+
436
+ sizeof(s->uicr_content));
204
+ memory_region_init_io(&s->iomem, OBJECT(dev), &bcm2835_systmr_ops,
437
+ sysbus_init_mmio(sbd, &s->uicr);
205
+ s, "bcm2835-sys-timer", 0x20);
438
+}
206
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
439
+
207
+ sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq);
440
+static void nrf51_nvm_realize(DeviceState *dev, Error **errp)
208
+}
441
+{
209
+
442
+ NRF51NVMState *s = NRF51_NVM(dev);
210
+static const VMStateDescription bcm2835_systmr_vmstate = {
443
+ Error *err = NULL;
211
+ .name = "bcm2835_sys_timer",
444
+
445
+ memory_region_init_rom_device(&s->flash, OBJECT(dev), &flash_ops, s,
446
+ "nrf51_soc.flash", s->flash_size, &err);
447
+ if (err) {
448
+ error_propagate(errp, err);
449
+ return;
450
+ }
451
+
452
+ s->storage = memory_region_get_ram_ptr(&s->flash);
453
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->flash);
454
+}
455
+
456
+static void nrf51_nvm_reset(DeviceState *dev)
457
+{
458
+ NRF51NVMState *s = NRF51_NVM(dev);
459
+
460
+ s->config = 0x00;
461
+ memset(s->uicr_content, 0xFF, sizeof(s->uicr_content));
462
+}
463
+
464
+static Property nrf51_nvm_properties[] = {
465
+ DEFINE_PROP_UINT32("flash-size", NRF51NVMState, flash_size, 0x40000),
466
+ DEFINE_PROP_END_OF_LIST(),
467
+};
468
+
469
+static const VMStateDescription vmstate_nvm = {
470
+ .name = "nrf51_soc.nvm",
212
+ .version_id = 1,
471
+ .version_id = 1,
213
+ .minimum_version_id = 1,
472
+ .minimum_version_id = 1,
214
+ .fields = (VMStateField[]) {
473
+ .fields = (VMStateField[]) {
215
+ VMSTATE_UINT32(reg.status, BCM2835SystemTimerState),
474
+ VMSTATE_UINT32_ARRAY(uicr_content, NRF51NVMState,
216
+ VMSTATE_UINT32_ARRAY(reg.compare, BCM2835SystemTimerState, 4),
475
+ NRF51_UICR_FIXTURE_SIZE),
476
+ VMSTATE_UINT32(config, NRF51NVMState),
217
+ VMSTATE_END_OF_LIST()
477
+ VMSTATE_END_OF_LIST()
218
+ }
478
+ }
219
+};
479
+};
220
+
480
+
221
+static void bcm2835_systmr_class_init(ObjectClass *klass, void *data)
481
+static void nrf51_nvm_class_init(ObjectClass *klass, void *data)
222
+{
482
+{
223
+ DeviceClass *dc = DEVICE_CLASS(klass);
483
+ DeviceClass *dc = DEVICE_CLASS(klass);
224
+
484
+
225
+ dc->realize = bcm2835_systmr_realize;
485
+ dc->props = nrf51_nvm_properties;
226
+ dc->reset = bcm2835_systmr_reset;
486
+ dc->vmsd = &vmstate_nvm;
227
+ dc->vmsd = &bcm2835_systmr_vmstate;
487
+ dc->realize = nrf51_nvm_realize;
228
+}
488
+ dc->reset = nrf51_nvm_reset;
229
+
489
+}
230
+static const TypeInfo bcm2835_systmr_info = {
490
+
231
+ .name = TYPE_BCM2835_SYSTIMER,
491
+static const TypeInfo nrf51_nvm_info = {
492
+ .name = TYPE_NRF51_NVM,
232
+ .parent = TYPE_SYS_BUS_DEVICE,
493
+ .parent = TYPE_SYS_BUS_DEVICE,
233
+ .instance_size = sizeof(BCM2835SystemTimerState),
494
+ .instance_size = sizeof(NRF51NVMState),
234
+ .class_init = bcm2835_systmr_class_init,
495
+ .instance_init = nrf51_nvm_init,
235
+};
496
+ .class_init = nrf51_nvm_class_init
236
+
497
+};
237
+static void bcm2835_systmr_register_types(void)
498
+
238
+{
499
+static void nrf51_nvm_register_types(void)
239
+ type_register_static(&bcm2835_systmr_info);
500
+{
240
+}
501
+ type_register_static(&nrf51_nvm_info);
241
+
502
+}
242
+type_init(bcm2835_systmr_register_types);
503
+
243
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
504
+type_init(nrf51_nvm_register_types)
244
index XXXXXXX..XXXXXXX 100644
245
--- a/hw/timer/trace-events
246
+++ b/hw/timer/trace-events
247
@@ -XXX,XX +XXX,XX @@ pl031_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
248
pl031_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
249
pl031_alarm_raised(void) "alarm raised"
250
pl031_set_alarm(uint32_t ticks) "alarm set for %u ticks"
251
+
252
+# bcm2835_systmr.c
253
+bcm2835_systmr_irq(bool enable) "timer irq state %u"
254
+bcm2835_systmr_read(uint64_t offset, uint64_t data) "timer read: offset 0x%" PRIx64 " data 0x%" PRIx64
255
+bcm2835_systmr_write(uint64_t offset, uint64_t data) "timer write: offset 0x%" PRIx64 " data 0x%" PRIx64
256
--
505
--
257
2.20.1
506
2.20.1
258
507
259
508
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Steffen Görtz <contrib@steffen-goertz.de>
2
2
3
Map the thermal sensor in the BCM2835 block.
3
Instantiates UICR, FICR, FLASH and NVMC in nRF51 SOC.
4
4
5
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
5
Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
6
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20191019234715.25750-3-f4bug@amsat.org
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Message-id: 20190201023357.22596-3-stefanha@redhat.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
11
---
10
include/hw/arm/bcm2835_peripherals.h | 2 ++
12
include/hw/arm/nrf51_soc.h | 2 ++
11
include/hw/arm/raspi_platform.h | 1 +
13
hw/arm/nrf51_soc.c | 41 +++++++++++++++++++++++++++-----------
12
hw/arm/bcm2835_peripherals.c | 13 +++++++++++++
14
2 files changed, 31 insertions(+), 12 deletions(-)
13
3 files changed, 16 insertions(+)
14
15
15
diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h
16
diff --git a/include/hw/arm/nrf51_soc.h b/include/hw/arm/nrf51_soc.h
16
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/arm/bcm2835_peripherals.h
18
--- a/include/hw/arm/nrf51_soc.h
18
+++ b/include/hw/arm/bcm2835_peripherals.h
19
+++ b/include/hw/arm/nrf51_soc.h
19
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@
20
#include "hw/misc/bcm2835_property.h"
21
#include "hw/char/nrf51_uart.h"
21
#include "hw/misc/bcm2835_rng.h"
22
#include "hw/misc/nrf51_rng.h"
22
#include "hw/misc/bcm2835_mbox.h"
23
#include "hw/gpio/nrf51_gpio.h"
23
+#include "hw/misc/bcm2835_thermal.h"
24
+#include "hw/nvram/nrf51_nvm.h"
24
#include "hw/sd/sdhci.h"
25
#include "hw/timer/nrf51_timer.h"
25
#include "hw/sd/bcm2835_sdhost.h"
26
26
#include "hw/gpio/bcm2835_gpio.h"
27
#define TYPE_NRF51_SOC "nrf51-soc"
27
@@ -XXX,XX +XXX,XX @@ typedef struct BCM2835PeripheralState {
28
@@ -XXX,XX +XXX,XX @@ typedef struct NRF51State {
28
SDHCIState sdhci;
29
29
BCM2835SDHostState sdhost;
30
NRF51UARTState uart;
30
BCM2835GpioState gpio;
31
NRF51RNGState rng;
31
+ Bcm2835ThermalState thermal;
32
+ NRF51NVMState nvm;
32
UnimplementedDeviceState i2s;
33
NRF51GPIOState gpio;
33
UnimplementedDeviceState spi[1];
34
NRF51TimerState timer[NRF51_NUM_TIMERS];
34
UnimplementedDeviceState i2c[3];
35
35
diff --git a/include/hw/arm/raspi_platform.h b/include/hw/arm/raspi_platform.h
36
diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c
36
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
37
--- a/include/hw/arm/raspi_platform.h
38
--- a/hw/arm/nrf51_soc.c
38
+++ b/include/hw/arm/raspi_platform.h
39
+++ b/hw/arm/nrf51_soc.c
39
@@ -XXX,XX +XXX,XX @@
40
@@ -XXX,XX +XXX,XX @@
40
#define SPI0_OFFSET 0x204000
41
* are supported in the future, add a sub-class of NRF51SoC for
41
#define BSC0_OFFSET 0x205000 /* BSC0 I2C/TWI */
42
* the specific variants
42
#define OTP_OFFSET 0x20f000
43
*/
43
+#define THERMAL_OFFSET 0x212000
44
-#define NRF51822_FLASH_SIZE (256 * NRF51_PAGE_SIZE)
44
#define BSC_SL_OFFSET 0x214000 /* SPI slave */
45
-#define NRF51822_SRAM_SIZE (16 * NRF51_PAGE_SIZE)
45
#define AUX_OFFSET 0x215000 /* AUX: UART1/SPI1/SPI2 */
46
+#define NRF51822_FLASH_PAGES 256
46
#define EMMC1_OFFSET 0x300000
47
+#define NRF51822_SRAM_PAGES 16
47
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
48
+#define NRF51822_FLASH_SIZE (NRF51822_FLASH_PAGES * NRF51_PAGE_SIZE)
48
index XXXXXXX..XXXXXXX 100644
49
+#define NRF51822_SRAM_SIZE (NRF51822_SRAM_PAGES * NRF51_PAGE_SIZE)
49
--- a/hw/arm/bcm2835_peripherals.c
50
50
+++ b/hw/arm/bcm2835_peripherals.c
51
#define BASE_TO_IRQ(base) ((base >> 12) & 0x1F)
51
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_init(Object *obj)
52
52
object_property_add_const_link(OBJECT(&s->dma), "dma-mr",
53
@@ -XXX,XX +XXX,XX @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
53
OBJECT(&s->gpu_bus_mr), &error_abort);
54
54
55
memory_region_add_subregion_overlap(&s->container, 0, s->board_memory, -1);
55
+ /* Thermal */
56
56
+ sysbus_init_child_obj(obj, "thermal", &s->thermal, sizeof(s->thermal),
57
- memory_region_init_rom(&s->flash, OBJECT(s), "nrf51.flash", s->flash_size,
57
+ TYPE_BCM2835_THERMAL);
58
- &err);
58
+
59
- if (err) {
59
/* GPIO */
60
- error_propagate(errp, err);
60
sysbus_init_child_obj(obj, "gpio", &s->gpio, sizeof(s->gpio),
61
- return;
61
TYPE_BCM2835_GPIO);
62
- }
62
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
63
- memory_region_add_subregion(&s->container, NRF51_FLASH_BASE, &s->flash);
63
INTERRUPT_DMA0 + n));
64
-
64
}
65
memory_region_init_ram(&s->sram, OBJECT(s), "nrf51.sram", s->sram_size,
65
66
&err);
66
+ /* THERMAL */
67
if (err) {
67
+ object_property_set_bool(OBJECT(&s->thermal), true, "realized", &err);
68
@@ -XXX,XX +XXX,XX @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
69
qdev_get_gpio_in(DEVICE(&s->cpu),
70
BASE_TO_IRQ(NRF51_RNG_BASE)));
71
72
+ /* UICR, FICR, NVMC, FLASH */
73
+ object_property_set_uint(OBJECT(&s->nvm), s->flash_size, "flash-size",
74
+ &err);
68
+ if (err) {
75
+ if (err) {
69
+ error_propagate(errp, err);
76
+ error_propagate(errp, err);
70
+ return;
77
+ return;
71
+ }
78
+ }
72
+ memory_region_add_subregion(&s->peri_mr, THERMAL_OFFSET,
79
+
73
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->thermal), 0));
80
+ object_property_set_bool(OBJECT(&s->nvm), true, "realized", &err);
81
+ if (err) {
82
+ error_propagate(errp, err);
83
+ return;
84
+ }
85
+
86
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->nvm), 0);
87
+ memory_region_add_subregion_overlap(&s->container, NRF51_NVMC_BASE, mr, 0);
88
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->nvm), 1);
89
+ memory_region_add_subregion_overlap(&s->container, NRF51_FICR_BASE, mr, 0);
90
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->nvm), 2);
91
+ memory_region_add_subregion_overlap(&s->container, NRF51_UICR_BASE, mr, 0);
92
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->nvm), 3);
93
+ memory_region_add_subregion_overlap(&s->container, NRF51_FLASH_BASE, mr, 0);
74
+
94
+
75
/* GPIO */
95
/* GPIO */
76
object_property_set_bool(OBJECT(&s->gpio), true, "realized", &err);
96
object_property_set_bool(OBJECT(&s->gpio), true, "realized", &err);
77
if (err) {
97
if (err) {
98
@@ -XXX,XX +XXX,XX @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
99
100
create_unimplemented_device("nrf51_soc.io", NRF51_IOMEM_BASE,
101
NRF51_IOMEM_SIZE);
102
- create_unimplemented_device("nrf51_soc.ficr", NRF51_FICR_BASE,
103
- NRF51_FICR_SIZE);
104
create_unimplemented_device("nrf51_soc.private",
105
NRF51_PRIVATE_BASE, NRF51_PRIVATE_SIZE);
106
}
107
@@ -XXX,XX +XXX,XX @@ static void nrf51_soc_init(Object *obj)
108
sysbus_init_child_obj(obj, "rng", &s->rng, sizeof(s->rng),
109
TYPE_NRF51_RNG);
110
111
+ sysbus_init_child_obj(obj, "nvm", &s->nvm, sizeof(s->nvm), TYPE_NRF51_NVM);
112
+
113
sysbus_init_child_obj(obj, "gpio", &s->gpio, sizeof(s->gpio),
114
TYPE_NRF51_GPIO);
115
78
--
116
--
79
2.20.1
117
2.20.1
80
118
81
119
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
1
From: Steffen Görtz <contrib@steffen-goertz.de>
2
2
3
Now that Arm CPUs have advertised features lets add tests to ensure
3
Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
4
we maintain their expected availability with and without KVM.
4
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
5
5
Acked-by: Thomas Huth <thuth@redhat.com>
6
Signed-off-by: Andrew Jones <drjones@redhat.com>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Eric Auger <eric.auger@redhat.com>
7
Message-id: 20190201023357.22596-4-stefanha@redhat.com
8
Message-id: 20191024121808.9612-3-drjones@redhat.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
9
---
11
tests/Makefile.include | 5 +-
10
tests/microbit-test.c | 108 ++++++++++++++++++++++++++++++++++++++++++
12
tests/arm-cpu-features.c | 240 +++++++++++++++++++++++++++++++++++++++
11
1 file changed, 108 insertions(+)
13
2 files changed, 244 insertions(+), 1 deletion(-)
14
create mode 100644 tests/arm-cpu-features.c
15
12
16
diff --git a/tests/Makefile.include b/tests/Makefile.include
13
diff --git a/tests/microbit-test.c b/tests/microbit-test.c
17
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
18
--- a/tests/Makefile.include
15
--- a/tests/microbit-test.c
19
+++ b/tests/Makefile.include
16
+++ b/tests/microbit-test.c
20
@@ -XXX,XX +XXX,XX @@ check-qtest-sparc64-$(CONFIG_ISA_TESTDEV) = tests/endianness-test$(EXESUF)
21
check-qtest-sparc64-y += tests/prom-env-test$(EXESUF)
22
check-qtest-sparc64-y += tests/boot-serial-test$(EXESUF)
23
24
+check-qtest-arm-y += tests/arm-cpu-features$(EXESUF)
25
check-qtest-arm-y += tests/microbit-test$(EXESUF)
26
check-qtest-arm-y += tests/m25p80-test$(EXESUF)
27
check-qtest-arm-y += tests/test-arm-mptimer$(EXESUF)
28
@@ -XXX,XX +XXX,XX @@ check-qtest-arm-y += tests/boot-serial-test$(EXESUF)
29
check-qtest-arm-y += tests/hexloader-test$(EXESUF)
30
check-qtest-arm-$(CONFIG_PFLASH_CFI02) += tests/pflash-cfi02-test$(EXESUF)
31
32
-check-qtest-aarch64-y = tests/numa-test$(EXESUF)
33
+check-qtest-aarch64-y += tests/arm-cpu-features$(EXESUF)
34
+check-qtest-aarch64-y += tests/numa-test$(EXESUF)
35
check-qtest-aarch64-y += tests/boot-serial-test$(EXESUF)
36
check-qtest-aarch64-y += tests/migration-test$(EXESUF)
37
# TODO: once aarch64 TCG is fixed on ARM 32 bit host, make test unconditional
38
@@ -XXX,XX +XXX,XX @@ tests/test-qapi-util$(EXESUF): tests/test-qapi-util.o $(test-util-obj-y)
39
tests/numa-test$(EXESUF): tests/numa-test.o
40
tests/vmgenid-test$(EXESUF): tests/vmgenid-test.o tests/boot-sector.o tests/acpi-utils.o
41
tests/cdrom-test$(EXESUF): tests/cdrom-test.o tests/boot-sector.o $(libqos-obj-y)
42
+tests/arm-cpu-features$(EXESUF): tests/arm-cpu-features.o
43
44
tests/migration/stress$(EXESUF): tests/migration/stress.o
45
    $(call quiet-command, $(LINKPROG) -static -O3 $(PTHREAD_LIB) -o $@ $< ,"LINK","$(TARGET_DIR)$@")
46
diff --git a/tests/arm-cpu-features.c b/tests/arm-cpu-features.c
47
new file mode 100644
48
index XXXXXXX..XXXXXXX
49
--- /dev/null
50
+++ b/tests/arm-cpu-features.c
51
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@
52
+/*
18
#include "hw/arm/nrf51.h"
53
+ * Arm CPU feature test cases
19
#include "hw/char/nrf51_uart.h"
54
+ *
20
#include "hw/gpio/nrf51_gpio.h"
55
+ * Copyright (c) 2019 Red Hat Inc.
21
+#include "hw/nvram/nrf51_nvm.h"
56
+ * Authors:
22
#include "hw/timer/nrf51_timer.h"
57
+ * Andrew Jones <drjones@redhat.com>
23
#include "hw/i2c/microbit_i2c.h"
58
+ *
24
59
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
25
@@ -XXX,XX +XXX,XX @@ static void test_microbit_i2c(void)
60
+ * See the COPYING file in the top-level directory.
26
qtest_quit(qts);
61
+ */
27
}
62
+#include "qemu/osdep.h"
28
63
+#include "libqtest.h"
29
+#define FLASH_SIZE (256 * NRF51_PAGE_SIZE)
64
+#include "qapi/qmp/qdict.h"
65
+#include "qapi/qmp/qjson.h"
66
+
30
+
67
+#define MACHINE "-machine virt,gic-version=max "
31
+static void fill_and_erase(QTestState *qts, hwaddr base, hwaddr size,
68
+#define QUERY_HEAD "{ 'execute': 'query-cpu-model-expansion', " \
32
+ uint32_t address_reg)
69
+ "'arguments': { 'type': 'full', "
33
+{
70
+#define QUERY_TAIL "}}"
34
+ hwaddr i;
71
+
35
+
72
+static QDict *do_query_no_props(QTestState *qts, const char *cpu_type)
36
+ /* Erase Page */
73
+{
37
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x02);
74
+ return qtest_qmp(qts, QUERY_HEAD "'model': { 'name': %s }"
38
+ qtest_writel(qts, NRF51_NVMC_BASE + address_reg, base);
75
+ QUERY_TAIL, cpu_type);
39
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x00);
40
+
41
+ /* Check memory */
42
+ for (i = 0; i < size / 4; i++) {
43
+ g_assert_cmpuint(qtest_readl(qts, base + i * 4), ==, 0xFFFFFFFF);
44
+ }
45
+
46
+ /* Fill memory */
47
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x01);
48
+ for (i = 0; i < size / 4; i++) {
49
+ qtest_writel(qts, base + i * 4, i);
50
+ g_assert_cmpuint(qtest_readl(qts, base + i * 4), ==, i);
51
+ }
52
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x00);
76
+}
53
+}
77
+
54
+
78
+static QDict *do_query(QTestState *qts, const char *cpu_type,
55
+static void test_nrf51_nvmc(void)
79
+ const char *fmt, ...)
80
+{
56
+{
81
+ QDict *resp;
57
+ uint32_t value;
58
+ hwaddr i;
59
+ QTestState *qts = qtest_init("-M microbit");
82
+
60
+
83
+ if (fmt) {
61
+ /* Test always ready */
84
+ QDict *args;
62
+ value = qtest_readl(qts, NRF51_NVMC_BASE + NRF51_NVMC_READY);
85
+ va_list ap;
63
+ g_assert_cmpuint(value & 0x01, ==, 0x01);
86
+
64
+
87
+ va_start(ap, fmt);
65
+ /* Test write-read config register */
88
+ args = qdict_from_vjsonf_nofail(fmt, ap);
66
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x03);
89
+ va_end(ap);
67
+ g_assert_cmpuint(qtest_readl(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG),
68
+ ==, 0x03);
69
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x00);
70
+ g_assert_cmpuint(qtest_readl(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG),
71
+ ==, 0x00);
90
+
72
+
91
+ resp = qtest_qmp(qts, QUERY_HEAD "'model': { 'name': %s, "
73
+ /* Test PCR0 */
92
+ "'props': %p }"
74
+ fill_and_erase(qts, NRF51_FLASH_BASE, NRF51_PAGE_SIZE,
93
+ QUERY_TAIL, cpu_type, args);
75
+ NRF51_NVMC_ERASEPCR0);
94
+ } else {
76
+ fill_and_erase(qts, NRF51_FLASH_BASE + NRF51_PAGE_SIZE,
95
+ resp = do_query_no_props(qts, cpu_type);
77
+ NRF51_PAGE_SIZE, NRF51_NVMC_ERASEPCR0);
78
+
79
+ /* Test PCR1 */
80
+ fill_and_erase(qts, NRF51_FLASH_BASE, NRF51_PAGE_SIZE,
81
+ NRF51_NVMC_ERASEPCR1);
82
+ fill_and_erase(qts, NRF51_FLASH_BASE + NRF51_PAGE_SIZE,
83
+ NRF51_PAGE_SIZE, NRF51_NVMC_ERASEPCR1);
84
+
85
+ /* Erase all */
86
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x02);
87
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_ERASEALL, 0x01);
88
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x00);
89
+
90
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x01);
91
+ for (i = 0; i < FLASH_SIZE / 4; i++) {
92
+ qtest_writel(qts, NRF51_FLASH_BASE + i * 4, i);
93
+ g_assert_cmpuint(qtest_readl(qts, NRF51_FLASH_BASE + i * 4), ==, i);
94
+ }
95
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x00);
96
+
97
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x02);
98
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_ERASEALL, 0x01);
99
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x00);
100
+
101
+ for (i = 0; i < FLASH_SIZE / 4; i++) {
102
+ g_assert_cmpuint(qtest_readl(qts, NRF51_FLASH_BASE + i * 4),
103
+ ==, 0xFFFFFFFF);
96
+ }
104
+ }
97
+
105
+
98
+ return resp;
106
+ /* Erase UICR */
99
+}
107
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x02);
108
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_ERASEUICR, 0x01);
109
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x00);
100
+
110
+
101
+static const char *resp_get_error(QDict *resp)
111
+ for (i = 0; i < NRF51_UICR_SIZE / 4; i++) {
102
+{
112
+ g_assert_cmpuint(qtest_readl(qts, NRF51_UICR_BASE + i * 4),
103
+ QDict *qdict;
113
+ ==, 0xFFFFFFFF);
114
+ }
104
+
115
+
105
+ g_assert(resp);
116
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x01);
117
+ for (i = 0; i < NRF51_UICR_SIZE / 4; i++) {
118
+ qtest_writel(qts, NRF51_UICR_BASE + i * 4, i);
119
+ g_assert_cmpuint(qtest_readl(qts, NRF51_UICR_BASE + i * 4), ==, i);
120
+ }
121
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x00);
106
+
122
+
107
+ qdict = qdict_get_qdict(resp, "error");
123
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x02);
108
+ if (qdict) {
124
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_ERASEUICR, 0x01);
109
+ return qdict_get_str(qdict, "desc");
125
+ qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x00);
110
+ }
111
+ return NULL;
112
+}
113
+
126
+
114
+#define assert_error(qts, cpu_type, expected_error, fmt, ...) \
127
+ for (i = 0; i < NRF51_UICR_SIZE / 4; i++) {
115
+({ \
128
+ g_assert_cmpuint(qtest_readl(qts, NRF51_UICR_BASE + i * 4),
116
+ QDict *_resp; \
129
+ ==, 0xFFFFFFFF);
117
+ const char *_error; \
118
+ \
119
+ _resp = do_query(qts, cpu_type, fmt, ##__VA_ARGS__); \
120
+ g_assert(_resp); \
121
+ _error = resp_get_error(_resp); \
122
+ g_assert(_error); \
123
+ g_assert(g_str_equal(_error, expected_error)); \
124
+ qobject_unref(_resp); \
125
+})
126
+
127
+static bool resp_has_props(QDict *resp)
128
+{
129
+ QDict *qdict;
130
+
131
+ g_assert(resp);
132
+
133
+ if (!qdict_haskey(resp, "return")) {
134
+ return false;
135
+ }
136
+ qdict = qdict_get_qdict(resp, "return");
137
+
138
+ if (!qdict_haskey(qdict, "model")) {
139
+ return false;
140
+ }
141
+ qdict = qdict_get_qdict(qdict, "model");
142
+
143
+ return qdict_haskey(qdict, "props");
144
+}
145
+
146
+static QDict *resp_get_props(QDict *resp)
147
+{
148
+ QDict *qdict;
149
+
150
+ g_assert(resp);
151
+ g_assert(resp_has_props(resp));
152
+
153
+ qdict = qdict_get_qdict(resp, "return");
154
+ qdict = qdict_get_qdict(qdict, "model");
155
+ qdict = qdict_get_qdict(qdict, "props");
156
+ return qdict;
157
+}
158
+
159
+#define assert_has_feature(qts, cpu_type, feature) \
160
+({ \
161
+ QDict *_resp = do_query_no_props(qts, cpu_type); \
162
+ g_assert(_resp); \
163
+ g_assert(resp_has_props(_resp)); \
164
+ g_assert(qdict_get(resp_get_props(_resp), feature)); \
165
+ qobject_unref(_resp); \
166
+})
167
+
168
+#define assert_has_not_feature(qts, cpu_type, feature) \
169
+({ \
170
+ QDict *_resp = do_query_no_props(qts, cpu_type); \
171
+ g_assert(_resp); \
172
+ g_assert(!resp_has_props(_resp) || \
173
+ !qdict_get(resp_get_props(_resp), feature)); \
174
+ qobject_unref(_resp); \
175
+})
176
+
177
+static void assert_type_full(QTestState *qts)
178
+{
179
+ const char *error;
180
+ QDict *resp;
181
+
182
+ resp = qtest_qmp(qts, "{ 'execute': 'query-cpu-model-expansion', "
183
+ "'arguments': { 'type': 'static', "
184
+ "'model': { 'name': 'foo' }}}");
185
+ g_assert(resp);
186
+ error = resp_get_error(resp);
187
+ g_assert(error);
188
+ g_assert(g_str_equal(error,
189
+ "The requested expansion type is not supported"));
190
+ qobject_unref(resp);
191
+}
192
+
193
+static void assert_bad_props(QTestState *qts, const char *cpu_type)
194
+{
195
+ const char *error;
196
+ QDict *resp;
197
+
198
+ resp = qtest_qmp(qts, "{ 'execute': 'query-cpu-model-expansion', "
199
+ "'arguments': { 'type': 'full', "
200
+ "'model': { 'name': %s, "
201
+ "'props': false }}}",
202
+ cpu_type);
203
+ g_assert(resp);
204
+ error = resp_get_error(resp);
205
+ g_assert(error);
206
+ g_assert(g_str_equal(error,
207
+ "Invalid parameter type for 'props', expected: dict"));
208
+ qobject_unref(resp);
209
+}
210
+
211
+static void test_query_cpu_model_expansion(const void *data)
212
+{
213
+ QTestState *qts;
214
+
215
+ qts = qtest_init(MACHINE "-cpu max");
216
+
217
+ /* Test common query-cpu-model-expansion input validation */
218
+ assert_type_full(qts);
219
+ assert_bad_props(qts, "max");
220
+ assert_error(qts, "foo", "The CPU type 'foo' is not a recognized "
221
+ "ARM CPU type", NULL);
222
+ assert_error(qts, "max", "Parameter 'not-a-prop' is unexpected",
223
+ "{ 'not-a-prop': false }");
224
+ assert_error(qts, "host", "The CPU type 'host' requires KVM", NULL);
225
+
226
+ /* Test expected feature presence/absence for some cpu types */
227
+ assert_has_feature(qts, "max", "pmu");
228
+ assert_has_feature(qts, "cortex-a15", "pmu");
229
+ assert_has_not_feature(qts, "cortex-a15", "aarch64");
230
+
231
+ if (g_str_equal(qtest_get_arch(), "aarch64")) {
232
+ assert_has_feature(qts, "max", "aarch64");
233
+ assert_has_feature(qts, "cortex-a57", "pmu");
234
+ assert_has_feature(qts, "cortex-a57", "aarch64");
235
+
236
+ /* Test that features that depend on KVM generate errors without. */
237
+ assert_error(qts, "max",
238
+ "'aarch64' feature cannot be disabled "
239
+ "unless KVM is enabled and 32-bit EL1 "
240
+ "is supported",
241
+ "{ 'aarch64': false }");
242
+ }
130
+ }
243
+
131
+
244
+ qtest_quit(qts);
132
+ qtest_quit(qts);
245
+}
133
+}
246
+
134
+
247
+static void test_query_cpu_model_expansion_kvm(const void *data)
135
static void test_nrf51_gpio(void)
248
+{
136
{
249
+ QTestState *qts;
137
size_t i;
250
+
138
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
251
+ qts = qtest_init(MACHINE "-accel kvm -cpu host");
139
252
+
140
qtest_add_func("/microbit/nrf51/uart", test_nrf51_uart);
253
+ if (g_str_equal(qtest_get_arch(), "aarch64")) {
141
qtest_add_func("/microbit/nrf51/gpio", test_nrf51_gpio);
254
+ assert_has_feature(qts, "host", "aarch64");
142
+ qtest_add_func("/microbit/nrf51/nvmc", test_nrf51_nvmc);
255
+ assert_has_feature(qts, "host", "pmu");
143
qtest_add_func("/microbit/nrf51/timer", test_nrf51_timer);
256
+
144
qtest_add_func("/microbit/microbit/i2c", test_microbit_i2c);
257
+ assert_error(qts, "cortex-a15",
145
258
+ "We cannot guarantee the CPU type 'cortex-a15' works "
259
+ "with KVM on this host", NULL);
260
+ } else {
261
+ assert_has_not_feature(qts, "host", "aarch64");
262
+ assert_has_not_feature(qts, "host", "pmu");
263
+ }
264
+
265
+ qtest_quit(qts);
266
+}
267
+
268
+int main(int argc, char **argv)
269
+{
270
+ bool kvm_available = false;
271
+
272
+ if (!access("/dev/kvm", R_OK | W_OK)) {
273
+#if defined(HOST_AARCH64)
274
+ kvm_available = g_str_equal(qtest_get_arch(), "aarch64");
275
+#elif defined(HOST_ARM)
276
+ kvm_available = g_str_equal(qtest_get_arch(), "arm");
277
+#endif
278
+ }
279
+
280
+ g_test_init(&argc, &argv, NULL);
281
+
282
+ qtest_add_data_func("/arm/query-cpu-model-expansion",
283
+ NULL, test_query_cpu_model_expansion);
284
+
285
+ if (kvm_available) {
286
+ qtest_add_data_func("/arm/kvm/query-cpu-model-expansion",
287
+ NULL, test_query_cpu_model_expansion_kvm);
288
+ }
289
+
290
+ return g_test_run();
291
+}
292
--
146
--
293
2.20.1
147
2.20.1
294
148
295
149
diff view generated by jsdifflib