1
Probably the last arm pullreq before softfreeze...
1
Hi; here's this week's arm pullreq. Mostly this is my
2
work on FEAT_MOPS and FEAT_HBC, but there are some
3
other bits and pieces in there too, including a recent
4
set of elf2dmp patches.
2
5
3
The following changes since commit 58560ad254fbda71d4daa6622d71683190070ee2:
6
thanks
7
-- PMM
4
8
5
Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-4.2-20191024' into staging (2019-10-24 16:22:58 +0100)
9
The following changes since commit 55394dcbec8f0c29c30e792c102a0edd50a52bf4:
10
11
Merge tag 'pull-loongarch-20230920' of https://gitlab.com/gaosong/qemu into staging (2023-09-20 13:56:18 -0400)
6
12
7
are available in the Git repository at:
13
are available in the Git repository at:
8
14
9
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20191024
15
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20230921
10
16
11
for you to fetch changes up to a01a4a3e85ae8f6fe21adbedc80f7013faabdcf4:
17
for you to fetch changes up to 231f6a7d66254a58bedbee458591b780e0a507b1:
12
18
13
hw/arm/highbank: Use AddressSpace when using write_secondary_boot() (2019-10-24 17:16:30 +0100)
19
elf2dmp: rework PDB_STREAM_INDEXES::segments obtaining (2023-09-21 16:13:54 +0100)
14
20
15
----------------------------------------------------------------
21
----------------------------------------------------------------
16
target-arm queue:
22
target-arm queue:
17
* raspi boards: some cleanup
23
* target/m68k: Add URL to semihosting spec
18
* raspi: implement the bcm2835 system timer device
24
* docs/devel/loads-stores: Fix git grep regexes
19
* raspi: implement a dummy thermal sensor
25
* hw/arm/boot: Set SCR_EL3.FGTEn when booting kernel
20
* KVM: support providing SVE to the guest
26
* linux-user: Correct SME feature names reported in cpuinfo
21
* misc devices: switch to ptimer transaction API
27
* linux-user: Add missing arm32 hwcaps
22
* cache TB flag state to improve performance of cpu_get_tb_cpu_state
28
* Don't skip MTE checks for LDRT/STRT at EL0
23
* aspeed: Add an AST2600 eval board
29
* Implement FEAT_HBC
30
* Implement FEAT_MOPS
31
* audio/jackaudio: Avoid dynamic stack allocation
32
* sbsa-ref: add non-secure EL2 virtual timer
33
* elf2dmp: improve Win2022, Win11 and large dumps
24
34
25
----------------------------------------------------------------
35
----------------------------------------------------------------
26
Andrew Jones (9):
36
Fabian Vogt (1):
27
target/arm/monitor: Introduce qmp_query_cpu_model_expansion
37
hw/arm/boot: Set SCR_EL3.FGTEn when booting kernel
28
tests: arm: Introduce cpu feature tests
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
38
37
Cédric Le Goater (2):
39
Marcin Juszkiewicz (1):
38
hw/gpio: Fix property accessors of the AST2600 GPIO 1.8V model
40
sbsa-ref: add non-secure EL2 virtual timer
39
aspeed: Add an AST2600 eval board
40
41
41
Peter Maydell (8):
42
Peter Maydell (23):
42
hw/net/fsl_etsec/etsec.c: Switch to transaction-based ptimer API
43
target/m68k: Add URL to semihosting spec
43
hw/timer/xilinx_timer.c: Switch to transaction-based ptimer API
44
docs/devel/loads-stores: Fix git grep regexes
44
hw/dma/xilinx_axidma.c: Switch to transaction-based ptimer API
45
linux-user/elfload.c: Correct SME feature names reported in cpuinfo
45
hw/timer/slavio_timer: Remove useless check for NULL t->timer
46
linux-user/elfload.c: Add missing arm and arm64 hwcap values
46
hw/timer/slavio_timer.c: Switch to transaction-based ptimer API
47
linux-user/elfload.c: Report previously missing arm32 hwcaps
47
hw/timer/grlib_gptimer.c: Switch to transaction-based ptimer API
48
target/arm: Update AArch64 ID register field definitions
48
hw/m68k/mcf5206.c: Switch to transaction-based ptimer API
49
target/arm: Update user-mode ID reg mask values
49
hw/watchdog/milkymist-sysctl.c: Switch to transaction-based ptimer API
50
target/arm: Implement FEAT_HBC
51
target/arm: Remove unused allocation_tag_mem() argument
52
target/arm: Don't skip MTE checks for LDRT/STRT at EL0
53
target/arm: Implement FEAT_MOPS enable bits
54
target/arm: Pass unpriv bool to get_a64_user_mem_index()
55
target/arm: Define syndrome function for MOPS exceptions
56
target/arm: New function allocation_tag_mem_probe()
57
target/arm: Implement MTE tag-checking functions for FEAT_MOPS
58
target/arm: Implement the SET* instructions
59
target/arm: Define new TB flag for ATA0
60
target/arm: Implement the SETG* instructions
61
target/arm: Implement MTE tag-checking functions for FEAT_MOPS copies
62
target/arm: Implement the CPY* instructions
63
target/arm: Enable FEAT_MOPS for CPU 'max'
64
audio/jackaudio: Avoid dynamic stack allocation in qjack_client_init
65
audio/jackaudio: Avoid dynamic stack allocation in qjack_process()
50
66
51
Philippe Mathieu-Daudé (8):
67
Viktor Prutyanov (5):
52
hw/misc/bcm2835_thermal: Add a dummy BCM2835 thermal sensor
68
elf2dmp: replace PE export name check with PDB name check
53
hw/arm/bcm2835_peripherals: Use the thermal sensor block
69
elf2dmp: introduce physical block alignment
54
hw/timer/bcm2835: Add the BCM2835 SYS_timer
70
elf2dmp: introduce merging of physical memory runs
55
hw/arm/bcm2835_peripherals: Use the SYS_timer
71
elf2dmp: use Linux mmap with MAP_NORESERVE when possible
56
hw/arm/bcm2836: Make the SoC code modular
72
elf2dmp: rework PDB_STREAM_INDEXES::segments obtaining
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
docs/devel/loads-stores.rst | 40 +-
62
target/arm: Split out rebuild_hflags_common
75
docs/system/arm/emulation.rst | 2 +
63
target/arm: Split out rebuild_hflags_a64
76
contrib/elf2dmp/addrspace.h | 1 +
64
target/arm: Split out rebuild_hflags_common_32
77
contrib/elf2dmp/pdb.h | 2 +-
65
target/arm: Split arm_cpu_data_is_big_endian
78
contrib/elf2dmp/qemu_elf.h | 2 +
66
target/arm: Split out rebuild_hflags_m32
79
target/arm/cpu.h | 35 ++
67
target/arm: Reduce tests vs M-profile in cpu_get_tb_cpu_state
80
target/arm/internals.h | 55 +++
68
target/arm: Split out rebuild_hflags_a32
81
target/arm/syndrome.h | 12 +
69
target/arm: Split out rebuild_hflags_aprofile
82
target/arm/tcg/helper-a64.h | 14 +
70
target/arm: Hoist XSCALE_CPAR, VECLEN, VECSTRIDE in cpu_get_tb_cpu_state
83
target/arm/tcg/translate.h | 4 +-
71
target/arm: Simplify set of PSTATE_SS in cpu_get_tb_cpu_state
84
target/arm/tcg/a64.decode | 38 +-
72
target/arm: Hoist computation of TBFLAG_A32.VFPEN
85
audio/jackaudio.c | 21 +-
73
target/arm: Add arm_rebuild_hflags
86
contrib/elf2dmp/addrspace.c | 31 +-
74
target/arm: Split out arm_mmu_idx_el
87
contrib/elf2dmp/main.c | 154 ++++----
75
target/arm: Hoist store to cs_base in cpu_get_tb_cpu_state
88
contrib/elf2dmp/pdb.c | 15 +-
76
target/arm: Add HELPER(rebuild_hflags_{a32, a64, m32})
89
contrib/elf2dmp/qemu_elf.c | 68 +++-
77
target/arm: Rebuild hflags at EL changes
90
hw/arm/boot.c | 4 +
78
target/arm: Rebuild hflags at MSR writes
91
hw/arm/sbsa-ref.c | 2 +
79
target/arm: Rebuild hflags at CPSR writes
92
linux-user/elfload.c | 72 +++-
80
target/arm: Rebuild hflags at Xscale SCTLR writes
93
target/arm/helper.c | 39 +-
81
target/arm: Rebuild hflags for M-profile
94
target/arm/tcg/cpu64.c | 5 +
82
target/arm: Rebuild hflags for M-profile NVIC
95
target/arm/tcg/helper-a64.c | 878 +++++++++++++++++++++++++++++++++++++++++
83
linux-user/aarch64: Rebuild hflags for TARGET_WORDS_BIGENDIAN
96
target/arm/tcg/hflags.c | 21 +
84
linux-user/arm: Rebuild hflags for TARGET_WORDS_BIGENDIAN
97
target/arm/tcg/mte_helper.c | 281 +++++++++++--
85
target/arm: Rely on hflags correct in cpu_get_tb_cpu_state
98
target/arm/tcg/translate-a64.c | 164 +++++++-
86
99
target/m68k/m68k-semi.c | 4 +
87
hw/misc/Makefile.objs | 1 +
100
tests/tcg/aarch64/sysregs.c | 4 +-
88
hw/timer/Makefile.objs | 1 +
101
27 files changed, 1768 insertions(+), 200 deletions(-)
89
tests/Makefile.include | 5 +-
90
qapi/machine-target.json | 6 +-
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
diff view generated by jsdifflib
Deleted patch
1
From: Cédric Le Goater <clg@kaod.org>
2
1
3
The property names of AST2600 GPIO 1.8V model are one character bigger
4
than the names of the other ASPEED GPIO model. Increase the string
5
buffer size by one and be more strict on the expected pattern of the
6
property name.
7
8
This fixes the QOM test of the ast2600-evb machine under :
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
27
--- a/hw/gpio/aspeed_gpio.c
28
+++ b/hw/gpio/aspeed_gpio.c
29
@@ -XXX,XX +XXX,XX @@ static void aspeed_gpio_get_pin(Object *obj, Visitor *v, const char *name,
30
{
31
int pin = 0xfff;
32
bool level = true;
33
- char group[3];
34
+ char group[4];
35
AspeedGPIOState *s = ASPEED_GPIO(obj);
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;
62
}
63
--
64
2.20.1
65
66
diff view generated by jsdifflib
1
Switch the mcf5206 code away from bottom-half based ptimers to
1
The spec for m68k semihosting is documented in the libgloss
2
the new transaction-based ptimer API. This just requires adding
2
sources. Add a comment with the URL for it, as we already
3
begin/commit calls around the various places that modify the ptimer
3
have for nios2 semihosting.
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: Thomas Huth <thuth@redhat.com>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20191021140600.10725-1-peter.maydell@linaro.org
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Message-id: 20230801154451.3505492-1-peter.maydell@linaro.org
9
---
10
---
10
hw/m68k/mcf5206.c | 15 +++++++++------
11
target/m68k/m68k-semi.c | 4 ++++
11
1 file changed, 9 insertions(+), 6 deletions(-)
12
1 file changed, 4 insertions(+)
12
13
13
diff --git a/hw/m68k/mcf5206.c b/hw/m68k/mcf5206.c
14
diff --git a/target/m68k/m68k-semi.c b/target/m68k/m68k-semi.c
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/m68k/mcf5206.c
16
--- a/target/m68k/m68k-semi.c
16
+++ b/hw/m68k/mcf5206.c
17
+++ b/target/m68k/m68k-semi.c
17
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@
19
*
20
* You should have received a copy of the GNU General Public License
21
* along with this program; if not, see <http://www.gnu.org/licenses/>.
22
+ *
23
+ * The semihosting protocol implemented here is described in the
24
+ * libgloss sources:
25
+ * https://sourceware.org/git/?p=newlib-cygwin.git;a=blob;f=libgloss/m68k/m68k-semi.txt;hb=HEAD
26
*/
18
27
19
#include "qemu/osdep.h"
28
#include "qemu/osdep.h"
20
#include "qemu/error-report.h"
21
-#include "qemu/main-loop.h"
22
#include "cpu.h"
23
#include "hw/hw.h"
24
#include "hw/irq.h"
25
@@ -XXX,XX +XXX,XX @@ static void m5206_timer_recalibrate(m5206_timer_state *s)
26
int prescale;
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
+ }
37
38
prescale = (s->tmr >> 8) + 1;
39
mode = (s->tmr >> 1) & 3;
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
--
29
--
73
2.20.1
30
2.34.1
74
31
75
32
diff view generated by jsdifflib
1
In the slavio timer devcie, the ptimer TimerContext::timer is
1
The loads-and-stores documentation includes git grep regexes to find
2
always created by slavio_timer_init(), so there's no need to
2
occurrences of the various functions. Some of these regexes have
3
check it for NULL; remove the single unneeded NULL check.
3
errors, typically failing to escape the '?', '(' and ')' when they
4
should be metacharacters (since these are POSIX basic REs). We also
5
weren't consistent about whether to have a ':' on the end of the
6
line introducing the list of regexes in each section.
4
7
5
This will be useful to avoid compiler/Coverity errors when
8
Fix the errors.
6
a subsequent change adds a use of t->timer before the location
9
7
we currently do the NULL check.
10
The following shell rune will complain about any REs in the
11
file which don't have any matches in the codebase:
12
for re in $(sed -ne 's/ - ``\(\\<.*\)``/\1/p' docs/devel/loads-stores.rst); do git grep -q "$re" || echo "no matches for re $re"; done
8
13
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
15
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 20230904161703.3996734-1-peter.maydell@linaro.org
12
Message-id: 20191021134357.14266-2-peter.maydell@linaro.org
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
17
---
15
hw/timer/slavio_timer.c | 12 +++++-------
18
docs/devel/loads-stores.rst | 40 ++++++++++++++++++-------------------
16
1 file changed, 5 insertions(+), 7 deletions(-)
19
1 file changed, 20 insertions(+), 20 deletions(-)
17
20
18
diff --git a/hw/timer/slavio_timer.c b/hw/timer/slavio_timer.c
21
diff --git a/docs/devel/loads-stores.rst b/docs/devel/loads-stores.rst
19
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/timer/slavio_timer.c
23
--- a/docs/devel/loads-stores.rst
21
+++ b/hw/timer/slavio_timer.c
24
+++ b/docs/devel/loads-stores.rst
22
@@ -XXX,XX +XXX,XX @@ static void slavio_timer_mem_writel(void *opaque, hwaddr addr,
25
@@ -XXX,XX +XXX,XX @@ which stores ``val`` to ``ptr`` as an ``{endian}`` order value
23
// set limit, reset counter
26
of size ``sz`` bytes.
24
qemu_irq_lower(t->irq);
27
25
t->limit = val & TIMER_MAX_COUNT32;
28
26
- if (t->timer) {
29
-Regexes for git grep
27
- if (t->limit == 0) { /* free-run */
30
+Regexes for git grep:
28
- ptimer_set_limit(t->timer,
31
- ``\<ld[us]\?[bwlq]\(_[hbl]e\)\?_p\>``
29
- LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 1);
32
- ``\<st[bwlq]\(_[hbl]e\)\?_p\>``
30
- } else {
33
- ``\<st24\(_[hbl]e\)\?_p\>``
31
- ptimer_set_limit(t->timer, LIMIT_TO_PERIODS(t->limit), 1);
34
- - ``\<ldn_\([hbl]e\)?_p\>``
32
- }
35
- - ``\<stn_\([hbl]e\)?_p\>``
33
+ if (t->limit == 0) { /* free-run */
36
+ - ``\<ldn_\([hbl]e\)\?_p\>``
34
+ ptimer_set_limit(t->timer,
37
+ - ``\<stn_\([hbl]e\)\?_p\>``
35
+ LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 1);
38
36
+ } else {
39
``cpu_{ld,st}*_mmu``
37
+ ptimer_set_limit(t->timer, LIMIT_TO_PERIODS(t->limit), 1);
40
~~~~~~~~~~~~~~~~~~~~
38
}
41
@@ -XXX,XX +XXX,XX @@ store: ``cpu_st{size}{end}_mmu(env, ptr, val, oi, retaddr)``
39
}
42
- ``_le`` : little endian
40
break;
43
44
Regexes for git grep:
45
- - ``\<cpu_ld[bwlq](_[bl]e)\?_mmu\>``
46
- - ``\<cpu_st[bwlq](_[bl]e)\?_mmu\>``
47
+ - ``\<cpu_ld[bwlq]\(_[bl]e\)\?_mmu\>``
48
+ - ``\<cpu_st[bwlq]\(_[bl]e\)\?_mmu\>``
49
50
51
``cpu_{ld,st}*_mmuidx_ra``
52
@@ -XXX,XX +XXX,XX @@ store: ``cpu_st{size}{end}_mmuidx_ra(env, ptr, val, mmuidx, retaddr)``
53
- ``_le`` : little endian
54
55
Regexes for git grep:
56
- - ``\<cpu_ld[us]\?[bwlq](_[bl]e)\?_mmuidx_ra\>``
57
- - ``\<cpu_st[bwlq](_[bl]e)\?_mmuidx_ra\>``
58
+ - ``\<cpu_ld[us]\?[bwlq]\(_[bl]e\)\?_mmuidx_ra\>``
59
+ - ``\<cpu_st[bwlq]\(_[bl]e\)\?_mmuidx_ra\>``
60
61
``cpu_{ld,st}*_data_ra``
62
~~~~~~~~~~~~~~~~~~~~~~~~
63
@@ -XXX,XX +XXX,XX @@ store: ``cpu_st{size}{end}_data_ra(env, ptr, val, ra)``
64
- ``_le`` : little endian
65
66
Regexes for git grep:
67
- - ``\<cpu_ld[us]\?[bwlq](_[bl]e)\?_data_ra\>``
68
- - ``\<cpu_st[bwlq](_[bl]e)\?_data_ra\>``
69
+ - ``\<cpu_ld[us]\?[bwlq]\(_[bl]e\)\?_data_ra\>``
70
+ - ``\<cpu_st[bwlq]\(_[bl]e\)\?_data_ra\>``
71
72
``cpu_{ld,st}*_data``
73
~~~~~~~~~~~~~~~~~~~~~
74
@@ -XXX,XX +XXX,XX @@ store: ``cpu_st{size}{end}_data(env, ptr, val)``
75
- ``_be`` : big endian
76
- ``_le`` : little endian
77
78
-Regexes for git grep
79
- - ``\<cpu_ld[us]\?[bwlq](_[bl]e)\?_data\>``
80
- - ``\<cpu_st[bwlq](_[bl]e)\?_data\+\>``
81
+Regexes for git grep:
82
+ - ``\<cpu_ld[us]\?[bwlq]\(_[bl]e\)\?_data\>``
83
+ - ``\<cpu_st[bwlq]\(_[bl]e\)\?_data\+\>``
84
85
``cpu_ld*_code``
86
~~~~~~~~~~~~~~~~
87
@@ -XXX,XX +XXX,XX @@ swap: ``translator_ld{sign}{size}_swap(env, ptr, swap)``
88
- ``l`` : 32 bits
89
- ``q`` : 64 bits
90
91
-Regexes for git grep
92
+Regexes for git grep:
93
- ``\<translator_ld[us]\?[bwlq]\(_swap\)\?\>``
94
95
``helper_{ld,st}*_mmu``
96
@@ -XXX,XX +XXX,XX @@ store: ``helper_{size}_mmu(env, addr, val, opindex, retaddr)``
97
- ``l`` : 32 bits
98
- ``q`` : 64 bits
99
100
-Regexes for git grep
101
+Regexes for git grep:
102
- ``\<helper_ld[us]\?[bwlq]_mmu\>``
103
- ``\<helper_st[bwlq]_mmu\>``
104
105
@@ -XXX,XX +XXX,XX @@ succeeded using a MemTxResult return code.
106
107
The ``_{endian}`` suffix is omitted for byte accesses.
108
109
-Regexes for git grep
110
+Regexes for git grep:
111
- ``\<address_space_\(read\|write\|rw\)\>``
112
- ``\<address_space_ldu\?[bwql]\(_[lb]e\)\?\>``
113
- ``\<address_space_st[bwql]\(_[lb]e\)\?\>``
114
@@ -XXX,XX +XXX,XX @@ Note that portions of the write which attempt to write data to a
115
device will be silently ignored -- only real RAM and ROM will
116
be written to.
117
118
-Regexes for git grep
119
+Regexes for git grep:
120
- ``address_space_write_rom``
121
122
``{ld,st}*_phys``
123
@@ -XXX,XX +XXX,XX @@ device doing the access has no way to report such an error.
124
125
The ``_{endian}_`` infix is omitted for byte accesses.
126
127
-Regexes for git grep
128
+Regexes for git grep:
129
- ``\<ldu\?[bwlq]\(_[bl]e\)\?_phys\>``
130
- ``\<st[bwlq]\(_[bl]e\)\?_phys\>``
131
132
@@ -XXX,XX +XXX,XX @@ For new code they are better avoided:
133
134
``cpu_physical_memory_rw``
135
136
-Regexes for git grep
137
+Regexes for git grep:
138
- ``\<cpu_physical_memory_\(read\|write\|rw\)\>``
139
140
``cpu_memory_rw_debug``
141
@@ -XXX,XX +XXX,XX @@ make sure our existing code is doing things correctly.
142
143
``dma_memory_rw``
144
145
-Regexes for git grep
146
+Regexes for git grep:
147
- ``\<dma_memory_\(read\|write\|rw\)\>``
148
- ``\<ldu\?[bwlq]\(_[bl]e\)\?_dma\>``
149
- ``\<st[bwlq]\(_[bl]e\)\?_dma\>``
150
@@ -XXX,XX +XXX,XX @@ correct address space for that device.
151
152
The ``_{endian}_`` infix is omitted for byte accesses.
153
154
-Regexes for git grep
155
+Regexes for git grep:
156
- ``\<pci_dma_\(read\|write\|rw\)\>``
157
- ``\<ldu\?[bwlq]\(_[bl]e\)\?_pci_dma\>``
158
- ``\<st[bwlq]\(_[bl]e\)\?_pci_dma\>``
41
--
159
--
42
2.20.1
160
2.34.1
43
161
44
162
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Fabian Vogt <fvogt@suse.de>
2
2
3
Continue setting, but not relying upon, env->hflags.
3
Just like d7ef5e16a17c sets SCR_EL3.HXEn for FEAT_HCX, this commit
4
handles SCR_EL3.FGTEn for FEAT_FGT:
4
5
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
When we direct boot a kernel on a CPU which emulates EL3, we need to
6
Message-id: 20191023150057.25731-24-richard.henderson@linaro.org
7
set up the EL3 system registers as the Linux kernel documentation
8
specifies:
9
https://www.kernel.org/doc/Documentation/arm64/booting.rst
10
11
> For CPUs with the Fine Grained Traps (FEAT_FGT) extension present:
12
> - If EL3 is present and the kernel is entered at EL2:
13
> - SCR_EL3.FGTEn (bit 27) must be initialised to 0b1.
14
15
Cc: qemu-stable@nongnu.org
16
Signed-off-by: Fabian Vogt <fvogt@suse.de>
17
Message-id: 4831384.GXAFRqVoOG@linux-e202.suse.de
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
18
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
20
---
10
linux-user/arm/cpu_loop.c | 1 +
21
hw/arm/boot.c | 4 ++++
11
1 file changed, 1 insertion(+)
22
1 file changed, 4 insertions(+)
12
23
13
diff --git a/linux-user/arm/cpu_loop.c b/linux-user/arm/cpu_loop.c
24
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
14
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
15
--- a/linux-user/arm/cpu_loop.c
26
--- a/hw/arm/boot.c
16
+++ b/linux-user/arm/cpu_loop.c
27
+++ b/hw/arm/boot.c
17
@@ -XXX,XX +XXX,XX @@ void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
28
@@ -XXX,XX +XXX,XX @@ static void do_cpu_reset(void *opaque)
18
} else {
29
if (cpu_isar_feature(aa64_hcx, cpu)) {
19
env->cp15.sctlr_el[1] |= SCTLR_B;
30
env->cp15.scr_el3 |= SCR_HXEN;
20
}
31
}
21
+ arm_rebuild_hflags(env);
32
+ if (cpu_isar_feature(aa64_fgt, cpu)) {
22
#endif
33
+ env->cp15.scr_el3 |= SCR_FGTEN;
23
34
+ }
24
ts->stack_base = info->start_stack;
35
+
36
/* AArch64 kernels never boot in secure mode */
37
assert(!info->secure_boot);
38
/* This hook is only supported for AArch32 currently:
25
--
39
--
26
2.20.1
40
2.34.1
27
28
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
Some of the names we use for CPU features in linux-user's dummy
2
/proc/cpuinfo don't match the strings in the real kernel in
3
arch/arm64/kernel/cpuinfo.c. Specifically, the SME related
4
features have an underscore in the HWCAP_FOO define name,
5
but (like the SVE ones) they do not have an underscore in the
6
string in cpuinfo. Correct the errors.
2
7
3
write_secondary_boot() is used in SMP configurations where the
8
Fixes: a55b9e7226708 ("linux-user: Emulate /proc/cpuinfo on aarch64 and arm")
4
CPU address space might not be the main System Bus.
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
The rom_add_blob_fixed_as() function allow us to specify an
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
address space. Use it to write each boot blob in the corresponding
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
CPU address space.
12
---
13
linux-user/elfload.c | 14 +++++++-------
14
1 file changed, 7 insertions(+), 7 deletions(-)
8
15
9
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
16
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
10
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
11
Message-id: 20191019234715.25750-11-f4bug@amsat.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
hw/arm/raspi.c | 14 ++++++++------
15
1 file changed, 8 insertions(+), 6 deletions(-)
16
17
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
18
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/raspi.c
18
--- a/linux-user/elfload.c
20
+++ b/hw/arm/raspi.c
19
+++ b/linux-user/elfload.c
21
@@ -XXX,XX +XXX,XX @@ static void write_smpboot(ARMCPU *cpu, const struct arm_boot_info *info)
20
@@ -XXX,XX +XXX,XX @@ const char *elf_hwcap2_str(uint32_t bit)
22
QEMU_BUILD_BUG_ON((BOARDSETUP_ADDR & 0xf) != 0
21
[__builtin_ctz(ARM_HWCAP2_A64_RPRES )] = "rpres",
23
|| (BOARDSETUP_ADDR >> 4) >= 0x100);
22
[__builtin_ctz(ARM_HWCAP2_A64_MTE3 )] = "mte3",
24
23
[__builtin_ctz(ARM_HWCAP2_A64_SME )] = "sme",
25
- rom_add_blob_fixed("raspi_smpboot", smpboot, sizeof(smpboot),
24
- [__builtin_ctz(ARM_HWCAP2_A64_SME_I16I64 )] = "sme_i16i64",
26
- info->smp_loader_start);
25
- [__builtin_ctz(ARM_HWCAP2_A64_SME_F64F64 )] = "sme_f64f64",
27
+ rom_add_blob_fixed_as("raspi_smpboot", smpboot, sizeof(smpboot),
26
- [__builtin_ctz(ARM_HWCAP2_A64_SME_I8I32 )] = "sme_i8i32",
28
+ info->smp_loader_start,
27
- [__builtin_ctz(ARM_HWCAP2_A64_SME_F16F32 )] = "sme_f16f32",
29
+ arm_boot_address_space(cpu, info));
28
- [__builtin_ctz(ARM_HWCAP2_A64_SME_B16F32 )] = "sme_b16f32",
30
}
29
- [__builtin_ctz(ARM_HWCAP2_A64_SME_F32F32 )] = "sme_f32f32",
31
30
- [__builtin_ctz(ARM_HWCAP2_A64_SME_FA64 )] = "sme_fa64",
32
static void write_smpboot64(ARMCPU *cpu, const struct arm_boot_info *info)
31
+ [__builtin_ctz(ARM_HWCAP2_A64_SME_I16I64 )] = "smei16i64",
33
{
32
+ [__builtin_ctz(ARM_HWCAP2_A64_SME_F64F64 )] = "smef64f64",
34
+ AddressSpace *as = arm_boot_address_space(cpu, info);
33
+ [__builtin_ctz(ARM_HWCAP2_A64_SME_I8I32 )] = "smei8i32",
35
/* Unlike the AArch32 version we don't need to call the board setup hook.
34
+ [__builtin_ctz(ARM_HWCAP2_A64_SME_F16F32 )] = "smef16f32",
36
* The mechanism for doing the spin-table is also entirely different.
35
+ [__builtin_ctz(ARM_HWCAP2_A64_SME_B16F32 )] = "smeb16f32",
37
* We must have four 64-bit fields at absolute addresses
36
+ [__builtin_ctz(ARM_HWCAP2_A64_SME_F32F32 )] = "smef32f32",
38
@@ -XXX,XX +XXX,XX @@ static void write_smpboot64(ARMCPU *cpu, const struct arm_boot_info *info)
37
+ [__builtin_ctz(ARM_HWCAP2_A64_SME_FA64 )] = "smefa64",
39
0, 0, 0, 0
40
};
38
};
41
39
42
- rom_add_blob_fixed("raspi_smpboot", smpboot, sizeof(smpboot),
40
return bit < ARRAY_SIZE(hwcap_str) ? hwcap_str[bit] : NULL;
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
--
41
--
54
2.20.1
42
2.34.1
55
43
56
44
diff view generated by jsdifflib
1
Switch the milkymist-sysctl code away from bottom-half based
1
Our lists of Arm 32 and 64 bit hwcap values have lagged behind
2
ptimers to the new transaction-based ptimer API. This just requires
2
the Linux kernel. Update them to include all the bits defined
3
adding begin/commit calls around the various places that modify the
3
as of upstream Linux git commit a48fa7efaf1161c1 (in the middle
4
ptimer state, and using the new ptimer_init() function to create the
4
of the kernel 6.6 dev cycle).
5
timer.
5
6
For 64-bit, we don't yet implement any of the features reported via
7
these hwcap bits. For 32-bit we do in fact already implement them
8
all; we'll add the code to set them in a subsequent commit.
6
9
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Message-id: 20191021141040.11007-1-peter.maydell@linaro.org
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
---
13
---
11
hw/timer/milkymist-sysctl.c | 25 ++++++++++++++++++-------
14
linux-user/elfload.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
12
1 file changed, 18 insertions(+), 7 deletions(-)
15
1 file changed, 44 insertions(+)
13
16
14
diff --git a/hw/timer/milkymist-sysctl.c b/hw/timer/milkymist-sysctl.c
17
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
15
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/timer/milkymist-sysctl.c
19
--- a/linux-user/elfload.c
17
+++ b/hw/timer/milkymist-sysctl.c
20
+++ b/linux-user/elfload.c
18
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@ enum
19
#include "hw/ptimer.h"
22
ARM_HWCAP_ARM_VFPD32 = 1 << 19,
20
#include "hw/qdev-properties.h"
23
ARM_HWCAP_ARM_LPAE = 1 << 20,
21
#include "qemu/error-report.h"
24
ARM_HWCAP_ARM_EVTSTRM = 1 << 21,
22
-#include "qemu/main-loop.h"
25
+ ARM_HWCAP_ARM_FPHP = 1 << 22,
23
#include "qemu/module.h"
26
+ ARM_HWCAP_ARM_ASIMDHP = 1 << 23,
27
+ ARM_HWCAP_ARM_ASIMDDP = 1 << 24,
28
+ ARM_HWCAP_ARM_ASIMDFHM = 1 << 25,
29
+ ARM_HWCAP_ARM_ASIMDBF16 = 1 << 26,
30
+ ARM_HWCAP_ARM_I8MM = 1 << 27,
31
};
24
32
25
enum {
33
enum {
26
@@ -XXX,XX +XXX,XX @@ struct MilkymistSysctlState {
34
@@ -XXX,XX +XXX,XX @@ enum {
27
35
ARM_HWCAP2_ARM_SHA1 = 1 << 2,
28
MemoryRegion regs_region;
36
ARM_HWCAP2_ARM_SHA2 = 1 << 3,
29
37
ARM_HWCAP2_ARM_CRC32 = 1 << 4,
30
- QEMUBH *bh0;
38
+ ARM_HWCAP2_ARM_SB = 1 << 5,
31
- QEMUBH *bh1;
39
+ ARM_HWCAP2_ARM_SSBS = 1 << 6,
32
ptimer_state *ptimer0;
40
};
33
ptimer_state *ptimer1;
41
34
42
/* The commpage only exists for 32 bit kernels */
35
@@ -XXX,XX +XXX,XX @@ static void sysctl_write(void *opaque, hwaddr addr, uint64_t value,
43
@@ -XXX,XX +XXX,XX @@ const char *elf_hwcap_str(uint32_t bit)
36
s->regs[addr] = value;
44
[__builtin_ctz(ARM_HWCAP_ARM_VFPD32 )] = "vfpd32",
37
break;
45
[__builtin_ctz(ARM_HWCAP_ARM_LPAE )] = "lpae",
38
case R_TIMER0_COMPARE:
46
[__builtin_ctz(ARM_HWCAP_ARM_EVTSTRM )] = "evtstrm",
39
+ ptimer_transaction_begin(s->ptimer0);
47
+ [__builtin_ctz(ARM_HWCAP_ARM_FPHP )] = "fphp",
40
ptimer_set_limit(s->ptimer0, value, 0);
48
+ [__builtin_ctz(ARM_HWCAP_ARM_ASIMDHP )] = "asimdhp",
41
s->regs[addr] = value;
49
+ [__builtin_ctz(ARM_HWCAP_ARM_ASIMDDP )] = "asimddp",
42
+ ptimer_transaction_commit(s->ptimer0);
50
+ [__builtin_ctz(ARM_HWCAP_ARM_ASIMDFHM )] = "asimdfhm",
43
break;
51
+ [__builtin_ctz(ARM_HWCAP_ARM_ASIMDBF16)] = "asimdbf16",
44
case R_TIMER1_COMPARE:
52
+ [__builtin_ctz(ARM_HWCAP_ARM_I8MM )] = "i8mm",
45
+ ptimer_transaction_begin(s->ptimer1);
53
};
46
ptimer_set_limit(s->ptimer1, value, 0);
54
47
s->regs[addr] = value;
55
return bit < ARRAY_SIZE(hwcap_str) ? hwcap_str[bit] : NULL;
48
+ ptimer_transaction_commit(s->ptimer1);
56
@@ -XXX,XX +XXX,XX @@ const char *elf_hwcap2_str(uint32_t bit)
49
break;
57
[__builtin_ctz(ARM_HWCAP2_ARM_SHA1 )] = "sha1",
50
case R_TIMER0_CONTROL:
58
[__builtin_ctz(ARM_HWCAP2_ARM_SHA2 )] = "sha2",
51
+ ptimer_transaction_begin(s->ptimer0);
59
[__builtin_ctz(ARM_HWCAP2_ARM_CRC32)] = "crc32",
52
s->regs[addr] = value;
60
+ [__builtin_ctz(ARM_HWCAP2_ARM_SB )] = "sb",
53
if (s->regs[R_TIMER0_CONTROL] & CTRL_ENABLE) {
61
+ [__builtin_ctz(ARM_HWCAP2_ARM_SSBS )] = "ssbs",
54
trace_milkymist_sysctl_start_timer0();
62
};
55
@@ -XXX,XX +XXX,XX @@ static void sysctl_write(void *opaque, hwaddr addr, uint64_t value,
63
56
trace_milkymist_sysctl_stop_timer0();
64
return bit < ARRAY_SIZE(hwcap_str) ? hwcap_str[bit] : NULL;
57
ptimer_stop(s->ptimer0);
65
@@ -XXX,XX +XXX,XX @@ enum {
58
}
66
ARM_HWCAP2_A64_SME_B16F32 = 1 << 28,
59
+ ptimer_transaction_commit(s->ptimer0);
67
ARM_HWCAP2_A64_SME_F32F32 = 1 << 29,
60
break;
68
ARM_HWCAP2_A64_SME_FA64 = 1 << 30,
61
case R_TIMER1_CONTROL:
69
+ ARM_HWCAP2_A64_WFXT = 1ULL << 31,
62
+ ptimer_transaction_begin(s->ptimer1);
70
+ ARM_HWCAP2_A64_EBF16 = 1ULL << 32,
63
s->regs[addr] = value;
71
+ ARM_HWCAP2_A64_SVE_EBF16 = 1ULL << 33,
64
if (s->regs[R_TIMER1_CONTROL] & CTRL_ENABLE) {
72
+ ARM_HWCAP2_A64_CSSC = 1ULL << 34,
65
trace_milkymist_sysctl_start_timer1();
73
+ ARM_HWCAP2_A64_RPRFM = 1ULL << 35,
66
@@ -XXX,XX +XXX,XX @@ static void sysctl_write(void *opaque, hwaddr addr, uint64_t value,
74
+ ARM_HWCAP2_A64_SVE2P1 = 1ULL << 36,
67
trace_milkymist_sysctl_stop_timer1();
75
+ ARM_HWCAP2_A64_SME2 = 1ULL << 37,
68
ptimer_stop(s->ptimer1);
76
+ ARM_HWCAP2_A64_SME2P1 = 1ULL << 38,
69
}
77
+ ARM_HWCAP2_A64_SME_I16I32 = 1ULL << 39,
70
+ ptimer_transaction_commit(s->ptimer1);
78
+ ARM_HWCAP2_A64_SME_BI32I32 = 1ULL << 40,
71
break;
79
+ ARM_HWCAP2_A64_SME_B16B16 = 1ULL << 41,
72
case R_ICAP:
80
+ ARM_HWCAP2_A64_SME_F16F16 = 1ULL << 42,
73
sysctl_icap_write(s, value);
81
+ ARM_HWCAP2_A64_MOPS = 1ULL << 43,
74
@@ -XXX,XX +XXX,XX @@ static void milkymist_sysctl_reset(DeviceState *d)
82
+ ARM_HWCAP2_A64_HBC = 1ULL << 44,
75
s->regs[i] = 0;
83
};
76
}
84
77
85
#define ELF_HWCAP get_elf_hwcap()
78
+ ptimer_transaction_begin(s->ptimer0);
86
@@ -XXX,XX +XXX,XX @@ const char *elf_hwcap2_str(uint32_t bit)
79
ptimer_stop(s->ptimer0);
87
[__builtin_ctz(ARM_HWCAP2_A64_SME_B16F32 )] = "smeb16f32",
80
+ ptimer_transaction_commit(s->ptimer0);
88
[__builtin_ctz(ARM_HWCAP2_A64_SME_F32F32 )] = "smef32f32",
81
+ ptimer_transaction_begin(s->ptimer1);
89
[__builtin_ctz(ARM_HWCAP2_A64_SME_FA64 )] = "smefa64",
82
ptimer_stop(s->ptimer1);
90
+ [__builtin_ctz(ARM_HWCAP2_A64_WFXT )] = "wfxt",
83
+ ptimer_transaction_commit(s->ptimer1);
91
+ [__builtin_ctzll(ARM_HWCAP2_A64_EBF16 )] = "ebf16",
84
92
+ [__builtin_ctzll(ARM_HWCAP2_A64_SVE_EBF16 )] = "sveebf16",
85
/* defaults */
93
+ [__builtin_ctzll(ARM_HWCAP2_A64_CSSC )] = "cssc",
86
s->regs[R_ICAP] = ICAP_READY;
94
+ [__builtin_ctzll(ARM_HWCAP2_A64_RPRFM )] = "rprfm",
87
@@ -XXX,XX +XXX,XX @@ static void milkymist_sysctl_realize(DeviceState *dev, Error **errp)
95
+ [__builtin_ctzll(ARM_HWCAP2_A64_SVE2P1 )] = "sve2p1",
88
{
96
+ [__builtin_ctzll(ARM_HWCAP2_A64_SME2 )] = "sme2",
89
MilkymistSysctlState *s = MILKYMIST_SYSCTL(dev);
97
+ [__builtin_ctzll(ARM_HWCAP2_A64_SME2P1 )] = "sme2p1",
90
98
+ [__builtin_ctzll(ARM_HWCAP2_A64_SME_I16I32 )] = "smei16i32",
91
- s->bh0 = qemu_bh_new(timer0_hit, s);
99
+ [__builtin_ctzll(ARM_HWCAP2_A64_SME_BI32I32)] = "smebi32i32",
92
- s->bh1 = qemu_bh_new(timer1_hit, s);
100
+ [__builtin_ctzll(ARM_HWCAP2_A64_SME_B16B16 )] = "smeb16b16",
93
- s->ptimer0 = ptimer_init_with_bh(s->bh0, PTIMER_POLICY_DEFAULT);
101
+ [__builtin_ctzll(ARM_HWCAP2_A64_SME_F16F16 )] = "smef16f16",
94
- s->ptimer1 = ptimer_init_with_bh(s->bh1, PTIMER_POLICY_DEFAULT);
102
+ [__builtin_ctzll(ARM_HWCAP2_A64_MOPS )] = "mops",
95
+ s->ptimer0 = ptimer_init(timer0_hit, s, PTIMER_POLICY_DEFAULT);
103
+ [__builtin_ctzll(ARM_HWCAP2_A64_HBC )] = "hbc",
96
+ s->ptimer1 = ptimer_init(timer1_hit, s, PTIMER_POLICY_DEFAULT);
104
};
97
105
98
+ ptimer_transaction_begin(s->ptimer0);
106
return bit < ARRAY_SIZE(hwcap_str) ? hwcap_str[bit] : NULL;
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
}
105
106
static const VMStateDescription vmstate_milkymist_sysctl = {
107
--
107
--
108
2.20.1
108
2.34.1
109
109
110
110
diff view generated by jsdifflib
1
Switch the grlib_gptimer code away from bottom-half based ptimers to
1
Add the code to report the arm32 hwcaps we were previously missing:
2
the new transaction-based ptimer API. This just requires adding
2
ss, ssbs, fphp, asimdhp, asimddp, asimdfhm, asimdbf16, i8mm
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>
9
Message-id: 20191021134357.14266-3-peter.maydell@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
6
---
12
hw/timer/grlib_gptimer.c | 28 ++++++++++++++++++++++++----
7
linux-user/elfload.c | 12 ++++++++++++
13
1 file changed, 24 insertions(+), 4 deletions(-)
8
1 file changed, 12 insertions(+)
14
9
15
diff --git a/hw/timer/grlib_gptimer.c b/hw/timer/grlib_gptimer.c
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/hw/timer/grlib_gptimer.c
12
--- a/linux-user/elfload.c
18
+++ b/hw/timer/grlib_gptimer.c
13
+++ b/linux-user/elfload.c
19
@@ -XXX,XX +XXX,XX @@
14
@@ -XXX,XX +XXX,XX @@ uint32_t get_elf_hwcap(void)
20
#include "hw/irq.h"
15
}
21
#include "hw/ptimer.h"
16
}
22
#include "hw/qdev-properties.h"
17
GET_FEATURE_ID(aa32_simdfmac, ARM_HWCAP_ARM_VFPv4);
23
-#include "qemu/main-loop.h"
18
+ /*
24
#include "qemu/module.h"
19
+ * MVFR1.FPHP and .SIMDHP must be in sync, and QEMU uses the same
25
20
+ * isar_feature function for both. The kernel reports them as two hwcaps.
26
#include "trace.h"
21
+ */
27
@@ -XXX,XX +XXX,XX @@ typedef struct GPTimer GPTimer;
22
+ GET_FEATURE_ID(aa32_fp16_arith, ARM_HWCAP_ARM_FPHP);
28
typedef struct GPTimerUnit GPTimerUnit;
23
+ GET_FEATURE_ID(aa32_fp16_arith, ARM_HWCAP_ARM_ASIMDHP);
29
24
+ GET_FEATURE_ID(aa32_dp, ARM_HWCAP_ARM_ASIMDDP);
30
struct GPTimer {
25
+ GET_FEATURE_ID(aa32_fhm, ARM_HWCAP_ARM_ASIMDFHM);
31
- QEMUBH *bh;
26
+ GET_FEATURE_ID(aa32_bf16, ARM_HWCAP_ARM_ASIMDBF16);
32
struct ptimer_state *ptimer;
27
+ GET_FEATURE_ID(aa32_i8mm, ARM_HWCAP_ARM_I8MM);
33
28
34
qemu_irq irq;
29
return hwcaps;
35
@@ -XXX,XX +XXX,XX @@ struct GPTimerUnit {
36
uint32_t config;
37
};
38
39
+static void grlib_gptimer_tx_begin(GPTimer *timer)
40
+{
41
+ ptimer_transaction_begin(timer->ptimer);
42
+}
43
+
44
+static void grlib_gptimer_tx_commit(GPTimer *timer)
45
+{
46
+ ptimer_transaction_commit(timer->ptimer);
47
+}
48
+
49
+/* Must be called within grlib_gptimer_tx_begin/commit block */
50
static void grlib_gptimer_enable(GPTimer *timer)
51
{
52
assert(timer != NULL);
53
@@ -XXX,XX +XXX,XX @@ static void grlib_gptimer_enable(GPTimer *timer)
54
ptimer_run(timer->ptimer, 1);
55
}
30
}
56
31
@@ -XXX,XX +XXX,XX @@ uint32_t get_elf_hwcap2(void)
57
+/* Must be called within grlib_gptimer_tx_begin/commit block */
32
GET_FEATURE_ID(aa32_sha1, ARM_HWCAP2_ARM_SHA1);
58
static void grlib_gptimer_restart(GPTimer *timer)
33
GET_FEATURE_ID(aa32_sha2, ARM_HWCAP2_ARM_SHA2);
59
{
34
GET_FEATURE_ID(aa32_crc32, ARM_HWCAP2_ARM_CRC32);
60
assert(timer != NULL);
35
+ GET_FEATURE_ID(aa32_sb, ARM_HWCAP2_ARM_SB);
61
@@ -XXX,XX +XXX,XX @@ static void grlib_gptimer_set_scaler(GPTimerUnit *unit, uint32_t scaler)
36
+ GET_FEATURE_ID(aa32_ssbs, ARM_HWCAP2_ARM_SSBS);
62
trace_grlib_gptimer_set_scaler(scaler, value);
37
return hwcaps;
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
}
38
}
70
39
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
--
40
--
130
2.20.1
41
2.34.1
131
132
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Update our AArch64 ID register field definitions from the 2023-06
2
system register XML release:
3
https://developer.arm.com/documentation/ddi0601/2023-06/
2
4
3
There are 3 conditions that each enable this flag. M-profile always
4
enables; A-profile with EL1 as AA64 always enables. Both of these
5
conditions can easily be cached. The final condition relies on the
6
FPEXC register which we are not prepared to cache.
7
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20191023150057.25731-12-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
---
7
---
13
target/arm/cpu.h | 2 +-
8
target/arm/cpu.h | 23 +++++++++++++++++++++++
14
target/arm/helper.c | 14 ++++++++++----
9
1 file changed, 23 insertions(+)
15
2 files changed, 11 insertions(+), 5 deletions(-)
16
10
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
11
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
18
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/cpu.h
13
--- a/target/arm/cpu.h
20
+++ b/target/arm/cpu.h
14
+++ b/target/arm/cpu.h
21
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_A32, XSCALE_CPAR, 4, 2)
15
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64ISAR0, SHA1, 8, 4)
22
* the same thing as the current security state of the processor!
16
FIELD(ID_AA64ISAR0, SHA2, 12, 4)
23
*/
17
FIELD(ID_AA64ISAR0, CRC32, 16, 4)
24
FIELD(TBFLAG_A32, NS, 6, 1)
18
FIELD(ID_AA64ISAR0, ATOMIC, 20, 4)
25
-FIELD(TBFLAG_A32, VFPEN, 7, 1) /* Not cached. */
19
+FIELD(ID_AA64ISAR0, TME, 24, 4)
26
+FIELD(TBFLAG_A32, VFPEN, 7, 1) /* Partially cached, minus FPEXC. */
20
FIELD(ID_AA64ISAR0, RDM, 28, 4)
27
FIELD(TBFLAG_A32, CONDEXEC, 8, 8) /* Not cached. */
21
FIELD(ID_AA64ISAR0, SHA3, 32, 4)
28
FIELD(TBFLAG_A32, SCTLR_B, 16, 1)
22
FIELD(ID_AA64ISAR0, SM3, 36, 4)
29
/* For M profile only, set if FPCCR.LSPACT is set */
23
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64ISAR2, APA3, 12, 4)
30
diff --git a/target/arm/helper.c b/target/arm/helper.c
24
FIELD(ID_AA64ISAR2, MOPS, 16, 4)
31
index XXXXXXX..XXXXXXX 100644
25
FIELD(ID_AA64ISAR2, BC, 20, 4)
32
--- a/target/arm/helper.c
26
FIELD(ID_AA64ISAR2, PAC_FRAC, 24, 4)
33
+++ b/target/arm/helper.c
27
+FIELD(ID_AA64ISAR2, CLRBHB, 28, 4)
34
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_m32(CPUARMState *env, int fp_el,
28
+FIELD(ID_AA64ISAR2, SYSREG_128, 32, 4)
35
{
29
+FIELD(ID_AA64ISAR2, SYSINSTR_128, 36, 4)
36
uint32_t flags = 0;
30
+FIELD(ID_AA64ISAR2, PRFMSLC, 40, 4)
37
31
+FIELD(ID_AA64ISAR2, RPRFM, 48, 4)
38
+ /* v8M always enables the fpu. */
32
+FIELD(ID_AA64ISAR2, CSSC, 52, 4)
39
+ flags = FIELD_DP32(flags, TBFLAG_A32, VFPEN, 1);
33
+FIELD(ID_AA64ISAR2, ATS1A, 60, 4)
40
+
34
41
if (arm_v7m_is_handler_mode(env)) {
35
FIELD(ID_AA64PFR0, EL0, 0, 4)
42
flags = FIELD_DP32(flags, TBFLAG_A32, HANDLER, 1);
36
FIELD(ID_AA64PFR0, EL1, 4, 4)
43
}
37
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64PFR1, SME, 24, 4)
44
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_a32(CPUARMState *env, int fp_el,
38
FIELD(ID_AA64PFR1, RNDR_TRAP, 28, 4)
45
ARMMMUIdx mmu_idx)
39
FIELD(ID_AA64PFR1, CSV2_FRAC, 32, 4)
46
{
40
FIELD(ID_AA64PFR1, NMI, 36, 4)
47
uint32_t flags = rebuild_hflags_aprofile(env);
41
+FIELD(ID_AA64PFR1, MTE_FRAC, 40, 4)
48
+
42
+FIELD(ID_AA64PFR1, GCS, 44, 4)
49
+ if (arm_el_is_aa64(env, 1)) {
43
+FIELD(ID_AA64PFR1, THE, 48, 4)
50
+ flags = FIELD_DP32(flags, TBFLAG_A32, VFPEN, 1);
44
+FIELD(ID_AA64PFR1, MTEX, 52, 4)
51
+ }
45
+FIELD(ID_AA64PFR1, DF2, 56, 4)
52
return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags);
46
+FIELD(ID_AA64PFR1, PFAR, 60, 4)
53
}
47
54
48
FIELD(ID_AA64MMFR0, PARANGE, 0, 4)
55
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
49
FIELD(ID_AA64MMFR0, ASIDBITS, 4, 4)
56
flags = FIELD_DP32(flags, TBFLAG_A32, VECSTRIDE,
50
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64MMFR1, AFP, 44, 4)
57
env->vfp.vec_stride);
51
FIELD(ID_AA64MMFR1, NTLBPA, 48, 4)
58
}
52
FIELD(ID_AA64MMFR1, TIDCP1, 52, 4)
59
+ if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) {
53
FIELD(ID_AA64MMFR1, CMOW, 56, 4)
60
+ flags = FIELD_DP32(flags, TBFLAG_A32, VFPEN, 1);
54
+FIELD(ID_AA64MMFR1, ECBHB, 60, 4)
61
+ }
55
62
}
56
FIELD(ID_AA64MMFR2, CNP, 0, 4)
63
57
FIELD(ID_AA64MMFR2, UAO, 4, 4)
64
flags = FIELD_DP32(flags, TBFLAG_A32, THUMB, env->thumb);
58
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64DFR0, DEBUGVER, 0, 4)
65
flags = FIELD_DP32(flags, TBFLAG_A32, CONDEXEC, env->condexec_bits);
59
FIELD(ID_AA64DFR0, TRACEVER, 4, 4)
66
- if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)
60
FIELD(ID_AA64DFR0, PMUVER, 8, 4)
67
- || arm_el_is_aa64(env, 1) || arm_feature(env, ARM_FEATURE_M)) {
61
FIELD(ID_AA64DFR0, BRPS, 12, 4)
68
- flags = FIELD_DP32(flags, TBFLAG_A32, VFPEN, 1);
62
+FIELD(ID_AA64DFR0, PMSS, 16, 4)
69
- }
63
FIELD(ID_AA64DFR0, WRPS, 20, 4)
70
pstate_for_ss = env->uncached_cpsr;
64
+FIELD(ID_AA64DFR0, SEBEP, 24, 4)
71
}
65
FIELD(ID_AA64DFR0, CTX_CMPS, 28, 4)
72
66
FIELD(ID_AA64DFR0, PMSVER, 32, 4)
67
FIELD(ID_AA64DFR0, DOUBLELOCK, 36, 4)
68
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64DFR0, TRACEFILT, 40, 4)
69
FIELD(ID_AA64DFR0, TRACEBUFFER, 44, 4)
70
FIELD(ID_AA64DFR0, MTPMU, 48, 4)
71
FIELD(ID_AA64DFR0, BRBE, 52, 4)
72
+FIELD(ID_AA64DFR0, EXTTRCBUFF, 56, 4)
73
FIELD(ID_AA64DFR0, HPMN0, 60, 4)
74
75
FIELD(ID_AA64ZFR0, SVEVER, 0, 4)
76
FIELD(ID_AA64ZFR0, AES, 4, 4)
77
FIELD(ID_AA64ZFR0, BITPERM, 16, 4)
78
FIELD(ID_AA64ZFR0, BFLOAT16, 20, 4)
79
+FIELD(ID_AA64ZFR0, B16B16, 24, 4)
80
FIELD(ID_AA64ZFR0, SHA3, 32, 4)
81
FIELD(ID_AA64ZFR0, SM4, 40, 4)
82
FIELD(ID_AA64ZFR0, I8MM, 44, 4)
83
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64ZFR0, F32MM, 52, 4)
84
FIELD(ID_AA64ZFR0, F64MM, 56, 4)
85
86
FIELD(ID_AA64SMFR0, F32F32, 32, 1)
87
+FIELD(ID_AA64SMFR0, BI32I32, 33, 1)
88
FIELD(ID_AA64SMFR0, B16F32, 34, 1)
89
FIELD(ID_AA64SMFR0, F16F32, 35, 1)
90
FIELD(ID_AA64SMFR0, I8I32, 36, 4)
91
+FIELD(ID_AA64SMFR0, F16F16, 42, 1)
92
+FIELD(ID_AA64SMFR0, B16B16, 43, 1)
93
+FIELD(ID_AA64SMFR0, I16I32, 44, 4)
94
FIELD(ID_AA64SMFR0, F64F64, 48, 1)
95
FIELD(ID_AA64SMFR0, I16I64, 52, 4)
96
FIELD(ID_AA64SMFR0, SMEVER, 56, 4)
73
--
97
--
74
2.20.1
98
2.34.1
75
76
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
For user-only mode we reveal a subset of the AArch64 ID registers
2
to the guest, to emulate the kernel's trap-and-emulate-ID-regs
3
handling. Update the feature bit masks to match upstream kernel
4
commit a48fa7efaf1161c1c.
2
5
3
This is the payoff.
6
None of these features are yet implemented by QEMU, so this
7
doesn't yet have a behavioural change, but implementation of
8
FEAT_MOPS and FEAT_HBC is imminent.
4
9
5
From perf record -g data of ubuntu 18 boot and shutdown:
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>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
49
---
12
---
50
target/arm/helper.c | 9 ++++++---
13
target/arm/helper.c | 11 ++++++++++-
51
1 file changed, 6 insertions(+), 3 deletions(-)
14
tests/tcg/aarch64/sysregs.c | 4 ++--
15
2 files changed, 12 insertions(+), 3 deletions(-)
52
16
53
diff --git a/target/arm/helper.c b/target/arm/helper.c
17
diff --git a/target/arm/helper.c b/target/arm/helper.c
54
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
55
--- a/target/arm/helper.c
19
--- a/target/arm/helper.c
56
+++ b/target/arm/helper.c
20
+++ b/target/arm/helper.c
57
@@ -XXX,XX +XXX,XX @@ void HELPER(rebuild_hflags_a64)(CPUARMState *env, int el)
21
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
58
void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
22
R_ID_AA64ZFR0_F64MM_MASK },
59
target_ulong *cs_base, uint32_t *pflags)
23
{ .name = "ID_AA64SMFR0_EL1",
60
{
24
.exported_bits = R_ID_AA64SMFR0_F32F32_MASK |
61
- uint32_t flags, pstate_for_ss;
25
+ R_ID_AA64SMFR0_BI32I32_MASK |
62
+ uint32_t flags = env->hflags;
26
R_ID_AA64SMFR0_B16F32_MASK |
63
+ uint32_t pstate_for_ss;
27
R_ID_AA64SMFR0_F16F32_MASK |
64
28
R_ID_AA64SMFR0_I8I32_MASK |
65
*cs_base = 0;
29
+ R_ID_AA64SMFR0_F16F16_MASK |
66
- flags = rebuild_hflags_internal(env);
30
+ R_ID_AA64SMFR0_B16B16_MASK |
67
+#ifdef CONFIG_DEBUG_TCG
31
+ R_ID_AA64SMFR0_I16I32_MASK |
68
+ assert(flags == rebuild_hflags_internal(env));
32
R_ID_AA64SMFR0_F64F64_MASK |
69
+#endif
33
R_ID_AA64SMFR0_I16I64_MASK |
70
34
+ R_ID_AA64SMFR0_SMEVER_MASK |
71
- if (is_a64(env)) {
35
R_ID_AA64SMFR0_FA64_MASK },
72
+ if (FIELD_EX32(flags, TBFLAG_ANY, AARCH64_STATE)) {
36
{ .name = "ID_AA64MMFR0_EL1",
73
*pc = env->pc;
37
.exported_bits = R_ID_AA64MMFR0_ECV_MASK,
74
if (cpu_isar_feature(aa64_bti, env_archcpu(env))) {
38
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
75
flags = FIELD_DP32(flags, TBFLAG_A64, BTYPE, env->btype);
39
.exported_bits = R_ID_AA64ISAR2_WFXT_MASK |
40
R_ID_AA64ISAR2_RPRES_MASK |
41
R_ID_AA64ISAR2_GPA3_MASK |
42
- R_ID_AA64ISAR2_APA3_MASK },
43
+ R_ID_AA64ISAR2_APA3_MASK |
44
+ R_ID_AA64ISAR2_MOPS_MASK |
45
+ R_ID_AA64ISAR2_BC_MASK |
46
+ R_ID_AA64ISAR2_RPRFM_MASK |
47
+ R_ID_AA64ISAR2_CSSC_MASK },
48
{ .name = "ID_AA64ISAR*_EL1_RESERVED",
49
.is_glob = true },
50
};
51
diff --git a/tests/tcg/aarch64/sysregs.c b/tests/tcg/aarch64/sysregs.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/tests/tcg/aarch64/sysregs.c
54
+++ b/tests/tcg/aarch64/sysregs.c
55
@@ -XXX,XX +XXX,XX @@ int main(void)
56
*/
57
get_cpu_reg_check_mask(id_aa64isar0_el1, _m(f0ff,ffff,f0ff,fff0));
58
get_cpu_reg_check_mask(id_aa64isar1_el1, _m(00ff,f0ff,ffff,ffff));
59
- get_cpu_reg_check_mask(SYS_ID_AA64ISAR2_EL1, _m(0000,0000,0000,ffff));
60
+ get_cpu_reg_check_mask(SYS_ID_AA64ISAR2_EL1, _m(00ff,0000,00ff,ffff));
61
/* TGran4 & TGran64 as pegged to -1 */
62
get_cpu_reg_check_mask(id_aa64mmfr0_el1, _m(f000,0000,ff00,0000));
63
get_cpu_reg_check_mask(id_aa64mmfr1_el1, _m(0000,f000,0000,0000));
64
@@ -XXX,XX +XXX,XX @@ int main(void)
65
get_cpu_reg_check_mask(id_aa64dfr0_el1, _m(0000,0000,0000,0006));
66
get_cpu_reg_check_zero(id_aa64dfr1_el1);
67
get_cpu_reg_check_mask(SYS_ID_AA64ZFR0_EL1, _m(0ff0,ff0f,00ff,00ff));
68
- get_cpu_reg_check_mask(SYS_ID_AA64SMFR0_EL1, _m(80f1,00fd,0000,0000));
69
+ get_cpu_reg_check_mask(SYS_ID_AA64SMFR0_EL1, _m(8ff1,fcff,0000,0000));
70
71
get_cpu_reg_check_zero(id_aa64afr0_el1);
72
get_cpu_reg_check_zero(id_aa64afr1_el1);
76
--
73
--
77
2.20.1
74
2.34.1
78
79
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
FEAT_HBC (Hinted conditional branches) provides a new instruction
2
BC.cond, which behaves exactly like the existing B.cond except
3
that it provides a hint to the branch predictor about the
4
likely behaviour of the branch.
2
5
3
This function assumes nothing about the current state of the cpu,
6
Since QEMU does not implement branch prediction, we can treat
4
and writes the computed value to env->hflags.
7
this identically to B.cond.
5
8
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>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
---
12
---
11
target/arm/cpu.h | 6 ++++++
13
docs/system/arm/emulation.rst | 1 +
12
target/arm/helper.c | 30 ++++++++++++++++++++++--------
14
target/arm/cpu.h | 5 +++++
13
2 files changed, 28 insertions(+), 8 deletions(-)
15
target/arm/tcg/a64.decode | 3 ++-
16
linux-user/elfload.c | 1 +
17
target/arm/tcg/cpu64.c | 4 ++++
18
target/arm/tcg/translate-a64.c | 4 ++++
19
6 files changed, 17 insertions(+), 1 deletion(-)
14
20
21
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
22
index XXXXXXX..XXXXXXX 100644
23
--- a/docs/system/arm/emulation.rst
24
+++ b/docs/system/arm/emulation.rst
25
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
26
- FEAT_FlagM2 (Enhancements to flag manipulation instructions)
27
- FEAT_GTG (Guest translation granule size)
28
- FEAT_HAFDBS (Hardware management of the access flag and dirty bit state)
29
+- FEAT_HBC (Hinted conditional branches)
30
- FEAT_HCX (Support for the HCRX_EL2 register)
31
- FEAT_HPDS (Hierarchical permission disables)
32
- FEAT_HPDS2 (Translation table page-based hardware attributes)
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
33
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/cpu.h
35
--- a/target/arm/cpu.h
18
+++ b/target/arm/cpu.h
36
+++ b/target/arm/cpu.h
19
@@ -XXX,XX +XXX,XX @@ void arm_register_pre_el_change_hook(ARMCPU *cpu, ARMELChangeHookFn *hook,
37
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_i8mm(const ARMISARegisters *id)
20
void arm_register_el_change_hook(ARMCPU *cpu, ARMELChangeHookFn *hook, void
38
return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, I8MM) != 0;
21
*opaque);
22
23
+/**
24
+ * arm_rebuild_hflags:
25
+ * Rebuild the cached TBFLAGS for arbitrary changed processor state.
26
+ */
27
+void arm_rebuild_hflags(CPUARMState *env);
28
+
29
/**
30
* aa32_vfp_dreg:
31
* Return a pointer to the Dn register within env in 32-bit mode.
32
diff --git a/target/arm/helper.c b/target/arm/helper.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/helper.c
35
+++ b/target/arm/helper.c
36
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
37
return rebuild_hflags_common(env, fp_el, mmu_idx, flags);
38
}
39
}
39
40
40
+static uint32_t rebuild_hflags_internal(CPUARMState *env)
41
+static inline bool isar_feature_aa64_hbc(const ARMISARegisters *id)
41
+{
42
+{
42
+ int el = arm_current_el(env);
43
+ return FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, BC) != 0;
43
+ int fp_el = fp_exception_el(env, el);
44
+ ARMMMUIdx mmu_idx = arm_mmu_idx(env);
45
+
46
+ if (is_a64(env)) {
47
+ return rebuild_hflags_a64(env, el, fp_el, mmu_idx);
48
+ } else if (arm_feature(env, ARM_FEATURE_M)) {
49
+ return rebuild_hflags_m32(env, fp_el, mmu_idx);
50
+ } else {
51
+ return rebuild_hflags_a32(env, fp_el, mmu_idx);
52
+ }
53
+}
44
+}
54
+
45
+
55
+void arm_rebuild_hflags(CPUARMState *env)
46
static inline bool isar_feature_aa64_tgran4_lpa2(const ARMISARegisters *id)
56
+{
47
{
57
+ env->hflags = rebuild_hflags_internal(env);
48
return FIELD_SEX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4) >= 1;
58
+}
49
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
50
index XXXXXXX..XXXXXXX 100644
51
--- a/target/arm/tcg/a64.decode
52
+++ b/target/arm/tcg/a64.decode
53
@@ -XXX,XX +XXX,XX @@ CBZ sf:1 011010 nz:1 ................... rt:5 &cbz imm=%imm19
54
55
TBZ . 011011 nz:1 ..... .............. rt:5 &tbz imm=%imm14 bitpos=%imm31_19
56
57
-B_cond 0101010 0 ................... 0 cond:4 imm=%imm19
58
+# B.cond and BC.cond
59
+B_cond 0101010 0 ................... c:1 cond:4 imm=%imm19
60
61
BR 1101011 0000 11111 000000 rn:5 00000 &r
62
BLR 1101011 0001 11111 000000 rn:5 00000 &r
63
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/linux-user/elfload.c
66
+++ b/linux-user/elfload.c
67
@@ -XXX,XX +XXX,XX @@ uint32_t get_elf_hwcap2(void)
68
GET_FEATURE_ID(aa64_sme_f64f64, ARM_HWCAP2_A64_SME_F64F64);
69
GET_FEATURE_ID(aa64_sme_i16i64, ARM_HWCAP2_A64_SME_I16I64);
70
GET_FEATURE_ID(aa64_sme_fa64, ARM_HWCAP2_A64_SME_FA64);
71
+ GET_FEATURE_ID(aa64_hbc, ARM_HWCAP2_A64_HBC);
72
73
return hwcaps;
74
}
75
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
76
index XXXXXXX..XXXXXXX 100644
77
--- a/target/arm/tcg/cpu64.c
78
+++ b/target/arm/tcg/cpu64.c
79
@@ -XXX,XX +XXX,XX @@ void aarch64_max_tcg_initfn(Object *obj)
80
t = FIELD_DP64(t, ID_AA64ISAR1, I8MM, 1); /* FEAT_I8MM */
81
cpu->isar.id_aa64isar1 = t;
82
83
+ t = cpu->isar.id_aa64isar2;
84
+ t = FIELD_DP64(t, ID_AA64ISAR2, BC, 1); /* FEAT_HBC */
85
+ cpu->isar.id_aa64isar2 = t;
59
+
86
+
60
void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
87
t = cpu->isar.id_aa64pfr0;
61
target_ulong *cs_base, uint32_t *pflags)
88
t = FIELD_DP64(t, ID_AA64PFR0, FP, 1); /* FEAT_FP16 */
89
t = FIELD_DP64(t, ID_AA64PFR0, ADVSIMD, 1); /* FEAT_FP16 */
90
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
91
index XXXXXXX..XXXXXXX 100644
92
--- a/target/arm/tcg/translate-a64.c
93
+++ b/target/arm/tcg/translate-a64.c
94
@@ -XXX,XX +XXX,XX @@ static bool trans_TBZ(DisasContext *s, arg_tbz *a)
95
96
static bool trans_B_cond(DisasContext *s, arg_B_cond *a)
62
{
97
{
63
- ARMMMUIdx mmu_idx = arm_mmu_idx(env);
98
+ /* BC.cond is only present with FEAT_HBC */
64
- int current_el = arm_current_el(env);
99
+ if (a->c && !dc_isar_feature(aa64_hbc, s)) {
65
- int fp_el = fp_exception_el(env, current_el);
100
+ return false;
66
uint32_t flags, pstate_for_ss;
101
+ }
67
102
reset_btype(s);
68
+ flags = rebuild_hflags_internal(env);
103
if (a->cond < 0x0e) {
69
+
104
/* genuinely conditional branches */
70
if (is_a64(env)) {
71
*pc = env->pc;
72
- flags = rebuild_hflags_a64(env, current_el, fp_el, mmu_idx);
73
if (cpu_isar_feature(aa64_bti, env_archcpu(env))) {
74
flags = FIELD_DP32(flags, TBFLAG_A64, BTYPE, env->btype);
75
}
76
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
77
*pc = env->regs[15];
78
79
if (arm_feature(env, ARM_FEATURE_M)) {
80
- flags = rebuild_hflags_m32(env, fp_el, mmu_idx);
81
-
82
if (arm_feature(env, ARM_FEATURE_M_SECURITY) &&
83
FIELD_EX32(env->v7m.fpccr[M_REG_S], V7M_FPCCR, S)
84
!= env->v7m.secure) {
85
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
86
flags = FIELD_DP32(flags, TBFLAG_A32, LSPACT, 1);
87
}
88
} else {
89
- flags = rebuild_hflags_a32(env, fp_el, mmu_idx);
90
-
91
/*
92
* Note that XSCALE_CPAR shares bits with VECSTRIDE.
93
* Note that VECLEN+VECSTRIDE are RES0 for M-profile.
94
--
105
--
95
2.20.1
106
2.34.1
96
107
97
108
diff view generated by jsdifflib
1
Switch the fsl_etsec code away from bottom-half based ptimers to
1
The allocation_tag_mem() function takes an argument tag_size,
2
the new transaction-based ptimer API. This just requires adding
2
but it never uses it. Remove the argument. In mte_probe_int()
3
begin/commit calls around the various places that modify the ptimer
3
in particular this also lets us delete the code computing
4
state, and using the new ptimer_init() function to create the timer.
4
the value we were passing in.
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
Reviewed-by: Philippe Mathieu-Daudé <philmd@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
---
9
---
13
hw/net/fsl_etsec/etsec.h | 1 -
10
target/arm/tcg/mte_helper.c | 42 +++++++++++++------------------------
14
hw/net/fsl_etsec/etsec.c | 9 +++++----
11
1 file changed, 14 insertions(+), 28 deletions(-)
15
2 files changed, 5 insertions(+), 5 deletions(-)
16
12
17
diff --git a/hw/net/fsl_etsec/etsec.h b/hw/net/fsl_etsec/etsec.h
13
diff --git a/target/arm/tcg/mte_helper.c b/target/arm/tcg/mte_helper.c
18
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/net/fsl_etsec/etsec.h
15
--- a/target/arm/tcg/mte_helper.c
20
+++ b/hw/net/fsl_etsec/etsec.h
16
+++ b/target/arm/tcg/mte_helper.c
21
@@ -XXX,XX +XXX,XX @@ typedef struct eTSEC {
17
@@ -XXX,XX +XXX,XX @@ static int choose_nonexcluded_tag(int tag, int offset, uint16_t exclude)
22
uint16_t phy_control;
18
* @ptr_access: the access to use for the virtual address
23
19
* @ptr_size: the number of bytes in the normal memory access
24
/* Polling */
20
* @tag_access: the access to use for the tag memory
25
- QEMUBH *bh;
21
- * @tag_size: the number of bytes in the tag memory access
26
struct ptimer_state *ptimer;
22
* @ra: the return address for exception handling
27
23
*
28
/* Whether we should flush the rx queue when buffer becomes available. */
24
* Our tag memory is formatted as a sequence of little-endian nibbles.
29
diff --git a/hw/net/fsl_etsec/etsec.c b/hw/net/fsl_etsec/etsec.c
25
@@ -XXX,XX +XXX,XX @@ static int choose_nonexcluded_tag(int tag, int offset, uint16_t exclude)
30
index XXXXXXX..XXXXXXX 100644
26
* a pointer to the corresponding tag byte. Exit with exception if the
31
--- a/hw/net/fsl_etsec/etsec.c
27
* virtual address is not accessible for @ptr_access.
32
+++ b/hw/net/fsl_etsec/etsec.c
28
*
33
@@ -XXX,XX +XXX,XX @@
29
- * The @ptr_size and @tag_size values may not have an obvious relation
34
#include "etsec.h"
30
- * due to the alignment of @ptr, and the number of tag checks required.
35
#include "registers.h"
31
- *
36
#include "qemu/log.h"
32
* If there is no tag storage corresponding to @ptr, return NULL.
37
-#include "qemu/main-loop.h"
33
*/
38
#include "qemu/module.h"
34
static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx,
39
35
uint64_t ptr, MMUAccessType ptr_access,
40
/* #define HEX_DUMP */
36
int ptr_size, MMUAccessType tag_access,
41
@@ -XXX,XX +XXX,XX @@ static void write_dmactrl(eTSEC *etsec,
37
- int tag_size, uintptr_t ra)
42
38
+ uintptr_t ra)
43
if (!(value & DMACTRL_WOP)) {
39
{
44
/* Start polling */
40
#ifdef CONFIG_USER_ONLY
45
+ ptimer_transaction_begin(etsec->ptimer);
41
uint64_t clean_ptr = useronly_clean_ptr(ptr);
46
ptimer_stop(etsec->ptimer);
42
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(ldg)(CPUARMState *env, uint64_t ptr, uint64_t xt)
47
ptimer_set_count(etsec->ptimer, 1);
43
48
ptimer_run(etsec->ptimer, 1);
44
/* Trap if accessing an invalid page. */
49
+ ptimer_transaction_commit(etsec->ptimer);
45
mem = allocation_tag_mem(env, mmu_idx, ptr, MMU_DATA_LOAD, 1,
46
- MMU_DATA_LOAD, 1, GETPC());
47
+ MMU_DATA_LOAD, GETPC());
48
49
/* Load if page supports tags. */
50
if (mem) {
51
@@ -XXX,XX +XXX,XX @@ static inline void do_stg(CPUARMState *env, uint64_t ptr, uint64_t xt,
52
53
/* Trap if accessing an invalid page. */
54
mem = allocation_tag_mem(env, mmu_idx, ptr, MMU_DATA_STORE, TAG_GRANULE,
55
- MMU_DATA_STORE, 1, ra);
56
+ MMU_DATA_STORE, ra);
57
58
/* Store if page supports tags. */
59
if (mem) {
60
@@ -XXX,XX +XXX,XX @@ static inline void do_st2g(CPUARMState *env, uint64_t ptr, uint64_t xt,
61
if (ptr & TAG_GRANULE) {
62
/* Two stores unaligned mod TAG_GRANULE*2 -- modify two bytes. */
63
mem1 = allocation_tag_mem(env, mmu_idx, ptr, MMU_DATA_STORE,
64
- TAG_GRANULE, MMU_DATA_STORE, 1, ra);
65
+ TAG_GRANULE, MMU_DATA_STORE, ra);
66
mem2 = allocation_tag_mem(env, mmu_idx, ptr + TAG_GRANULE,
67
MMU_DATA_STORE, TAG_GRANULE,
68
- MMU_DATA_STORE, 1, ra);
69
+ MMU_DATA_STORE, ra);
70
71
/* Store if page(s) support tags. */
72
if (mem1) {
73
@@ -XXX,XX +XXX,XX @@ static inline void do_st2g(CPUARMState *env, uint64_t ptr, uint64_t xt,
74
} else {
75
/* Two stores aligned mod TAG_GRANULE*2 -- modify one byte. */
76
mem1 = allocation_tag_mem(env, mmu_idx, ptr, MMU_DATA_STORE,
77
- 2 * TAG_GRANULE, MMU_DATA_STORE, 1, ra);
78
+ 2 * TAG_GRANULE, MMU_DATA_STORE, ra);
79
if (mem1) {
80
tag |= tag << 4;
81
qatomic_set(mem1, tag);
82
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(ldgm)(CPUARMState *env, uint64_t ptr)
83
84
/* Trap if accessing an invalid page. */
85
tag_mem = allocation_tag_mem(env, mmu_idx, ptr, MMU_DATA_LOAD,
86
- gm_bs_bytes, MMU_DATA_LOAD,
87
- gm_bs_bytes / (2 * TAG_GRANULE), ra);
88
+ gm_bs_bytes, MMU_DATA_LOAD, ra);
89
90
/* The tag is squashed to zero if the page does not support tags. */
91
if (!tag_mem) {
92
@@ -XXX,XX +XXX,XX @@ void HELPER(stgm)(CPUARMState *env, uint64_t ptr, uint64_t val)
93
94
/* Trap if accessing an invalid page. */
95
tag_mem = allocation_tag_mem(env, mmu_idx, ptr, MMU_DATA_STORE,
96
- gm_bs_bytes, MMU_DATA_LOAD,
97
- gm_bs_bytes / (2 * TAG_GRANULE), ra);
98
+ gm_bs_bytes, MMU_DATA_LOAD, ra);
99
100
/*
101
* Tag store only happens if the page support tags,
102
@@ -XXX,XX +XXX,XX @@ void HELPER(stzgm_tags)(CPUARMState *env, uint64_t ptr, uint64_t val)
103
ptr &= -dcz_bytes;
104
105
mem = allocation_tag_mem(env, mmu_idx, ptr, MMU_DATA_STORE, dcz_bytes,
106
- MMU_DATA_STORE, tag_bytes, ra);
107
+ MMU_DATA_STORE, ra);
108
if (mem) {
109
int tag_pair = (val & 0xf) * 0x11;
110
memset(mem, tag_pair, tag_bytes);
111
@@ -XXX,XX +XXX,XX @@ static int mte_probe_int(CPUARMState *env, uint32_t desc, uint64_t ptr,
112
int mmu_idx, ptr_tag, bit55;
113
uint64_t ptr_last, prev_page, next_page;
114
uint64_t tag_first, tag_last;
115
- uint64_t tag_byte_first, tag_byte_last;
116
- uint32_t sizem1, tag_count, tag_size, n, c;
117
+ uint32_t sizem1, tag_count, n, c;
118
uint8_t *mem1, *mem2;
119
MMUAccessType type;
120
121
@@ -XXX,XX +XXX,XX @@ static int mte_probe_int(CPUARMState *env, uint32_t desc, uint64_t ptr,
122
tag_last = QEMU_ALIGN_DOWN(ptr_last, TAG_GRANULE);
123
tag_count = ((tag_last - tag_first) / TAG_GRANULE) + 1;
124
125
- /* Round the bounds to twice the tag granule, and compute the bytes. */
126
- tag_byte_first = QEMU_ALIGN_DOWN(ptr, 2 * TAG_GRANULE);
127
- tag_byte_last = QEMU_ALIGN_DOWN(ptr_last, 2 * TAG_GRANULE);
128
-
129
/* Locate the page boundaries. */
130
prev_page = ptr & TARGET_PAGE_MASK;
131
next_page = prev_page + TARGET_PAGE_SIZE;
132
133
if (likely(tag_last - prev_page < TARGET_PAGE_SIZE)) {
134
/* Memory access stays on one page. */
135
- tag_size = ((tag_byte_last - tag_byte_first) / (2 * TAG_GRANULE)) + 1;
136
mem1 = allocation_tag_mem(env, mmu_idx, ptr, type, sizem1 + 1,
137
- MMU_DATA_LOAD, tag_size, ra);
138
+ MMU_DATA_LOAD, ra);
139
if (!mem1) {
140
return 1;
141
}
142
@@ -XXX,XX +XXX,XX @@ static int mte_probe_int(CPUARMState *env, uint32_t desc, uint64_t ptr,
143
n = checkN(mem1, ptr & TAG_GRANULE, ptr_tag, tag_count);
144
} else {
145
/* Memory access crosses to next page. */
146
- tag_size = (next_page - tag_byte_first) / (2 * TAG_GRANULE);
147
mem1 = allocation_tag_mem(env, mmu_idx, ptr, type, next_page - ptr,
148
- MMU_DATA_LOAD, tag_size, ra);
149
+ MMU_DATA_LOAD, ra);
150
151
- tag_size = ((tag_byte_last - next_page) / (2 * TAG_GRANULE)) + 1;
152
mem2 = allocation_tag_mem(env, mmu_idx, next_page, type,
153
ptr_last - next_page + 1,
154
- MMU_DATA_LOAD, tag_size, ra);
155
+ MMU_DATA_LOAD, ra);
156
157
/*
158
* Perform all of the comparisons.
159
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(mte_check_zva)(CPUARMState *env, uint32_t desc, uint64_t ptr)
160
mmu_idx = FIELD_EX32(desc, MTEDESC, MIDX);
161
(void) probe_write(env, ptr, 1, mmu_idx, ra);
162
mem = allocation_tag_mem(env, mmu_idx, align_ptr, MMU_DATA_STORE,
163
- dcz_bytes, MMU_DATA_LOAD, tag_bytes, ra);
164
+ dcz_bytes, MMU_DATA_LOAD, ra);
165
if (!mem) {
166
goto done;
50
}
167
}
51
}
52
53
@@ -XXX,XX +XXX,XX @@ static void etsec_realize(DeviceState *dev, Error **errp)
54
object_get_typename(OBJECT(dev)), dev->id, etsec);
55
qemu_format_nic_info_str(qemu_get_queue(etsec->nic), etsec->conf.macaddr.a);
56
57
-
58
- etsec->bh = qemu_bh_new(etsec_timer_hit, etsec);
59
- etsec->ptimer = ptimer_init_with_bh(etsec->bh, PTIMER_POLICY_DEFAULT);
60
+ etsec->ptimer = ptimer_init(etsec_timer_hit, etsec, PTIMER_POLICY_DEFAULT);
61
+ ptimer_transaction_begin(etsec->ptimer);
62
ptimer_set_freq(etsec->ptimer, 100);
63
+ ptimer_transaction_commit(etsec->ptimer);
64
}
65
66
static void etsec_instance_init(Object *obj)
67
--
168
--
68
2.20.1
169
2.34.1
69
170
70
171
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The LDRT/STRT "unprivileged load/store" instructions behave like
2
normal ones if executed at EL0. We handle this correctly for
3
the load/store semantics, but get the MTE checking wrong.
2
4
3
Continue setting, but not relying upon, env->hflags.
5
We always look at s->mte_active[is_unpriv] to see whether we should
6
be doing MTE checks, but in hflags.c when we set the TB flags that
7
will be used to fill the mte_active[] array we only set the
8
MTE0_ACTIVE bit if UNPRIV is true (i.e. we are not at EL0).
4
9
5
Suggested-by: Peter Maydell <peter.maydell@linaro.org>
10
This means that a LDRT at EL0 will see s->mte_active[1] as 0,
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
and will not do MTE checks even when MTE is enabled.
7
Message-id: 20191023150057.25731-22-richard.henderson@linaro.org
12
13
To avoid the translate-time code having to do an explicit check on
14
s->unpriv to see if it is OK to index into the mte_active[] array,
15
duplicate MTE_ACTIVE into MTE0_ACTIVE when UNPRIV is false.
16
17
(This isn't a very serious bug because generally nobody executes
18
LDRT/STRT at EL0, because they have no use there.)
19
20
Cc: qemu-stable@nongnu.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
23
Message-id: 20230912140434.1333369-2-peter.maydell@linaro.org
9
---
24
---
10
hw/intc/armv7m_nvic.c | 22 +++++++++++++---------
25
target/arm/tcg/hflags.c | 9 +++++++++
11
1 file changed, 13 insertions(+), 9 deletions(-)
26
1 file changed, 9 insertions(+)
12
27
13
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
28
diff --git a/target/arm/tcg/hflags.c b/target/arm/tcg/hflags.c
14
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/intc/armv7m_nvic.c
30
--- a/target/arm/tcg/hflags.c
16
+++ b/hw/intc/armv7m_nvic.c
31
+++ b/target/arm/tcg/hflags.c
17
@@ -XXX,XX +XXX,XX @@ static MemTxResult nvic_sysreg_write(void *opaque, hwaddr addr,
32
@@ -XXX,XX +XXX,XX @@ static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
33
&& !(env->pstate & PSTATE_TCO)
34
&& (sctlr & (el == 0 ? SCTLR_TCF0 : SCTLR_TCF))) {
35
DP_TBFLAG_A64(flags, MTE_ACTIVE, 1);
36
+ if (!EX_TBFLAG_A64(flags, UNPRIV)) {
37
+ /*
38
+ * In non-unpriv contexts (eg EL0), unpriv load/stores
39
+ * act like normal ones; duplicate the MTE info to
40
+ * avoid translate-a64.c having to check UNPRIV to see
41
+ * whether it is OK to index into MTE_ACTIVE[].
42
+ */
43
+ DP_TBFLAG_A64(flags, MTE0_ACTIVE, 1);
44
+ }
18
}
45
}
19
}
46
}
20
nvic_irq_update(s);
47
/* And again for unprivileged accesses, if required. */
21
- return MEMTX_OK;
22
+ goto exit_ok;
23
case 0x200 ... 0x23f: /* NVIC Set pend */
24
/* the special logic in armv7m_nvic_set_pending()
25
* is not needed since IRQs are never escalated
26
@@ -XXX,XX +XXX,XX @@ static MemTxResult nvic_sysreg_write(void *opaque, hwaddr addr,
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
--
48
--
87
2.20.1
49
2.34.1
88
89
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
FEAT_MOPS defines a handful of new enable bits:
2
* HCRX_EL2.MSCEn, SCTLR_EL1.MSCEn, SCTLR_EL2.MSCen:
3
define whether the new insns should UNDEF or not
4
* HCRX_EL2.MCE2: defines whether memops exceptions from
5
EL1 should be taken to EL1 or EL2
2
6
3
Set TBFLAG_ANY.BE_DATA in rebuild_hflags_common_32 and
7
Since we don't sanitise what bits can be written for the SCTLR
4
rebuild_hflags_a64 instead of rebuild_hflags_common, where we do
8
registers, we only need to handle the new bits in HCRX_EL2, and
5
not need to re-test is_a64() nor re-compute the various inputs.
9
define SCTLR_MSCEN for the new SCTLR bit value.
6
10
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
11
The precedence of "HCRX bits acts as 0 if SCR_EL3.HXEn is 0" versus
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
"bit acts as 1 if EL2 disabled" is not clear from the register
9
Message-id: 20191023150057.25731-5-richard.henderson@linaro.org
13
definition text, but it is clear in the CheckMOPSEnabled()
14
pseudocode(), so we follow that. We'll have to check whether other
15
bits we need to implement in future follow the same logic or not.
16
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
Message-id: 20230912140434.1333369-3-peter.maydell@linaro.org
11
---
20
---
12
target/arm/cpu.h | 49 +++++++++++++++++++++++++++------------------
21
target/arm/cpu.h | 6 ++++++
13
target/arm/helper.c | 16 +++++++++++----
22
target/arm/helper.c | 28 +++++++++++++++++++++-------
14
2 files changed, 42 insertions(+), 23 deletions(-)
23
2 files changed, 27 insertions(+), 7 deletions(-)
15
24
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
25
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu.h
27
--- a/target/arm/cpu.h
19
+++ b/target/arm/cpu.h
28
+++ b/target/arm/cpu.h
20
@@ -XXX,XX +XXX,XX @@ static inline uint64_t arm_sctlr(CPUARMState *env, int el)
29
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
21
}
30
#define SCTLR_EnIB (1U << 30) /* v8.3, AArch64 only */
31
#define SCTLR_EnIA (1U << 31) /* v8.3, AArch64 only */
32
#define SCTLR_DSSBS_32 (1U << 31) /* v8.5, AArch32 only */
33
+#define SCTLR_MSCEN (1ULL << 33) /* FEAT_MOPS */
34
#define SCTLR_BT0 (1ULL << 35) /* v8.5-BTI */
35
#define SCTLR_BT1 (1ULL << 36) /* v8.5-BTI */
36
#define SCTLR_ITFSB (1ULL << 37) /* v8.5-MemTag */
37
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_doublelock(const ARMISARegisters *id)
38
return FIELD_SEX64(id->id_aa64dfr0, ID_AA64DFR0, DOUBLELOCK) >= 0;
22
}
39
}
23
40
24
+static inline bool arm_cpu_data_is_big_endian_a32(CPUARMState *env,
41
+static inline bool isar_feature_aa64_mops(const ARMISARegisters *id)
25
+ bool sctlr_b)
26
+{
42
+{
27
+#ifdef CONFIG_USER_ONLY
43
+ return FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, MOPS);
28
+ /*
29
+ * In system mode, BE32 is modelled in line with the
30
+ * architecture (as word-invariant big-endianness), where loads
31
+ * and stores are done little endian but from addresses which
32
+ * are adjusted by XORing with the appropriate constant. So the
33
+ * endianness to use for the raw data access is not affected by
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
+}
44
+}
47
+
45
+
48
+static inline bool arm_cpu_data_is_big_endian_a64(int el, uint64_t sctlr)
46
/*
49
+{
47
* Feature tests for "does this exist in either 32-bit or 64-bit?"
50
+ return sctlr & (el ? SCTLR_EE : SCTLR_E0E);
48
*/
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
{
56
- /* In 32bit endianness is determined by looking at CPSR's E bit */
57
if (!is_a64(env)) {
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
}
82
}
83
84
diff --git a/target/arm/helper.c b/target/arm/helper.c
49
diff --git a/target/arm/helper.c b/target/arm/helper.c
85
index XXXXXXX..XXXXXXX 100644
50
index XXXXXXX..XXXXXXX 100644
86
--- a/target/arm/helper.c
51
--- a/target/arm/helper.c
87
+++ b/target/arm/helper.c
52
+++ b/target/arm/helper.c
88
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_common(CPUARMState *env, int fp_el,
53
@@ -XXX,XX +XXX,XX @@ static void hcrx_write(CPUARMState *env, const ARMCPRegInfo *ri,
89
flags = FIELD_DP32(flags, TBFLAG_ANY, MMUIDX,
54
{
90
arm_to_core_mmu_idx(mmu_idx));
55
uint64_t valid_mask = 0;
91
56
92
- if (arm_cpu_data_is_big_endian(env)) {
57
- /* No features adding bits to HCRX are implemented. */
93
- flags = FIELD_DP32(flags, TBFLAG_ANY, BE_DATA, 1);
58
+ /* FEAT_MOPS adds MSCEn and MCE2 */
94
- }
59
+ if (cpu_isar_feature(aa64_mops, env_archcpu(env))) {
95
if (arm_singlestep_active(env)) {
60
+ valid_mask |= HCRX_MSCEN | HCRX_MCE2;
96
flags = FIELD_DP32(flags, TBFLAG_ANY, SS_ACTIVE, 1);
61
+ }
62
63
/* Clear RES0 bits. */
64
env->cp15.hcrx_el2 = value & valid_mask;
65
@@ -XXX,XX +XXX,XX @@ uint64_t arm_hcrx_el2_eff(CPUARMState *env)
66
{
67
/*
68
* The bits in this register behave as 0 for all purposes other than
69
- * direct reads of the register if:
70
- * - EL2 is not enabled in the current security state,
71
- * - SCR_EL3.HXEn is 0.
72
+ * direct reads of the register if SCR_EL3.HXEn is 0.
73
+ * If EL2 is not enabled in the current security state, then the
74
+ * bit may behave as if 0, or as if 1, depending on the bit.
75
+ * For the moment, we treat the EL2-disabled case as taking
76
+ * priority over the HXEn-disabled case. This is true for the only
77
+ * bit for a feature which we implement where the answer is different
78
+ * for the two cases (MSCEn for FEAT_MOPS).
79
+ * This may need to be revisited for future bits.
80
*/
81
- if (!arm_is_el2_enabled(env)
82
- || (arm_feature(env, ARM_FEATURE_EL3)
83
- && !(env->cp15.scr_el3 & SCR_HXEN))) {
84
+ if (!arm_is_el2_enabled(env)) {
85
+ uint64_t hcrx = 0;
86
+ if (cpu_isar_feature(aa64_mops, env_archcpu(env))) {
87
+ /* MSCEn behaves as 1 if EL2 is not enabled */
88
+ hcrx |= HCRX_MSCEN;
89
+ }
90
+ return hcrx;
91
+ }
92
+ if (arm_feature(env, ARM_FEATURE_EL3) && !(env->cp15.scr_el3 & SCR_HXEN)) {
93
return 0;
97
}
94
}
98
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_common(CPUARMState *env, int fp_el,
95
return env->cp15.hcrx_el2;
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
+
105
+ if (sctlr_b) {
106
+ flags = FIELD_DP32(flags, TBFLAG_A32, SCTLR_B, 1);
107
+ }
108
+ if (arm_cpu_data_is_big_endian_a32(env, sctlr_b)) {
109
+ flags = FIELD_DP32(flags, TBFLAG_ANY, BE_DATA, 1);
110
+ }
111
flags = FIELD_DP32(flags, TBFLAG_A32, NS, !access_secure_reg(env));
112
113
return rebuild_hflags_common(env, fp_el, mmu_idx, flags);
114
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
115
116
sctlr = arm_sctlr(env, el);
117
118
+ if (arm_cpu_data_is_big_endian_a64(el, sctlr)) {
119
+ flags = FIELD_DP32(flags, TBFLAG_ANY, BE_DATA, 1);
120
+ }
121
+
122
if (cpu_isar_feature(aa64_pauth, env_archcpu(env))) {
123
/*
124
* In order to save space in flags, we record only whether
125
--
96
--
126
2.20.1
97
2.34.1
127
128
diff view generated by jsdifflib
1
Switch the slavio_timer code away from bottom-half based ptimers to
1
In every place that we call the get_a64_user_mem_index() function
2
the new transaction-based ptimer API. This just requires adding
2
we do it like this:
3
begin/commit calls around the various places that modify the ptimer
3
memidx = a->unpriv ? get_a64_user_mem_index(s) : get_mem_index(s);
4
state, and using the new ptimer_init() function to create the timer.
4
Refactor so the caller passes in the bool that says whether they
5
want the 'unpriv' or 'normal' mem_index rather than having to
6
do the ?: themselves.
5
7
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Message-id: 20230912140434.1333369-4-peter.maydell@linaro.org
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20191021134357.14266-4-peter.maydell@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
10
---
12
hw/timer/slavio_timer.c | 20 ++++++++++++++++----
11
target/arm/tcg/translate-a64.c | 20 ++++++++++++++------
13
1 file changed, 16 insertions(+), 4 deletions(-)
12
1 file changed, 14 insertions(+), 6 deletions(-)
14
13
15
diff --git a/hw/timer/slavio_timer.c b/hw/timer/slavio_timer.c
14
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/timer/slavio_timer.c
16
--- a/target/arm/tcg/translate-a64.c
18
+++ b/hw/timer/slavio_timer.c
17
+++ b/target/arm/tcg/translate-a64.c
19
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ void a64_translate_init(void)
20
#include "hw/sysbus.h"
19
}
21
#include "migration/vmstate.h"
22
#include "trace.h"
23
-#include "qemu/main-loop.h"
24
#include "qemu/module.h"
25
20
26
/*
21
/*
27
@@ -XXX,XX +XXX,XX @@ static void slavio_timer_mem_writel(void *opaque, hwaddr addr,
22
- * Return the core mmu_idx to use for A64 "unprivileged load/store" insns
28
saddr = addr >> 2;
23
+ * Return the core mmu_idx to use for A64 load/store insns which
29
switch (saddr) {
24
+ * have a "unprivileged load/store" variant. Those insns access
30
case TIMER_LIMIT:
25
+ * EL0 if executed from an EL which has control over EL0 (usually
31
+ ptimer_transaction_begin(t->timer);
26
+ * EL1) but behave like normal loads and stores if executed from
32
if (slavio_timer_is_user(tc)) {
27
+ * elsewhere (eg EL3).
33
uint64_t count;
28
+ *
34
29
+ * @unpriv : true for the unprivileged encoding; false for the
35
@@ -XXX,XX +XXX,XX @@ static void slavio_timer_mem_writel(void *opaque, hwaddr addr,
30
+ * normal encoding (in which case we will return the same
36
ptimer_set_limit(t->timer, LIMIT_TO_PERIODS(t->limit), 1);
31
+ * thing as get_mem_index().
37
}
32
*/
38
}
33
-static int get_a64_user_mem_index(DisasContext *s)
39
+ ptimer_transaction_commit(t->timer);
34
+static int get_a64_user_mem_index(DisasContext *s, bool unpriv)
40
break;
35
{
41
case TIMER_COUNTER:
36
/*
42
if (slavio_timer_is_user(tc)) {
37
* If AccType_UNPRIV is not used, the insn uses AccType_NORMAL,
43
@@ -XXX,XX +XXX,XX @@ static void slavio_timer_mem_writel(void *opaque, hwaddr addr,
38
@@ -XXX,XX +XXX,XX @@ static int get_a64_user_mem_index(DisasContext *s)
44
t->reached = 0;
39
*/
45
count = ((uint64_t)t->counthigh) << 32 | t->count;
40
ARMMMUIdx useridx = s->mmu_idx;
46
trace_slavio_timer_mem_writel_limit(timer_index, count);
41
47
+ ptimer_transaction_begin(t->timer);
42
- if (s->unpriv) {
48
ptimer_set_count(t->timer, LIMIT_TO_PERIODS(t->limit - count));
43
+ if (unpriv && s->unpriv) {
49
+ ptimer_transaction_commit(t->timer);
44
/*
50
} else {
45
* We have pre-computed the condition for AccType_UNPRIV.
51
trace_slavio_timer_mem_writel_counter_invalid();
46
* Therefore we should never get here with a mmu_idx for
52
}
47
@@ -XXX,XX +XXX,XX @@ static void op_addr_ldst_imm_pre(DisasContext *s, arg_ldst_imm *a,
53
@@ -XXX,XX +XXX,XX @@ static void slavio_timer_mem_writel(void *opaque, hwaddr addr,
48
if (!a->p) {
54
case TIMER_COUNTER_NORST:
49
tcg_gen_addi_i64(*dirty_addr, *dirty_addr, offset);
55
// set limit without resetting counter
56
t->limit = val & TIMER_MAX_COUNT32;
57
+ ptimer_transaction_begin(t->timer);
58
if (t->limit == 0) { /* free-run */
59
ptimer_set_limit(t->timer, LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 0);
60
} else {
61
ptimer_set_limit(t->timer, LIMIT_TO_PERIODS(t->limit), 0);
62
}
63
+ ptimer_transaction_commit(t->timer);
64
break;
65
case TIMER_STATUS:
66
+ ptimer_transaction_begin(t->timer);
67
if (slavio_timer_is_user(tc)) {
68
// start/stop user counter
69
if (val & 1) {
70
@@ -XXX,XX +XXX,XX @@ static void slavio_timer_mem_writel(void *opaque, hwaddr addr,
71
}
72
}
73
t->run = val & 1;
74
+ ptimer_transaction_commit(t->timer);
75
break;
76
case TIMER_MODE:
77
if (timer_index == 0) {
78
@@ -XXX,XX +XXX,XX @@ static void slavio_timer_mem_writel(void *opaque, hwaddr addr,
79
unsigned int processor = 1 << i;
80
CPUTimerState *curr_timer = &s->cputimer[i + 1];
81
82
+ ptimer_transaction_begin(curr_timer->timer);
83
// check for a change in timer mode for this processor
84
if ((val & processor) != (s->cputimer_mode & processor)) {
85
if (val & processor) { // counter -> user timer
86
@@ -XXX,XX +XXX,XX @@ static void slavio_timer_mem_writel(void *opaque, hwaddr addr,
87
trace_slavio_timer_mem_writel_mode_counter(timer_index);
88
}
89
}
90
+ ptimer_transaction_commit(curr_timer->timer);
91
}
92
} else {
93
trace_slavio_timer_mem_writel_mode_invalid();
94
@@ -XXX,XX +XXX,XX @@ static void slavio_timer_reset(DeviceState *d)
95
curr_timer->count = 0;
96
curr_timer->reached = 0;
97
if (i <= s->num_cpus) {
98
+ ptimer_transaction_begin(curr_timer->timer);
99
ptimer_set_limit(curr_timer->timer,
100
LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 1);
101
ptimer_run(curr_timer->timer, 0);
102
curr_timer->run = 1;
103
+ ptimer_transaction_commit(curr_timer->timer);
104
}
105
}
50
}
106
s->cputimer_mode = 0;
51
- memidx = a->unpriv ? get_a64_user_mem_index(s) : get_mem_index(s);
107
@@ -XXX,XX +XXX,XX @@ static void slavio_timer_init(Object *obj)
52
+ memidx = get_a64_user_mem_index(s, a->unpriv);
53
*clean_addr = gen_mte_check1_mmuidx(s, *dirty_addr, is_store,
54
a->w || a->rn != 31,
55
mop, a->unpriv, memidx);
56
@@ -XXX,XX +XXX,XX @@ static bool trans_STR_i(DisasContext *s, arg_ldst_imm *a)
108
{
57
{
109
SLAVIO_TIMERState *s = SLAVIO_TIMER(obj);
58
bool iss_sf, iss_valid = !a->w;
110
SysBusDevice *dev = SYS_BUS_DEVICE(obj);
59
TCGv_i64 clean_addr, dirty_addr, tcg_rt;
111
- QEMUBH *bh;
60
- int memidx = a->unpriv ? get_a64_user_mem_index(s) : get_mem_index(s);
112
unsigned int i;
61
+ int memidx = get_a64_user_mem_index(s, a->unpriv);
113
TimerContext *tc;
62
MemOp mop = finalize_memop(s, a->sz + a->sign * MO_SIGN);
114
63
115
@@ -XXX,XX +XXX,XX @@ static void slavio_timer_init(Object *obj)
64
op_addr_ldst_imm_pre(s, a, &clean_addr, &dirty_addr, a->imm, true, mop);
116
tc->s = s;
65
@@ -XXX,XX +XXX,XX @@ static bool trans_LDR_i(DisasContext *s, arg_ldst_imm *a)
117
tc->timer_index = i;
66
{
118
67
bool iss_sf, iss_valid = !a->w;
119
- bh = qemu_bh_new(slavio_timer_irq, tc);
68
TCGv_i64 clean_addr, dirty_addr, tcg_rt;
120
- s->cputimer[i].timer = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
69
- int memidx = a->unpriv ? get_a64_user_mem_index(s) : get_mem_index(s);
121
+ s->cputimer[i].timer = ptimer_init(slavio_timer_irq, tc,
70
+ int memidx = get_a64_user_mem_index(s, a->unpriv);
122
+ PTIMER_POLICY_DEFAULT);
71
MemOp mop = finalize_memop(s, a->sz + a->sign * MO_SIGN);
123
+ ptimer_transaction_begin(s->cputimer[i].timer);
72
124
ptimer_set_period(s->cputimer[i].timer, TIMER_PERIOD);
73
op_addr_ldst_imm_pre(s, a, &clean_addr, &dirty_addr, a->imm, false, mop);
125
+ ptimer_transaction_commit(s->cputimer[i].timer);
126
127
size = i == 0 ? SYS_TIMER_SIZE : CPU_TIMER_SIZE;
128
snprintf(timer_name, sizeof(timer_name), "timer-%i", i);
129
--
74
--
130
2.20.1
75
2.34.1
131
132
diff view generated by jsdifflib
1
Switch the xilinx_timer code away from bottom-half based ptimers to
1
The FEAT_MOPS memory operations can raise a Memory Copy or Memory Set
2
the new transaction-based ptimer API. This just requires adding
2
exception if a copy or set instruction is executed when the CPU
3
begin/commit calls around the various places that modify the ptimer
3
register state is not correct for that instruction. Define the
4
state, and using the new ptimer_init() function to create the timer.
4
usual syn_* function that constructs the syndrome register value
5
for these exceptions.
5
6
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Message-id: 20230912140434.1333369-5-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
---
10
---
13
hw/timer/xilinx_timer.c | 13 ++++++++-----
11
target/arm/syndrome.h | 12 ++++++++++++
14
1 file changed, 8 insertions(+), 5 deletions(-)
12
1 file changed, 12 insertions(+)
15
13
16
diff --git a/hw/timer/xilinx_timer.c b/hw/timer/xilinx_timer.c
14
diff --git a/target/arm/syndrome.h b/target/arm/syndrome.h
17
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/timer/xilinx_timer.c
16
--- a/target/arm/syndrome.h
19
+++ b/hw/timer/xilinx_timer.c
17
+++ b/target/arm/syndrome.h
20
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ enum arm_exception_class {
21
#include "hw/ptimer.h"
19
EC_DATAABORT = 0x24,
22
#include "hw/qdev-properties.h"
20
EC_DATAABORT_SAME_EL = 0x25,
23
#include "qemu/log.h"
21
EC_SPALIGNMENT = 0x26,
24
-#include "qemu/main-loop.h"
22
+ EC_MOP = 0x27,
25
#include "qemu/module.h"
23
EC_AA32_FPTRAP = 0x28,
26
24
EC_AA64_FPTRAP = 0x2c,
27
#define D(x)
25
EC_SERROR = 0x2f,
28
@@ -XXX,XX +XXX,XX @@
26
@@ -XXX,XX +XXX,XX @@ static inline uint32_t syn_serror(uint32_t extra)
29
27
return (EC_SERROR << ARM_EL_EC_SHIFT) | ARM_EL_IL | extra;
30
struct xlx_timer
31
{
32
- QEMUBH *bh;
33
ptimer_state *ptimer;
34
void *parent;
35
int nr; /* for debug. */
36
@@ -XXX,XX +XXX,XX @@ timer_read(void *opaque, hwaddr addr, unsigned int size)
37
return r;
38
}
28
}
39
29
40
+/* Must be called inside ptimer transaction block */
30
+static inline uint32_t syn_mop(bool is_set, bool is_setg, int options,
41
static void timer_enable(struct xlx_timer *xt)
31
+ bool epilogue, bool wrong_option, bool option_a,
42
{
32
+ int destreg, int srcreg, int sizereg)
43
uint64_t count;
33
+{
44
@@ -XXX,XX +XXX,XX @@ timer_write(void *opaque, hwaddr addr,
34
+ return (EC_MOP << ARM_EL_EC_SHIFT) | ARM_EL_IL |
45
value &= ~TCSR_TINT;
35
+ (is_set << 24) | (is_setg << 23) | (options << 19) |
46
36
+ (epilogue << 18) | (wrong_option << 17) | (option_a << 16) |
47
xt->regs[addr] = value & 0x7ff;
37
+ (destreg << 10) | (srcreg << 5) | sizereg;
48
- if (value & TCSR_ENT)
38
+}
49
+ if (value & TCSR_ENT) {
39
+
50
+ ptimer_transaction_begin(xt->ptimer);
40
+
51
timer_enable(xt);
41
#endif /* TARGET_ARM_SYNDROME_H */
52
+ ptimer_transaction_commit(xt->ptimer);
53
+ }
54
break;
55
56
default:
57
@@ -XXX,XX +XXX,XX @@ static void xilinx_timer_realize(DeviceState *dev, Error **errp)
58
59
xt->parent = t;
60
xt->nr = i;
61
- xt->bh = qemu_bh_new(timer_hit, xt);
62
- xt->ptimer = ptimer_init_with_bh(xt->bh, PTIMER_POLICY_DEFAULT);
63
+ xt->ptimer = ptimer_init(timer_hit, xt, PTIMER_POLICY_DEFAULT);
64
+ ptimer_transaction_begin(xt->ptimer);
65
ptimer_set_freq(xt->ptimer, t->freq_hz);
66
+ ptimer_transaction_commit(xt->ptimer);
67
}
68
69
memory_region_init_io(&t->mmio, OBJECT(t), &timer_ops, t, "xlnx.xps-timer",
70
--
42
--
71
2.20.1
43
2.34.1
72
73
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
1
For the FEAT_MOPS operations, the existing allocation_tag_mem()
2
function almost does what we want, but it will take a watchpoint
3
exception even for an ra == 0 probe request, and it requires that the
4
caller guarantee that the memory is accessible. For FEAT_MOPS we
5
want a function that will not take any kind of exception, and will
6
return NULL for the not-accessible case.
2
7
3
Since 97a28b0eeac14 ("target/arm: Allow VFP and Neon to be disabled via
8
Rename allocation_tag_mem() to allocation_tag_mem_probe() and add an
4
a CPU property") we can disable the 'max' cpu model's VFP and neon
9
extra 'probe' argument that lets us distinguish these cases;
5
features, but there's no way to disable SVE. Add the 'sve=on|off'
10
allocation_tag_mem() is now a wrapper that always passes 'false'.
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
11
10
Signed-off-by: Andrew Jones <drjones@redhat.com>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Eric Auger <eric.auger@redhat.com>
14
Message-id: 20230912140434.1333369-6-peter.maydell@linaro.org
13
Tested-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
14
Reviewed-by: Beata Michalska <beata.michalska@linaro.org>
15
Message-id: 20191024121808.9612-4-drjones@redhat.com
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
15
---
18
target/arm/cpu.c | 3 ++-
16
target/arm/tcg/mte_helper.c | 48 ++++++++++++++++++++++++++++---------
19
target/arm/cpu64.c | 52 ++++++++++++++++++++++++++++++++++------
17
1 file changed, 37 insertions(+), 11 deletions(-)
20
target/arm/monitor.c | 2 +-
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/tcg/mte_helper.c b/target/arm/tcg/mte_helper.c
25
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/cpu.c
21
--- a/target/arm/tcg/mte_helper.c
27
+++ b/target/arm/cpu.c
22
+++ b/target/arm/tcg/mte_helper.c
28
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
23
@@ -XXX,XX +XXX,XX @@ static int choose_nonexcluded_tag(int tag, int offset, uint16_t exclude)
29
env->cp15.cpacr_el1 = deposit64(env->cp15.cpacr_el1, 16, 2, 3);
30
env->cp15.cptr_el[3] |= CPTR_EZ;
31
/* with maximum vector length */
32
- env->vfp.zcr_el[1] = cpu->sve_max_vq - 1;
33
+ env->vfp.zcr_el[1] = cpu_isar_feature(aa64_sve, cpu) ?
34
+ cpu->sve_max_vq - 1 : 0;
35
env->vfp.zcr_el[2] = env->vfp.zcr_el[1];
36
env->vfp.zcr_el[3] = env->vfp.zcr_el[1];
37
/*
38
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/target/arm/cpu64.c
41
+++ 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
}
24
}
45
25
46
-static void cpu_max_get_sve_vq(Object *obj, Visitor *v, const char *name,
26
/**
47
- void *opaque, Error **errp)
27
- * allocation_tag_mem:
48
+static void cpu_max_get_sve_max_vq(Object *obj, Visitor *v, const char *name,
28
+ * allocation_tag_mem_probe:
49
+ void *opaque, Error **errp)
29
* @env: the cpu environment
30
* @ptr_mmu_idx: the addressing regime to use for the virtual address
31
* @ptr: the virtual address for which to look up tag memory
32
* @ptr_access: the access to use for the virtual address
33
* @ptr_size: the number of bytes in the normal memory access
34
* @tag_access: the access to use for the tag memory
35
+ * @probe: true to merely probe, never taking an exception
36
* @ra: the return address for exception handling
37
*
38
* Our tag memory is formatted as a sequence of little-endian nibbles.
39
@@ -XXX,XX +XXX,XX @@ static int choose_nonexcluded_tag(int tag, int offset, uint16_t exclude)
40
* for the higher addr.
41
*
42
* Here, resolve the physical address from the virtual address, and return
43
- * a pointer to the corresponding tag byte. Exit with exception if the
44
- * virtual address is not accessible for @ptr_access.
45
+ * a pointer to the corresponding tag byte.
46
*
47
* If there is no tag storage corresponding to @ptr, return NULL.
48
+ *
49
+ * If the page is inaccessible for @ptr_access, or has a watchpoint, there are
50
+ * three options:
51
+ * (1) probe = true, ra = 0 : pure probe -- we return NULL if the page is not
52
+ * accessible, and do not take watchpoint traps. The calling code must
53
+ * handle those cases in the right priority compared to MTE traps.
54
+ * (2) probe = false, ra = 0 : probe, no fault expected -- the caller guarantees
55
+ * that the page is going to be accessible. We will take watchpoint traps.
56
+ * (3) probe = false, ra != 0 : non-probe -- we will take both memory access
57
+ * traps and watchpoint traps.
58
+ * (probe = true, ra != 0 is invalid and will assert.)
59
*/
60
-static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx,
61
- uint64_t ptr, MMUAccessType ptr_access,
62
- int ptr_size, MMUAccessType tag_access,
63
- uintptr_t ra)
64
+static uint8_t *allocation_tag_mem_probe(CPUARMState *env, int ptr_mmu_idx,
65
+ uint64_t ptr, MMUAccessType ptr_access,
66
+ int ptr_size, MMUAccessType tag_access,
67
+ bool probe, uintptr_t ra)
50
{
68
{
51
ARMCPU *cpu = ARM_CPU(obj);
69
#ifdef CONFIG_USER_ONLY
52
- visit_type_uint32(v, name, &cpu->sve_max_vq, errp);
70
uint64_t clean_ptr = useronly_clean_ptr(ptr);
53
+ uint32_t value;
71
@@ -XXX,XX +XXX,XX @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx,
72
uint8_t *tags;
73
uintptr_t index;
74
75
+ assert(!(probe && ra));
54
+
76
+
55
+ /* All vector lengths are disabled when SVE is off. */
77
if (!(flags & (ptr_access == MMU_DATA_STORE ? PAGE_WRITE_ORG : PAGE_READ))) {
56
+ if (!cpu_isar_feature(aa64_sve, cpu)) {
78
cpu_loop_exit_sigsegv(env_cpu(env), ptr, ptr_access,
57
+ value = 0;
79
!(flags & PAGE_VALID), ra);
58
+ } else {
80
@@ -XXX,XX +XXX,XX @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx,
59
+ value = cpu->sve_max_vq;
81
* exception for inaccessible pages, and resolves the virtual address
82
* into the softmmu tlb.
83
*
84
- * When RA == 0, this is for mte_probe. The page is expected to be
85
- * valid. Indicate to probe_access_flags no-fault, then assert that
86
- * we received a valid page.
87
+ * When RA == 0, this is either a pure probe or a no-fault-expected probe.
88
+ * Indicate to probe_access_flags no-fault, then either return NULL
89
+ * for the pure probe, or assert that we received a valid page for the
90
+ * no-fault-expected probe.
91
*/
92
flags = probe_access_full(env, ptr, 0, ptr_access, ptr_mmu_idx,
93
ra == 0, &host, &full, ra);
94
+ if (probe && (flags & TLB_INVALID_MASK)) {
95
+ return NULL;
60
+ }
96
+ }
61
+ visit_type_uint32(v, name, &value, errp);
97
assert(!(flags & TLB_INVALID_MASK));
98
99
/* If the virtual page MemAttr != Tagged, access unchecked. */
100
@@ -XXX,XX +XXX,XX @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx,
101
}
102
103
/* Any debug exception has priority over a tag check exception. */
104
- if (unlikely(flags & TLB_WATCHPOINT)) {
105
+ if (!probe && unlikely(flags & TLB_WATCHPOINT)) {
106
int wp = ptr_access == MMU_DATA_LOAD ? BP_MEM_READ : BP_MEM_WRITE;
107
assert(ra != 0);
108
cpu_check_watchpoint(env_cpu(env), ptr, ptr_size, attrs, wp, ra);
109
@@ -XXX,XX +XXX,XX @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx,
110
#endif
62
}
111
}
63
112
64
-static void cpu_max_set_sve_vq(Object *obj, Visitor *v, const char *name,
113
+static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx,
65
- void *opaque, Error **errp)
114
+ uint64_t ptr, MMUAccessType ptr_access,
66
+static void cpu_max_set_sve_max_vq(Object *obj, Visitor *v, const char *name,
115
+ int ptr_size, MMUAccessType tag_access,
67
+ void *opaque, Error **errp)
116
+ uintptr_t ra)
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,
72
error_propagate(errp, err);
73
}
74
75
+static void cpu_arm_get_sve(Object *obj, Visitor *v, const char *name,
76
+ void *opaque, Error **errp)
77
+{
117
+{
78
+ ARMCPU *cpu = ARM_CPU(obj);
118
+ return allocation_tag_mem_probe(env, ptr_mmu_idx, ptr, ptr_access,
79
+ bool value = cpu_isar_feature(aa64_sve, cpu);
119
+ ptr_size, tag_access, false, ra);
80
+
81
+ visit_type_bool(v, name, &value, errp);
82
+}
120
+}
83
+
121
+
84
+static void cpu_arm_set_sve(Object *obj, Visitor *v, const char *name,
122
uint64_t HELPER(irg)(CPUARMState *env, uint64_t rn, uint64_t rm)
85
+ void *opaque, Error **errp)
123
{
86
+{
124
uint16_t exclude = extract32(rm | env->cp15.gcr_el1, 0, 16);
87
+ ARMCPU *cpu = ARM_CPU(obj);
88
+ Error *err = NULL;
89
+ bool value;
90
+ uint64_t t;
91
+
92
+ visit_type_bool(v, name, &value, &err);
93
+ if (err) {
94
+ error_propagate(errp, err);
95
+ return;
96
+ }
97
+
98
+ t = cpu->isar.id_aa64pfr0;
99
+ t = FIELD_DP64(t, ID_AA64PFR0, SVE, value);
100
+ cpu->isar.id_aa64pfr0 = t;
101
+}
102
+
103
/* -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.
105
* 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)
107
#endif
108
109
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
--
125
--
145
2.20.1
126
2.34.1
146
147
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
1
The FEAT_MOPS instructions need a couple of helper routines that
2
check for MTE tag failures:
3
* mte_mops_probe() checks whether there is going to be a tag
4
error in the next up-to-a-page worth of data
5
* mte_check_fail() is an existing function to record the fact
6
of a tag failure, which we need to make global so we can
7
call it from helper-a64.c
2
8
3
Introduce cpu properties to give fine control over SVE vector lengths.
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
We introduce a property for each valid length up to the current
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
maximum supported, which is 2048-bits. The properties are named, e.g.
11
Message-id: 20230912140434.1333369-7-peter.maydell@linaro.org
6
sve128, sve256, sve384, sve512, ..., where the number is the number of
12
---
7
bits. See the updates to docs/arm-cpu-features.rst for a description
13
target/arm/internals.h | 28 +++++++++++++++++++
8
of the semantics and for example uses.
14
target/arm/tcg/mte_helper.c | 54 +++++++++++++++++++++++++++++++++++--
15
2 files changed, 80 insertions(+), 2 deletions(-)
9
16
10
Note, as sve-max-vq is still present and we'd like to be able to
17
diff --git a/target/arm/internals.h b/target/arm/internals.h
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>
29
Reviewed-by: Eric Auger <eric.auger@redhat.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>
34
---
35
include/qemu/bitops.h | 1 +
36
target/arm/cpu.h | 19 ++++
37
target/arm/cpu.c | 19 ++++
38
target/arm/cpu64.c | 192 ++++++++++++++++++++++++++++++++++++-
39
target/arm/helper.c | 10 +-
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
18
index XXXXXXX..XXXXXXX 100644
47
--- a/include/qemu/bitops.h
19
--- a/target/arm/internals.h
48
+++ b/include/qemu/bitops.h
20
+++ b/target/arm/internals.h
49
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@ FIELD(MTEDESC, SIZEM1, 12, SIMD_DATA_BITS - 12) /* size - 1 */
50
#define BITS_PER_LONG (sizeof (unsigned long) * BITS_PER_BYTE)
22
bool mte_probe(CPUARMState *env, uint32_t desc, uint64_t ptr);
51
23
uint64_t mte_check(CPUARMState *env, uint32_t desc, uint64_t ptr, uintptr_t ra);
52
#define BIT(nr) (1UL << (nr))
24
53
+#define BIT_ULL(nr) (1ULL << (nr))
25
+/**
54
#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
26
+ * mte_mops_probe: Check where the next MTE failure is for a FEAT_MOPS operation
55
#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
27
+ * @env: CPU env
56
#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
28
+ * @ptr: start address of memory region (dirty pointer)
57
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
29
+ * @size: length of region (guaranteed not to cross a page boundary)
30
+ * @desc: MTEDESC descriptor word (0 means no MTE checks)
31
+ * Returns: the size of the region that can be copied without hitting
32
+ * an MTE tag failure
33
+ *
34
+ * Note that we assume that the caller has already checked the TBI
35
+ * and TCMA bits with mte_checks_needed() and an MTE check is definitely
36
+ * required.
37
+ */
38
+uint64_t mte_mops_probe(CPUARMState *env, uint64_t ptr, uint64_t size,
39
+ uint32_t desc);
40
+
41
+/**
42
+ * mte_check_fail: Record an MTE tag check failure
43
+ * @env: CPU env
44
+ * @desc: MTEDESC descriptor word
45
+ * @dirty_ptr: Failing dirty address
46
+ * @ra: TCG retaddr
47
+ *
48
+ * This may never return (if the MTE tag checks are configured to fault).
49
+ */
50
+void mte_check_fail(CPUARMState *env, uint32_t desc,
51
+ uint64_t dirty_ptr, uintptr_t ra);
52
+
53
static inline int allocation_tag_from_addr(uint64_t ptr)
54
{
55
return extract64(ptr, 56, 4);
56
diff --git a/target/arm/tcg/mte_helper.c b/target/arm/tcg/mte_helper.c
58
index XXXXXXX..XXXXXXX 100644
57
index XXXXXXX..XXXXXXX 100644
59
--- a/target/arm/cpu.h
58
--- a/target/arm/tcg/mte_helper.c
60
+++ b/target/arm/cpu.h
59
+++ b/target/arm/tcg/mte_helper.c
61
@@ -XXX,XX +XXX,XX @@ typedef struct {
60
@@ -XXX,XX +XXX,XX @@ static void mte_async_check_fail(CPUARMState *env, uint64_t dirty_ptr,
62
61
}
63
#ifdef TARGET_AARCH64
62
64
# define ARM_MAX_VQ 16
63
/* Record a tag check failure. */
65
+void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp);
64
-static void mte_check_fail(CPUARMState *env, uint32_t desc,
66
+uint32_t arm_cpu_vq_map_next_smaller(ARMCPU *cpu, uint32_t vq);
65
- uint64_t dirty_ptr, uintptr_t ra)
67
#else
66
+void mte_check_fail(CPUARMState *env, uint32_t desc,
68
# define ARM_MAX_VQ 1
67
+ uint64_t dirty_ptr, uintptr_t ra)
69
+static inline void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp) { }
68
{
70
+static inline uint32_t arm_cpu_vq_map_next_smaller(ARMCPU *cpu, uint32_t vq)
69
int mmu_idx = FIELD_EX32(desc, MTEDESC, MIDX);
71
+{ return 0; }
70
ARMMMUIdx arm_mmu_idx = core_to_aa64_mmu_idx(mmu_idx);
72
#endif
71
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(mte_check_zva)(CPUARMState *env, uint32_t desc, uint64_t ptr)
73
72
done:
74
typedef struct ARMVectorReg {
73
return useronly_clean_ptr(ptr);
75
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
74
}
76
77
/* Used to set the maximum vector length the cpu will support. */
78
uint32_t sve_max_vq;
79
+
75
+
80
+ /*
76
+uint64_t mte_mops_probe(CPUARMState *env, uint64_t ptr, uint64_t size,
81
+ * In sve_vq_map each set bit is a supported vector length of
77
+ uint32_t desc)
82
+ * (bit-number + 1) * 16 bytes, i.e. each bit number + 1 is the vector
78
+{
83
+ * length in quadwords.
79
+ int mmu_idx, tag_count;
84
+ *
80
+ uint64_t ptr_tag, tag_first, tag_last;
85
+ * While processing properties during initialization, corresponding
81
+ void *mem;
86
+ * sve_vq_init bits are set for bits in sve_vq_map that have been
82
+ bool w = FIELD_EX32(desc, MTEDESC, WRITE);
87
+ * set by properties.
83
+ uint32_t n;
88
+ */
89
+ DECLARE_BITMAP(sve_vq_map, ARM_MAX_VQ);
90
+ DECLARE_BITMAP(sve_vq_init, ARM_MAX_VQ);
91
};
92
93
void arm_cpu_post_init(Object *obj);
94
@@ -XXX,XX +XXX,XX @@ static inline int arm_feature(CPUARMState *env, int feature)
95
return (env->features & (1ULL << feature)) != 0;
96
}
97
98
+void arm_cpu_finalize_features(ARMCPU *cpu, Error **errp);
99
+
84
+
100
#if !defined(CONFIG_USER_ONLY)
85
+ mmu_idx = FIELD_EX32(desc, MTEDESC, MIDX);
101
/* Return true if exception levels below EL3 are in secure state,
86
+ /* True probe; this will never fault */
102
* or would be following an exception return to that level.
87
+ mem = allocation_tag_mem_probe(env, mmu_idx, ptr,
103
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
88
+ w ? MMU_DATA_STORE : MMU_DATA_LOAD,
104
index XXXXXXX..XXXXXXX 100644
89
+ size, MMU_DATA_LOAD, true, 0);
105
--- a/target/arm/cpu.c
90
+ if (!mem) {
106
+++ b/target/arm/cpu.c
91
+ return size;
107
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_finalizefn(Object *obj)
108
#endif
109
}
110
111
+void arm_cpu_finalize_features(ARMCPU *cpu, Error **errp)
112
+{
113
+ Error *local_err = NULL;
114
+
115
+ if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
116
+ arm_cpu_sve_finalize(cpu, &local_err);
117
+ if (local_err != NULL) {
118
+ error_propagate(errp, local_err);
119
+ return;
120
+ }
121
+ }
122
+}
123
+
124
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)
128
return;
129
}
130
131
+ arm_cpu_finalize_features(cpu, &local_err);
132
+ if (local_err != NULL) {
133
+ error_propagate(errp, local_err);
134
+ return;
135
+ }
136
+
137
if (arm_feature(env, ARM_FEATURE_AARCH64) &&
138
cpu->has_vfp != cpu->has_neon) {
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
+ }
92
+ }
219
+
93
+
220
+ /*
94
+ /*
221
+ * Process the sve-max-vq property.
95
+ * TODO: checkN() is not designed for checks of the size we expect
222
+ * Note that we know from the above that no bit above
96
+ * for FEAT_MOPS operations, so we should implement this differently.
223
+ * sve-max-vq is currently set.
97
+ * Maybe we should do something like
98
+ * if (region start and size are aligned nicely) {
99
+ * do direct loads of 64 tag bits at a time;
100
+ * } else {
101
+ * call checkN()
102
+ * }
224
+ */
103
+ */
225
+ if (cpu->sve_max_vq != 0) {
104
+ /* Round the bounds to the tag granule, and compute the number of tags. */
226
+ max_vq = cpu->sve_max_vq;
105
+ ptr_tag = allocation_tag_from_addr(ptr);
227
+
106
+ tag_first = QEMU_ALIGN_DOWN(ptr, TAG_GRANULE);
228
+ if (!test_bit(max_vq - 1, cpu->sve_vq_map) &&
107
+ tag_last = QEMU_ALIGN_DOWN(ptr + size - 1, TAG_GRANULE);
229
+ test_bit(max_vq - 1, cpu->sve_vq_init)) {
108
+ tag_count = ((tag_last - tag_first) / TAG_GRANULE) + 1;
230
+ error_setg(errp, "cannot disable sve%d", max_vq * 128);
109
+ n = checkN(mem, ptr & TAG_GRANULE, ptr_tag, tag_count);
231
+ error_append_hint(errp, "The maximum vector length must be "
110
+ if (likely(n == tag_count)) {
232
+ "enabled, sve-max-vq=%d (%d bits)\n",
111
+ return size;
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
+ }
112
+ }
241
+
113
+
242
+ /*
114
+ /*
243
+ * We should know what max-vq is now. Also, as we're done
115
+ * Failure; for the first granule, it's at @ptr. Otherwise
244
+ * manipulating sve-vq-map, we ensure any bits above max-vq
116
+ * it's at the first byte of the nth granule. Calculate how
245
+ * are clear, just in case anybody looks.
117
+ * many bytes we can access without hitting that failure.
246
+ */
118
+ */
247
+ assert(max_vq != 0);
119
+ if (n == 0) {
248
+ bitmap_clear(cpu->sve_vq_map, max_vq, ARM_MAX_VQ - max_vq);
120
+ return 0;
249
+
121
+ } else {
250
+ /* Ensure all required powers-of-two are enabled. */
122
+ return n * TAG_GRANULE - (ptr - tag_first);
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
+ }
123
+ }
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
+}
124
+}
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
369
index XXXXXXX..XXXXXXX 100644
370
--- a/target/arm/helper.c
371
+++ b/target/arm/helper.c
372
@@ -XXX,XX +XXX,XX @@ int sve_exception_el(CPUARMState *env, int el)
373
return 0;
374
}
375
376
+static uint32_t sve_zcr_get_valid_len(ARMCPU *cpu, uint32_t start_len)
377
+{
378
+ uint32_t start_vq = (start_len & 0xf) + 1;
379
+
380
+ return arm_cpu_vq_map_next_smaller(cpu, start_vq + 1) - 1;
381
+}
382
+
383
/*
384
* Given that SVE is enabled, return the vector length for EL.
385
*/
386
@@ -XXX,XX +XXX,XX @@ uint32_t sve_zcr_len_for_el(CPUARMState *env, int el)
387
if (arm_feature(env, ARM_FEATURE_EL3)) {
388
zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[3]);
389
}
390
- return zcr_len;
391
+
392
+ return sve_zcr_get_valid_len(cpu, zcr_len);
393
}
394
395
static void zcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
396
diff --git a/target/arm/monitor.c b/target/arm/monitor.c
397
index XXXXXXX..XXXXXXX 100644
398
--- a/target/arm/monitor.c
399
+++ b/target/arm/monitor.c
400
@@ -XXX,XX +XXX,XX @@ GICCapabilityList *qmp_query_gic_capabilities(Error **errp)
401
return head;
402
}
403
404
+QEMU_BUILD_BUG_ON(ARM_MAX_VQ > 16);
405
+
406
/*
407
* These are cpu model features we want to advertise. The order here
408
* matters as this is the order in which qmp_query_cpu_model_expansion
409
@@ -XXX,XX +XXX,XX @@ GICCapabilityList *qmp_query_gic_capabilities(Error **errp)
410
*/
411
static const char *cpu_model_advertised_features[] = {
412
"aarch64", "pmu", "sve",
413
+ "sve128", "sve256", "sve384", "sve512",
414
+ "sve640", "sve768", "sve896", "sve1024", "sve1152", "sve1280",
415
+ "sve1408", "sve1536", "sve1664", "sve1792", "sve1920", "sve2048",
416
NULL
417
};
418
419
@@ -XXX,XX +XXX,XX @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
420
if (!err) {
421
visit_check_struct(visitor, &err);
422
}
423
+ if (!err) {
424
+ arm_cpu_finalize_features(ARM_CPU(obj), &err);
425
+ }
426
visit_end_struct(visitor, NULL);
427
visit_free(visitor);
428
if (err) {
429
@@ -XXX,XX +XXX,XX @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
430
error_propagate(errp, err);
431
return NULL;
432
}
433
+ } else {
434
+ Error *err = NULL;
435
+ arm_cpu_finalize_features(ARM_CPU(obj), &err);
436
+ assert(err == NULL);
437
}
438
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
+ /*
513
+ * With no sve-max-vq or sve<N> properties on the command line
514
+ * the default is to have all vector lengths enabled. This also
515
+ * tests that 'sve' is 'on' by default.
516
+ */
517
+ assert_sve_vls(qts, cpu_type, BIT_ULL(SVE_MAX_VQ) - 1, NULL);
518
+
519
+ /* With SVE off, all vector lengths should also be off. */
520
+ assert_sve_vls(qts, cpu_type, 0, "{ 'sve': false }");
521
+
522
+ /* With SVE on, we must have at least one vector length enabled. */
523
+ assert_error(qts, cpu_type, "cannot disable sve128", "{ 'sve128': false }");
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
--
125
--
874
2.20.1
126
2.34.1
875
876
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
1
Implement the SET* instructions which collectively implement a
2
"memset" operation. These come in a set of three, eg SETP
3
(prologue), SETM (main), SETE (epilogue), and each of those has
4
different flavours to indicate whether memory accesses should be
5
unpriv or non-temporal.
2
6
3
Add support for the query-cpu-model-expansion QMP command to Arm. We
7
This commit does not include the "memset with tag setting"
4
do this selectively, only exposing CPU properties which represent
8
SETG* instructions.
5
optional CPU features which the user may want to enable/disable.
6
Additionally we restrict the list of queryable cpu models to 'max',
7
'host', or the current type when KVM is in use. And, finally, we only
8
implement expansion type 'full', as Arm does not yet have a "base"
9
CPU type. More details and example queries are described in a new
10
document (docs/arm-cpu-features.rst).
11
9
12
Note, certainly more features may be added to the list of advertised
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
features, e.g. 'vfp' and 'neon'. The only requirement is that we can
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
detect invalid configurations and emit failures at QMP query time.
12
Message-id: 20230912140434.1333369-8-peter.maydell@linaro.org
15
For 'vfp' and 'neon' this will require some refactoring to share a
13
---
16
validation function between the QMP query and the CPU realize
14
target/arm/tcg/helper-a64.h | 4 +
17
functions.
15
target/arm/tcg/a64.decode | 16 ++
16
target/arm/tcg/helper-a64.c | 344 +++++++++++++++++++++++++++++++++
17
target/arm/tcg/translate-a64.c | 49 +++++
18
4 files changed, 413 insertions(+)
18
19
19
Signed-off-by: Andrew Jones <drjones@redhat.com>
20
diff --git a/target/arm/tcg/helper-a64.h b/target/arm/tcg/helper-a64.h
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Reviewed-by: Eric Auger <eric.auger@redhat.com>
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
---
26
qapi/machine-target.json | 6 +-
27
target/arm/monitor.c | 146 ++++++++++++++++++++++++++++++++++++++
28
docs/arm-cpu-features.rst | 137 +++++++++++++++++++++++++++++++++++
29
3 files changed, 286 insertions(+), 3 deletions(-)
30
create mode 100644 docs/arm-cpu-features.rst
31
32
diff --git a/qapi/machine-target.json b/qapi/machine-target.json
33
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
34
--- a/qapi/machine-target.json
22
--- a/target/arm/tcg/helper-a64.h
35
+++ b/qapi/machine-target.json
23
+++ b/target/arm/tcg/helper-a64.h
36
@@ -XXX,XX +XXX,XX @@
24
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(stzgm_tags, TCG_CALL_NO_WG, void, env, i64, i64)
37
##
25
38
{ 'struct': 'CpuModelExpansionInfo',
26
DEF_HELPER_FLAGS_4(unaligned_access, TCG_CALL_NO_WG,
39
'data': { 'model': 'CpuModelInfo' },
27
noreturn, env, i64, i32, i32)
40
- 'if': 'defined(TARGET_S390X) || defined(TARGET_I386)' }
28
+
41
+ 'if': 'defined(TARGET_S390X) || defined(TARGET_I386) || defined(TARGET_ARM)' }
29
+DEF_HELPER_3(setp, void, env, i32, i32)
42
30
+DEF_HELPER_3(setm, void, env, i32, i32)
43
##
31
+DEF_HELPER_3(sete, void, env, i32, i32)
44
# @query-cpu-model-expansion:
32
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
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
33
index XXXXXXX..XXXXXXX 100644
65
--- a/target/arm/monitor.c
34
--- a/target/arm/tcg/a64.decode
66
+++ b/target/arm/monitor.c
35
+++ b/target/arm/tcg/a64.decode
67
@@ -XXX,XX +XXX,XX @@
36
@@ -XXX,XX +XXX,XX @@ LDGM 11011001 11 1 ......... 00 ..... ..... @ldst_tag_mult p=0 w=0
68
*/
37
STZ2G 11011001 11 1 ......... 01 ..... ..... @ldst_tag p=1 w=1
69
38
STZ2G 11011001 11 1 ......... 10 ..... ..... @ldst_tag p=0 w=0
70
#include "qemu/osdep.h"
39
STZ2G 11011001 11 1 ......... 11 ..... ..... @ldst_tag p=0 w=1
71
+#include "hw/boards.h"
40
+
72
#include "kvm_arm.h"
41
+# Memory operations (memset, memcpy, memmove)
73
+#include "qapi/error.h"
42
+# Each of these comes in a set of three, eg SETP (prologue), SETM (main),
74
+#include "qapi/visitor.h"
43
+# SETE (epilogue), and each of those has different flavours to
75
+#include "qapi/qobject-input-visitor.h"
44
+# indicate whether memory accesses should be unpriv or non-temporal.
76
+#include "qapi/qapi-commands-machine-target.h"
45
+# We don't distinguish temporal and non-temporal accesses, but we
77
#include "qapi/qapi-commands-misc-target.h"
46
+# do need to report it in syndrome register values.
78
+#include "qapi/qmp/qerror.h"
47
+
79
+#include "qapi/qmp/qdict.h"
48
+# Memset
80
+#include "qom/qom-qobject.h"
49
+&set rs rn rd unpriv nontemp
81
50
+# op2 bit 1 is nontemporal bit
82
static GICCapability *gic_cap_new(int version)
51
+@set .. ......... rs:5 .. nontemp:1 unpriv:1 .. rn:5 rd:5 &set
83
{
52
+
84
@@ -XXX,XX +XXX,XX @@ GICCapabilityList *qmp_query_gic_capabilities(Error **errp)
53
+SETP 00 011001110 ..... 00 . . 01 ..... ..... @set
85
54
+SETM 00 011001110 ..... 01 . . 01 ..... ..... @set
86
return head;
55
+SETE 00 011001110 ..... 10 . . 01 ..... ..... @set
56
diff --git a/target/arm/tcg/helper-a64.c b/target/arm/tcg/helper-a64.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/target/arm/tcg/helper-a64.c
59
+++ b/target/arm/tcg/helper-a64.c
60
@@ -XXX,XX +XXX,XX @@ void HELPER(unaligned_access)(CPUARMState *env, uint64_t addr,
61
arm_cpu_do_unaligned_access(env_cpu(env), addr, access_type,
62
mmu_idx, GETPC());
87
}
63
}
88
+
64
+
89
+/*
65
+/* Memory operations (memset, memmove, memcpy) */
90
+ * These are cpu model features we want to advertise. The order here
66
+
91
+ * matters as this is the order in which qmp_query_cpu_model_expansion
67
+/*
92
+ * will attempt to set them. If there are dependencies between features,
68
+ * Return true if the CPY* and SET* insns can execute; compare
93
+ * then the order that considers those dependencies must be used.
69
+ * pseudocode CheckMOPSEnabled(), though we refactor it a little.
94
+ */
70
+ */
95
+static const char *cpu_model_advertised_features[] = {
71
+static bool mops_enabled(CPUARMState *env)
96
+ "aarch64", "pmu",
72
+{
97
+ NULL
73
+ int el = arm_current_el(env);
98
+};
74
+
99
+
75
+ if (el < 2 &&
100
+CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
76
+ (arm_hcr_el2_eff(env) & (HCR_E2H | HCR_TGE)) != (HCR_E2H | HCR_TGE) &&
101
+ CpuModelInfo *model,
77
+ !(arm_hcrx_el2_eff(env) & HCRX_MSCEN)) {
102
+ Error **errp)
78
+ return false;
103
+{
79
+ }
104
+ CpuModelExpansionInfo *expansion_info;
80
+
105
+ const QDict *qdict_in = NULL;
81
+ if (el == 0) {
106
+ QDict *qdict_out;
82
+ if (!el_is_in_host(env, 0)) {
107
+ ObjectClass *oc;
83
+ return env->cp15.sctlr_el[1] & SCTLR_MSCEN;
108
+ Object *obj;
84
+ } else {
109
+ const char *name;
85
+ return env->cp15.sctlr_el[2] & SCTLR_MSCEN;
110
+ int i;
111
+
112
+ if (type != CPU_MODEL_EXPANSION_TYPE_FULL) {
113
+ error_setg(errp, "The requested expansion type is not supported");
114
+ return NULL;
115
+ }
116
+
117
+ if (!kvm_enabled() && !strcmp(model->name, "host")) {
118
+ error_setg(errp, "The CPU type '%s' requires KVM", model->name);
119
+ return NULL;
120
+ }
121
+
122
+ oc = cpu_class_by_name(TYPE_ARM_CPU, model->name);
123
+ if (!oc) {
124
+ error_setg(errp, "The CPU type '%s' is not a recognized ARM CPU type",
125
+ model->name);
126
+ return NULL;
127
+ }
128
+
129
+ if (kvm_enabled()) {
130
+ const char *cpu_type = current_machine->cpu_type;
131
+ int len = strlen(cpu_type) - strlen(ARM_CPU_TYPE_SUFFIX);
132
+ bool supported = false;
133
+
134
+ if (!strcmp(model->name, "host") || !strcmp(model->name, "max")) {
135
+ /* These are kvmarm's recommended cpu types */
136
+ supported = true;
137
+ } else if (strlen(model->name) == len &&
138
+ !strncmp(model->name, cpu_type, len)) {
139
+ /* KVM is enabled and we're using this type, so it works. */
140
+ supported = true;
141
+ }
86
+ }
142
+ if (!supported) {
87
+ }
143
+ error_setg(errp, "We cannot guarantee the CPU type '%s' works "
88
+ return true;
144
+ "with KVM on this host", model->name);
89
+}
145
+ return NULL;
90
+
91
+static void check_mops_enabled(CPUARMState *env, uintptr_t ra)
92
+{
93
+ if (!mops_enabled(env)) {
94
+ raise_exception_ra(env, EXCP_UDEF, syn_uncategorized(),
95
+ exception_target_el(env), ra);
96
+ }
97
+}
98
+
99
+/*
100
+ * Return the target exception level for an exception due
101
+ * to mismatched arguments in a FEAT_MOPS copy or set.
102
+ * Compare pseudocode MismatchedCpySetTargetEL()
103
+ */
104
+static int mops_mismatch_exception_target_el(CPUARMState *env)
105
+{
106
+ int el = arm_current_el(env);
107
+
108
+ if (el > 1) {
109
+ return el;
110
+ }
111
+ if (el == 0 && (arm_hcr_el2_eff(env) & HCR_TGE)) {
112
+ return 2;
113
+ }
114
+ if (el == 1 && (arm_hcrx_el2_eff(env) & HCRX_MCE2)) {
115
+ return 2;
116
+ }
117
+ return 1;
118
+}
119
+
120
+/*
121
+ * Check whether an M or E instruction was executed with a CF value
122
+ * indicating the wrong option for this implementation.
123
+ * Assumes we are always Option A.
124
+ */
125
+static void check_mops_wrong_option(CPUARMState *env, uint32_t syndrome,
126
+ uintptr_t ra)
127
+{
128
+ if (env->CF != 0) {
129
+ syndrome |= 1 << 17; /* Set the wrong-option bit */
130
+ raise_exception_ra(env, EXCP_UDEF, syndrome,
131
+ mops_mismatch_exception_target_el(env), ra);
132
+ }
133
+}
134
+
135
+/*
136
+ * Return the maximum number of bytes we can transfer starting at addr
137
+ * without crossing a page boundary.
138
+ */
139
+static uint64_t page_limit(uint64_t addr)
140
+{
141
+ return TARGET_PAGE_ALIGN(addr + 1) - addr;
142
+}
143
+
144
+/*
145
+ * Perform part of a memory set on an area of guest memory starting at
146
+ * toaddr (a dirty address) and extending for setsize bytes.
147
+ *
148
+ * Returns the number of bytes actually set, which might be less than
149
+ * setsize; the caller should loop until the whole set has been done.
150
+ * The caller should ensure that the guest registers are correct
151
+ * for the possibility that the first byte of the set encounters
152
+ * an exception or watchpoint. We guarantee not to take any faults
153
+ * for bytes other than the first.
154
+ */
155
+static uint64_t set_step(CPUARMState *env, uint64_t toaddr,
156
+ uint64_t setsize, uint32_t data, int memidx,
157
+ uint32_t *mtedesc, uintptr_t ra)
158
+{
159
+ void *mem;
160
+
161
+ setsize = MIN(setsize, page_limit(toaddr));
162
+ if (*mtedesc) {
163
+ uint64_t mtesize = mte_mops_probe(env, toaddr, setsize, *mtedesc);
164
+ if (mtesize == 0) {
165
+ /* Trap, or not. All CPU state is up to date */
166
+ mte_check_fail(env, *mtedesc, toaddr, ra);
167
+ /* Continue, with no further MTE checks required */
168
+ *mtedesc = 0;
169
+ } else {
170
+ /* Advance to the end, or to the tag mismatch */
171
+ setsize = MIN(setsize, mtesize);
146
+ }
172
+ }
147
+ }
173
+ }
148
+
174
+
149
+ if (model->props) {
175
+ toaddr = useronly_clean_ptr(toaddr);
150
+ qdict_in = qobject_to(QDict, model->props);
176
+ /*
151
+ if (!qdict_in) {
177
+ * Trapless lookup: returns NULL for invalid page, I/O,
152
+ error_setg(errp, QERR_INVALID_PARAMETER_TYPE, "props", "dict");
178
+ * watchpoints, clean pages, etc.
153
+ return NULL;
179
+ */
180
+ mem = tlb_vaddr_to_host(env, toaddr, MMU_DATA_STORE, memidx);
181
+
182
+#ifndef CONFIG_USER_ONLY
183
+ if (unlikely(!mem)) {
184
+ /*
185
+ * Slow-path: just do one byte write. This will handle the
186
+ * watchpoint, invalid page, etc handling correctly.
187
+ * For clean code pages, the next iteration will see
188
+ * the page dirty and will use the fast path.
189
+ */
190
+ cpu_stb_mmuidx_ra(env, toaddr, data, memidx, ra);
191
+ return 1;
192
+ }
193
+#endif
194
+ /* Easy case: just memset the host memory */
195
+ memset(mem, data, setsize);
196
+ return setsize;
197
+}
198
+
199
+typedef uint64_t StepFn(CPUARMState *env, uint64_t toaddr,
200
+ uint64_t setsize, uint32_t data,
201
+ int memidx, uint32_t *mtedesc, uintptr_t ra);
202
+
203
+/* Extract register numbers from a MOPS exception syndrome value */
204
+static int mops_destreg(uint32_t syndrome)
205
+{
206
+ return extract32(syndrome, 10, 5);
207
+}
208
+
209
+static int mops_srcreg(uint32_t syndrome)
210
+{
211
+ return extract32(syndrome, 5, 5);
212
+}
213
+
214
+static int mops_sizereg(uint32_t syndrome)
215
+{
216
+ return extract32(syndrome, 0, 5);
217
+}
218
+
219
+/*
220
+ * Return true if TCMA and TBI bits mean we need to do MTE checks.
221
+ * We only need to do this once per MOPS insn, not for every page.
222
+ */
223
+static bool mte_checks_needed(uint64_t ptr, uint32_t desc)
224
+{
225
+ int bit55 = extract64(ptr, 55, 1);
226
+
227
+ /*
228
+ * Note that tbi_check() returns true for "access checked" but
229
+ * tcma_check() returns true for "access unchecked".
230
+ */
231
+ if (!tbi_check(desc, bit55)) {
232
+ return false;
233
+ }
234
+ return !tcma_check(desc, bit55, allocation_tag_from_addr(ptr));
235
+}
236
+
237
+/*
238
+ * For the Memory Set operation, our implementation chooses
239
+ * always to use "option A", where we update Xd to the final
240
+ * address in the SETP insn, and set Xn to be -(bytes remaining).
241
+ * On SETM and SETE insns we only need update Xn.
242
+ *
243
+ * @env: CPU
244
+ * @syndrome: syndrome value for mismatch exceptions
245
+ * (also contains the register numbers we need to use)
246
+ * @mtedesc: MTE descriptor word
247
+ * @stepfn: function which does a single part of the set operation
248
+ * @is_setg: true if this is the tag-setting SETG variant
249
+ */
250
+static void do_setp(CPUARMState *env, uint32_t syndrome, uint32_t mtedesc,
251
+ StepFn *stepfn, bool is_setg, uintptr_t ra)
252
+{
253
+ /* Prologue: we choose to do up to the next page boundary */
254
+ int rd = mops_destreg(syndrome);
255
+ int rs = mops_srcreg(syndrome);
256
+ int rn = mops_sizereg(syndrome);
257
+ uint8_t data = env->xregs[rs];
258
+ uint32_t memidx = FIELD_EX32(mtedesc, MTEDESC, MIDX);
259
+ uint64_t toaddr = env->xregs[rd];
260
+ uint64_t setsize = env->xregs[rn];
261
+ uint64_t stagesetsize, step;
262
+
263
+ check_mops_enabled(env, ra);
264
+
265
+ if (setsize > INT64_MAX) {
266
+ setsize = INT64_MAX;
267
+ }
268
+
269
+ if (!mte_checks_needed(toaddr, mtedesc)) {
270
+ mtedesc = 0;
271
+ }
272
+
273
+ stagesetsize = MIN(setsize, page_limit(toaddr));
274
+ while (stagesetsize) {
275
+ env->xregs[rd] = toaddr;
276
+ env->xregs[rn] = setsize;
277
+ step = stepfn(env, toaddr, stagesetsize, data, memidx, &mtedesc, ra);
278
+ toaddr += step;
279
+ setsize -= step;
280
+ stagesetsize -= step;
281
+ }
282
+ /* Insn completed, so update registers to the Option A format */
283
+ env->xregs[rd] = toaddr + setsize;
284
+ env->xregs[rn] = -setsize;
285
+
286
+ /* Set NZCV = 0000 to indicate we are an Option A implementation */
287
+ env->NF = 0;
288
+ env->ZF = 1; /* our env->ZF encoding is inverted */
289
+ env->CF = 0;
290
+ env->VF = 0;
291
+ return;
292
+}
293
+
294
+void HELPER(setp)(CPUARMState *env, uint32_t syndrome, uint32_t mtedesc)
295
+{
296
+ do_setp(env, syndrome, mtedesc, set_step, false, GETPC());
297
+}
298
+
299
+static void do_setm(CPUARMState *env, uint32_t syndrome, uint32_t mtedesc,
300
+ StepFn *stepfn, bool is_setg, uintptr_t ra)
301
+{
302
+ /* Main: we choose to do all the full-page chunks */
303
+ CPUState *cs = env_cpu(env);
304
+ int rd = mops_destreg(syndrome);
305
+ int rs = mops_srcreg(syndrome);
306
+ int rn = mops_sizereg(syndrome);
307
+ uint8_t data = env->xregs[rs];
308
+ uint64_t toaddr = env->xregs[rd] + env->xregs[rn];
309
+ uint64_t setsize = -env->xregs[rn];
310
+ uint32_t memidx = FIELD_EX32(mtedesc, MTEDESC, MIDX);
311
+ uint64_t step, stagesetsize;
312
+
313
+ check_mops_enabled(env, ra);
314
+
315
+ /*
316
+ * We're allowed to NOP out "no data to copy" before the consistency
317
+ * checks; we choose to do so.
318
+ */
319
+ if (env->xregs[rn] == 0) {
320
+ return;
321
+ }
322
+
323
+ check_mops_wrong_option(env, syndrome, ra);
324
+
325
+ /*
326
+ * Our implementation will work fine even if we have an unaligned
327
+ * destination address, and because we update Xn every time around
328
+ * the loop below and the return value from stepfn() may be less
329
+ * than requested, we might find toaddr is unaligned. So we don't
330
+ * have an IMPDEF check for alignment here.
331
+ */
332
+
333
+ if (!mte_checks_needed(toaddr, mtedesc)) {
334
+ mtedesc = 0;
335
+ }
336
+
337
+ /* Do the actual memset: we leave the last partial page to SETE */
338
+ stagesetsize = setsize & TARGET_PAGE_MASK;
339
+ while (stagesetsize > 0) {
340
+ step = stepfn(env, toaddr, setsize, data, memidx, &mtedesc, ra);
341
+ toaddr += step;
342
+ setsize -= step;
343
+ stagesetsize -= step;
344
+ env->xregs[rn] = -setsize;
345
+ if (stagesetsize > 0 && unlikely(cpu_loop_exit_requested(cs))) {
346
+ cpu_loop_exit_restore(cs, ra);
154
+ }
347
+ }
155
+ }
348
+ }
156
+
349
+}
157
+ obj = object_new(object_class_get_name(oc));
350
+
158
+
351
+void HELPER(setm)(CPUARMState *env, uint32_t syndrome, uint32_t mtedesc)
159
+ if (qdict_in) {
352
+{
160
+ Visitor *visitor;
353
+ do_setm(env, syndrome, mtedesc, set_step, false, GETPC());
161
+ Error *err = NULL;
354
+}
162
+
355
+
163
+ visitor = qobject_input_visitor_new(model->props);
356
+static void do_sete(CPUARMState *env, uint32_t syndrome, uint32_t mtedesc,
164
+ visit_start_struct(visitor, NULL, NULL, 0, &err);
357
+ StepFn *stepfn, bool is_setg, uintptr_t ra)
165
+ if (err) {
358
+{
166
+ visit_free(visitor);
359
+ /* Epilogue: do the last partial page */
167
+ object_unref(obj);
360
+ int rd = mops_destreg(syndrome);
168
+ error_propagate(errp, err);
361
+ int rs = mops_srcreg(syndrome);
169
+ return NULL;
362
+ int rn = mops_sizereg(syndrome);
170
+ }
363
+ uint8_t data = env->xregs[rs];
171
+
364
+ uint64_t toaddr = env->xregs[rd] + env->xregs[rn];
172
+ i = 0;
365
+ uint64_t setsize = -env->xregs[rn];
173
+ while ((name = cpu_model_advertised_features[i++]) != NULL) {
366
+ uint32_t memidx = FIELD_EX32(mtedesc, MTEDESC, MIDX);
174
+ if (qdict_get(qdict_in, name)) {
367
+ uint64_t step;
175
+ object_property_set(obj, visitor, name, &err);
368
+
176
+ if (err) {
369
+ check_mops_enabled(env, ra);
177
+ break;
370
+
178
+ }
371
+ /*
179
+ }
372
+ * We're allowed to NOP out "no data to copy" before the consistency
180
+ }
373
+ * checks; we choose to do so.
181
+
374
+ */
182
+ if (!err) {
375
+ if (setsize == 0) {
183
+ visit_check_struct(visitor, &err);
376
+ return;
184
+ }
377
+ }
185
+ visit_end_struct(visitor, NULL);
378
+
186
+ visit_free(visitor);
379
+ check_mops_wrong_option(env, syndrome, ra);
187
+ if (err) {
380
+
188
+ object_unref(obj);
381
+ /*
189
+ error_propagate(errp, err);
382
+ * Our implementation has no address alignment requirements, but
190
+ return NULL;
383
+ * we do want to enforce the "less than a page" size requirement,
191
+ }
384
+ * so we don't need to have the "check for interrupts" here.
192
+ }
385
+ */
193
+
386
+ if (setsize >= TARGET_PAGE_SIZE) {
194
+ expansion_info = g_new0(CpuModelExpansionInfo, 1);
387
+ raise_exception_ra(env, EXCP_UDEF, syndrome,
195
+ expansion_info->model = g_malloc0(sizeof(*expansion_info->model));
388
+ mops_mismatch_exception_target_el(env), ra);
196
+ expansion_info->model->name = g_strdup(model->name);
389
+ }
197
+
390
+
198
+ qdict_out = qdict_new();
391
+ if (!mte_checks_needed(toaddr, mtedesc)) {
199
+
392
+ mtedesc = 0;
200
+ i = 0;
393
+ }
201
+ while ((name = cpu_model_advertised_features[i++]) != NULL) {
394
+
202
+ ObjectProperty *prop = object_property_find(obj, name, NULL);
395
+ /* Do the actual memset */
203
+ if (prop) {
396
+ while (setsize > 0) {
204
+ Error *err = NULL;
397
+ step = stepfn(env, toaddr, setsize, data, memidx, &mtedesc, ra);
205
+ QObject *value;
398
+ toaddr += step;
206
+
399
+ setsize -= step;
207
+ assert(prop->get);
400
+ env->xregs[rn] = -setsize;
208
+ value = object_property_get_qobject(obj, name, &err);
401
+ }
209
+ assert(!err);
402
+}
210
+
403
+
211
+ qdict_put_obj(qdict_out, name, value);
404
+void HELPER(sete)(CPUARMState *env, uint32_t syndrome, uint32_t mtedesc)
212
+ }
405
+{
213
+ }
406
+ do_sete(env, syndrome, mtedesc, set_step, false, GETPC());
214
+
407
+}
215
+ if (!qdict_size(qdict_out)) {
408
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
216
+ qobject_unref(qdict_out);
409
index XXXXXXX..XXXXXXX 100644
217
+ } else {
410
--- a/target/arm/tcg/translate-a64.c
218
+ expansion_info->model->props = QOBJECT(qdict_out);
411
+++ b/target/arm/tcg/translate-a64.c
219
+ expansion_info->model->has_props = true;
412
@@ -XXX,XX +XXX,XX @@ TRANS_FEAT(STZG, aa64_mte_insn_reg, do_STG, a, true, false)
220
+ }
413
TRANS_FEAT(ST2G, aa64_mte_insn_reg, do_STG, a, false, true)
221
+
414
TRANS_FEAT(STZ2G, aa64_mte_insn_reg, do_STG, a, true, true)
222
+ object_unref(obj);
415
223
+
416
+typedef void SetFn(TCGv_env, TCGv_i32, TCGv_i32);
224
+ return expansion_info;
417
+
225
+}
418
+static bool do_SET(DisasContext *s, arg_set *a, bool is_epilogue, SetFn fn)
226
diff --git a/docs/arm-cpu-features.rst b/docs/arm-cpu-features.rst
419
+{
227
new file mode 100644
420
+ int memidx;
228
index XXXXXXX..XXXXXXX
421
+ uint32_t syndrome, desc = 0;
229
--- /dev/null
422
+
230
+++ b/docs/arm-cpu-features.rst
423
+ /*
231
@@ -XXX,XX +XXX,XX @@
424
+ * UNPREDICTABLE cases: we choose to UNDEF, which allows
232
+================
425
+ * us to pull this check before the CheckMOPSEnabled() test
233
+ARM CPU Features
426
+ * (which we do in the helper function)
234
+================
427
+ */
235
+
428
+ if (a->rs == a->rn || a->rs == a->rd || a->rn == a->rd ||
236
+Examples of probing and using ARM CPU features
429
+ a->rd == 31 || a->rn == 31) {
237
+
430
+ return false;
238
+Introduction
431
+ }
239
+============
432
+
240
+
433
+ memidx = get_a64_user_mem_index(s, a->unpriv);
241
+CPU features are optional features that a CPU of supporting type may
434
+
242
+choose to implement or not. In QEMU, optional CPU features have
435
+ /*
243
+corresponding boolean CPU proprieties that, when enabled, indicate
436
+ * We pass option_a == true, matching our implementation;
244
+that the feature is implemented, and, conversely, when disabled,
437
+ * we pass wrong_option == false: helper function may set that bit.
245
+indicate that it is not implemented. An example of an ARM CPU feature
438
+ */
246
+is the Performance Monitoring Unit (PMU). CPU types such as the
439
+ syndrome = syn_mop(true, false, (a->nontemp << 1) | a->unpriv,
247
+Cortex-A15 and the Cortex-A57, which respectively implement ARM
440
+ is_epilogue, false, true, a->rd, a->rs, a->rn);
248
+architecture reference manuals ARMv7-A and ARMv8-A, may both optionally
441
+
249
+implement PMUs. For example, if a user wants to use a Cortex-A15 without
442
+ if (s->mte_active[a->unpriv]) {
250
+a PMU, then the `-cpu` parameter should contain `pmu=off` on the QEMU
443
+ /* We may need to do MTE tag checking, so assemble the descriptor */
251
+command line, i.e. `-cpu cortex-a15,pmu=off`.
444
+ desc = FIELD_DP32(desc, MTEDESC, TBI, s->tbid);
252
+
445
+ desc = FIELD_DP32(desc, MTEDESC, TCMA, s->tcma);
253
+As not all CPU types support all optional CPU features, then whether or
446
+ desc = FIELD_DP32(desc, MTEDESC, WRITE, true);
254
+not a CPU property exists depends on the CPU type. For example, CPUs
447
+ /* SIZEM1 and ALIGN we leave 0 (byte write) */
255
+that implement the ARMv8-A architecture reference manual may optionally
448
+ }
256
+support the AArch32 CPU feature, which may be enabled by disabling the
449
+ /* The helper function always needs the memidx even with MTE disabled */
257
+`aarch64` CPU property. A CPU type such as the Cortex-A15, which does
450
+ desc = FIELD_DP32(desc, MTEDESC, MIDX, memidx);
258
+not implement ARMv8-A, will not have the `aarch64` CPU property.
451
+
259
+
452
+ /*
260
+QEMU's support may be limited for some CPU features, only partially
453
+ * The helper needs the register numbers, but since they're in
261
+supporting the feature or only supporting the feature under certain
454
+ * the syndrome anyway, we let it extract them from there rather
262
+configurations. For example, the `aarch64` CPU feature, which, when
455
+ * than passing in an extra three integer arguments.
263
+disabled, enables the optional AArch32 CPU feature, is only supported
456
+ */
264
+when using the KVM accelerator and when running on a host CPU type that
457
+ fn(cpu_env, tcg_constant_i32(syndrome), tcg_constant_i32(desc));
265
+supports the feature.
458
+ return true;
266
+
459
+}
267
+CPU Feature Probing
460
+
268
+===================
461
+TRANS_FEAT(SETP, aa64_mops, do_SET, a, false, gen_helper_setp)
269
+
462
+TRANS_FEAT(SETM, aa64_mops, do_SET, a, false, gen_helper_setm)
270
+Determining which CPU features are available and functional for a given
463
+TRANS_FEAT(SETE, aa64_mops, do_SET, a, true, gen_helper_sete)
271
+CPU type is possible with the `query-cpu-model-expansion` QMP command.
464
+
272
+Below are some examples where `scripts/qmp/qmp-shell` (see the top comment
465
typedef void ArithTwoOp(TCGv_i64, TCGv_i64, TCGv_i64);
273
+block in the script for usage) is used to issue the QMP commands.
466
274
+
467
static bool gen_rri(DisasContext *s, arg_rri_sf *a,
275
+(1) Determine which CPU features are available for the `max` CPU type
276
+ (Note, we started QEMU with qemu-system-aarch64, so `max` is
277
+ implementing the ARMv8-A reference manual in this case)::
278
+
279
+ (QEMU) query-cpu-model-expansion type=full model={"name":"max"}
280
+ { "return": {
281
+ "model": { "name": "max", "props": {
282
+ "pmu": true, "aarch64": true
283
+ }}}}
284
+
285
+We see that the `max` CPU type has the `pmu` and `aarch64` CPU features.
286
+We also see that the CPU features are enabled, as they are all `true`.
287
+
288
+(2) Let's try to disable the PMU::
289
+
290
+ (QEMU) query-cpu-model-expansion type=full model={"name":"max","props":{"pmu":false}}
291
+ { "return": {
292
+ "model": { "name": "max", "props": {
293
+ "pmu": false, "aarch64": true
294
+ }}}}
295
+
296
+We see it worked, as `pmu` is now `false`.
297
+
298
+(3) Let's try to disable `aarch64`, which enables the AArch32 CPU feature::
299
+
300
+ (QEMU) query-cpu-model-expansion type=full model={"name":"max","props":{"aarch64":false}}
301
+ {"error": {
302
+ "class": "GenericError", "desc":
303
+ "'aarch64' feature cannot be disabled unless KVM is enabled and 32-bit EL1 is supported"
304
+ }}
305
+
306
+It looks like this feature is limited to a configuration we do not
307
+currently have.
308
+
309
+(4) Let's try probing CPU features for the Cortex-A15 CPU type::
310
+
311
+ (QEMU) query-cpu-model-expansion type=full model={"name":"cortex-a15"}
312
+ {"return": {"model": {"name": "cortex-a15", "props": {"pmu": true}}}}
313
+
314
+Only the `pmu` CPU feature is available.
315
+
316
+A note about CPU feature dependencies
317
+-------------------------------------
318
+
319
+It's possible for features to have dependencies on other features. I.e.
320
+it may be possible to change one feature at a time without error, but
321
+when attempting to change all features at once an error could occur
322
+depending on the order they are processed. It's also possible changing
323
+all at once doesn't generate an error, because a feature's dependencies
324
+are satisfied with other features, but the same feature cannot be changed
325
+independently without error. For these reasons callers should always
326
+attempt to make their desired changes all at once in order to ensure the
327
+collection is valid.
328
+
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
--
468
--
370
2.20.1
469
2.34.1
371
372
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Currently the only tag-setting instructions always do so in the
2
context of the current EL, and so we only need one ATA bit in the TB
3
flags. The FEAT_MOPS SETG instructions include ones which set tags
4
for a non-privileged access, so we now also need the equivalent "are
5
tags enabled?" information for EL0.
2
6
3
Create a function to compute the values of the TBFLAG_ANY bits
7
Add the new TB flag, and convert the existing 'bool ata' field in
4
that will be cached. For now, the env->hflags variable is not
8
DisasContext to a 'bool ata[2]' that can be indexed by the is_unpriv
5
used, and the results are fed back to cpu_get_tb_cpu_state.
9
bit in an instruction, similarly to mte[2].
6
10
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-2-richard.henderson@linaro.org
10
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: 20230912140434.1333369-9-peter.maydell@linaro.org
11
---
14
---
12
target/arm/cpu.h | 29 ++++++++++++++++++-----------
15
target/arm/cpu.h | 1 +
13
target/arm/helper.c | 26 +++++++++++++++++++-------
16
target/arm/tcg/translate.h | 4 ++--
14
2 files changed, 37 insertions(+), 18 deletions(-)
17
target/arm/tcg/hflags.c | 12 ++++++++++++
18
target/arm/tcg/translate-a64.c | 23 ++++++++++++-----------
19
4 files changed, 27 insertions(+), 13 deletions(-)
15
20
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
21
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu.h
23
--- a/target/arm/cpu.h
19
+++ b/target/arm/cpu.h
24
+++ b/target/arm/cpu.h
20
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
25
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_A64, SVL, 24, 4)
21
uint32_t pstate;
26
FIELD(TBFLAG_A64, SME_TRAP_NONSTREAMING, 28, 1)
22
uint32_t aarch64; /* 1 if CPU is in aarch64 state; inverse of PSTATE.nRW */
27
FIELD(TBFLAG_A64, FGT_ERET, 29, 1)
23
28
FIELD(TBFLAG_A64, NAA, 30, 1)
24
+ /* Cached TBFLAGS state. See below for which bits are included. */
29
+FIELD(TBFLAG_A64, ATA0, 31, 1)
25
+ uint32_t hflags;
30
26
+
27
/* Frequently accessed CPSR bits are stored separately for efficiency.
28
This contains all the other bits. Use cpsr_{read,write} to access
29
the whole CPSR. */
30
@@ -XXX,XX +XXX,XX @@ typedef ARMCPU ArchCPU;
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
/*
31
/*
62
* We store the bottom two bits of the CPAR as TB flags and handle
32
* Helpers for using the above.
63
* checks on the other bits at runtime. This shares the same bits as
33
diff --git a/target/arm/tcg/translate.h b/target/arm/tcg/translate.h
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/target/arm/tcg/translate.h
102
+++ b/target/arm/helper.c
36
+++ b/target/arm/tcg/translate.h
103
@@ -XXX,XX +XXX,XX @@ ARMMMUIdx arm_stage1_mmu_idx(CPUARMState *env)
37
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
104
}
38
bool unpriv;
105
#endif
39
/* True if v8.3-PAuth is active. */
106
40
bool pauth_active;
107
+static uint32_t rebuild_hflags_common(CPUARMState *env, int fp_el,
41
- /* True if v8.5-MTE access to tags is enabled. */
108
+ ARMMMUIdx mmu_idx, uint32_t flags)
42
- bool ata;
109
+{
43
+ /* True if v8.5-MTE access to tags is enabled; index with is_unpriv. */
110
+ flags = FIELD_DP32(flags, TBFLAG_ANY, FPEXC_EL, fp_el);
44
+ bool ata[2];
111
+ flags = FIELD_DP32(flags, TBFLAG_ANY, MMUIDX,
45
/* True if v8.5-MTE tag checks affect the PE; index with is_unpriv. */
112
+ arm_to_core_mmu_idx(mmu_idx));
46
bool mte_active[2];
113
+
47
/* True with v8.5-BTI and SCTLR_ELx.BT* set. */
114
+ if (arm_cpu_data_is_big_endian(env)) {
48
diff --git a/target/arm/tcg/hflags.c b/target/arm/tcg/hflags.c
115
+ flags = FIELD_DP32(flags, TBFLAG_ANY, BE_DATA, 1);
49
index XXXXXXX..XXXXXXX 100644
116
+ }
50
--- a/target/arm/tcg/hflags.c
117
+ if (arm_singlestep_active(env)) {
51
+++ b/target/arm/tcg/hflags.c
118
+ flags = FIELD_DP32(flags, TBFLAG_ANY, SS_ACTIVE, 1);
52
@@ -XXX,XX +XXX,XX @@ static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
119
+ }
53
&& allocation_tag_access_enabled(env, 0, sctlr)) {
120
+ return flags;
54
DP_TBFLAG_A64(flags, MTE0_ACTIVE, 1);
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
}
56
+ /*
57
+ * For unpriv tag-setting accesses we alse need ATA0. Again, in
58
+ * contexts where unpriv and normal insns are the same we
59
+ * duplicate the ATA bit to save effort for translate-a64.c.
60
+ */
61
+ if (EX_TBFLAG_A64(flags, UNPRIV)) {
62
+ if (allocation_tag_access_enabled(env, 0, sctlr)) {
63
+ DP_TBFLAG_A64(flags, ATA0, 1);
64
+ }
65
+ } else {
66
+ DP_TBFLAG_A64(flags, ATA0, EX_TBFLAG_A64(flags, ATA));
67
+ }
68
/* Cache TCMA as well as TBI. */
69
DP_TBFLAG_A64(flags, TCMA, aa64_va_parameter_tcma(tcr, mmu_idx));
128
}
70
}
129
71
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
130
- flags = FIELD_DP32(flags, TBFLAG_ANY, MMUIDX, arm_to_core_mmu_idx(mmu_idx));
72
index XXXXXXX..XXXXXXX 100644
131
+ flags = rebuild_hflags_common(env, fp_el, mmu_idx, flags);
73
--- a/target/arm/tcg/translate-a64.c
132
74
+++ b/target/arm/tcg/translate-a64.c
133
/* The SS_ACTIVE and PSTATE_SS bits correspond to the state machine
75
@@ -XXX,XX +XXX,XX @@ static void handle_sys(DisasContext *s, bool isread,
134
* states defined in the ARM ARM for software singlestep:
76
clean_addr = clean_data_tbi(s, tcg_rt);
135
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
77
gen_probe_access(s, clean_addr, MMU_DATA_STORE, MO_8);
136
* 0 x Inactive (the TB flag for SS is always 0)
78
137
* 1 0 Active-pending
79
- if (s->ata) {
138
* 1 1 Active-not-pending
80
+ if (s->ata[0]) {
139
+ * SS_ACTIVE is set in hflags; PSTATE_SS is computed every TB.
81
/* Extract the tag from the register to match STZGM. */
140
*/
82
tag = tcg_temp_new_i64();
141
- if (arm_singlestep_active(env)) {
83
tcg_gen_shri_i64(tag, tcg_rt, 56);
142
- flags = FIELD_DP32(flags, TBFLAG_ANY, SS_ACTIVE, 1);
84
@@ -XXX,XX +XXX,XX @@ static void handle_sys(DisasContext *s, bool isread,
143
+ if (FIELD_EX32(flags, TBFLAG_ANY, SS_ACTIVE)) {
85
clean_addr = clean_data_tbi(s, tcg_rt);
144
if (is_a64(env)) {
86
gen_helper_dc_zva(cpu_env, clean_addr);
145
if (env->pstate & PSTATE_SS) {
87
146
flags = FIELD_DP32(flags, TBFLAG_ANY, PSTATE_SS, 1);
88
- if (s->ata) {
147
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
89
+ if (s->ata[0]) {
148
}
90
/* Extract the tag from the register to match STZGM. */
91
tag = tcg_temp_new_i64();
92
tcg_gen_shri_i64(tag, tcg_rt, 56);
93
@@ -XXX,XX +XXX,XX @@ static bool trans_STGP(DisasContext *s, arg_ldstpair *a)
94
tcg_gen_qemu_st_i128(tmp, clean_addr, get_mem_index(s), mop);
95
96
/* Perform the tag store, if tag access enabled. */
97
- if (s->ata) {
98
+ if (s->ata[0]) {
99
if (tb_cflags(s->base.tb) & CF_PARALLEL) {
100
gen_helper_stg_parallel(cpu_env, dirty_addr, dirty_addr);
101
} else {
102
@@ -XXX,XX +XXX,XX @@ static bool trans_STZGM(DisasContext *s, arg_ldst_tag *a)
103
tcg_gen_addi_i64(addr, addr, a->imm);
104
tcg_rt = cpu_reg(s, a->rt);
105
106
- if (s->ata) {
107
+ if (s->ata[0]) {
108
gen_helper_stzgm_tags(cpu_env, addr, tcg_rt);
109
}
110
/*
111
@@ -XXX,XX +XXX,XX @@ static bool trans_STGM(DisasContext *s, arg_ldst_tag *a)
112
tcg_gen_addi_i64(addr, addr, a->imm);
113
tcg_rt = cpu_reg(s, a->rt);
114
115
- if (s->ata) {
116
+ if (s->ata[0]) {
117
gen_helper_stgm(cpu_env, addr, tcg_rt);
118
} else {
119
MMUAccessType acc = MMU_DATA_STORE;
120
@@ -XXX,XX +XXX,XX @@ static bool trans_LDGM(DisasContext *s, arg_ldst_tag *a)
121
tcg_gen_addi_i64(addr, addr, a->imm);
122
tcg_rt = cpu_reg(s, a->rt);
123
124
- if (s->ata) {
125
+ if (s->ata[0]) {
126
gen_helper_ldgm(tcg_rt, cpu_env, addr);
127
} else {
128
MMUAccessType acc = MMU_DATA_LOAD;
129
@@ -XXX,XX +XXX,XX @@ static bool trans_LDG(DisasContext *s, arg_ldst_tag *a)
130
131
tcg_gen_andi_i64(addr, addr, -TAG_GRANULE);
132
tcg_rt = cpu_reg(s, a->rt);
133
- if (s->ata) {
134
+ if (s->ata[0]) {
135
gen_helper_ldg(tcg_rt, cpu_env, addr, tcg_rt);
136
} else {
137
/*
138
@@ -XXX,XX +XXX,XX @@ static bool do_STG(DisasContext *s, arg_ldst_tag *a, bool is_zero, bool is_pair)
139
tcg_gen_addi_i64(addr, addr, a->imm);
140
}
141
tcg_rt = cpu_reg_sp(s, a->rt);
142
- if (!s->ata) {
143
+ if (!s->ata[0]) {
144
/*
145
* For STG and ST2G, we need to check alignment and probe memory.
146
* TODO: For STZG and STZ2G, we could rely on the stores below,
147
@@ -XXX,XX +XXX,XX @@ static bool gen_add_sub_imm_with_tags(DisasContext *s, arg_rri_tag *a,
148
tcg_rn = cpu_reg_sp(s, a->rn);
149
tcg_rd = cpu_reg_sp(s, a->rd);
150
151
- if (s->ata) {
152
+ if (s->ata[0]) {
153
gen_helper_addsubg(tcg_rd, cpu_env, tcg_rn,
154
tcg_constant_i32(imm),
155
tcg_constant_i32(a->uimm4));
156
@@ -XXX,XX +XXX,XX @@ static void disas_data_proc_2src(DisasContext *s, uint32_t insn)
157
if (sf == 0 || !dc_isar_feature(aa64_mte_insn_reg, s)) {
158
goto do_unallocated;
149
}
159
}
150
}
160
- if (s->ata) {
151
- if (arm_cpu_data_is_big_endian(env)) {
161
+ if (s->ata[0]) {
152
- flags = FIELD_DP32(flags, TBFLAG_ANY, BE_DATA, 1);
162
gen_helper_irg(cpu_reg_sp(s, rd), cpu_env,
153
- }
163
cpu_reg_sp(s, rn), cpu_reg(s, rm));
154
- flags = FIELD_DP32(flags, TBFLAG_ANY, FPEXC_EL, fp_el);
164
} else {
155
165
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
156
if (arm_v7m_is_handler_mode(env)) {
166
dc->bt = EX_TBFLAG_A64(tb_flags, BT);
157
flags = FIELD_DP32(flags, TBFLAG_A32, HANDLER, 1);
167
dc->btype = EX_TBFLAG_A64(tb_flags, BTYPE);
168
dc->unpriv = EX_TBFLAG_A64(tb_flags, UNPRIV);
169
- dc->ata = EX_TBFLAG_A64(tb_flags, ATA);
170
+ dc->ata[0] = EX_TBFLAG_A64(tb_flags, ATA);
171
+ dc->ata[1] = EX_TBFLAG_A64(tb_flags, ATA0);
172
dc->mte_active[0] = EX_TBFLAG_A64(tb_flags, MTE_ACTIVE);
173
dc->mte_active[1] = EX_TBFLAG_A64(tb_flags, MTE0_ACTIVE);
174
dc->pstate_sm = EX_TBFLAG_A64(tb_flags, PSTATE_SM);
158
--
175
--
159
2.20.1
176
2.34.1
160
161
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
1
The FEAT_MOPS SETG* instructions are very similar to the SET*
2
instructions, but as well as setting memory contents they also
3
set the MTE tags. They are architecturally required to operate
4
on tag-granule aligned regions only.
2
5
3
Enable SVE in the KVM guest when the 'max' cpu type is configured
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
and KVM supports it. KVM SVE requires use of the new finalize
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
vcpu ioctl, so we add that now too. For starters SVE can only be
8
Message-id: 20230912140434.1333369-10-peter.maydell@linaro.org
6
turned on or off, getting all vector lengths the host CPU supports
9
---
7
when on. We'll add the other SVE CPU properties in later patches.
10
target/arm/internals.h | 10 ++++
11
target/arm/tcg/helper-a64.h | 3 ++
12
target/arm/tcg/a64.decode | 5 ++
13
target/arm/tcg/helper-a64.c | 86 ++++++++++++++++++++++++++++++++--
14
target/arm/tcg/mte_helper.c | 40 ++++++++++++++++
15
target/arm/tcg/translate-a64.c | 20 +++++---
16
6 files changed, 155 insertions(+), 9 deletions(-)
8
17
9
Signed-off-by: Andrew Jones <drjones@redhat.com>
18
diff --git a/target/arm/internals.h b/target/arm/internals.h
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
index XXXXXXX..XXXXXXX 100644
11
Reviewed-by: Eric Auger <eric.auger@redhat.com>
20
--- a/target/arm/internals.h
12
Tested-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
21
+++ b/target/arm/internals.h
13
Reviewed-by: Beata Michalska <beata.michalska@linaro.org>
22
@@ -XXX,XX +XXX,XX @@ uint64_t mte_mops_probe(CPUARMState *env, uint64_t ptr, uint64_t size,
14
Message-id: 20191024121808.9612-7-drjones@redhat.com
23
void mte_check_fail(CPUARMState *env, uint32_t desc,
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
uint64_t dirty_ptr, uintptr_t ra);
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
26
--- a/target/arm/kvm_arm.h
27
+++ b/target/arm/kvm_arm.h
28
@@ -XXX,XX +XXX,XX @@
29
*/
30
int kvm_arm_vcpu_init(CPUState *cs);
31
25
32
+/**
26
+/**
33
+ * kvm_arm_vcpu_finalize
27
+ * mte_mops_set_tags: Set MTE tags for a portion of a FEAT_MOPS operation
34
+ * @cs: CPUState
28
+ * @env: CPU env
35
+ * @feature: int
29
+ * @dirty_ptr: Start address of memory region (dirty pointer)
36
+ *
30
+ * @size: length of region (guaranteed not to cross page boundary)
37
+ * Finalizes the configuration of the specified VCPU feature by
31
+ * @desc: MTEDESC descriptor word
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
+ */
32
+ */
44
+int kvm_arm_vcpu_finalize(CPUState *cs, int feature);
33
+void mte_mops_set_tags(CPUARMState *env, uint64_t dirty_ptr, uint64_t size,
45
+
34
+ uint32_t desc);
46
/**
35
+
47
* kvm_arm_register_device:
36
static inline int allocation_tag_from_addr(uint64_t ptr)
48
* @mr: memory region for this device
37
{
49
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_aarch32_supported(CPUState *cs);
38
return extract64(ptr, 56, 4);
50
*/
39
diff --git a/target/arm/tcg/helper-a64.h b/target/arm/tcg/helper-a64.h
51
bool kvm_arm_pmu_supported(CPUState *cs);
40
index XXXXXXX..XXXXXXX 100644
52
41
--- a/target/arm/tcg/helper-a64.h
53
+/**
42
+++ b/target/arm/tcg/helper-a64.h
54
+ * bool kvm_arm_sve_supported:
43
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(unaligned_access, TCG_CALL_NO_WG,
55
+ * @cs: CPUState
44
DEF_HELPER_3(setp, void, env, i32, i32)
56
+ *
45
DEF_HELPER_3(setm, void, env, i32, i32)
57
+ * Returns true if the KVM VCPU can enable SVE and false otherwise.
46
DEF_HELPER_3(sete, void, env, i32, i32)
47
+DEF_HELPER_3(setgp, void, env, i32, i32)
48
+DEF_HELPER_3(setgm, void, env, i32, i32)
49
+DEF_HELPER_3(setge, void, env, i32, i32)
50
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
51
index XXXXXXX..XXXXXXX 100644
52
--- a/target/arm/tcg/a64.decode
53
+++ b/target/arm/tcg/a64.decode
54
@@ -XXX,XX +XXX,XX @@ STZ2G 11011001 11 1 ......... 11 ..... ..... @ldst_tag p=0 w=1
55
SETP 00 011001110 ..... 00 . . 01 ..... ..... @set
56
SETM 00 011001110 ..... 01 . . 01 ..... ..... @set
57
SETE 00 011001110 ..... 10 . . 01 ..... ..... @set
58
+
59
+# Like SET, but also setting MTE tags
60
+SETGP 00 011101110 ..... 00 . . 01 ..... ..... @set
61
+SETGM 00 011101110 ..... 01 . . 01 ..... ..... @set
62
+SETGE 00 011101110 ..... 10 . . 01 ..... ..... @set
63
diff --git a/target/arm/tcg/helper-a64.c b/target/arm/tcg/helper-a64.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/target/arm/tcg/helper-a64.c
66
+++ b/target/arm/tcg/helper-a64.c
67
@@ -XXX,XX +XXX,XX @@ static uint64_t set_step(CPUARMState *env, uint64_t toaddr,
68
return setsize;
69
}
70
71
+/*
72
+ * Similar, but setting tags. The architecture requires us to do this
73
+ * in 16-byte chunks. SETP accesses are not tag checked; they set
74
+ * the tags.
58
+ */
75
+ */
59
+bool kvm_arm_sve_supported(CPUState *cs);
76
+static uint64_t set_step_tags(CPUARMState *env, uint64_t toaddr,
60
+
77
+ uint64_t setsize, uint32_t data, int memidx,
61
/**
78
+ uint32_t *mtedesc, uintptr_t ra)
62
* kvm_arm_get_max_vm_ipa_size - Returns the number of bits in the
79
+{
63
* IPA address space supported by KVM
80
+ void *mem;
64
@@ -XXX,XX +XXX,XX @@ static inline bool kvm_arm_pmu_supported(CPUState *cs)
81
+ uint64_t cleanaddr;
65
return false;
82
+
66
}
83
+ setsize = MIN(setsize, page_limit(toaddr));
67
84
+
68
+static inline bool kvm_arm_sve_supported(CPUState *cs)
85
+ cleanaddr = useronly_clean_ptr(toaddr);
69
+{
86
+ /*
70
+ return false;
87
+ * Trapless lookup: returns NULL for invalid page, I/O,
71
+}
88
+ * watchpoints, clean pages, etc.
72
+
89
+ */
73
static inline int kvm_arm_get_max_vm_ipa_size(MachineState *ms)
90
+ mem = tlb_vaddr_to_host(env, cleanaddr, MMU_DATA_STORE, memidx);
74
{
91
+
75
return -ENOENT;
92
+#ifndef CONFIG_USER_ONLY
76
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
93
+ if (unlikely(!mem)) {
77
index XXXXXXX..XXXXXXX 100644
94
+ /*
78
--- a/target/arm/cpu64.c
95
+ * Slow-path: just do one write. This will handle the
79
+++ b/target/arm/cpu64.c
96
+ * watchpoint, invalid page, etc handling correctly.
80
@@ -XXX,XX +XXX,XX @@ static void cpu_arm_set_sve(Object *obj, Visitor *v, const char *name,
97
+ * The architecture requires that we do 16 bytes at a time,
81
return;
98
+ * and we know both ptr and size are 16 byte aligned.
82
}
99
+ * For clean code pages, the next iteration will see
83
100
+ * the page dirty and will use the fast path.
84
+ if (value && kvm_enabled() && !kvm_arm_sve_supported(CPU(cpu))) {
101
+ */
85
+ error_setg(errp, "'sve' feature not supported by KVM on this host");
102
+ uint64_t repldata = data * 0x0101010101010101ULL;
103
+ MemOpIdx oi16 = make_memop_idx(MO_TE | MO_128, memidx);
104
+ cpu_st16_mmu(env, toaddr, int128_make128(repldata, repldata), oi16, ra);
105
+ mte_mops_set_tags(env, toaddr, 16, *mtedesc);
106
+ return 16;
107
+ }
108
+#endif
109
+ /* Easy case: just memset the host memory */
110
+ memset(mem, data, setsize);
111
+ mte_mops_set_tags(env, toaddr, setsize, *mtedesc);
112
+ return setsize;
113
+}
114
+
115
typedef uint64_t StepFn(CPUARMState *env, uint64_t toaddr,
116
uint64_t setsize, uint32_t data,
117
int memidx, uint32_t *mtedesc, uintptr_t ra);
118
@@ -XXX,XX +XXX,XX @@ static bool mte_checks_needed(uint64_t ptr, uint32_t desc)
119
return !tcma_check(desc, bit55, allocation_tag_from_addr(ptr));
120
}
121
122
+/* Take an exception if the SETG addr/size are not granule aligned */
123
+static void check_setg_alignment(CPUARMState *env, uint64_t ptr, uint64_t size,
124
+ uint32_t memidx, uintptr_t ra)
125
+{
126
+ if ((size != 0 && !QEMU_IS_ALIGNED(ptr, TAG_GRANULE)) ||
127
+ !QEMU_IS_ALIGNED(size, TAG_GRANULE)) {
128
+ arm_cpu_do_unaligned_access(env_cpu(env), ptr, MMU_DATA_STORE,
129
+ memidx, ra);
130
+
131
+ }
132
+}
133
+
134
/*
135
* For the Memory Set operation, our implementation chooses
136
* always to use "option A", where we update Xd to the final
137
@@ -XXX,XX +XXX,XX @@ static void do_setp(CPUARMState *env, uint32_t syndrome, uint32_t mtedesc,
138
139
if (setsize > INT64_MAX) {
140
setsize = INT64_MAX;
141
+ if (is_setg) {
142
+ setsize &= ~0xf;
143
+ }
144
}
145
146
- if (!mte_checks_needed(toaddr, mtedesc)) {
147
+ if (unlikely(is_setg)) {
148
+ check_setg_alignment(env, toaddr, setsize, memidx, ra);
149
+ } else if (!mte_checks_needed(toaddr, mtedesc)) {
150
mtedesc = 0;
151
}
152
153
@@ -XXX,XX +XXX,XX @@ void HELPER(setp)(CPUARMState *env, uint32_t syndrome, uint32_t mtedesc)
154
do_setp(env, syndrome, mtedesc, set_step, false, GETPC());
155
}
156
157
+void HELPER(setgp)(CPUARMState *env, uint32_t syndrome, uint32_t mtedesc)
158
+{
159
+ do_setp(env, syndrome, mtedesc, set_step_tags, true, GETPC());
160
+}
161
+
162
static void do_setm(CPUARMState *env, uint32_t syndrome, uint32_t mtedesc,
163
StepFn *stepfn, bool is_setg, uintptr_t ra)
164
{
165
@@ -XXX,XX +XXX,XX @@ static void do_setm(CPUARMState *env, uint32_t syndrome, uint32_t mtedesc,
166
* have an IMPDEF check for alignment here.
167
*/
168
169
- if (!mte_checks_needed(toaddr, mtedesc)) {
170
+ if (unlikely(is_setg)) {
171
+ check_setg_alignment(env, toaddr, setsize, memidx, ra);
172
+ } else if (!mte_checks_needed(toaddr, mtedesc)) {
173
mtedesc = 0;
174
}
175
176
@@ -XXX,XX +XXX,XX @@ void HELPER(setm)(CPUARMState *env, uint32_t syndrome, uint32_t mtedesc)
177
do_setm(env, syndrome, mtedesc, set_step, false, GETPC());
178
}
179
180
+void HELPER(setgm)(CPUARMState *env, uint32_t syndrome, uint32_t mtedesc)
181
+{
182
+ do_setm(env, syndrome, mtedesc, set_step_tags, true, GETPC());
183
+}
184
+
185
static void do_sete(CPUARMState *env, uint32_t syndrome, uint32_t mtedesc,
186
StepFn *stepfn, bool is_setg, uintptr_t ra)
187
{
188
@@ -XXX,XX +XXX,XX @@ static void do_sete(CPUARMState *env, uint32_t syndrome, uint32_t mtedesc,
189
mops_mismatch_exception_target_el(env), ra);
190
}
191
192
- if (!mte_checks_needed(toaddr, mtedesc)) {
193
+ if (unlikely(is_setg)) {
194
+ check_setg_alignment(env, toaddr, setsize, memidx, ra);
195
+ } else if (!mte_checks_needed(toaddr, mtedesc)) {
196
mtedesc = 0;
197
}
198
199
@@ -XXX,XX +XXX,XX @@ void HELPER(sete)(CPUARMState *env, uint32_t syndrome, uint32_t mtedesc)
200
{
201
do_sete(env, syndrome, mtedesc, set_step, false, GETPC());
202
}
203
+
204
+void HELPER(setge)(CPUARMState *env, uint32_t syndrome, uint32_t mtedesc)
205
+{
206
+ do_sete(env, syndrome, mtedesc, set_step_tags, true, GETPC());
207
+}
208
diff --git a/target/arm/tcg/mte_helper.c b/target/arm/tcg/mte_helper.c
209
index XXXXXXX..XXXXXXX 100644
210
--- a/target/arm/tcg/mte_helper.c
211
+++ b/target/arm/tcg/mte_helper.c
212
@@ -XXX,XX +XXX,XX @@ uint64_t mte_mops_probe(CPUARMState *env, uint64_t ptr, uint64_t size,
213
return n * TAG_GRANULE - (ptr - tag_first);
214
}
215
}
216
+
217
+void mte_mops_set_tags(CPUARMState *env, uint64_t ptr, uint64_t size,
218
+ uint32_t desc)
219
+{
220
+ int mmu_idx, tag_count;
221
+ uint64_t ptr_tag;
222
+ void *mem;
223
+
224
+ if (!desc) {
225
+ /* Tags not actually enabled */
86
+ return;
226
+ return;
87
+ }
227
+ }
88
+
228
+
89
t = cpu->isar.id_aa64pfr0;
229
+ mmu_idx = FIELD_EX32(desc, MTEDESC, MIDX);
90
t = FIELD_DP64(t, ID_AA64PFR0, SVE, value);
230
+ /* True probe: this will never fault */
91
cpu->isar.id_aa64pfr0 = t;
231
+ mem = allocation_tag_mem_probe(env, mmu_idx, ptr, MMU_DATA_STORE, size,
92
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
232
+ MMU_DATA_STORE, true, 0);
93
{
233
+ if (!mem) {
94
ARMCPU *cpu = ARM_CPU(obj);
234
+ return;
95
uint32_t vq;
235
+ }
96
+ uint64_t t;
236
+
97
237
+ /*
98
if (kvm_enabled()) {
238
+ * We know that ptr and size are both TAG_GRANULE aligned; store
99
kvm_arm_set_cpu_features_from_host(cpu);
239
+ * the tag from the pointer value into the tag memory.
100
+ if (kvm_arm_sve_supported(CPU(cpu))) {
240
+ */
101
+ t = cpu->isar.id_aa64pfr0;
241
+ ptr_tag = allocation_tag_from_addr(ptr);
102
+ t = FIELD_DP64(t, ID_AA64PFR0, SVE, 1);
242
+ tag_count = size / TAG_GRANULE;
103
+ cpu->isar.id_aa64pfr0 = t;
243
+ if (ptr & TAG_GRANULE) {
104
+ }
244
+ /* Not 2*TAG_GRANULE-aligned: store tag to first nibble */
105
} else {
245
+ store_tag1_parallel(TAG_GRANULE, mem, ptr_tag);
106
- uint64_t t;
246
+ mem++;
107
uint32_t u;
247
+ tag_count--;
108
aarch64_a57_initfn(obj);
248
+ }
109
249
+ memset(mem, ptr_tag | (ptr_tag << 4), tag_count / 2);
110
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
250
+ if (tag_count & 1) {
111
251
+ /* Final trailing unaligned nibble */
112
object_property_add(obj, "sve-max-vq", "uint32", cpu_max_get_sve_max_vq,
252
+ mem += tag_count / 2;
113
cpu_max_set_sve_max_vq, NULL, NULL, &error_fatal);
253
+ store_tag1_parallel(0, mem, ptr_tag);
114
- object_property_add(obj, "sve", "bool", cpu_arm_get_sve,
254
+ }
115
- cpu_arm_set_sve, NULL, NULL, &error_fatal);
255
+}
116
256
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
117
for (vq = 1; vq <= ARM_MAX_VQ; ++vq) {
257
index XXXXXXX..XXXXXXX 100644
118
char name[8];
258
--- a/target/arm/tcg/translate-a64.c
119
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
259
+++ b/target/arm/tcg/translate-a64.c
120
cpu_arm_set_sve_vq, NULL, NULL, &error_fatal);
260
@@ -XXX,XX +XXX,XX @@ TRANS_FEAT(STZ2G, aa64_mte_insn_reg, do_STG, a, true, true)
121
}
261
122
}
262
typedef void SetFn(TCGv_env, TCGv_i32, TCGv_i32);
123
+
263
124
+ object_property_add(obj, "sve", "bool", cpu_arm_get_sve,
264
-static bool do_SET(DisasContext *s, arg_set *a, bool is_epilogue, SetFn fn)
125
+ cpu_arm_set_sve, NULL, NULL, &error_fatal);
265
+static bool do_SET(DisasContext *s, arg_set *a, bool is_epilogue,
126
}
266
+ bool is_setg, SetFn fn)
127
267
{
128
struct ARMCPUInfo {
268
int memidx;
129
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
269
uint32_t syndrome, desc = 0;
130
index XXXXXXX..XXXXXXX 100644
270
131
--- a/target/arm/kvm.c
271
+ if (is_setg && !dc_isar_feature(aa64_mte, s)) {
132
+++ b/target/arm/kvm.c
272
+ return false;
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
+ }
273
+ }
192
+
274
+
193
/*
275
/*
194
* When KVM is in use, PSCI is emulated in-kernel and not by qemu.
276
* UNPREDICTABLE cases: we choose to UNDEF, which allows
195
* Currently KVM has its own idea about MPIDR assignment, so we
277
* us to pull this check before the CheckMOPSEnabled() test
196
diff --git a/tests/arm-cpu-features.c b/tests/arm-cpu-features.c
278
@@ -XXX,XX +XXX,XX @@ static bool do_SET(DisasContext *s, arg_set *a, bool is_epilogue, SetFn fn)
197
index XXXXXXX..XXXXXXX 100644
279
* We pass option_a == true, matching our implementation;
198
--- a/tests/arm-cpu-features.c
280
* we pass wrong_option == false: helper function may set that bit.
199
+++ b/tests/arm-cpu-features.c
281
*/
200
@@ -XXX,XX +XXX,XX @@ static void test_query_cpu_model_expansion_kvm(const void *data)
282
- syndrome = syn_mop(true, false, (a->nontemp << 1) | a->unpriv,
201
assert_has_feature(qts, "host", "aarch64");
283
+ syndrome = syn_mop(true, is_setg, (a->nontemp << 1) | a->unpriv,
202
assert_has_feature(qts, "host", "pmu");
284
is_epilogue, false, true, a->rd, a->rs, a->rn);
203
285
204
+ assert_has_feature(qts, "max", "sve");
286
- if (s->mte_active[a->unpriv]) {
205
+
287
+ if (is_setg ? s->ata[a->unpriv] : s->mte_active[a->unpriv]) {
206
assert_error(qts, "cortex-a15",
288
/* We may need to do MTE tag checking, so assemble the descriptor */
207
"We cannot guarantee the CPU type 'cortex-a15' works "
289
desc = FIELD_DP32(desc, MTEDESC, TBI, s->tbid);
208
"with KVM on this host", NULL);
290
desc = FIELD_DP32(desc, MTEDESC, TCMA, s->tcma);
209
} else {
291
@@ -XXX,XX +XXX,XX @@ static bool do_SET(DisasContext *s, arg_set *a, bool is_epilogue, SetFn fn)
210
assert_has_not_feature(qts, "host", "aarch64");
292
return true;
211
assert_has_not_feature(qts, "host", "pmu");
293
}
212
+
294
213
+ assert_has_not_feature(qts, "max", "sve");
295
-TRANS_FEAT(SETP, aa64_mops, do_SET, a, false, gen_helper_setp)
214
}
296
-TRANS_FEAT(SETM, aa64_mops, do_SET, a, false, gen_helper_setm)
215
297
-TRANS_FEAT(SETE, aa64_mops, do_SET, a, true, gen_helper_sete)
216
qtest_quit(qts);
298
+TRANS_FEAT(SETP, aa64_mops, do_SET, a, false, false, gen_helper_setp)
299
+TRANS_FEAT(SETM, aa64_mops, do_SET, a, false, false, gen_helper_setm)
300
+TRANS_FEAT(SETE, aa64_mops, do_SET, a, true, false, gen_helper_sete)
301
+TRANS_FEAT(SETGP, aa64_mops, do_SET, a, false, true, gen_helper_setgp)
302
+TRANS_FEAT(SETGM, aa64_mops, do_SET, a, false, true, gen_helper_setgm)
303
+TRANS_FEAT(SETGE, aa64_mops, do_SET, a, true, true, gen_helper_setge)
304
305
typedef void ArithTwoOp(TCGv_i64, TCGv_i64, TCGv_i64);
306
217
--
307
--
218
2.20.1
308
2.34.1
219
220
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The FEAT_MOPS memory copy operations need an extra helper routine
2
for checking for MTE tag checking failures beyond the ones we
3
already added for memory set operations:
4
* mte_mops_probe_rev() does the same job as mte_mops_probe(), but
5
it checks tags starting at the provided address and working
6
backwards, rather than forwards
2
7
3
Avoid calling arm_current_el() twice.
4
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
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>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20230912140434.1333369-11-peter.maydell@linaro.org
10
---
11
---
11
target/arm/internals.h | 9 +++++++++
12
target/arm/internals.h | 17 +++++++
12
target/arm/helper.c | 12 +++++++-----
13
target/arm/tcg/mte_helper.c | 99 +++++++++++++++++++++++++++++++++++++
13
2 files changed, 16 insertions(+), 5 deletions(-)
14
2 files changed, 116 insertions(+)
14
15
15
diff --git a/target/arm/internals.h b/target/arm/internals.h
16
diff --git a/target/arm/internals.h b/target/arm/internals.h
16
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/internals.h
18
--- a/target/arm/internals.h
18
+++ b/target/arm/internals.h
19
+++ b/target/arm/internals.h
19
@@ -XXX,XX +XXX,XX @@ void arm_cpu_update_virq(ARMCPU *cpu);
20
@@ -XXX,XX +XXX,XX @@ uint64_t mte_check(CPUARMState *env, uint32_t desc, uint64_t ptr, uintptr_t ra);
20
*/
21
uint64_t mte_mops_probe(CPUARMState *env, uint64_t ptr, uint64_t size,
21
void arm_cpu_update_vfiq(ARMCPU *cpu);
22
uint32_t desc);
22
23
23
+/**
24
+/**
24
+ * arm_mmu_idx_el:
25
+ * mte_mops_probe_rev: Check where the next MTE failure is for a FEAT_MOPS
25
+ * @env: The cpu environment
26
+ * operation going in the reverse direction
26
+ * @el: The EL to use.
27
+ * @env: CPU env
28
+ * @ptr: *end* address of memory region (dirty pointer)
29
+ * @size: length of region (guaranteed not to cross a page boundary)
30
+ * @desc: MTEDESC descriptor word (0 means no MTE checks)
31
+ * Returns: the size of the region that can be copied without hitting
32
+ * an MTE tag failure
27
+ *
33
+ *
28
+ * Return the full ARMMMUIdx for the translation regime for EL.
34
+ * Note that we assume that the caller has already checked the TBI
35
+ * and TCMA bits with mte_checks_needed() and an MTE check is definitely
36
+ * required.
29
+ */
37
+ */
30
+ARMMMUIdx arm_mmu_idx_el(CPUARMState *env, int el);
38
+uint64_t mte_mops_probe_rev(CPUARMState *env, uint64_t ptr, uint64_t size,
39
+ uint32_t desc);
31
+
40
+
32
/**
41
/**
33
* arm_mmu_idx:
42
* mte_check_fail: Record an MTE tag check failure
34
* @env: The cpu environment
43
* @env: CPU env
35
diff --git a/target/arm/helper.c b/target/arm/helper.c
44
diff --git a/target/arm/tcg/mte_helper.c b/target/arm/tcg/mte_helper.c
36
index XXXXXXX..XXXXXXX 100644
45
index XXXXXXX..XXXXXXX 100644
37
--- a/target/arm/helper.c
46
--- a/target/arm/tcg/mte_helper.c
38
+++ b/target/arm/helper.c
47
+++ b/target/arm/tcg/mte_helper.c
39
@@ -XXX,XX +XXX,XX @@ ARMMMUIdx arm_v7m_mmu_idx_for_secstate(CPUARMState *env, bool secstate)
48
@@ -XXX,XX +XXX,XX @@ static int checkN(uint8_t *mem, int odd, int cmp, int count)
49
return n;
40
}
50
}
41
#endif
51
42
52
+/**
43
-ARMMMUIdx arm_mmu_idx(CPUARMState *env)
53
+ * checkNrev:
44
+ARMMMUIdx arm_mmu_idx_el(CPUARMState *env, int el)
54
+ * @tag: tag memory to test
45
{
55
+ * @odd: true to begin testing at tags at odd nibble
46
- int el;
56
+ * @cmp: the tag to compare against
47
-
57
+ * @count: number of tags to test
48
if (arm_feature(env, ARM_FEATURE_M)) {
58
+ *
49
return arm_v7m_mmu_idx_for_secstate(env, env->v7m.secure);
59
+ * Return the number of successful tests.
50
}
60
+ * Thus a return value < @count indicates a failure.
51
61
+ *
52
- el = arm_current_el(env);
62
+ * This is like checkN, but it runs backwards, checking the
53
if (el < 2 && arm_is_secure_below_el3(env)) {
63
+ * tags starting with @tag and then the tags preceding it.
54
return ARMMMUIdx_S1SE0 + el;
64
+ * This is needed by the backwards-memory-copying operations.
55
} else {
65
+ */
56
@@ -XXX,XX +XXX,XX @@ ARMMMUIdx arm_mmu_idx(CPUARMState *env)
66
+static int checkNrev(uint8_t *mem, int odd, int cmp, int count)
67
+{
68
+ int n = 0, diff;
69
+
70
+ /* Replicate the test tag and compare. */
71
+ cmp *= 0x11;
72
+ diff = *mem-- ^ cmp;
73
+
74
+ if (!odd) {
75
+ goto start_even;
76
+ }
77
+
78
+ while (1) {
79
+ /* Test odd tag. */
80
+ if (unlikely((diff) & 0xf0)) {
81
+ break;
82
+ }
83
+ if (++n == count) {
84
+ break;
85
+ }
86
+
87
+ start_even:
88
+ /* Test even tag. */
89
+ if (unlikely((diff) & 0x0f)) {
90
+ break;
91
+ }
92
+ if (++n == count) {
93
+ break;
94
+ }
95
+
96
+ diff = *mem-- ^ cmp;
97
+ }
98
+ return n;
99
+}
100
+
101
/**
102
* mte_probe_int() - helper for mte_probe and mte_check
103
* @env: CPU environment
104
@@ -XXX,XX +XXX,XX @@ uint64_t mte_mops_probe(CPUARMState *env, uint64_t ptr, uint64_t size,
57
}
105
}
58
}
106
}
59
107
60
+ARMMMUIdx arm_mmu_idx(CPUARMState *env)
108
+uint64_t mte_mops_probe_rev(CPUARMState *env, uint64_t ptr, uint64_t size,
109
+ uint32_t desc)
61
+{
110
+{
62
+ return arm_mmu_idx_el(env, arm_current_el(env));
111
+ int mmu_idx, tag_count;
112
+ uint64_t ptr_tag, tag_first, tag_last;
113
+ void *mem;
114
+ bool w = FIELD_EX32(desc, MTEDESC, WRITE);
115
+ uint32_t n;
116
+
117
+ mmu_idx = FIELD_EX32(desc, MTEDESC, MIDX);
118
+ /* True probe; this will never fault */
119
+ mem = allocation_tag_mem_probe(env, mmu_idx, ptr,
120
+ w ? MMU_DATA_STORE : MMU_DATA_LOAD,
121
+ size, MMU_DATA_LOAD, true, 0);
122
+ if (!mem) {
123
+ return size;
124
+ }
125
+
126
+ /*
127
+ * TODO: checkNrev() is not designed for checks of the size we expect
128
+ * for FEAT_MOPS operations, so we should implement this differently.
129
+ * Maybe we should do something like
130
+ * if (region start and size are aligned nicely) {
131
+ * do direct loads of 64 tag bits at a time;
132
+ * } else {
133
+ * call checkN()
134
+ * }
135
+ */
136
+ /* Round the bounds to the tag granule, and compute the number of tags. */
137
+ ptr_tag = allocation_tag_from_addr(ptr);
138
+ tag_first = QEMU_ALIGN_DOWN(ptr - (size - 1), TAG_GRANULE);
139
+ tag_last = QEMU_ALIGN_DOWN(ptr, TAG_GRANULE);
140
+ tag_count = ((tag_last - tag_first) / TAG_GRANULE) + 1;
141
+ n = checkNrev(mem, ptr & TAG_GRANULE, ptr_tag, tag_count);
142
+ if (likely(n == tag_count)) {
143
+ return size;
144
+ }
145
+
146
+ /*
147
+ * Failure; for the first granule, it's at @ptr. Otherwise
148
+ * it's at the last byte of the nth granule. Calculate how
149
+ * many bytes we can access without hitting that failure.
150
+ */
151
+ if (n == 0) {
152
+ return 0;
153
+ } else {
154
+ return (n - 1) * TAG_GRANULE + ((ptr + 1) - tag_last);
155
+ }
63
+}
156
+}
64
+
157
+
65
int cpu_mmu_index(CPUARMState *env, bool ifetch)
158
void mte_mops_set_tags(CPUARMState *env, uint64_t ptr, uint64_t size,
159
uint32_t desc)
66
{
160
{
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
--
161
--
78
2.20.1
162
2.34.1
79
80
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
1
The FEAT_MOPS CPY* instructions implement memory copies. These
2
come in both "always forwards" (memcpy-style) and "overlap OK"
3
(memmove-style) flavours.
2
4
3
These are the SVE equivalents to kvm_arch_get/put_fpsimd. Note, the
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
swabbing is different than it is for fpsmid because the vector format
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
is a little-endian stream of words.
7
Message-id: 20230912140434.1333369-12-peter.maydell@linaro.org
8
---
9
target/arm/tcg/helper-a64.h | 7 +
10
target/arm/tcg/a64.decode | 14 +
11
target/arm/tcg/helper-a64.c | 454 +++++++++++++++++++++++++++++++++
12
target/arm/tcg/translate-a64.c | 60 +++++
13
4 files changed, 535 insertions(+)
6
14
7
Signed-off-by: Andrew Jones <drjones@redhat.com>
15
diff --git a/target/arm/tcg/helper-a64.h b/target/arm/tcg/helper-a64.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/target/arm/tcg/helper-a64.h
20
+++ b/target/arm/kvm64.c
18
+++ b/target/arm/tcg/helper-a64.h
21
@@ -XXX,XX +XXX,XX @@ int kvm_arch_destroy_vcpu(CPUState *cs)
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(sete, void, env, i32, i32)
22
bool kvm_arm_reg_syncs_via_cpreg_list(uint64_t regidx)
20
DEF_HELPER_3(setgp, void, env, i32, i32)
21
DEF_HELPER_3(setgm, void, env, i32, i32)
22
DEF_HELPER_3(setge, void, env, i32, i32)
23
+
24
+DEF_HELPER_4(cpyp, void, env, i32, i32, i32)
25
+DEF_HELPER_4(cpym, void, env, i32, i32, i32)
26
+DEF_HELPER_4(cpye, void, env, i32, i32, i32)
27
+DEF_HELPER_4(cpyfp, void, env, i32, i32, i32)
28
+DEF_HELPER_4(cpyfm, void, env, i32, i32, i32)
29
+DEF_HELPER_4(cpyfe, void, env, i32, i32, i32)
30
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
31
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/tcg/a64.decode
33
+++ b/target/arm/tcg/a64.decode
34
@@ -XXX,XX +XXX,XX @@ SETE 00 011001110 ..... 10 . . 01 ..... ..... @set
35
SETGP 00 011101110 ..... 00 . . 01 ..... ..... @set
36
SETGM 00 011101110 ..... 01 . . 01 ..... ..... @set
37
SETGE 00 011101110 ..... 10 . . 01 ..... ..... @set
38
+
39
+# Memmove/Memcopy: the CPY insns allow overlapping src/dest and
40
+# copy in the correct direction; the CPYF insns always copy forwards.
41
+#
42
+# options has the nontemporal and unpriv bits for src and dest
43
+&cpy rs rn rd options
44
+@cpy .. ... . ..... rs:5 options:4 .. rn:5 rd:5 &cpy
45
+
46
+CPYFP 00 011 0 01000 ..... .... 01 ..... ..... @cpy
47
+CPYFM 00 011 0 01010 ..... .... 01 ..... ..... @cpy
48
+CPYFE 00 011 0 01100 ..... .... 01 ..... ..... @cpy
49
+CPYP 00 011 1 01000 ..... .... 01 ..... ..... @cpy
50
+CPYM 00 011 1 01010 ..... .... 01 ..... ..... @cpy
51
+CPYE 00 011 1 01100 ..... .... 01 ..... ..... @cpy
52
diff --git a/target/arm/tcg/helper-a64.c b/target/arm/tcg/helper-a64.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/target/arm/tcg/helper-a64.c
55
+++ b/target/arm/tcg/helper-a64.c
56
@@ -XXX,XX +XXX,XX @@ static uint64_t page_limit(uint64_t addr)
57
return TARGET_PAGE_ALIGN(addr + 1) - addr;
58
}
59
60
+/*
61
+ * Return the number of bytes we can copy starting from addr and working
62
+ * backwards without crossing a page boundary.
63
+ */
64
+static uint64_t page_limit_rev(uint64_t addr)
65
+{
66
+ return (addr & ~TARGET_PAGE_MASK) + 1;
67
+}
68
+
69
/*
70
* Perform part of a memory set on an area of guest memory starting at
71
* toaddr (a dirty address) and extending for setsize bytes.
72
@@ -XXX,XX +XXX,XX @@ void HELPER(setge)(CPUARMState *env, uint32_t syndrome, uint32_t mtedesc)
23
{
73
{
24
/* Return true if the regidx is a register we should synchronize
74
do_sete(env, syndrome, mtedesc, set_step_tags, true, GETPC());
25
- * via the cpreg_tuples array (ie is not a core reg we sync by
75
}
26
- * hand in kvm_arch_get/put_registers())
27
+ * via the cpreg_tuples array (ie is not a core or sve reg that
28
+ * we sync by hand in kvm_arch_get/put_registers())
29
*/
30
switch (regidx & KVM_REG_ARM_COPROC_MASK) {
31
case KVM_REG_ARM_CORE:
32
+ case KVM_REG_ARM64_SVE:
33
return false;
34
default:
35
return true;
36
@@ -XXX,XX +XXX,XX @@ int kvm_arm_cpreg_level(uint64_t regidx)
37
38
static int kvm_arch_put_fpsimd(CPUState *cs)
39
{
40
- ARMCPU *cpu = ARM_CPU(cs);
41
- CPUARMState *env = &cpu->env;
42
+ CPUARMState *env = &ARM_CPU(cs)->env;
43
struct kvm_one_reg reg;
44
- uint32_t fpr;
45
int i, ret;
46
47
for (i = 0; i < 32; i++) {
48
@@ -XXX,XX +XXX,XX @@ static int kvm_arch_put_fpsimd(CPUState *cs)
49
}
50
}
51
52
- reg.addr = (uintptr_t)(&fpr);
53
- fpr = vfp_get_fpsr(env);
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
+
76
+
61
+/*
77
+/*
62
+ * SVE registers are encoded in KVM's memory in an endianness-invariant format.
78
+ * Perform part of a memory copy from the guest memory at fromaddr
63
+ * The byte at offset i from the start of the in-memory representation contains
79
+ * and extending for copysize bytes, to the guest memory at
64
+ * the bits [(7 + 8 * i) : (8 * i)] of the register value. As this means the
80
+ * toaddr. Both addreses are dirty.
65
+ * lowest offsets are stored in the lowest memory addresses, then that nearly
81
+ *
66
+ * matches QEMU's representation, which is to use an array of host-endian
82
+ * Returns the number of bytes actually set, which might be less than
67
+ * uint64_t's, where the lower offsets are at the lower indices. To complete
83
+ * copysize; the caller should loop until the whole copy has been done.
68
+ * the translation we just need to byte swap the uint64_t's on big-endian hosts.
84
+ * The caller should ensure that the guest registers are correct
85
+ * for the possibility that the first byte of the copy encounters
86
+ * an exception or watchpoint. We guarantee not to take any faults
87
+ * for bytes other than the first.
69
+ */
88
+ */
70
+static uint64_t *sve_bswap64(uint64_t *dst, uint64_t *src, int nr)
89
+static uint64_t copy_step(CPUARMState *env, uint64_t toaddr, uint64_t fromaddr,
71
+{
90
+ uint64_t copysize, int wmemidx, int rmemidx,
72
+#ifdef HOST_WORDS_BIGENDIAN
91
+ uint32_t *wdesc, uint32_t *rdesc, uintptr_t ra)
73
+ int i;
92
+{
74
+
93
+ void *rmem;
75
+ for (i = 0; i < nr; ++i) {
94
+ void *wmem;
76
+ dst[i] = bswap64(src[i]);
95
+
77
}
96
+ /* Don't cross a page boundary on either source or destination */
78
97
+ copysize = MIN(copysize, page_limit(toaddr));
79
- reg.addr = (uintptr_t)(&fpr);
98
+ copysize = MIN(copysize, page_limit(fromaddr));
80
- fpr = vfp_get_fpcr(env);
99
+ /*
81
- reg.id = AARCH64_SIMD_CTRL_REG(fp_regs.fpcr);
100
+ * Handle MTE tag checks: either handle the tag mismatch for byte 0,
82
+ return dst;
101
+ * or else copy up to but not including the byte with the mismatch.
83
+#else
102
+ */
84
+ return src;
103
+ if (*rdesc) {
104
+ uint64_t mtesize = mte_mops_probe(env, fromaddr, copysize, *rdesc);
105
+ if (mtesize == 0) {
106
+ mte_check_fail(env, *rdesc, fromaddr, ra);
107
+ *rdesc = 0;
108
+ } else {
109
+ copysize = MIN(copysize, mtesize);
110
+ }
111
+ }
112
+ if (*wdesc) {
113
+ uint64_t mtesize = mte_mops_probe(env, toaddr, copysize, *wdesc);
114
+ if (mtesize == 0) {
115
+ mte_check_fail(env, *wdesc, toaddr, ra);
116
+ *wdesc = 0;
117
+ } else {
118
+ copysize = MIN(copysize, mtesize);
119
+ }
120
+ }
121
+
122
+ toaddr = useronly_clean_ptr(toaddr);
123
+ fromaddr = useronly_clean_ptr(fromaddr);
124
+ /* Trapless lookup of whether we can get a host memory pointer */
125
+ wmem = tlb_vaddr_to_host(env, toaddr, MMU_DATA_STORE, wmemidx);
126
+ rmem = tlb_vaddr_to_host(env, fromaddr, MMU_DATA_LOAD, rmemidx);
127
+
128
+#ifndef CONFIG_USER_ONLY
129
+ /*
130
+ * If we don't have host memory for both source and dest then just
131
+ * do a single byte copy. This will handle watchpoints, invalid pages,
132
+ * etc correctly. For clean code pages, the next iteration will see
133
+ * the page dirty and will use the fast path.
134
+ */
135
+ if (unlikely(!rmem || !wmem)) {
136
+ uint8_t byte;
137
+ if (rmem) {
138
+ byte = *(uint8_t *)rmem;
139
+ } else {
140
+ byte = cpu_ldub_mmuidx_ra(env, fromaddr, rmemidx, ra);
141
+ }
142
+ if (wmem) {
143
+ *(uint8_t *)wmem = byte;
144
+ } else {
145
+ cpu_stb_mmuidx_ra(env, toaddr, byte, wmemidx, ra);
146
+ }
147
+ return 1;
148
+ }
85
+#endif
149
+#endif
150
+ /* Easy case: just memmove the host memory */
151
+ memmove(wmem, rmem, copysize);
152
+ return copysize;
86
+}
153
+}
87
+
154
+
88
+/*
155
+/*
89
+ * KVM SVE registers come in slices where ZREGs have a slice size of 2048 bits
156
+ * Do part of a backwards memory copy. Here toaddr and fromaddr point
90
+ * and PREGS and the FFR have a slice size of 256 bits. However we simply hard
157
+ * to the *last* byte to be copied.
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
+ */
158
+ */
94
+static int kvm_arch_put_sve(CPUState *cs)
159
+static uint64_t copy_step_rev(CPUARMState *env, uint64_t toaddr,
95
+{
160
+ uint64_t fromaddr,
96
+ ARMCPU *cpu = ARM_CPU(cs);
161
+ uint64_t copysize, int wmemidx, int rmemidx,
97
+ CPUARMState *env = &cpu->env;
162
+ uint32_t *wdesc, uint32_t *rdesc, uintptr_t ra)
98
+ uint64_t tmp[ARM_MAX_VQ * 2];
163
+{
99
+ uint64_t *r;
164
+ void *rmem;
100
+ struct kvm_one_reg reg;
165
+ void *wmem;
101
+ int n, ret;
166
+
102
+
167
+ /* Don't cross a page boundary on either source or destination */
103
+ for (n = 0; n < KVM_ARM64_SVE_NUM_ZREGS; ++n) {
168
+ copysize = MIN(copysize, page_limit_rev(toaddr));
104
+ r = sve_bswap64(tmp, &env->vfp.zregs[n].d[0], cpu->sve_max_vq * 2);
169
+ copysize = MIN(copysize, page_limit_rev(fromaddr));
105
+ reg.addr = (uintptr_t)r;
170
+
106
+ reg.id = KVM_REG_ARM64_SVE_ZREG(n, 0);
171
+ /*
107
+ ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
172
+ * Handle MTE tag checks: either handle the tag mismatch for byte 0,
108
+ if (ret) {
173
+ * or else copy up to but not including the byte with the mismatch.
109
+ return ret;
174
+ */
110
+ }
175
+ if (*rdesc) {
111
+ }
176
+ uint64_t mtesize = mte_mops_probe_rev(env, fromaddr, copysize, *rdesc);
112
+
177
+ if (mtesize == 0) {
113
+ for (n = 0; n < KVM_ARM64_SVE_NUM_PREGS; ++n) {
178
+ mte_check_fail(env, *rdesc, fromaddr, ra);
114
+ r = sve_bswap64(tmp, r = &env->vfp.pregs[n].p[0],
179
+ *rdesc = 0;
115
+ DIV_ROUND_UP(cpu->sve_max_vq * 2, 8));
180
+ } else {
116
+ reg.addr = (uintptr_t)r;
181
+ copysize = MIN(copysize, mtesize);
117
+ reg.id = KVM_REG_ARM64_SVE_PREG(n, 0);
182
+ }
118
+ ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
183
+ }
119
+ if (ret) {
184
+ if (*wdesc) {
120
+ return ret;
185
+ uint64_t mtesize = mte_mops_probe_rev(env, toaddr, copysize, *wdesc);
121
+ }
186
+ if (mtesize == 0) {
122
+ }
187
+ mte_check_fail(env, *wdesc, toaddr, ra);
123
+
188
+ *wdesc = 0;
124
+ r = sve_bswap64(tmp, &env->vfp.pregs[FFR_PRED_NUM].p[0],
189
+ } else {
125
+ DIV_ROUND_UP(cpu->sve_max_vq * 2, 8));
190
+ copysize = MIN(copysize, mtesize);
126
+ reg.addr = (uintptr_t)r;
191
+ }
127
+ reg.id = KVM_REG_ARM64_SVE_FFR(0);
192
+ }
128
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
193
+
129
if (ret) {
194
+ toaddr = useronly_clean_ptr(toaddr);
130
return ret;
195
+ fromaddr = useronly_clean_ptr(fromaddr);
131
@@ -XXX,XX +XXX,XX @@ int kvm_arch_put_registers(CPUState *cs, int level)
196
+ /* Trapless lookup of whether we can get a host memory pointer */
132
{
197
+ wmem = tlb_vaddr_to_host(env, toaddr, MMU_DATA_STORE, wmemidx);
133
struct kvm_one_reg reg;
198
+ rmem = tlb_vaddr_to_host(env, fromaddr, MMU_DATA_LOAD, rmemidx);
134
uint64_t val;
199
+
135
+ uint32_t fpr;
200
+#ifndef CONFIG_USER_ONLY
136
int i, ret;
201
+ /*
137
unsigned int el;
202
+ * If we don't have host memory for both source and dest then just
138
203
+ * do a single byte copy. This will handle watchpoints, invalid pages,
139
@@ -XXX,XX +XXX,XX @@ int kvm_arch_put_registers(CPUState *cs, int level)
204
+ * etc correctly. For clean code pages, the next iteration will see
140
}
205
+ * the page dirty and will use the fast path.
141
}
206
+ */
142
207
+ if (unlikely(!rmem || !wmem)) {
143
- ret = kvm_arch_put_fpsimd(cs);
208
+ uint8_t byte;
144
+ if (cpu_isar_feature(aa64_sve, cpu)) {
209
+ if (rmem) {
145
+ ret = kvm_arch_put_sve(cs);
210
+ byte = *(uint8_t *)rmem;
211
+ } else {
212
+ byte = cpu_ldub_mmuidx_ra(env, fromaddr, rmemidx, ra);
213
+ }
214
+ if (wmem) {
215
+ *(uint8_t *)wmem = byte;
216
+ } else {
217
+ cpu_stb_mmuidx_ra(env, toaddr, byte, wmemidx, ra);
218
+ }
219
+ return 1;
220
+ }
221
+#endif
222
+ /*
223
+ * Easy case: just memmove the host memory. Note that wmem and
224
+ * rmem here point to the *last* byte to copy.
225
+ */
226
+ memmove(wmem - (copysize - 1), rmem - (copysize - 1), copysize);
227
+ return copysize;
228
+}
229
+
230
+/*
231
+ * for the Memory Copy operation, our implementation chooses always
232
+ * to use "option A", where we update Xd and Xs to the final addresses
233
+ * in the CPYP insn, and then in CPYM and CPYE only need to update Xn.
234
+ *
235
+ * @env: CPU
236
+ * @syndrome: syndrome value for mismatch exceptions
237
+ * (also contains the register numbers we need to use)
238
+ * @wdesc: MTE descriptor for the writes (destination)
239
+ * @rdesc: MTE descriptor for the reads (source)
240
+ * @move: true if this is CPY (memmove), false for CPYF (memcpy forwards)
241
+ */
242
+static void do_cpyp(CPUARMState *env, uint32_t syndrome, uint32_t wdesc,
243
+ uint32_t rdesc, uint32_t move, uintptr_t ra)
244
+{
245
+ int rd = mops_destreg(syndrome);
246
+ int rs = mops_srcreg(syndrome);
247
+ int rn = mops_sizereg(syndrome);
248
+ uint32_t rmemidx = FIELD_EX32(rdesc, MTEDESC, MIDX);
249
+ uint32_t wmemidx = FIELD_EX32(wdesc, MTEDESC, MIDX);
250
+ bool forwards = true;
251
+ uint64_t toaddr = env->xregs[rd];
252
+ uint64_t fromaddr = env->xregs[rs];
253
+ uint64_t copysize = env->xregs[rn];
254
+ uint64_t stagecopysize, step;
255
+
256
+ check_mops_enabled(env, ra);
257
+
258
+
259
+ if (move) {
260
+ /*
261
+ * Copy backwards if necessary. The direction for a non-overlapping
262
+ * copy is IMPDEF; we choose forwards.
263
+ */
264
+ if (copysize > 0x007FFFFFFFFFFFFFULL) {
265
+ copysize = 0x007FFFFFFFFFFFFFULL;
266
+ }
267
+ uint64_t fs = extract64(fromaddr, 0, 56);
268
+ uint64_t ts = extract64(toaddr, 0, 56);
269
+ uint64_t fe = extract64(fromaddr + copysize, 0, 56);
270
+
271
+ if (fs < ts && fe > ts) {
272
+ forwards = false;
273
+ }
146
+ } else {
274
+ } else {
147
+ ret = kvm_arch_put_fpsimd(cs);
275
+ if (copysize > INT64_MAX) {
148
+ }
276
+ copysize = INT64_MAX;
149
+ if (ret) {
277
+ }
150
+ return ret;
278
+ }
151
+ }
279
+
152
+
280
+ if (!mte_checks_needed(fromaddr, rdesc)) {
153
+ reg.addr = (uintptr_t)(&fpr);
281
+ rdesc = 0;
154
+ fpr = vfp_get_fpsr(env);
282
+ }
155
+ reg.id = AARCH64_SIMD_CTRL_REG(fp_regs.fpsr);
283
+ if (!mte_checks_needed(toaddr, wdesc)) {
156
+ ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
284
+ wdesc = 0;
157
+ if (ret) {
285
+ }
158
+ return ret;
286
+
159
+ }
287
+ if (forwards) {
160
+
288
+ stagecopysize = MIN(copysize, page_limit(toaddr));
161
+ reg.addr = (uintptr_t)(&fpr);
289
+ stagecopysize = MIN(stagecopysize, page_limit(fromaddr));
162
+ fpr = vfp_get_fpcr(env);
290
+ while (stagecopysize) {
163
+ reg.id = AARCH64_SIMD_CTRL_REG(fp_regs.fpcr);
291
+ env->xregs[rd] = toaddr;
164
+ ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
292
+ env->xregs[rs] = fromaddr;
165
if (ret) {
293
+ env->xregs[rn] = copysize;
166
return ret;
294
+ step = copy_step(env, toaddr, fromaddr, stagecopysize,
167
}
295
+ wmemidx, rmemidx, &wdesc, &rdesc, ra);
168
@@ -XXX,XX +XXX,XX @@ int kvm_arch_put_registers(CPUState *cs, int level)
296
+ toaddr += step;
169
297
+ fromaddr += step;
170
static int kvm_arch_get_fpsimd(CPUState *cs)
298
+ copysize -= step;
171
{
299
+ stagecopysize -= step;
172
- ARMCPU *cpu = ARM_CPU(cs);
300
+ }
173
- CPUARMState *env = &cpu->env;
301
+ /* Insn completed, so update registers to the Option A format */
174
+ CPUARMState *env = &ARM_CPU(cs)->env;
302
+ env->xregs[rd] = toaddr + copysize;
175
struct kvm_one_reg reg;
303
+ env->xregs[rs] = fromaddr + copysize;
176
- uint32_t fpr;
304
+ env->xregs[rn] = -copysize;
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 {
305
+ } else {
260
+ ret = kvm_arch_get_fpsimd(cs);
306
+ /*
261
+ }
307
+ * In a reverse copy the to and from addrs in Xs and Xd are the start
262
if (ret) {
308
+ * of the range, but it's more convenient for us to work with pointers
263
return ret;
309
+ * to the last byte being copied.
264
}
310
+ */
265
311
+ toaddr += copysize - 1;
266
+ reg.addr = (uintptr_t)(&fpr);
312
+ fromaddr += copysize - 1;
267
+ reg.id = AARCH64_SIMD_CTRL_REG(fp_regs.fpsr);
313
+ stagecopysize = MIN(copysize, page_limit_rev(toaddr));
268
+ ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
314
+ stagecopysize = MIN(stagecopysize, page_limit_rev(fromaddr));
269
+ if (ret) {
315
+ while (stagecopysize) {
270
+ return ret;
316
+ env->xregs[rn] = copysize;
271
+ }
317
+ step = copy_step_rev(env, toaddr, fromaddr, stagecopysize,
272
+ vfp_set_fpsr(env, fpr);
318
+ wmemidx, rmemidx, &wdesc, &rdesc, ra);
273
+
319
+ copysize -= step;
274
+ reg.addr = (uintptr_t)(&fpr);
320
+ stagecopysize -= step;
275
+ reg.id = AARCH64_SIMD_CTRL_REG(fp_regs.fpcr);
321
+ toaddr -= step;
276
+ ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
322
+ fromaddr -= step;
277
+ if (ret) {
323
+ }
278
+ return ret;
324
+ /*
279
+ }
325
+ * Insn completed, so update registers to the Option A format.
280
+ vfp_set_fpcr(env, fpr);
326
+ * For a reverse copy this is no different to the CPYP input format.
281
+
327
+ */
282
ret = kvm_get_vcpu_events(cpu);
328
+ env->xregs[rn] = copysize;
283
if (ret) {
329
+ }
284
return ret;
330
+
331
+ /* Set NZCV = 0000 to indicate we are an Option A implementation */
332
+ env->NF = 0;
333
+ env->ZF = 1; /* our env->ZF encoding is inverted */
334
+ env->CF = 0;
335
+ env->VF = 0;
336
+ return;
337
+}
338
+
339
+void HELPER(cpyp)(CPUARMState *env, uint32_t syndrome, uint32_t wdesc,
340
+ uint32_t rdesc)
341
+{
342
+ do_cpyp(env, syndrome, wdesc, rdesc, true, GETPC());
343
+}
344
+
345
+void HELPER(cpyfp)(CPUARMState *env, uint32_t syndrome, uint32_t wdesc,
346
+ uint32_t rdesc)
347
+{
348
+ do_cpyp(env, syndrome, wdesc, rdesc, false, GETPC());
349
+}
350
+
351
+static void do_cpym(CPUARMState *env, uint32_t syndrome, uint32_t wdesc,
352
+ uint32_t rdesc, uint32_t move, uintptr_t ra)
353
+{
354
+ /* Main: we choose to copy until less than a page remaining */
355
+ CPUState *cs = env_cpu(env);
356
+ int rd = mops_destreg(syndrome);
357
+ int rs = mops_srcreg(syndrome);
358
+ int rn = mops_sizereg(syndrome);
359
+ uint32_t rmemidx = FIELD_EX32(rdesc, MTEDESC, MIDX);
360
+ uint32_t wmemidx = FIELD_EX32(wdesc, MTEDESC, MIDX);
361
+ bool forwards = true;
362
+ uint64_t toaddr, fromaddr, copysize, step;
363
+
364
+ check_mops_enabled(env, ra);
365
+
366
+ /* We choose to NOP out "no data to copy" before consistency checks */
367
+ if (env->xregs[rn] == 0) {
368
+ return;
369
+ }
370
+
371
+ check_mops_wrong_option(env, syndrome, ra);
372
+
373
+ if (move) {
374
+ forwards = (int64_t)env->xregs[rn] < 0;
375
+ }
376
+
377
+ if (forwards) {
378
+ toaddr = env->xregs[rd] + env->xregs[rn];
379
+ fromaddr = env->xregs[rs] + env->xregs[rn];
380
+ copysize = -env->xregs[rn];
381
+ } else {
382
+ copysize = env->xregs[rn];
383
+ /* This toaddr and fromaddr point to the *last* byte to copy */
384
+ toaddr = env->xregs[rd] + copysize - 1;
385
+ fromaddr = env->xregs[rs] + copysize - 1;
386
+ }
387
+
388
+ if (!mte_checks_needed(fromaddr, rdesc)) {
389
+ rdesc = 0;
390
+ }
391
+ if (!mte_checks_needed(toaddr, wdesc)) {
392
+ wdesc = 0;
393
+ }
394
+
395
+ /* Our implementation has no particular parameter requirements for CPYM */
396
+
397
+ /* Do the actual memmove */
398
+ if (forwards) {
399
+ while (copysize >= TARGET_PAGE_SIZE) {
400
+ step = copy_step(env, toaddr, fromaddr, copysize,
401
+ wmemidx, rmemidx, &wdesc, &rdesc, ra);
402
+ toaddr += step;
403
+ fromaddr += step;
404
+ copysize -= step;
405
+ env->xregs[rn] = -copysize;
406
+ if (copysize >= TARGET_PAGE_SIZE &&
407
+ unlikely(cpu_loop_exit_requested(cs))) {
408
+ cpu_loop_exit_restore(cs, ra);
409
+ }
410
+ }
411
+ } else {
412
+ while (copysize >= TARGET_PAGE_SIZE) {
413
+ step = copy_step_rev(env, toaddr, fromaddr, copysize,
414
+ wmemidx, rmemidx, &wdesc, &rdesc, ra);
415
+ toaddr -= step;
416
+ fromaddr -= step;
417
+ copysize -= step;
418
+ env->xregs[rn] = copysize;
419
+ if (copysize >= TARGET_PAGE_SIZE &&
420
+ unlikely(cpu_loop_exit_requested(cs))) {
421
+ cpu_loop_exit_restore(cs, ra);
422
+ }
423
+ }
424
+ }
425
+}
426
+
427
+void HELPER(cpym)(CPUARMState *env, uint32_t syndrome, uint32_t wdesc,
428
+ uint32_t rdesc)
429
+{
430
+ do_cpym(env, syndrome, wdesc, rdesc, true, GETPC());
431
+}
432
+
433
+void HELPER(cpyfm)(CPUARMState *env, uint32_t syndrome, uint32_t wdesc,
434
+ uint32_t rdesc)
435
+{
436
+ do_cpym(env, syndrome, wdesc, rdesc, false, GETPC());
437
+}
438
+
439
+static void do_cpye(CPUARMState *env, uint32_t syndrome, uint32_t wdesc,
440
+ uint32_t rdesc, uint32_t move, uintptr_t ra)
441
+{
442
+ /* Epilogue: do the last partial page */
443
+ int rd = mops_destreg(syndrome);
444
+ int rs = mops_srcreg(syndrome);
445
+ int rn = mops_sizereg(syndrome);
446
+ uint32_t rmemidx = FIELD_EX32(rdesc, MTEDESC, MIDX);
447
+ uint32_t wmemidx = FIELD_EX32(wdesc, MTEDESC, MIDX);
448
+ bool forwards = true;
449
+ uint64_t toaddr, fromaddr, copysize, step;
450
+
451
+ check_mops_enabled(env, ra);
452
+
453
+ /* We choose to NOP out "no data to copy" before consistency checks */
454
+ if (env->xregs[rn] == 0) {
455
+ return;
456
+ }
457
+
458
+ check_mops_wrong_option(env, syndrome, ra);
459
+
460
+ if (move) {
461
+ forwards = (int64_t)env->xregs[rn] < 0;
462
+ }
463
+
464
+ if (forwards) {
465
+ toaddr = env->xregs[rd] + env->xregs[rn];
466
+ fromaddr = env->xregs[rs] + env->xregs[rn];
467
+ copysize = -env->xregs[rn];
468
+ } else {
469
+ copysize = env->xregs[rn];
470
+ /* This toaddr and fromaddr point to the *last* byte to copy */
471
+ toaddr = env->xregs[rd] + copysize - 1;
472
+ fromaddr = env->xregs[rs] + copysize - 1;
473
+ }
474
+
475
+ if (!mte_checks_needed(fromaddr, rdesc)) {
476
+ rdesc = 0;
477
+ }
478
+ if (!mte_checks_needed(toaddr, wdesc)) {
479
+ wdesc = 0;
480
+ }
481
+
482
+ /* Check the size; we don't want to have do a check-for-interrupts */
483
+ if (copysize >= TARGET_PAGE_SIZE) {
484
+ raise_exception_ra(env, EXCP_UDEF, syndrome,
485
+ mops_mismatch_exception_target_el(env), ra);
486
+ }
487
+
488
+ /* Do the actual memmove */
489
+ if (forwards) {
490
+ while (copysize > 0) {
491
+ step = copy_step(env, toaddr, fromaddr, copysize,
492
+ wmemidx, rmemidx, &wdesc, &rdesc, ra);
493
+ toaddr += step;
494
+ fromaddr += step;
495
+ copysize -= step;
496
+ env->xregs[rn] = -copysize;
497
+ }
498
+ } else {
499
+ while (copysize > 0) {
500
+ step = copy_step_rev(env, toaddr, fromaddr, copysize,
501
+ wmemidx, rmemidx, &wdesc, &rdesc, ra);
502
+ toaddr -= step;
503
+ fromaddr -= step;
504
+ copysize -= step;
505
+ env->xregs[rn] = copysize;
506
+ }
507
+ }
508
+}
509
+
510
+void HELPER(cpye)(CPUARMState *env, uint32_t syndrome, uint32_t wdesc,
511
+ uint32_t rdesc)
512
+{
513
+ do_cpye(env, syndrome, wdesc, rdesc, true, GETPC());
514
+}
515
+
516
+void HELPER(cpyfe)(CPUARMState *env, uint32_t syndrome, uint32_t wdesc,
517
+ uint32_t rdesc)
518
+{
519
+ do_cpye(env, syndrome, wdesc, rdesc, false, GETPC());
520
+}
521
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
522
index XXXXXXX..XXXXXXX 100644
523
--- a/target/arm/tcg/translate-a64.c
524
+++ b/target/arm/tcg/translate-a64.c
525
@@ -XXX,XX +XXX,XX @@ TRANS_FEAT(SETGP, aa64_mops, do_SET, a, false, true, gen_helper_setgp)
526
TRANS_FEAT(SETGM, aa64_mops, do_SET, a, false, true, gen_helper_setgm)
527
TRANS_FEAT(SETGE, aa64_mops, do_SET, a, true, true, gen_helper_setge)
528
529
+typedef void CpyFn(TCGv_env, TCGv_i32, TCGv_i32, TCGv_i32);
530
+
531
+static bool do_CPY(DisasContext *s, arg_cpy *a, bool is_epilogue, CpyFn fn)
532
+{
533
+ int rmemidx, wmemidx;
534
+ uint32_t syndrome, rdesc = 0, wdesc = 0;
535
+ bool wunpriv = extract32(a->options, 0, 1);
536
+ bool runpriv = extract32(a->options, 1, 1);
537
+
538
+ /*
539
+ * UNPREDICTABLE cases: we choose to UNDEF, which allows
540
+ * us to pull this check before the CheckMOPSEnabled() test
541
+ * (which we do in the helper function)
542
+ */
543
+ if (a->rs == a->rn || a->rs == a->rd || a->rn == a->rd ||
544
+ a->rd == 31 || a->rs == 31 || a->rn == 31) {
545
+ return false;
546
+ }
547
+
548
+ rmemidx = get_a64_user_mem_index(s, runpriv);
549
+ wmemidx = get_a64_user_mem_index(s, wunpriv);
550
+
551
+ /*
552
+ * We pass option_a == true, matching our implementation;
553
+ * we pass wrong_option == false: helper function may set that bit.
554
+ */
555
+ syndrome = syn_mop(false, false, a->options, is_epilogue,
556
+ false, true, a->rd, a->rs, a->rn);
557
+
558
+ /* If we need to do MTE tag checking, assemble the descriptors */
559
+ if (s->mte_active[runpriv]) {
560
+ rdesc = FIELD_DP32(rdesc, MTEDESC, TBI, s->tbid);
561
+ rdesc = FIELD_DP32(rdesc, MTEDESC, TCMA, s->tcma);
562
+ }
563
+ if (s->mte_active[wunpriv]) {
564
+ wdesc = FIELD_DP32(wdesc, MTEDESC, TBI, s->tbid);
565
+ wdesc = FIELD_DP32(wdesc, MTEDESC, TCMA, s->tcma);
566
+ wdesc = FIELD_DP32(wdesc, MTEDESC, WRITE, true);
567
+ }
568
+ /* The helper function needs these parts of the descriptor regardless */
569
+ rdesc = FIELD_DP32(rdesc, MTEDESC, MIDX, rmemidx);
570
+ wdesc = FIELD_DP32(wdesc, MTEDESC, MIDX, wmemidx);
571
+
572
+ /*
573
+ * The helper needs the register numbers, but since they're in
574
+ * the syndrome anyway, we let it extract them from there rather
575
+ * than passing in an extra three integer arguments.
576
+ */
577
+ fn(cpu_env, tcg_constant_i32(syndrome), tcg_constant_i32(wdesc),
578
+ tcg_constant_i32(rdesc));
579
+ return true;
580
+}
581
+
582
+TRANS_FEAT(CPYP, aa64_mops, do_CPY, a, false, gen_helper_cpyp)
583
+TRANS_FEAT(CPYM, aa64_mops, do_CPY, a, false, gen_helper_cpym)
584
+TRANS_FEAT(CPYE, aa64_mops, do_CPY, a, true, gen_helper_cpye)
585
+TRANS_FEAT(CPYFP, aa64_mops, do_CPY, a, false, gen_helper_cpyfp)
586
+TRANS_FEAT(CPYFM, aa64_mops, do_CPY, a, false, gen_helper_cpyfm)
587
+TRANS_FEAT(CPYFE, aa64_mops, do_CPY, a, true, gen_helper_cpyfe)
588
+
589
typedef void ArithTwoOp(TCGv_i64, TCGv_i64, TCGv_i64);
590
591
static bool gen_rri(DisasContext *s, arg_rri_sf *a,
285
--
592
--
286
2.20.1
593
2.34.1
287
288
diff view generated by jsdifflib
1
Switch the xilinx_axidma code away from bottom-half based ptimers to
1
Enable FEAT_MOPS on the AArch64 'max' CPU, and add it to
2
the new transaction-based ptimer API. This just requires adding
2
the list of features we implement.
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: 20230912140434.1333369-13-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
docs/system/arm/emulation.rst | 1 +
14
1 file changed, 5 insertions(+), 4 deletions(-)
9
linux-user/elfload.c | 1 +
10
target/arm/tcg/cpu64.c | 1 +
11
3 files changed, 3 insertions(+)
15
12
16
diff --git a/hw/dma/xilinx_axidma.c b/hw/dma/xilinx_axidma.c
13
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
17
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/dma/xilinx_axidma.c
15
--- a/docs/system/arm/emulation.rst
19
+++ b/hw/dma/xilinx_axidma.c
16
+++ b/docs/system/arm/emulation.rst
20
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
21
#include "hw/ptimer.h"
18
- FEAT_LSE (Large System Extensions)
22
#include "hw/qdev-properties.h"
19
- FEAT_LSE2 (Large System Extensions v2)
23
#include "qemu/log.h"
20
- FEAT_LVA (Large Virtual Address space)
24
-#include "qemu/main-loop.h"
21
+- FEAT_MOPS (Standardization of memory operations)
25
#include "qemu/module.h"
22
- FEAT_MTE (Memory Tagging Extension)
26
23
- FEAT_MTE2 (Memory Tagging Extension)
27
#include "hw/stream.h"
24
- FEAT_MTE3 (MTE Asymmetric Fault Handling)
28
@@ -XXX,XX +XXX,XX @@ enum {
25
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
29
};
26
index XXXXXXX..XXXXXXX 100644
30
27
--- a/linux-user/elfload.c
31
struct Stream {
28
+++ b/linux-user/elfload.c
32
- QEMUBH *bh;
29
@@ -XXX,XX +XXX,XX @@ uint32_t get_elf_hwcap2(void)
33
ptimer_state *ptimer;
30
GET_FEATURE_ID(aa64_sme_i16i64, ARM_HWCAP2_A64_SME_I16I64);
34
qemu_irq irq;
31
GET_FEATURE_ID(aa64_sme_fa64, ARM_HWCAP2_A64_SME_FA64);
35
32
GET_FEATURE_ID(aa64_hbc, ARM_HWCAP2_A64_HBC);
36
@@ -XXX,XX +XXX,XX @@ static void stream_complete(struct Stream *s)
33
+ GET_FEATURE_ID(aa64_mops, ARM_HWCAP2_A64_MOPS);
37
unsigned int comp_delay;
34
38
35
return hwcaps;
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
}
36
}
50
37
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
51
static void stream_process_mem2s(struct Stream *s, StreamSlave *tx_data_dev,
38
index XXXXXXX..XXXXXXX 100644
52
@@ -XXX,XX +XXX,XX @@ static void xilinx_axidma_realize(DeviceState *dev, Error **errp)
39
--- a/target/arm/tcg/cpu64.c
53
struct Stream *st = &s->streams[i];
40
+++ b/target/arm/tcg/cpu64.c
54
41
@@ -XXX,XX +XXX,XX @@ void aarch64_max_tcg_initfn(Object *obj)
55
st->nr = i;
42
cpu->isar.id_aa64isar1 = t;
56
- st->bh = qemu_bh_new(timer_hit, st);
43
57
- st->ptimer = ptimer_init_with_bh(st->bh, PTIMER_POLICY_DEFAULT);
44
t = cpu->isar.id_aa64isar2;
58
+ st->ptimer = ptimer_init(timer_hit, st, PTIMER_POLICY_DEFAULT);
45
+ t = FIELD_DP64(t, ID_AA64ISAR2, MOPS, 1); /* FEAT_MOPS */
59
+ ptimer_transaction_begin(st->ptimer);
46
t = FIELD_DP64(t, ID_AA64ISAR2, BC, 1); /* FEAT_HBC */
60
ptimer_set_freq(st->ptimer, s->freqhz);
47
cpu->isar.id_aa64isar2 = t;
61
+ ptimer_transaction_commit(st->ptimer);
62
}
63
return;
64
48
65
--
49
--
66
2.20.1
50
2.34.1
67
68
diff view generated by jsdifflib
1
From: Cédric Le Goater <clg@kaod.org>
1
Avoid a dynamic stack allocation in qjack_client_init(), by using
2
a g_autofree heap allocation instead.
2
3
3
Signed-off-by: Cédric Le Goater <clg@kaod.org>
4
(We stick with allocate + snprintf() because the JACK API requires
4
Reviewed-by: Joel Stanley <joel@jms.id.au>
5
the name to be no more than its maximum size, so g_strdup_printf()
5
Message-id: 20191023130455.1347-3-clg@kaod.org
6
would require an extra truncation step.)
7
8
The codebase has very few VLAs, and if we can get rid of them all we
9
can make the compiler error on new additions. This is a defensive
10
measure against security bugs where an on-stack dynamic allocation
11
isn't correctly size-checked (e.g. CVE-2021-3527).
12
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
15
Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com>
16
Reviewed-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
17
Message-id: 20230818155846.1651287-2-peter.maydell@linaro.org
7
---
18
---
8
include/hw/arm/aspeed.h | 1 +
19
audio/jackaudio.c | 5 +++--
9
hw/arm/aspeed.c | 23 +++++++++++++++++++++++
20
1 file changed, 3 insertions(+), 2 deletions(-)
10
2 files changed, 24 insertions(+)
11
21
12
diff --git a/include/hw/arm/aspeed.h b/include/hw/arm/aspeed.h
22
diff --git a/audio/jackaudio.c b/audio/jackaudio.c
13
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
14
--- a/include/hw/arm/aspeed.h
24
--- a/audio/jackaudio.c
15
+++ b/include/hw/arm/aspeed.h
25
+++ b/audio/jackaudio.c
16
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedBoardConfig {
26
@@ -XXX,XX +XXX,XX @@ static void qjack_client_connect_ports(QJackClient *c)
17
const char *desc;
27
static int qjack_client_init(QJackClient *c)
18
const char *soc_name;
19
uint32_t hw_strap1;
20
+ uint32_t hw_strap2;
21
const char *fmc_model;
22
const char *spi_model;
23
uint32_t num_cs;
24
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
25
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/arm/aspeed.c
27
+++ b/hw/arm/aspeed.c
28
@@ -XXX,XX +XXX,XX @@ struct AspeedBoardState {
29
/* Witherspoon hardware value: 0xF10AD216 (but use romulus definition) */
30
#define WITHERSPOON_BMC_HW_STRAP1 ROMULUS_BMC_HW_STRAP1
31
32
+/* AST2600 evb hardware value */
33
+#define AST2600_EVB_HW_STRAP1 0x000000C0
34
+#define AST2600_EVB_HW_STRAP2 0x00000003
35
+
36
/*
37
* The max ram region is for firmwares that scan the address space
38
* with load/store to guess how much RAM the SoC has.
39
@@ -XXX,XX +XXX,XX @@ static void aspeed_board_init(MachineState *machine,
40
&error_abort);
41
object_property_set_int(OBJECT(&bmc->soc), cfg->hw_strap1, "hw-strap1",
42
&error_abort);
43
+ object_property_set_int(OBJECT(&bmc->soc), cfg->hw_strap2, "hw-strap2",
44
+ &error_abort);
45
object_property_set_int(OBJECT(&bmc->soc), cfg->num_cs, "num-cs",
46
&error_abort);
47
object_property_set_int(OBJECT(&bmc->soc), machine->smp.cpus, "num-cpus",
48
@@ -XXX,XX +XXX,XX @@ static void ast2500_evb_i2c_init(AspeedBoardState *bmc)
49
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 11), "ds1338", 0x32);
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
{
28
{
60
AspeedSoCState *soc = &bmc->soc;
29
jack_status_t status;
61
@@ -XXX,XX +XXX,XX @@ static const AspeedBoardConfig aspeed_boards[] = {
30
- char client_name[jack_client_name_size()];
62
.num_cs = 2,
31
+ int client_name_len = jack_client_name_size(); /* includes NUL */
63
.i2c_init = witherspoon_bmc_i2c_init,
32
+ g_autofree char *client_name = g_new(char, client_name_len);
64
.ram = 512 * MiB,
33
jack_options_t options = JackNullOption;
65
+ }, {
34
66
+ .name = MACHINE_TYPE_NAME("ast2600-evb"),
35
if (c->state == QJACK_STATE_RUNNING) {
67
+ .desc = "Aspeed AST2600 EVB (Cortex A7)",
36
@@ -XXX,XX +XXX,XX @@ static int qjack_client_init(QJackClient *c)
68
+ .soc_name = "ast2600-a0",
37
69
+ .hw_strap1 = AST2600_EVB_HW_STRAP1,
38
c->connect_ports = true;
70
+ .hw_strap2 = AST2600_EVB_HW_STRAP2,
39
71
+ .fmc_model = "w25q512jv",
40
- snprintf(client_name, sizeof(client_name), "%s-%s",
72
+ .spi_model = "mx66u51235f",
41
+ snprintf(client_name, client_name_len, "%s-%s",
73
+ .num_cs = 1,
42
c->out ? "out" : "in",
74
+ .i2c_init = ast2600_evb_i2c_init,
43
c->opt->client_name ? c->opt->client_name : audio_application_name());
75
+ .ram = 1 * GiB,
76
},
77
};
78
44
79
--
45
--
80
2.20.1
46
2.34.1
81
47
82
48
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_A64 bits
4
that will be cached. For now, the env->hflags variable is not
5
used, and the results are fed back to cpu_get_tb_cpu_state.
6
7
Note that not all BTI related flags are cached, so we have to
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
22
--- a/target/arm/helper.c
23
+++ b/target/arm/helper.c
24
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_common(CPUARMState *env, int fp_el,
25
return flags;
26
}
27
28
+static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
29
+ ARMMMUIdx mmu_idx)
30
+{
31
+ ARMMMUIdx stage1 = stage_1_mmu_idx(mmu_idx);
32
+ ARMVAParameters p0 = aa64_va_parameters_both(env, 0, stage1);
33
+ uint32_t flags = 0;
34
+ uint64_t sctlr;
35
+ int tbii, tbid;
36
+
37
+ flags = FIELD_DP32(flags, TBFLAG_ANY, AARCH64_STATE, 1);
38
+
39
+ /* FIXME: ARMv8.1-VHE S2 translation regime. */
40
+ if (regime_el(env, stage1) < 2) {
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
+ }
81
+ }
82
+
83
+ if (cpu_isar_feature(aa64_bti, env_archcpu(env))) {
84
+ /* Note that SCTLR_EL[23].BT == SCTLR_BT1. */
85
+ if (sctlr & (el == 0 ? SCTLR_BT0 : SCTLR_BT1)) {
86
+ flags = FIELD_DP32(flags, TBFLAG_A64, BT, 1);
87
+ }
88
+ }
89
+
90
+ return rebuild_hflags_common(env, fp_el, mmu_idx, flags);
91
+}
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
--
179
2.20.1
180
181
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Avoid a dynamic stack allocation in qjack_process(). Since this
2
function is a JACK process callback, we are not permitted to malloc()
3
here, so we allocate a working buffer in qjack_client_init() instead.
2
4
3
Create a function to compute the values of the TBFLAG_A32 bits
5
The codebase has very few VLAs, and if we can get rid of them all we
4
that will be cached, and are used by all profiles.
6
can make the compiler error on new additions. This is a defensive
7
measure against security bugs where an on-stack dynamic allocation
8
isn't correctly size-checked (e.g. CVE-2021-3527).
5
9
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
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
12
Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com>
13
Reviewed-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
14
Message-id: 20230818155846.1651287-3-peter.maydell@linaro.org
10
---
15
---
11
target/arm/helper.c | 16 +++++++++++-----
16
audio/jackaudio.c | 16 +++++++++++-----
12
1 file changed, 11 insertions(+), 5 deletions(-)
17
1 file changed, 11 insertions(+), 5 deletions(-)
13
18
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
19
diff --git a/audio/jackaudio.c b/audio/jackaudio.c
15
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
21
--- a/audio/jackaudio.c
17
+++ b/target/arm/helper.c
22
+++ b/audio/jackaudio.c
18
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_common(CPUARMState *env, int fp_el,
23
@@ -XXX,XX +XXX,XX @@ typedef struct QJackClient {
19
return flags;
24
int buffersize;
25
jack_port_t **port;
26
QJackBuffer fifo;
27
+
28
+ /* Used as workspace by qjack_process() */
29
+ float **process_buffers;
20
}
30
}
21
31
QJackClient;
22
+static uint32_t rebuild_hflags_common_32(CPUARMState *env, int fp_el,
32
23
+ ARMMMUIdx mmu_idx, uint32_t flags)
33
@@ -XXX,XX +XXX,XX @@ static int qjack_process(jack_nframes_t nframes, void *arg)
24
+{
34
}
25
+ flags = FIELD_DP32(flags, TBFLAG_A32, SCTLR_B, arm_sctlr_b(env));
35
26
+ flags = FIELD_DP32(flags, TBFLAG_A32, NS, !access_secure_reg(env));
36
/* get the buffers for the ports */
27
+
37
- float *buffers[c->nchannels];
28
+ return rebuild_hflags_common(env, fp_el, mmu_idx, flags);
38
for (int i = 0; i < c->nchannels; ++i) {
29
+}
39
- buffers[i] = jack_port_get_buffer(c->port[i], nframes);
30
+
40
+ c->process_buffers[i] = jack_port_get_buffer(c->port[i], nframes);
31
static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
41
}
32
ARMMMUIdx mmu_idx)
42
33
{
43
if (c->out) {
34
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
44
if (likely(c->enabled)) {
35
ARMMMUIdx mmu_idx = arm_mmu_idx(env);
45
- qjack_buffer_read_l(&c->fifo, buffers, nframes);
36
int current_el = arm_current_el(env);
46
+ qjack_buffer_read_l(&c->fifo, c->process_buffers, nframes);
37
int fp_el = fp_exception_el(env, current_el);
47
} else {
38
- uint32_t flags = 0;
48
for (int i = 0; i < c->nchannels; ++i) {
39
+ uint32_t flags;
49
- memset(buffers[i], 0, nframes * sizeof(float));
40
50
+ memset(c->process_buffers[i], 0, nframes * sizeof(float));
41
if (is_a64(env)) {
51
}
42
*pc = env->pc;
43
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
44
}
52
}
45
} else {
53
} else {
46
*pc = env->regs[15];
54
if (likely(c->enabled)) {
47
+ flags = rebuild_hflags_common_32(env, fp_el, mmu_idx, 0);
55
- qjack_buffer_write_l(&c->fifo, buffers, nframes);
48
flags = FIELD_DP32(flags, TBFLAG_A32, THUMB, env->thumb);
56
+ qjack_buffer_write_l(&c->fifo, c->process_buffers, nframes);
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
}
57
}
61
-
62
- flags = rebuild_hflags_common(env, fp_el, mmu_idx, flags);
63
}
58
}
64
59
65
/* The SS_ACTIVE and PSTATE_SS bits correspond to the state machine
60
@@ -XXX,XX +XXX,XX @@ static int qjack_client_init(QJackClient *c)
61
jack_get_client_name(c->client));
62
}
63
64
+ /* Allocate working buffer for process callback */
65
+ c->process_buffers = g_new(float *, c->nchannels);
66
+
67
jack_set_process_callback(c->client, qjack_process , c);
68
jack_set_port_registration_callback(c->client, qjack_port_registration, c);
69
jack_set_xrun_callback(c->client, qjack_xrun, c);
70
@@ -XXX,XX +XXX,XX @@ static void qjack_client_fini_locked(QJackClient *c)
71
72
qjack_buffer_free(&c->fifo);
73
g_free(c->port);
74
+ g_free(c->process_buffers);
75
76
c->state = QJACK_STATE_DISCONNECTED;
77
/* fallthrough */
66
--
78
--
67
2.20.1
79
2.34.1
68
80
69
81
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
2
2
3
Continue setting, but not relying upon, env->hflags.
3
Armv8.1+ cpus have Virtual Host Extension (VHE) which added non-secure
4
EL2 virtual timer.
4
5
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
This change adds it to fullfil Arm BSA (Base System Architecture)
6
Message-id: 20191023150057.25731-23-richard.henderson@linaro.org
7
requirements.
8
9
Signed-off-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
10
Message-id: 20230913140610.214893-2-marcin.juszkiewicz@linaro.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
13
---
10
linux-user/aarch64/cpu_loop.c | 1 +
14
hw/arm/sbsa-ref.c | 2 ++
11
1 file changed, 1 insertion(+)
15
1 file changed, 2 insertions(+)
12
16
13
diff --git a/linux-user/aarch64/cpu_loop.c b/linux-user/aarch64/cpu_loop.c
17
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
14
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
15
--- a/linux-user/aarch64/cpu_loop.c
19
--- a/hw/arm/sbsa-ref.c
16
+++ b/linux-user/aarch64/cpu_loop.c
20
+++ b/hw/arm/sbsa-ref.c
17
@@ -XXX,XX +XXX,XX @@ void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
21
@@ -XXX,XX +XXX,XX @@
18
for (i = 1; i < 4; ++i) {
22
#define ARCH_TIMER_S_EL1_IRQ 13
19
env->cp15.sctlr_el[i] |= SCTLR_EE;
23
#define ARCH_TIMER_NS_EL1_IRQ 14
20
}
24
#define ARCH_TIMER_NS_EL2_IRQ 10
21
+ arm_rebuild_hflags(env);
25
+#define ARCH_TIMER_NS_EL2_VIRT_IRQ 12
22
#endif
26
23
27
enum {
24
if (cpu_isar_feature(aa64_pauth, cpu)) {
28
SBSA_FLASH,
29
@@ -XXX,XX +XXX,XX @@ static void create_gic(SBSAMachineState *sms, MemoryRegion *mem)
30
[GTIMER_VIRT] = ARCH_TIMER_VIRT_IRQ,
31
[GTIMER_HYP] = ARCH_TIMER_NS_EL2_IRQ,
32
[GTIMER_SEC] = ARCH_TIMER_S_EL1_IRQ,
33
+ [GTIMER_HYPVIRT] = ARCH_TIMER_NS_EL2_VIRT_IRQ,
34
};
35
36
for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
25
--
37
--
26
2.20.1
38
2.34.1
27
28
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Viktor Prutyanov <viktor@daynix.com>
2
2
3
As we are going to add more core-specific fields, add a 'cpu'
3
PE export name check introduced in d399d6b179 isn't reliable enough,
4
structure and move the ARMCPU field there as 'core'.
4
because a page with the export directory may be not present for some
5
reason. On the other hand, elf2dmp retrieves the PDB name in any case.
6
It can be also used to check that a PE image is the kernel image. So,
7
check PDB name when searching for Windows kernel image.
5
8
6
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=2165917
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
8
Message-id: 20191019234715.25750-7-f4bug@amsat.org
11
Signed-off-by: Viktor Prutyanov <viktor@daynix.com>
12
Reviewed-by: Akihiko Odaki <akihiko.odaki@daynix.com>
13
Message-id: 20230915170153.10959-2-viktor@daynix.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
15
---
11
include/hw/arm/bcm2836.h | 4 +++-
16
contrib/elf2dmp/main.c | 93 +++++++++++++++---------------------------
12
hw/arm/bcm2836.c | 26 ++++++++++++++------------
17
1 file changed, 33 insertions(+), 60 deletions(-)
13
2 files changed, 17 insertions(+), 13 deletions(-)
14
18
15
diff --git a/include/hw/arm/bcm2836.h b/include/hw/arm/bcm2836.h
19
diff --git a/contrib/elf2dmp/main.c b/contrib/elf2dmp/main.c
16
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/arm/bcm2836.h
21
--- a/contrib/elf2dmp/main.c
18
+++ b/include/hw/arm/bcm2836.h
22
+++ b/contrib/elf2dmp/main.c
19
@@ -XXX,XX +XXX,XX @@ typedef struct BCM283XState {
23
@@ -XXX,XX +XXX,XX @@ static int write_dump(struct pa_space *ps,
20
char *cpu_type;
24
return fclose(dmp_file);
21
uint32_t enabled_cpus;
25
}
22
26
23
- ARMCPU cpus[BCM283X_NCPUS];
27
-static bool pe_check_export_name(uint64_t base, void *start_addr,
24
+ struct {
28
- struct va_space *vs)
25
+ ARMCPU core;
29
-{
26
+ } cpu[BCM283X_NCPUS];
30
- IMAGE_EXPORT_DIRECTORY export_dir;
27
BCM2836ControlState control;
31
- const char *pe_name;
28
BCM2835PeripheralState peripherals;
32
-
29
} BCM283XState;
33
- if (pe_get_data_dir_entry(base, start_addr, IMAGE_FILE_EXPORT_DIRECTORY,
30
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
34
- &export_dir, sizeof(export_dir), vs)) {
31
index XXXXXXX..XXXXXXX 100644
35
- return false;
32
--- a/hw/arm/bcm2836.c
36
- }
33
+++ b/hw/arm/bcm2836.c
37
-
34
@@ -XXX,XX +XXX,XX @@ static void bcm2836_init(Object *obj)
38
- pe_name = va_space_resolve(vs, base + export_dir.Name);
35
int n;
39
- if (!pe_name) {
36
40
- return false;
37
for (n = 0; n < BCM283X_NCPUS; n++) {
41
- }
38
- object_initialize_child(obj, "cpu[*]", &s->cpus[n], sizeof(s->cpus[n]),
42
-
39
- info->cpu_type, &error_abort, NULL);
43
- return !strcmp(pe_name, PE_NAME);
40
+ object_initialize_child(obj, "cpu[*]", &s->cpu[n].core,
44
-}
41
+ sizeof(s->cpu[n].core), info->cpu_type,
45
-
42
+ &error_abort, NULL);
46
-static int pe_get_pdb_symstore_hash(uint64_t base, void *start_addr,
47
- char *hash, struct va_space *vs)
48
+static bool pe_check_pdb_name(uint64_t base, void *start_addr,
49
+ struct va_space *vs, OMFSignatureRSDS *rsds)
50
{
51
const char sign_rsds[4] = "RSDS";
52
IMAGE_DEBUG_DIRECTORY debug_dir;
53
- OMFSignatureRSDS rsds;
54
- char *pdb_name;
55
- size_t pdb_name_sz;
56
- size_t i;
57
+ char pdb_name[sizeof(PDB_NAME)];
58
59
if (pe_get_data_dir_entry(base, start_addr, IMAGE_FILE_DEBUG_DIRECTORY,
60
&debug_dir, sizeof(debug_dir), vs)) {
61
eprintf("Failed to get Debug Directory\n");
62
- return 1;
63
+ return false;
43
}
64
}
44
65
45
sysbus_init_child_obj(obj, "control", &s->control, sizeof(s->control),
66
if (debug_dir.Type != IMAGE_DEBUG_TYPE_CODEVIEW) {
46
@@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
67
- return 1;
47
68
+ eprintf("Debug Directory type is not CodeView\n");
48
for (n = 0; n < BCM283X_NCPUS; n++) {
69
+ return false;
49
/* TODO: this should be converted to a property of ARM_CPU */
70
}
50
- s->cpus[n].mp_affinity = (info->clusterid << 8) | n;
71
51
+ s->cpu[n].core.mp_affinity = (info->clusterid << 8) | n;
72
if (va_space_rw(vs,
52
73
base + debug_dir.AddressOfRawData,
53
/* set periphbase/CBAR value for CPU-local registers */
74
- &rsds, sizeof(rsds), 0)) {
54
- object_property_set_int(OBJECT(&s->cpus[n]),
75
- return 1;
55
+ object_property_set_int(OBJECT(&s->cpu[n].core),
76
+ rsds, sizeof(*rsds), 0)) {
56
info->peri_base,
77
+ eprintf("Failed to resolve OMFSignatureRSDS\n");
57
"reset-cbar", &err);
78
+ return false;
58
if (err) {
79
}
59
@@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
80
81
- printf("CodeView signature is \'%.4s\'\n", rsds.Signature);
82
-
83
- if (memcmp(&rsds.Signature, sign_rsds, sizeof(sign_rsds))) {
84
- return 1;
85
+ if (memcmp(&rsds->Signature, sign_rsds, sizeof(sign_rsds))) {
86
+ eprintf("CodeView signature is \'%.4s\', \'%s\' expected\n",
87
+ rsds->Signature, sign_rsds);
88
+ return false;
89
}
90
91
- pdb_name_sz = debug_dir.SizeOfData - sizeof(rsds);
92
- pdb_name = malloc(pdb_name_sz);
93
- if (!pdb_name) {
94
- return 1;
95
+ if (debug_dir.SizeOfData - sizeof(*rsds) != sizeof(PDB_NAME)) {
96
+ eprintf("PDB name size doesn't match\n");
97
+ return false;
98
}
99
100
if (va_space_rw(vs, base + debug_dir.AddressOfRawData +
101
- offsetof(OMFSignatureRSDS, name), pdb_name, pdb_name_sz, 0)) {
102
- free(pdb_name);
103
- return 1;
104
+ offsetof(OMFSignatureRSDS, name), pdb_name, sizeof(PDB_NAME),
105
+ 0)) {
106
+ eprintf("Failed to resolve PDB name\n");
107
+ return false;
108
}
109
110
printf("PDB name is \'%s\', \'%s\' expected\n", pdb_name, PDB_NAME);
111
112
- if (strcmp(pdb_name, PDB_NAME)) {
113
- eprintf("Unexpected PDB name, it seems the kernel isn't found\n");
114
- free(pdb_name);
115
- return 1;
116
- }
117
+ return !strcmp(pdb_name, PDB_NAME);
118
+}
119
120
- free(pdb_name);
121
-
122
- sprintf(hash, "%.08x%.04x%.04x%.02x%.02x", rsds.guid.a, rsds.guid.b,
123
- rsds.guid.c, rsds.guid.d[0], rsds.guid.d[1]);
124
+static void pe_get_pdb_symstore_hash(OMFSignatureRSDS *rsds, char *hash)
125
+{
126
+ sprintf(hash, "%.08x%.04x%.04x%.02x%.02x", rsds->guid.a, rsds->guid.b,
127
+ rsds->guid.c, rsds->guid.d[0], rsds->guid.d[1]);
128
hash += 20;
129
- for (i = 0; i < 6; i++, hash += 2) {
130
- sprintf(hash, "%.02x", rsds.guid.e[i]);
131
+ for (unsigned int i = 0; i < 6; i++, hash += 2) {
132
+ sprintf(hash, "%.02x", rsds->guid.e[i]);
133
}
134
135
- sprintf(hash, "%.01x", rsds.age);
136
-
137
- return 0;
138
+ sprintf(hash, "%.01x", rsds->age);
139
}
140
141
int main(int argc, char *argv[])
142
@@ -XXX,XX +XXX,XX @@ int main(int argc, char *argv[])
143
KDDEBUGGER_DATA64 *kdbg;
144
uint64_t KdVersionBlock;
145
bool kernel_found = false;
146
+ OMFSignatureRSDS rsds;
147
148
if (argc != 3) {
149
eprintf("usage:\n\t%s elf_file dmp_file\n", argv[0]);
150
@@ -XXX,XX +XXX,XX @@ int main(int argc, char *argv[])
60
}
151
}
61
152
62
/* start powered off if not enabled */
153
if (*(uint16_t *)nt_start_addr == 0x5a4d) { /* MZ */
63
- object_property_set_bool(OBJECT(&s->cpus[n]), n >= s->enabled_cpus,
154
- if (pe_check_export_name(KernBase, nt_start_addr, &vs)) {
64
+ object_property_set_bool(OBJECT(&s->cpu[n].core), n >= s->enabled_cpus,
155
+ printf("Checking candidate KernBase = 0x%016"PRIx64"\n", KernBase);
65
"start-powered-off", &err);
156
+ if (pe_check_pdb_name(KernBase, nt_start_addr, &vs, &rsds)) {
66
if (err) {
157
kernel_found = true;
67
error_propagate(errp, err);
158
break;
68
return;
159
}
69
}
160
@@ -XXX,XX +XXX,XX @@ int main(int argc, char *argv[])
70
161
printf("KernBase = 0x%016"PRIx64", signature is \'%.2s\'\n", KernBase,
71
- object_property_set_bool(OBJECT(&s->cpus[n]), true, "realized", &err);
162
(char *)nt_start_addr);
72
+ object_property_set_bool(OBJECT(&s->cpu[n].core), true,
163
73
+ "realized", &err);
164
- if (pe_get_pdb_symstore_hash(KernBase, nt_start_addr, pdb_hash, &vs)) {
74
if (err) {
165
- eprintf("Failed to get PDB symbol store hash\n");
75
error_propagate(errp, err);
166
- err = 1;
76
return;
167
- goto out_ps;
77
@@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
168
- }
78
169
+ pe_get_pdb_symstore_hash(&rsds, pdb_hash);
79
/* Connect irq/fiq outputs from the interrupt controller. */
170
80
qdev_connect_gpio_out_named(DEVICE(&s->control), "irq", n,
171
sprintf(pdb_url, "%s%s/%s/%s", SYM_URL_BASE, PDB_NAME, pdb_hash, PDB_NAME);
81
- qdev_get_gpio_in(DEVICE(&s->cpus[n]), ARM_CPU_IRQ));
172
printf("PDB URL is %s\n", pdb_url);
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
--
173
--
103
2.20.1
174
2.34.1
104
105
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Viktor Prutyanov <viktor@daynix.com>
2
2
3
Create a function to compute the values of the TBFLAG_A32 bits
3
Physical memory ranges may not be aligned to page size in QEMU ELF, but
4
that will be cached, and are used by M-profile.
4
DMP can only contain page-aligned runs. So, align them.
5
5
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Signed-off-by: Viktor Prutyanov <viktor@daynix.com>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Akihiko Odaki <akihiko.odaki@daynix.com>
8
Message-id: 20191023150057.25731-6-richard.henderson@linaro.org
8
Message-id: 20230915170153.10959-3-viktor@daynix.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
10
---
11
target/arm/helper.c | 45 ++++++++++++++++++++++++++++++---------------
11
contrib/elf2dmp/addrspace.h | 1 +
12
1 file changed, 30 insertions(+), 15 deletions(-)
12
contrib/elf2dmp/addrspace.c | 31 +++++++++++++++++++++++++++++--
13
contrib/elf2dmp/main.c | 5 +++--
14
3 files changed, 33 insertions(+), 4 deletions(-)
13
15
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
diff --git a/contrib/elf2dmp/addrspace.h b/contrib/elf2dmp/addrspace.h
15
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
18
--- a/contrib/elf2dmp/addrspace.h
17
+++ b/target/arm/helper.c
19
+++ b/contrib/elf2dmp/addrspace.h
18
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_common_32(CPUARMState *env, int fp_el,
20
@@ -XXX,XX +XXX,XX @@
19
return rebuild_hflags_common(env, fp_el, mmu_idx, flags);
21
22
#define ELF2DMP_PAGE_BITS 12
23
#define ELF2DMP_PAGE_SIZE (1ULL << ELF2DMP_PAGE_BITS)
24
+#define ELF2DMP_PAGE_MASK (ELF2DMP_PAGE_SIZE - 1)
25
#define ELF2DMP_PFN_MASK (~(ELF2DMP_PAGE_SIZE - 1))
26
27
#define INVALID_PA UINT64_MAX
28
diff --git a/contrib/elf2dmp/addrspace.c b/contrib/elf2dmp/addrspace.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/contrib/elf2dmp/addrspace.c
31
+++ b/contrib/elf2dmp/addrspace.c
32
@@ -XXX,XX +XXX,XX @@ static struct pa_block *pa_space_find_block(struct pa_space *ps, uint64_t pa)
33
34
for (i = 0; i < ps->block_nr; i++) {
35
if (ps->block[i].paddr <= pa &&
36
- pa <= ps->block[i].paddr + ps->block[i].size) {
37
+ pa < ps->block[i].paddr + ps->block[i].size) {
38
return ps->block + i;
39
}
40
}
41
@@ -XXX,XX +XXX,XX @@ static uint8_t *pa_space_resolve(struct pa_space *ps, uint64_t pa)
42
return block->addr + (pa - block->paddr);
20
}
43
}
21
44
22
+static uint32_t rebuild_hflags_m32(CPUARMState *env, int fp_el,
45
+static void pa_block_align(struct pa_block *b)
23
+ ARMMMUIdx mmu_idx)
24
+{
46
+{
25
+ uint32_t flags = 0;
47
+ uint64_t low_align = ((b->paddr - 1) | ELF2DMP_PAGE_MASK) + 1 - b->paddr;
48
+ uint64_t high_align = (b->paddr + b->size) & ELF2DMP_PAGE_MASK;
26
+
49
+
27
+ if (arm_v7m_is_handler_mode(env)) {
50
+ if (low_align == 0 && high_align == 0) {
28
+ flags = FIELD_DP32(flags, TBFLAG_A32, HANDLER, 1);
51
+ return;
29
+ }
52
+ }
30
+
53
+
31
+ /*
54
+ if (low_align + high_align < b->size) {
32
+ * v8M always applies stack limit checks unless CCR.STKOFHFNMIGN
55
+ printf("Block 0x%"PRIx64"+:0x%"PRIx64" will be aligned to "
33
+ * is suppressing them because the requested execution priority
56
+ "0x%"PRIx64"+:0x%"PRIx64"\n", b->paddr, b->size,
34
+ * is less than 0.
57
+ b->paddr + low_align, b->size - low_align - high_align);
35
+ */
58
+ b->size -= low_align + high_align;
36
+ if (arm_feature(env, ARM_FEATURE_V8) &&
59
+ } else {
37
+ !((mmu_idx & ARM_MMU_IDX_M_NEGPRI) &&
60
+ printf("Block 0x%"PRIx64"+:0x%"PRIx64" is too small to align\n",
38
+ (env->v7m.ccr[env->v7m.secure] & R_V7M_CCR_STKOFHFNMIGN_MASK))) {
61
+ b->paddr, b->size);
39
+ flags = FIELD_DP32(flags, TBFLAG_A32, STACKCHECK, 1);
62
+ b->size = 0;
40
+ }
63
+ }
41
+
64
+
42
+ return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags);
65
+ b->addr += low_align;
66
+ b->paddr += low_align;
43
+}
67
+}
44
+
68
+
45
static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
69
int pa_space_create(struct pa_space *ps, QEMU_Elf *qemu_elf)
46
ARMMMUIdx mmu_idx)
47
{
70
{
48
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
71
Elf64_Half phdr_nr = elf_getphdrnum(qemu_elf->map);
49
}
72
@@ -XXX,XX +XXX,XX @@ int pa_space_create(struct pa_space *ps, QEMU_Elf *qemu_elf)
50
} else {
73
.paddr = phdr[i].p_paddr,
51
*pc = env->regs[15];
74
.size = phdr[i].p_filesz,
52
- flags = rebuild_hflags_common_32(env, fp_el, mmu_idx, 0);
75
};
53
+
76
- block_i++;
54
+ if (arm_feature(env, ARM_FEATURE_M)) {
77
+ pa_block_align(&ps->block[block_i]);
55
+ flags = rebuild_hflags_m32(env, fp_el, mmu_idx);
78
+ block_i = ps->block[block_i].size ? (block_i + 1) : block_i;
56
+ } else {
57
+ flags = rebuild_hflags_common_32(env, fp_el, mmu_idx, 0);
58
+ }
59
+
60
flags = FIELD_DP32(flags, TBFLAG_A32, THUMB, env->thumb);
61
flags = FIELD_DP32(flags, TBFLAG_A32, VECLEN, env->vfp.vec_len);
62
flags = FIELD_DP32(flags, TBFLAG_A32, VECSTRIDE, env->vfp.vec_stride);
63
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
64
}
79
}
65
}
80
}
66
81
67
- if (arm_v7m_is_handler_mode(env)) {
82
+ ps->block_nr = block_i;
68
- flags = FIELD_DP32(flags, TBFLAG_A32, HANDLER, 1);
83
+
69
- }
84
return 0;
70
-
85
}
71
- /* v8M always applies stack limit checks unless CCR.STKOFHFNMIGN is
86
72
- * suppressing them because the requested execution priority is less than 0.
87
diff --git a/contrib/elf2dmp/main.c b/contrib/elf2dmp/main.c
73
- */
88
index XXXXXXX..XXXXXXX 100644
74
- if (arm_feature(env, ARM_FEATURE_V8) &&
89
--- a/contrib/elf2dmp/main.c
75
- arm_feature(env, ARM_FEATURE_M) &&
90
+++ b/contrib/elf2dmp/main.c
76
- !((mmu_idx & ARM_MMU_IDX_M_NEGPRI) &&
91
@@ -XXX,XX +XXX,XX @@ static int write_dump(struct pa_space *ps,
77
- (env->v7m.ccr[env->v7m.secure] & R_V7M_CCR_STKOFHFNMIGN_MASK))) {
92
for (i = 0; i < ps->block_nr; i++) {
78
- flags = FIELD_DP32(flags, TBFLAG_A32, STACKCHECK, 1);
93
struct pa_block *b = &ps->block[i];
79
- }
94
80
-
95
- printf("Writing block #%zu/%zu to file...\n", i, ps->block_nr);
81
if (arm_feature(env, ARM_FEATURE_M_SECURITY) &&
96
+ printf("Writing block #%zu/%zu of %"PRIu64" bytes to file...\n", i,
82
FIELD_EX32(env->v7m.fpccr[M_REG_S], V7M_FPCCR, S) != env->v7m.secure) {
97
+ ps->block_nr, b->size);
83
flags = FIELD_DP32(flags, TBFLAG_A32, FPCCR_S_WRONG, 1);
98
if (fwrite(b->addr, b->size, 1, dmp_file) != 1) {
99
- eprintf("Failed to write dump header\n");
100
+ eprintf("Failed to write block\n");
101
fclose(dmp_file);
102
return 1;
103
}
84
--
104
--
85
2.20.1
105
2.34.1
86
87
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
1
From: Viktor Prutyanov <viktor@daynix.com>
2
2
3
Allow cpu 'host' to enable SVE when it's available, unless the
3
DMP supports 42 physical memory runs at most. So, merge adjacent
4
user chooses to disable it with the added 'sve=off' cpu property.
4
physical memory ranges from QEMU ELF when possible to minimize total
5
Also give the user the ability to select vector lengths with the
5
number of runs.
6
sve<N> properties. We don't adopt 'max' cpu's other sve property,
7
sve-max-vq, because that property is difficult to use with KVM.
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
6
14
Signed-off-by: Andrew Jones <drjones@redhat.com>
7
Signed-off-by: Viktor Prutyanov <viktor@daynix.com>
15
Reviewed-by: Eric Auger <eric.auger@redhat.com>
8
Reviewed-by: Akihiko Odaki <akihiko.odaki@daynix.com>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20230915170153.10959-4-viktor@daynix.com
17
Tested-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
10
[PMM: fixed format string for printing size_t values]
18
Message-id: 20191024121808.9612-10-drjones@redhat.com
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
---
12
---
21
target/arm/cpu.h | 2 ++
13
contrib/elf2dmp/main.c | 56 ++++++++++++++++++++++++++++++++++++------
22
target/arm/cpu.c | 3 +++
14
1 file changed, 48 insertions(+), 8 deletions(-)
23
target/arm/cpu64.c | 33 +++++++++++++++++----------------
24
target/arm/kvm64.c | 14 +++++++++++++-
25
tests/arm-cpu-features.c | 23 +++++++++++------------
26
docs/arm-cpu-features.rst | 19 ++++++++++++-------
27
6 files changed, 58 insertions(+), 36 deletions(-)
28
15
29
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
diff --git a/contrib/elf2dmp/main.c b/contrib/elf2dmp/main.c
30
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/cpu.h
18
--- a/contrib/elf2dmp/main.c
32
+++ b/target/arm/cpu.h
19
+++ b/contrib/elf2dmp/main.c
33
@@ -XXX,XX +XXX,XX @@ int aarch64_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
20
@@ -XXX,XX +XXX,XX @@
34
void aarch64_sve_narrow_vq(CPUARMState *env, unsigned vq);
21
#define PE_NAME "ntoskrnl.exe"
35
void aarch64_sve_change_el(CPUARMState *env, int old_el,
22
36
int new_el, bool el0_a64);
23
#define INITIAL_MXCSR 0x1f80
37
+void aarch64_add_sve_properties(Object *obj);
24
+#define MAX_NUMBER_OF_RUNS 42
38
#else
25
39
static inline void aarch64_sve_narrow_vq(CPUARMState *env, unsigned vq) { }
26
typedef struct idt_desc {
40
static inline void aarch64_sve_change_el(CPUARMState *env, int o,
27
uint16_t offset1; /* offset bits 0..15 */
41
int n, bool a)
28
@@ -XXX,XX +XXX,XX @@ static int fix_dtb(struct va_space *vs, QEMU_Elf *qe)
42
{ }
29
return 1;
43
+static inline void aarch64_add_sve_properties(Object *obj) { }
44
#endif
45
46
#if !defined(CONFIG_TCG)
47
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/target/arm/cpu.c
50
+++ b/target/arm/cpu.c
51
@@ -XXX,XX +XXX,XX @@ static void arm_host_initfn(Object *obj)
52
ARMCPU *cpu = ARM_CPU(obj);
53
54
kvm_arm_set_cpu_features_from_host(cpu);
55
+ if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
56
+ aarch64_add_sve_properties(obj);
57
+ }
58
arm_cpu_post_init(obj);
59
}
30
}
60
31
61
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
32
+static void try_merge_runs(struct pa_space *ps,
62
index XXXXXXX..XXXXXXX 100644
33
+ WinDumpPhyMemDesc64 *PhysicalMemoryBlock)
63
--- a/target/arm/cpu64.c
64
+++ b/target/arm/cpu64.c
65
@@ -XXX,XX +XXX,XX @@ static void cpu_arm_set_sve(Object *obj, Visitor *v, const char *name,
66
cpu->isar.id_aa64pfr0 = t;
67
}
68
69
+void aarch64_add_sve_properties(Object *obj)
70
+{
34
+{
71
+ uint32_t vq;
35
+ unsigned int merge_cnt = 0, run_idx = 0;
72
+
36
+
73
+ object_property_add(obj, "sve", "bool", cpu_arm_get_sve,
37
+ PhysicalMemoryBlock->NumberOfRuns = 0;
74
+ cpu_arm_set_sve, NULL, NULL, &error_fatal);
75
+
38
+
76
+ for (vq = 1; vq <= ARM_MAX_VQ; ++vq) {
39
+ for (size_t idx = 0; idx < ps->block_nr; idx++) {
77
+ char name[8];
40
+ struct pa_block *blk = ps->block + idx;
78
+ sprintf(name, "sve%d", vq * 128);
41
+ struct pa_block *next = blk + 1;
79
+ object_property_add(obj, name, "bool", cpu_arm_get_sve_vq,
42
+
80
+ cpu_arm_set_sve_vq, NULL, NULL, &error_fatal);
43
+ PhysicalMemoryBlock->NumberOfPages += blk->size / ELF2DMP_PAGE_SIZE;
44
+
45
+ if (idx + 1 != ps->block_nr && blk->paddr + blk->size == next->paddr) {
46
+ printf("Block #%zu 0x%"PRIx64"+:0x%"PRIx64" and %u previous will be"
47
+ " merged\n", idx, blk->paddr, blk->size, merge_cnt);
48
+ merge_cnt++;
49
+ } else {
50
+ struct pa_block *first_merged = blk - merge_cnt;
51
+
52
+ printf("Block #%zu 0x%"PRIx64"+:0x%"PRIx64" and %u previous will be"
53
+ " merged to 0x%"PRIx64"+:0x%"PRIx64" (run #%u)\n",
54
+ idx, blk->paddr, blk->size, merge_cnt, first_merged->paddr,
55
+ blk->paddr + blk->size - first_merged->paddr, run_idx);
56
+ PhysicalMemoryBlock->Run[run_idx] = (WinDumpPhyMemRun64) {
57
+ .BasePage = first_merged->paddr / ELF2DMP_PAGE_SIZE,
58
+ .PageCount = (blk->paddr + blk->size - first_merged->paddr) /
59
+ ELF2DMP_PAGE_SIZE,
60
+ };
61
+ PhysicalMemoryBlock->NumberOfRuns++;
62
+ run_idx++;
63
+ merge_cnt = 0;
64
+ }
81
+ }
65
+ }
82
+}
66
+}
83
+
67
+
84
/* -cpu max: if KVM is enabled, like -cpu host (best possible with this host);
68
static int fill_header(WinDumpHeader64 *hdr, struct pa_space *ps,
85
* otherwise, a CPU with as many features enabled as our emulation supports.
69
struct va_space *vs, uint64_t KdDebuggerDataBlock,
86
* The version of '-cpu max' for qemu-system-arm is defined in cpu.c;
70
KDDEBUGGER_DATA64 *kdbg, uint64_t KdVersionBlock, int nr_cpus)
87
@@ -XXX,XX +XXX,XX @@ static void cpu_arm_set_sve(Object *obj, Visitor *v, const char *name,
71
@@ -XXX,XX +XXX,XX @@ static int fill_header(WinDumpHeader64 *hdr, struct pa_space *ps,
88
static void aarch64_max_initfn(Object *obj)
72
KUSD_OFFSET_PRODUCT_TYPE);
89
{
73
DBGKD_GET_VERSION64 kvb;
90
ARMCPU *cpu = ARM_CPU(obj);
74
WinDumpHeader64 h;
91
- uint32_t vq;
75
- size_t i;
92
- uint64_t t;
76
93
77
QEMU_BUILD_BUG_ON(KUSD_OFFSET_SUITE_MASK >= ELF2DMP_PAGE_SIZE);
94
if (kvm_enabled()) {
78
QEMU_BUILD_BUG_ON(KUSD_OFFSET_PRODUCT_TYPE >= ELF2DMP_PAGE_SIZE);
95
kvm_arm_set_cpu_features_from_host(cpu);
79
@@ -XXX,XX +XXX,XX @@ static int fill_header(WinDumpHeader64 *hdr, struct pa_space *ps,
96
- if (kvm_arm_sve_supported(CPU(cpu))) {
80
.RequiredDumpSpace = sizeof(h),
97
- t = cpu->isar.id_aa64pfr0;
81
};
98
- t = FIELD_DP64(t, ID_AA64PFR0, SVE, 1);
82
99
- cpu->isar.id_aa64pfr0 = t;
83
- for (i = 0; i < ps->block_nr; i++) {
100
- }
84
- h.PhysicalMemoryBlock.NumberOfPages +=
101
} else {
85
- ps->block[i].size / ELF2DMP_PAGE_SIZE;
102
+ uint64_t t;
86
- h.PhysicalMemoryBlock.Run[i] = (WinDumpPhyMemRun64) {
103
uint32_t u;
87
- .BasePage = ps->block[i].paddr / ELF2DMP_PAGE_SIZE,
104
aarch64_a57_initfn(obj);
88
- .PageCount = ps->block[i].size / ELF2DMP_PAGE_SIZE,
105
89
- };
106
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
90
+ if (h.PhysicalMemoryBlock.NumberOfRuns <= MAX_NUMBER_OF_RUNS) {
107
#endif
91
+ for (size_t idx = 0; idx < ps->block_nr; idx++) {
92
+ h.PhysicalMemoryBlock.NumberOfPages +=
93
+ ps->block[idx].size / ELF2DMP_PAGE_SIZE;
94
+ h.PhysicalMemoryBlock.Run[idx] = (WinDumpPhyMemRun64) {
95
+ .BasePage = ps->block[idx].paddr / ELF2DMP_PAGE_SIZE,
96
+ .PageCount = ps->block[idx].size / ELF2DMP_PAGE_SIZE,
97
+ };
98
+ }
99
+ } else {
100
+ try_merge_runs(ps, &h.PhysicalMemoryBlock);
108
}
101
}
109
102
110
- object_property_add(obj, "sve", "bool", cpu_arm_get_sve,
103
h.RequiredDumpSpace +=
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
--
104
--
309
2.20.1
105
2.34.1
310
311
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
1
From: Viktor Prutyanov <viktor@daynix.com>
2
2
3
Extend the SVE vq map initialization and validation with KVM's
3
Glib's g_mapped_file_new maps file with PROT_READ|PROT_WRITE and
4
supported vector lengths when KVM is enabled. In order to determine
4
MAP_PRIVATE. This leads to premature physical memory allocation of dump
5
and select supported lengths we add two new KVM functions for getting
5
file size on Linux hosts and may fail. On Linux, mapping the file with
6
and setting the KVM_REG_ARM64_SVE_VLS pseudo-register.
6
MAP_NORESERVE limits the allocation by available memory.
7
7
8
This patch has been co-authored with Richard Henderson, who reworked
8
Signed-off-by: Viktor Prutyanov <viktor@daynix.com>
9
the target/arm/cpu64.c changes in order to push all the validation and
9
Reviewed-by: Akihiko Odaki <akihiko.odaki@daynix.com>
10
auto-enabling/disabling steps into the finalizer, resulting in a nice
10
Message-id: 20230915170153.10959-5-viktor@daynix.com
11
LOC reduction.
12
13
Signed-off-by: Andrew Jones <drjones@redhat.com>
14
Reviewed-by: Eric Auger <eric.auger@redhat.com>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
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>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
---
12
---
20
target/arm/kvm_arm.h | 12 +++
13
contrib/elf2dmp/qemu_elf.h | 2 ++
21
target/arm/cpu64.c | 176 ++++++++++++++++++++++++++++----------
14
contrib/elf2dmp/qemu_elf.c | 68 +++++++++++++++++++++++++++++++-------
22
target/arm/kvm64.c | 100 +++++++++++++++++++++-
15
2 files changed, 58 insertions(+), 12 deletions(-)
23
tests/arm-cpu-features.c | 106 ++++++++++++++++++++++-
24
docs/arm-cpu-features.rst | 45 +++++++---
25
5 files changed, 381 insertions(+), 58 deletions(-)
26
16
27
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
17
diff --git a/contrib/elf2dmp/qemu_elf.h b/contrib/elf2dmp/qemu_elf.h
28
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/kvm_arm.h
19
--- a/contrib/elf2dmp/qemu_elf.h
30
+++ b/target/arm/kvm_arm.h
20
+++ b/contrib/elf2dmp/qemu_elf.h
31
@@ -XXX,XX +XXX,XX @@ typedef struct ARMHostCPUFeatures {
21
@@ -XXX,XX +XXX,XX @@ typedef struct QEMUCPUState {
32
*/
22
int is_system(QEMUCPUState *s);
33
bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf);
23
34
24
typedef struct QEMU_Elf {
35
+/**
25
+#ifndef CONFIG_LINUX
36
+ * kvm_arm_sve_get_vls:
26
GMappedFile *gmf;
37
+ * @cs: CPUState
27
+#endif
38
+ * @map: bitmap to fill in
28
size_t size;
39
+ *
29
void *map;
40
+ * Get all the SVE vector lengths supported by the KVM host, setting
30
QEMUCPUState **state;
41
+ * the bits corresponding to their length in quadwords minus one
31
diff --git a/contrib/elf2dmp/qemu_elf.c b/contrib/elf2dmp/qemu_elf.c
42
+ * (vq - 1) in @map up to ARM_MAX_VQ.
32
index XXXXXXX..XXXXXXX 100644
43
+ */
33
--- a/contrib/elf2dmp/qemu_elf.c
44
+void kvm_arm_sve_get_vls(CPUState *cs, unsigned long *map);
34
+++ b/contrib/elf2dmp/qemu_elf.c
35
@@ -XXX,XX +XXX,XX @@ static bool check_ehdr(QEMU_Elf *qe)
36
return true;
37
}
38
39
-int QEMU_Elf_init(QEMU_Elf *qe, const char *filename)
40
+static int QEMU_Elf_map(QEMU_Elf *qe, const char *filename)
41
{
42
+#ifdef CONFIG_LINUX
43
+ struct stat st;
44
+ int fd;
45
+
45
+
46
/**
46
+ printf("Using Linux mmap\n");
47
* kvm_arm_set_cpu_features_from_host:
47
+
48
* @cpu: ARMCPU to set the features for
48
+ fd = open(filename, O_RDONLY, 0);
49
@@ -XXX,XX +XXX,XX @@ static inline int kvm_arm_vgic_probe(void)
49
+ if (fd == -1) {
50
static inline void kvm_arm_pmu_set_irq(CPUState *cs, int irq) {}
50
+ eprintf("Failed to open ELF dump file \'%s\'\n", filename);
51
static inline void kvm_arm_pmu_init(CPUState *cs) {}
51
+ return 1;
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
+ }
52
+ }
76
+
53
+
77
/*
54
+ if (fstat(fd, &st)) {
78
* Process explicit sve<N> properties.
55
+ eprintf("Failed to get size of ELF dump file\n");
79
* From the properties, sve_vq_map<N> implies sve_vq_init<N>.
56
+ close(fd);
80
@@ -XXX,XX +XXX,XX @@ void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp)
57
+ return 1;
81
return;
58
+ }
82
}
59
+ qe->size = st.st_size;
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
{
223
ARMCPU *cpu = ARM_CPU(obj);
224
Error *err = NULL;
225
+ uint32_t max_vq;
226
227
- visit_type_uint32(v, name, &cpu->sve_max_vq, &err);
228
-
229
- if (!err && (cpu->sve_max_vq == 0 || cpu->sve_max_vq > ARM_MAX_VQ)) {
230
- error_setg(&err, "unsupported SVE vector length");
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
+
60
+
240
+ if (kvm_enabled() && !kvm_arm_sve_supported(CPU(cpu))) {
61
+ qe->map = mmap(NULL, qe->size, PROT_READ | PROT_WRITE,
241
+ error_setg(errp, "cannot set sve-max-vq");
62
+ MAP_PRIVATE | MAP_NORESERVE, fd, 0);
242
+ error_append_hint(errp, "SVE not supported by KVM on this host\n");
63
+ if (qe->map == MAP_FAILED) {
243
+ return;
64
+ eprintf("Failed to map ELF file\n");
65
+ close(fd);
66
+ return 1;
244
+ }
67
+ }
245
+
68
+
246
+ if (max_vq == 0 || max_vq > ARM_MAX_VQ) {
69
+ close(fd);
247
+ error_setg(errp, "unsupported SVE vector length");
70
+#else
248
+ error_append_hint(errp, "Valid sve-max-vq in range [1-%d]\n",
71
GError *gerr = NULL;
249
+ ARM_MAX_VQ);
72
- int err = 0;
250
+ return;
251
+ }
252
+
73
+
253
+ cpu->sve_max_vq = max_vq;
74
+ printf("Using GLib mmap\n");
254
}
75
255
76
qe->gmf = g_mapped_file_new(filename, TRUE, &gerr);
256
static void cpu_arm_get_sve_vq(Object *obj, Visitor *v, const char *name,
77
if (gerr) {
257
@@ -XXX,XX +XXX,XX @@ static void cpu_arm_set_sve_vq(Object *obj, Visitor *v, const char *name,
78
@@ -XXX,XX +XXX,XX @@ int QEMU_Elf_init(QEMU_Elf *qe, const char *filename)
258
return;
79
259
}
80
qe->map = g_mapped_file_get_contents(qe->gmf);
260
81
qe->size = g_mapped_file_get_length(qe->gmf);
261
+ if (value && kvm_enabled() && !kvm_arm_sve_supported(CPU(cpu))) {
82
+#endif
262
+ error_setg(errp, "cannot enable %s", name);
263
+ error_append_hint(errp, "SVE not supported by KVM on this host\n");
264
+ return;
265
+ }
266
+
83
+
267
if (value) {
84
+ return 0;
268
set_bit(vq - 1, cpu->sve_vq_map);
269
} else {
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
+}
85
+}
377
+
86
+
378
+static int kvm_arm_sve_set_vls(CPUState *cs)
87
+static void QEMU_Elf_unmap(QEMU_Elf *qe)
379
+{
88
+{
380
+ uint64_t vls[KVM_ARM64_SVE_VLS_WORDS] = {0};
89
+#ifdef CONFIG_LINUX
381
+ struct kvm_one_reg reg = {
90
+ munmap(qe->map, qe->size);
382
+ .id = KVM_REG_ARM64_SVE_VLS,
91
+#else
383
+ .addr = (uint64_t)&vls[0],
92
+ g_mapped_file_unref(qe->gmf);
384
+ };
93
+#endif
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
+}
94
+}
401
+
95
+
402
#define ARM_CPU_ID_MPIDR 3, 0, 0, 0, 5
96
+int QEMU_Elf_init(QEMU_Elf *qe, const char *filename)
403
97
+{
404
int kvm_arch_init_vcpu(CPUState *cs)
98
+ if (QEMU_Elf_map(qe, filename)) {
405
@@ -XXX,XX +XXX,XX @@ int kvm_arch_init_vcpu(CPUState *cs)
99
+ return 1;
406
100
+ }
407
if (cpu->kvm_target == QEMU_KVM_ARM_TARGET_NONE ||
101
408
!object_dynamic_cast(OBJECT(cpu), TYPE_AARCH64_CPU)) {
102
if (!check_ehdr(qe)) {
409
- fprintf(stderr, "KVM is not supported for this guest CPU type\n");
103
eprintf("Input file has the wrong format\n");
410
+ error_report("KVM is not supported for this guest CPU type");
104
- err = 1;
411
return -EINVAL;
105
- goto out_unmap;
106
+ QEMU_Elf_unmap(qe);
107
+ return 1;
412
}
108
}
413
109
414
@@ -XXX,XX +XXX,XX @@ int kvm_arch_init_vcpu(CPUState *cs)
110
if (init_states(qe)) {
111
eprintf("Failed to extract QEMU CPU states\n");
112
- err = 1;
113
- goto out_unmap;
114
+ QEMU_Elf_unmap(qe);
115
+ return 1;
415
}
116
}
416
117
417
if (cpu_isar_feature(aa64_sve, cpu)) {
118
return 0;
418
+ ret = kvm_arm_sve_set_vls(cs);
119
-
419
+ if (ret) {
120
-out_unmap:
420
+ return ret;
121
- g_mapped_file_unref(qe->gmf);
421
+ }
122
-
422
ret = kvm_arm_vcpu_finalize(cs, KVM_ARM_VCPU_SVE);
123
- return err;
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
}
124
}
432
125
433
+static bool resp_get_feature(QDict *resp, const char *feature)
126
void QEMU_Elf_exit(QEMU_Elf *qe)
434
+{
127
{
435
+ QDict *props;
128
exit_states(qe);
436
+
129
- g_mapped_file_unref(qe->gmf);
437
+ g_assert(resp);
130
+ QEMU_Elf_unmap(qe);
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
}
131
}
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
--
132
--
648
2.20.1
133
2.34.1
649
650
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Viktor Prutyanov <viktor@daynix.com>
2
2
3
Hoist the computation of some TBFLAG_A32 bits that only apply to
3
PDB for Windows 11 kernel has slightly different structure compared to
4
M-profile under a single test for ARM_FEATURE_M.
4
previous versions. Since elf2dmp don't use the other fields, copy only
5
'segments' field from PDB_STREAM_INDEXES.
5
6
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Signed-off-by: Viktor Prutyanov <viktor@daynix.com>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Akihiko Odaki <akihiko.odaki@daynix.com>
8
Message-id: 20191023150057.25731-7-richard.henderson@linaro.org
9
Message-id: 20230915170153.10959-6-viktor@daynix.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 | 49 +++++++++++++++++++++------------------------
12
contrib/elf2dmp/pdb.h | 2 +-
12
1 file changed, 23 insertions(+), 26 deletions(-)
13
contrib/elf2dmp/pdb.c | 15 ++++-----------
14
2 files changed, 5 insertions(+), 12 deletions(-)
13
15
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
diff --git a/contrib/elf2dmp/pdb.h b/contrib/elf2dmp/pdb.h
15
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
18
--- a/contrib/elf2dmp/pdb.h
17
+++ b/target/arm/helper.c
19
+++ b/contrib/elf2dmp/pdb.h
18
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
20
@@ -XXX,XX +XXX,XX @@ struct pdb_reader {
19
21
} ds;
20
if (arm_feature(env, ARM_FEATURE_M)) {
22
uint32_t file_used[1024];
21
flags = rebuild_hflags_m32(env, fp_el, mmu_idx);
23
PDB_SYMBOLS *symbols;
22
+
24
- PDB_STREAM_INDEXES sidx;
23
+ if (arm_feature(env, ARM_FEATURE_M_SECURITY) &&
25
+ uint16_t segments;
24
+ FIELD_EX32(env->v7m.fpccr[M_REG_S], V7M_FPCCR, S)
26
uint8_t *modimage;
25
+ != env->v7m.secure) {
27
char *segs;
26
+ flags = FIELD_DP32(flags, TBFLAG_A32, FPCCR_S_WRONG, 1);
28
size_t segs_size;
27
+ }
29
diff --git a/contrib/elf2dmp/pdb.c b/contrib/elf2dmp/pdb.c
28
+
30
index XXXXXXX..XXXXXXX 100644
29
+ if ((env->v7m.fpccr[env->v7m.secure] & R_V7M_FPCCR_ASPEN_MASK) &&
31
--- a/contrib/elf2dmp/pdb.c
30
+ (!(env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK) ||
32
+++ b/contrib/elf2dmp/pdb.c
31
+ (env->v7m.secure &&
33
@@ -XXX,XX +XXX,XX @@ static void *pdb_ds_read_file(struct pdb_reader* r, uint32_t file_number)
32
+ !(env->v7m.control[M_REG_S] & R_V7M_CONTROL_SFPA_MASK)))) {
34
static int pdb_init_segments(struct pdb_reader *r)
33
+ /*
35
{
34
+ * ASPEN is set, but FPCA/SFPA indicate that there is no
36
char *segs;
35
+ * active FP context; we must create a new FP context before
37
- unsigned stream_idx = r->sidx.segments;
36
+ * executing any FP insn.
38
+ unsigned stream_idx = r->segments;
37
+ */
39
38
+ flags = FIELD_DP32(flags, TBFLAG_A32, NEW_FP_CTXT_NEEDED, 1);
40
segs = pdb_ds_read_file(r, stream_idx);
39
+ }
41
if (!segs) {
40
+
42
@@ -XXX,XX +XXX,XX @@ static int pdb_init_symbols(struct pdb_reader *r)
41
+ bool is_secure = env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_S_MASK;
43
{
42
+ if (env->v7m.fpccr[is_secure] & R_V7M_FPCCR_LSPACT_MASK) {
44
int err = 0;
43
+ flags = FIELD_DP32(flags, TBFLAG_A32, LSPACT, 1);
45
PDB_SYMBOLS *symbols;
44
+ }
46
- PDB_STREAM_INDEXES *sidx = &r->sidx;
45
} else {
47
-
46
flags = rebuild_hflags_common_32(env, fp_el, mmu_idx, 0);
48
- memset(sidx, -1, sizeof(*sidx));
47
}
49
48
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
50
symbols = pdb_ds_read_file(r, 3);
49
}
51
if (!symbols) {
50
}
52
@@ -XXX,XX +XXX,XX @@ static int pdb_init_symbols(struct pdb_reader *r)
51
53
52
- if (arm_feature(env, ARM_FEATURE_M_SECURITY) &&
54
r->symbols = symbols;
53
- FIELD_EX32(env->v7m.fpccr[M_REG_S], V7M_FPCCR, S) != env->v7m.secure) {
55
54
- flags = FIELD_DP32(flags, TBFLAG_A32, FPCCR_S_WRONG, 1);
56
- if (symbols->stream_index_size != sizeof(PDB_STREAM_INDEXES)) {
57
- err = 1;
58
- goto out_symbols;
55
- }
59
- }
56
-
60
-
57
- if (arm_feature(env, ARM_FEATURE_M) &&
61
- memcpy(sidx, (const char *)symbols + sizeof(PDB_SYMBOLS) +
58
- (env->v7m.fpccr[env->v7m.secure] & R_V7M_FPCCR_ASPEN_MASK) &&
62
+ r->segments = *(uint16_t *)((const char *)symbols + sizeof(PDB_SYMBOLS) +
59
- (!(env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK) ||
63
symbols->module_size + symbols->offset_size +
60
- (env->v7m.secure &&
64
symbols->hash_size + symbols->srcmodule_size +
61
- !(env->v7m.control[M_REG_S] & R_V7M_CONTROL_SFPA_MASK)))) {
65
- symbols->pdbimport_size + symbols->unknown2_size, sizeof(*sidx));
62
- /*
66
+ symbols->pdbimport_size + symbols->unknown2_size +
63
- * ASPEN is set, but FPCA/SFPA indicate that there is no active
67
+ offsetof(PDB_STREAM_INDEXES, segments));
64
- * FP context; we must create a new FP context before executing
68
65
- * any FP insn.
69
/* Read global symbol table */
66
- */
70
r->modimage = pdb_ds_read_file(r, symbols->gsym_file);
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
--
71
--
82
2.20.1
72
2.34.1
83
84
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
Create a function to compute the values of the TBFLAG_ANY bits
4
that will be cached, and are used by A-profile.
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-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
16
--- a/target/arm/helper.c
17
+++ b/target/arm/helper.c
18
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_m32(CPUARMState *env, int fp_el,
19
return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags);
20
}
21
22
+static uint32_t rebuild_hflags_aprofile(CPUARMState *env)
23
+{
24
+ int flags = 0;
25
+
26
+ flags = FIELD_DP32(flags, TBFLAG_ANY, DEBUG_TARGET_EL,
27
+ arm_debug_target_el(env));
28
+ return flags;
29
+}
30
+
31
static uint32_t rebuild_hflags_a32(CPUARMState *env, int fp_el,
32
ARMMMUIdx mmu_idx)
33
{
34
- return rebuild_hflags_common_32(env, fp_el, mmu_idx, 0);
35
+ uint32_t flags = rebuild_hflags_aprofile(env);
36
+ return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags);
37
}
38
39
static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
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
--
63
2.20.1
64
65
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
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
By performing this store early, we avoid having to save and restore
4
the register holding the address around any function calls.
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-15-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/helper.c | 2 +-
12
1 file changed, 1 insertion(+), 1 deletion(-)
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 @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
19
{
20
uint32_t flags, pstate_for_ss;
21
22
+ *cs_base = 0;
23
flags = rebuild_hflags_internal(env);
24
25
if (is_a64(env)) {
26
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
27
}
28
29
*pflags = flags;
30
- *cs_base = 0;
31
}
32
33
#ifdef TARGET_AARCH64
34
--
35
2.20.1
36
37
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
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>
8
Message-id: 20191023150057.25731-16-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/helper.h | 4 ++++
12
target/arm/helper.c | 24 ++++++++++++++++++++++++
13
2 files changed, 28 insertions(+)
14
15
diff --git a/target/arm/helper.h b/target/arm/helper.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.h
18
+++ b/target/arm/helper.h
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_4(msr_banked, void, env, i32, i32, i32)
20
DEF_HELPER_2(get_user_reg, i32, env, i32)
21
DEF_HELPER_3(set_user_reg, void, env, i32, i32)
22
23
+DEF_HELPER_FLAGS_2(rebuild_hflags_m32, TCG_CALL_NO_RWG, void, env, int)
24
+DEF_HELPER_FLAGS_2(rebuild_hflags_a32, TCG_CALL_NO_RWG, void, env, int)
25
+DEF_HELPER_FLAGS_2(rebuild_hflags_a64, TCG_CALL_NO_RWG, void, env, int)
26
+
27
DEF_HELPER_1(vfp_get_fpscr, i32, env)
28
DEF_HELPER_2(vfp_set_fpscr, void, env, i32)
29
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 @@ void arm_rebuild_hflags(CPUARMState *env)
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
--
66
2.20.1
67
68
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Begin setting, but not relying upon, env->hflags.
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-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
20
--- a/linux-user/syscall.c
21
+++ b/linux-user/syscall.c
22
@@ -XXX,XX +XXX,XX @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
23
aarch64_sve_narrow_vq(env, vq);
24
}
25
env->vfp.zcr_el[1] = vq - 1;
26
+ arm_rebuild_hflags(env);
27
ret = vq * 16;
28
}
29
return ret;
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
}
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
--
112
2.20.1
113
114
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Continue setting, but not relying upon, env->hflags.
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-18-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
target/arm/translate-a64.c | 13 +++++++++++--
11
target/arm/translate.c | 28 +++++++++++++++++++++++-----
12
2 files changed, 34 insertions(+), 7 deletions(-)
13
14
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/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,
19
if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
20
/* I/O operations must end the TB here (whether read or write) */
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
}
54
55
- if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
56
- /* I/O operations must end the TB here (whether read or write) */
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
}
86
87
--
88
2.20.1
89
90
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Continue setting, but not relying upon, env->hflags.
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-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
15
--- a/target/arm/op_helper.c
16
+++ b/target/arm/op_helper.c
17
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(usat16)(CPUARMState *env, uint32_t x, uint32_t shift)
18
void HELPER(setend)(CPUARMState *env)
19
{
20
env->uncached_cpsr ^= CPSR_E;
21
+ arm_rebuild_hflags(env);
22
}
23
24
/* Function checks whether WFx (WFI/WFE) instructions are set up to be trapped.
25
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(cpsr_read)(CPUARMState *env)
26
void HELPER(cpsr_write)(CPUARMState *env, uint32_t val, uint32_t mask)
27
{
28
cpsr_write(env, val, mask, CPSRWriteByInstr);
29
+ /* TODO: Not all cpsr bits are relevant to hflags. */
30
+ arm_rebuild_hflags(env);
31
}
32
33
/* Write the CPSR for a 32-bit exception return */
34
--
35
2.20.1
36
37
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Continue setting, but not relying upon, env->hflags.
4
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20191023150057.25731-20-richard.henderson@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
9
target/arm/helper.c | 10 ++++++++++
10
1 file changed, 10 insertions(+)
11
12
diff --git a/target/arm/helper.c b/target/arm/helper.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/helper.c
15
+++ b/target/arm/helper.c
16
@@ -XXX,XX +XXX,XX @@ static void sctlr_write(CPUARMState *env, const ARMCPRegInfo *ri,
17
/* ??? Lots of these bits are not implemented. */
18
/* This may enable/disable the MMU, so do a TLB flush. */
19
tlb_flush(CPU(cpu));
20
+
21
+ if (ri->type & ARM_CP_SUPPRESS_TB_END) {
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
+ }
30
}
31
32
static CPAccessResult fpexc32_access(CPUARMState *env, const ARMCPRegInfo *ri,
33
--
34
2.20.1
35
36
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Continue setting, but not relying upon, env->hflags.
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-21-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
target/arm/m_helper.c | 6 ++++++
11
target/arm/translate.c | 5 ++++-
12
2 files changed, 10 insertions(+), 1 deletion(-)
13
14
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/m_helper.c
17
+++ b/target/arm/m_helper.c
18
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_bxns)(CPUARMState *env, uint32_t dest)
19
switch_v7m_security_state(env, dest & 1);
20
env->thumb = 1;
21
env->regs[15] = dest & ~1;
22
+ arm_rebuild_hflags(env);
23
}
24
25
void HELPER(v7m_blxns)(CPUARMState *env, uint32_t dest)
26
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_blxns)(CPUARMState *env, uint32_t dest)
27
switch_v7m_security_state(env, 0);
28
env->thumb = 1;
29
env->regs[15] = dest;
30
+ arm_rebuild_hflags(env);
31
}
32
33
static uint32_t *get_v7m_sp_ptr(CPUARMState *env, bool secure, bool threadmode,
34
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
35
env->regs[14] = lr;
36
env->regs[15] = addr & 0xfffffffe;
37
env->thumb = addr & 1;
38
+ arm_rebuild_hflags(env);
39
}
40
41
static void v7m_update_fpccr(CPUARMState *env, uint32_t frameptr,
42
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
43
44
/* Otherwise, we have a successful exception exit. */
45
arm_clear_exclusive(env);
46
+ arm_rebuild_hflags(env);
47
qemu_log_mask(CPU_LOG_INT, "...successful exception return\n");
48
}
49
50
@@ -XXX,XX +XXX,XX @@ static bool do_v7m_function_return(ARMCPU *cpu)
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
{
74
- TCGv_i32 addr, reg;
75
+ TCGv_i32 addr, reg, el;
76
77
if (!arm_dc_feature(s, ARM_FEATURE_M)) {
78
return false;
79
@@ -XXX,XX +XXX,XX @@ static bool trans_MSR_v7m(DisasContext *s, arg_MSR_v7m *a)
80
gen_helper_v7m_msr(cpu_env, addr, reg);
81
tcg_temp_free_i32(addr);
82
tcg_temp_free_i32(reg);
83
+ el = tcg_const_i32(s->current_el);
84
+ gen_helper_rebuild_hflags_m32(cpu_env, el);
85
+ tcg_temp_free_i32(el);
86
gen_lookup_tb(s);
87
return true;
88
}
89
--
90
2.20.1
91
92
diff view generated by jsdifflib
Deleted patch
1
From: Andrew Jones <drjones@redhat.com>
2
1
3
Now that Arm CPUs have advertised features lets add tests to ensure
4
we maintain their expected availability with and without KVM.
5
6
Signed-off-by: Andrew Jones <drjones@redhat.com>
7
Reviewed-by: Eric Auger <eric.auger@redhat.com>
8
Message-id: 20191024121808.9612-3-drjones@redhat.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
tests/Makefile.include | 5 +-
12
tests/arm-cpu-features.c | 240 +++++++++++++++++++++++++++++++++++++++
13
2 files changed, 244 insertions(+), 1 deletion(-)
14
create mode 100644 tests/arm-cpu-features.c
15
16
diff --git a/tests/Makefile.include b/tests/Makefile.include
17
index XXXXXXX..XXXXXXX 100644
18
--- a/tests/Makefile.include
19
+++ b/tests/Makefile.include
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 @@
52
+/*
53
+ * Arm CPU feature test cases
54
+ *
55
+ * Copyright (c) 2019 Red Hat Inc.
56
+ * Authors:
57
+ * Andrew Jones <drjones@redhat.com>
58
+ *
59
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
60
+ * See the COPYING file in the top-level directory.
61
+ */
62
+#include "qemu/osdep.h"
63
+#include "libqtest.h"
64
+#include "qapi/qmp/qdict.h"
65
+#include "qapi/qmp/qjson.h"
66
+
67
+#define MACHINE "-machine virt,gic-version=max "
68
+#define QUERY_HEAD "{ 'execute': 'query-cpu-model-expansion', " \
69
+ "'arguments': { 'type': 'full', "
70
+#define QUERY_TAIL "}}"
71
+
72
+static QDict *do_query_no_props(QTestState *qts, const char *cpu_type)
73
+{
74
+ return qtest_qmp(qts, QUERY_HEAD "'model': { 'name': %s }"
75
+ QUERY_TAIL, cpu_type);
76
+}
77
+
78
+static QDict *do_query(QTestState *qts, const char *cpu_type,
79
+ const char *fmt, ...)
80
+{
81
+ QDict *resp;
82
+
83
+ if (fmt) {
84
+ QDict *args;
85
+ va_list ap;
86
+
87
+ va_start(ap, fmt);
88
+ args = qdict_from_vjsonf_nofail(fmt, ap);
89
+ va_end(ap);
90
+
91
+ resp = qtest_qmp(qts, QUERY_HEAD "'model': { 'name': %s, "
92
+ "'props': %p }"
93
+ QUERY_TAIL, cpu_type, args);
94
+ } else {
95
+ resp = do_query_no_props(qts, cpu_type);
96
+ }
97
+
98
+ return resp;
99
+}
100
+
101
+static const char *resp_get_error(QDict *resp)
102
+{
103
+ QDict *qdict;
104
+
105
+ g_assert(resp);
106
+
107
+ qdict = qdict_get_qdict(resp, "error");
108
+ if (qdict) {
109
+ return qdict_get_str(qdict, "desc");
110
+ }
111
+ return NULL;
112
+}
113
+
114
+#define assert_error(qts, cpu_type, expected_error, fmt, ...) \
115
+({ \
116
+ QDict *_resp; \
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
+ }
243
+
244
+ qtest_quit(qts);
245
+}
246
+
247
+static void test_query_cpu_model_expansion_kvm(const void *data)
248
+{
249
+ QTestState *qts;
250
+
251
+ qts = qtest_init(MACHINE "-accel kvm -cpu host");
252
+
253
+ if (g_str_equal(qtest_get_arch(), "aarch64")) {
254
+ assert_has_feature(qts, "host", "aarch64");
255
+ assert_has_feature(qts, "host", "pmu");
256
+
257
+ assert_error(qts, "cortex-a15",
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
--
293
2.20.1
294
295
diff view generated by jsdifflib
Deleted patch
1
From: Andrew Jones <drjones@redhat.com>
2
1
3
kvm_arm_create_scratch_host_vcpu() takes a struct kvm_vcpu_init
4
parameter. Rather than just using it as an output parameter to
5
pass back the preferred target, use it also as an input parameter,
6
allowing a caller to pass a selected target if they wish and to
7
also pass cpu features. If the caller doesn't want to select a
8
target they can pass -1 for the target which indicates they want
9
to use the preferred target and have it passed back like before.
10
11
Signed-off-by: Andrew Jones <drjones@redhat.com>
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
26
--- a/target/arm/kvm.c
27
+++ b/target/arm/kvm.c
28
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_create_scratch_host_vcpu(const uint32_t *cpus_to_try,
29
int *fdarray,
30
struct kvm_vcpu_init *init)
31
{
32
- int ret, kvmfd = -1, vmfd = -1, cpufd = -1;
33
+ int ret = 0, kvmfd = -1, vmfd = -1, cpufd = -1;
34
35
kvmfd = qemu_open("/dev/kvm", O_RDWR);
36
if (kvmfd < 0) {
37
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_create_scratch_host_vcpu(const uint32_t *cpus_to_try,
38
goto finish;
39
}
40
41
- ret = ioctl(vmfd, KVM_ARM_PREFERRED_TARGET, init);
42
+ if (init->target == -1) {
43
+ struct kvm_vcpu_init preferred;
44
+
45
+ ret = ioctl(vmfd, KVM_ARM_PREFERRED_TARGET, &preferred);
46
+ if (!ret) {
47
+ init->target = preferred.target;
48
+ }
49
+ }
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
+
59
while (*cpus_to_try != QEMU_KVM_ARM_TARGET_NONE) {
60
- init->target = *cpus_to_try++;
61
- memset(init->features, 0, sizeof(init->features));
62
- ret = ioctl(cpufd, KVM_ARM_VCPU_INIT, init);
63
+ try.target = *cpus_to_try++;
64
+ memcpy(try.features, init->features, sizeof(init->features));
65
+ ret = ioctl(cpufd, KVM_ARM_VCPU_INIT, &try);
66
if (ret >= 0) {
67
break;
68
}
69
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_create_scratch_host_vcpu(const uint32_t *cpus_to_try,
70
if (ret < 0) {
71
goto err;
72
}
73
+ init->target = try.target;
74
} else {
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
--
112
2.20.1
113
114
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
We will soon implement the SYS_timer. This timer is used by Linux
4
in the thermal subsystem, so once available, the subsystem will be
5
enabled and poll the temperature sensors. We need to provide the
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>
15
---
16
hw/misc/Makefile.objs | 1 +
17
include/hw/misc/bcm2835_thermal.h | 27 ++++++
18
hw/misc/bcm2835_thermal.c | 135 ++++++++++++++++++++++++++++++
19
3 files changed, 163 insertions(+)
20
create mode 100644 include/hw/misc/bcm2835_thermal.h
21
create mode 100644 hw/misc/bcm2835_thermal.c
22
23
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
24
index XXXXXXX..XXXXXXX 100644
25
--- a/hw/misc/Makefile.objs
26
+++ b/hw/misc/Makefile.objs
27
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_OMAP) += omap_tap.o
28
common-obj-$(CONFIG_RASPI) += bcm2835_mbox.o
29
common-obj-$(CONFIG_RASPI) += bcm2835_property.o
30
common-obj-$(CONFIG_RASPI) += bcm2835_rng.o
31
+common-obj-$(CONFIG_RASPI) += bcm2835_thermal.o
32
common-obj-$(CONFIG_SLAVIO) += slavio_misc.o
33
common-obj-$(CONFIG_ZYNQ) += zynq_slcr.o
34
common-obj-$(CONFIG_ZYNQ) += zynq-xadc.o
35
diff --git a/include/hw/misc/bcm2835_thermal.h b/include/hw/misc/bcm2835_thermal.h
36
new file mode 100644
37
index XXXXXXX..XXXXXXX
38
--- /dev/null
39
+++ b/include/hw/misc/bcm2835_thermal.h
40
@@ -XXX,XX +XXX,XX @@
41
+/*
42
+ * BCM2835 dummy thermal sensor
43
+ *
44
+ * Copyright (C) 2019 Philippe Mathieu-Daudé <f4bug@amsat.org>
45
+ *
46
+ * SPDX-License-Identifier: GPL-2.0-or-later
47
+ */
48
+
49
+#ifndef HW_MISC_BCM2835_THERMAL_H
50
+#define HW_MISC_BCM2835_THERMAL_H
51
+
52
+#include "hw/sysbus.h"
53
+
54
+#define TYPE_BCM2835_THERMAL "bcm2835-thermal"
55
+
56
+#define BCM2835_THERMAL(obj) \
57
+ OBJECT_CHECK(Bcm2835ThermalState, (obj), TYPE_BCM2835_THERMAL)
58
+
59
+typedef struct {
60
+ /*< private >*/
61
+ SysBusDevice parent_obj;
62
+ /*< public >*/
63
+ MemoryRegion iomem;
64
+ uint32_t ctl;
65
+} Bcm2835ThermalState;
66
+
67
+#endif
68
diff --git a/hw/misc/bcm2835_thermal.c b/hw/misc/bcm2835_thermal.c
69
new file mode 100644
70
index XXXXXXX..XXXXXXX
71
--- /dev/null
72
+++ b/hw/misc/bcm2835_thermal.c
73
@@ -XXX,XX +XXX,XX @@
74
+/*
75
+ * BCM2835 dummy thermal sensor
76
+ *
77
+ * Copyright (C) 2019 Philippe Mathieu-Daudé <f4bug@amsat.org>
78
+ *
79
+ * SPDX-License-Identifier: GPL-2.0-or-later
80
+ */
81
+
82
+#include "qemu/osdep.h"
83
+#include "qemu/log.h"
84
+#include "qapi/error.h"
85
+#include "hw/misc/bcm2835_thermal.h"
86
+#include "hw/registerfields.h"
87
+#include "migration/vmstate.h"
88
+
89
+REG32(CTL, 0)
90
+FIELD(CTL, POWER_DOWN, 0, 1)
91
+FIELD(CTL, RESET, 1, 1)
92
+FIELD(CTL, BANDGAP_CTRL, 2, 3)
93
+FIELD(CTL, INTERRUPT_ENABLE, 5, 1)
94
+FIELD(CTL, DIRECT, 6, 1)
95
+FIELD(CTL, INTERRUPT_CLEAR, 7, 1)
96
+FIELD(CTL, HOLD, 8, 10)
97
+FIELD(CTL, RESET_DELAY, 18, 8)
98
+FIELD(CTL, REGULATOR_ENABLE, 26, 1)
99
+
100
+REG32(STAT, 4)
101
+FIELD(STAT, DATA, 0, 10)
102
+FIELD(STAT, VALID, 10, 1)
103
+FIELD(STAT, INTERRUPT, 11, 1)
104
+
105
+#define THERMAL_OFFSET_C 412
106
+#define THERMAL_COEFF (-0.538f)
107
+
108
+static uint16_t bcm2835_thermal_temp2adc(int temp_C)
109
+{
110
+ return (temp_C - THERMAL_OFFSET_C) / THERMAL_COEFF;
111
+}
112
+
113
+static uint64_t bcm2835_thermal_read(void *opaque, hwaddr addr, unsigned size)
114
+{
115
+ Bcm2835ThermalState *s = BCM2835_THERMAL(opaque);
116
+ uint32_t val = 0;
117
+
118
+ switch (addr) {
119
+ case A_CTL:
120
+ val = s->ctl;
121
+ break;
122
+ case A_STAT:
123
+ /* Temperature is constantly 25°C. */
124
+ val = FIELD_DP32(bcm2835_thermal_temp2adc(25), STAT, VALID, true);
125
+ break;
126
+ default:
127
+ /* MemoryRegionOps are aligned, so this can not happen. */
128
+ g_assert_not_reached();
129
+ }
130
+ return val;
131
+}
132
+
133
+static void bcm2835_thermal_write(void *opaque, hwaddr addr,
134
+ uint64_t value, unsigned size)
135
+{
136
+ Bcm2835ThermalState *s = BCM2835_THERMAL(opaque);
137
+
138
+ switch (addr) {
139
+ case A_CTL:
140
+ s->ctl = value;
141
+ break;
142
+ case A_STAT:
143
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: write 0x%" PRIx64
144
+ " to 0x%" HWADDR_PRIx "\n",
145
+ __func__, value, addr);
146
+ break;
147
+ default:
148
+ /* MemoryRegionOps are aligned, so this can not happen. */
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,
157
+ .valid.min_access_size = 4,
158
+ .endianness = DEVICE_NATIVE_ENDIAN,
159
+};
160
+
161
+static void bcm2835_thermal_reset(DeviceState *dev)
162
+{
163
+ Bcm2835ThermalState *s = BCM2835_THERMAL(dev);
164
+
165
+ s->ctl = 0;
166
+}
167
+
168
+static void bcm2835_thermal_realize(DeviceState *dev, Error **errp)
169
+{
170
+ Bcm2835ThermalState *s = BCM2835_THERMAL(dev);
171
+
172
+ memory_region_init_io(&s->iomem, OBJECT(s), &bcm2835_thermal_ops,
173
+ s, TYPE_BCM2835_THERMAL, 8);
174
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
175
+}
176
+
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
+{
189
+ DeviceClass *dc = DEVICE_CLASS(klass);
190
+
191
+ dc->realize = bcm2835_thermal_realize;
192
+ dc->reset = bcm2835_thermal_reset;
193
+ dc->vmsd = &bcm2835_thermal_vmstate;
194
+}
195
+
196
+static const TypeInfo bcm2835_thermal_info = {
197
+ .name = TYPE_BCM2835_THERMAL,
198
+ .parent = TYPE_SYS_BUS_DEVICE,
199
+ .instance_size = sizeof(Bcm2835ThermalState),
200
+ .class_init = bcm2835_thermal_class_init,
201
+};
202
+
203
+static void bcm2835_thermal_register_types(void)
204
+{
205
+ type_register_static(&bcm2835_thermal_info);
206
+}
207
+
208
+type_init(bcm2835_thermal_register_types)
209
--
210
2.20.1
211
212
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
Map the thermal sensor in the BCM2835 block.
4
5
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
6
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20191019234715.25750-3-f4bug@amsat.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
include/hw/arm/bcm2835_peripherals.h | 2 ++
11
include/hw/arm/raspi_platform.h | 1 +
12
hw/arm/bcm2835_peripherals.c | 13 +++++++++++++
13
3 files changed, 16 insertions(+)
14
15
diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/arm/bcm2835_peripherals.h
18
+++ b/include/hw/arm/bcm2835_peripherals.h
19
@@ -XXX,XX +XXX,XX @@
20
#include "hw/misc/bcm2835_property.h"
21
#include "hw/misc/bcm2835_rng.h"
22
#include "hw/misc/bcm2835_mbox.h"
23
+#include "hw/misc/bcm2835_thermal.h"
24
#include "hw/sd/sdhci.h"
25
#include "hw/sd/bcm2835_sdhost.h"
26
#include "hw/gpio/bcm2835_gpio.h"
27
@@ -XXX,XX +XXX,XX @@ typedef struct BCM2835PeripheralState {
28
SDHCIState sdhci;
29
BCM2835SDHostState sdhost;
30
BCM2835GpioState gpio;
31
+ Bcm2835ThermalState thermal;
32
UnimplementedDeviceState i2s;
33
UnimplementedDeviceState spi[1];
34
UnimplementedDeviceState i2c[3];
35
diff --git a/include/hw/arm/raspi_platform.h b/include/hw/arm/raspi_platform.h
36
index XXXXXXX..XXXXXXX 100644
37
--- a/include/hw/arm/raspi_platform.h
38
+++ b/include/hw/arm/raspi_platform.h
39
@@ -XXX,XX +XXX,XX @@
40
#define SPI0_OFFSET 0x204000
41
#define BSC0_OFFSET 0x205000 /* BSC0 I2C/TWI */
42
#define OTP_OFFSET 0x20f000
43
+#define THERMAL_OFFSET 0x212000
44
#define BSC_SL_OFFSET 0x214000 /* SPI slave */
45
#define AUX_OFFSET 0x215000 /* AUX: UART1/SPI1/SPI2 */
46
#define EMMC1_OFFSET 0x300000
47
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/hw/arm/bcm2835_peripherals.c
50
+++ b/hw/arm/bcm2835_peripherals.c
51
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_init(Object *obj)
52
object_property_add_const_link(OBJECT(&s->dma), "dma-mr",
53
OBJECT(&s->gpu_bus_mr), &error_abort);
54
55
+ /* Thermal */
56
+ sysbus_init_child_obj(obj, "thermal", &s->thermal, sizeof(s->thermal),
57
+ TYPE_BCM2835_THERMAL);
58
+
59
/* GPIO */
60
sysbus_init_child_obj(obj, "gpio", &s->gpio, sizeof(s->gpio),
61
TYPE_BCM2835_GPIO);
62
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
63
INTERRUPT_DMA0 + n));
64
}
65
66
+ /* THERMAL */
67
+ object_property_set_bool(OBJECT(&s->thermal), true, "realized", &err);
68
+ if (err) {
69
+ error_propagate(errp, err);
70
+ return;
71
+ }
72
+ memory_region_add_subregion(&s->peri_mr, THERMAL_OFFSET,
73
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->thermal), 0));
74
+
75
/* GPIO */
76
object_property_set_bool(OBJECT(&s->gpio), true, "realized", &err);
77
if (err) {
78
--
79
2.20.1
80
81
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
Add the 64-bit free running timer. Do not model the COMPARE register
4
(no IRQ generated).
5
This timer is used by Linux kernel and recently U-Boot:
6
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/clocksource/bcm2835_timer.c?h=v3.7
7
https://github.com/u-boot/u-boot/blob/v2019.07/include/configs/rpi.h#L19
8
9
Datasheet used:
10
https://www.raspberrypi.org/app/uploads/2012/02/BCM2835-ARM-Peripherals.pdf
11
12
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
14
Message-id: 20191019234715.25750-4-f4bug@amsat.org
15
[PMM: squashed in switch to using memset in reset]
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
hw/timer/Makefile.objs | 1 +
19
include/hw/timer/bcm2835_systmr.h | 33 ++++++
20
hw/timer/bcm2835_systmr.c | 163 ++++++++++++++++++++++++++++++
21
hw/timer/trace-events | 5 +
22
4 files changed, 202 insertions(+)
23
create mode 100644 include/hw/timer/bcm2835_systmr.h
24
create mode 100644 hw/timer/bcm2835_systmr.c
25
26
diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs
27
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/timer/Makefile.objs
29
+++ b/hw/timer/Makefile.objs
30
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_SUN4V_RTC) += sun4v-rtc.o
31
common-obj-$(CONFIG_CMSDK_APB_TIMER) += cmsdk-apb-timer.o
32
common-obj-$(CONFIG_CMSDK_APB_DUALTIMER) += cmsdk-apb-dualtimer.o
33
common-obj-$(CONFIG_MSF2) += mss-timer.o
34
+common-obj-$(CONFIG_RASPI) += bcm2835_systmr.o
35
diff --git a/include/hw/timer/bcm2835_systmr.h b/include/hw/timer/bcm2835_systmr.h
36
new file mode 100644
37
index XXXXXXX..XXXXXXX
38
--- /dev/null
39
+++ b/include/hw/timer/bcm2835_systmr.h
40
@@ -XXX,XX +XXX,XX @@
41
+/*
42
+ * BCM2835 SYS timer emulation
43
+ *
44
+ * Copyright (c) 2019 Philippe Mathieu-Daudé <f4bug@amsat.org>
45
+ *
46
+ * SPDX-License-Identifier: GPL-2.0-or-later
47
+ */
48
+
49
+#ifndef BCM2835_SYSTIMER_H
50
+#define BCM2835_SYSTIMER_H
51
+
52
+#include "hw/sysbus.h"
53
+#include "hw/irq.h"
54
+
55
+#define TYPE_BCM2835_SYSTIMER "bcm2835-sys-timer"
56
+#define BCM2835_SYSTIMER(obj) \
57
+ OBJECT_CHECK(BCM2835SystemTimerState, (obj), TYPE_BCM2835_SYSTIMER)
58
+
59
+typedef struct {
60
+ /*< private >*/
61
+ SysBusDevice parent_obj;
62
+
63
+ /*< public >*/
64
+ MemoryRegion iomem;
65
+ qemu_irq irq;
66
+
67
+ struct {
68
+ uint32_t status;
69
+ uint32_t compare[4];
70
+ } reg;
71
+} BCM2835SystemTimerState;
72
+
73
+#endif
74
diff --git a/hw/timer/bcm2835_systmr.c b/hw/timer/bcm2835_systmr.c
75
new file mode 100644
76
index XXXXXXX..XXXXXXX
77
--- /dev/null
78
+++ b/hw/timer/bcm2835_systmr.c
79
@@ -XXX,XX +XXX,XX @@
80
+/*
81
+ * BCM2835 SYS timer emulation
82
+ *
83
+ * Copyright (C) 2019 Philippe Mathieu-Daudé <f4bug@amsat.org>
84
+ *
85
+ * SPDX-License-Identifier: GPL-2.0-or-later
86
+ *
87
+ * Datasheet: BCM2835 ARM Peripherals (C6357-M-1398)
88
+ * https://www.raspberrypi.org/app/uploads/2012/02/BCM2835-ARM-Peripherals.pdf
89
+ *
90
+ * Only the free running 64-bit counter is implemented.
91
+ * The 4 COMPARE registers and the interruption are not implemented.
92
+ */
93
+
94
+#include "qemu/osdep.h"
95
+#include "qemu/log.h"
96
+#include "qemu/timer.h"
97
+#include "hw/timer/bcm2835_systmr.h"
98
+#include "hw/registerfields.h"
99
+#include "migration/vmstate.h"
100
+#include "trace.h"
101
+
102
+REG32(CTRL_STATUS, 0x00)
103
+REG32(COUNTER_LOW, 0x04)
104
+REG32(COUNTER_HIGH, 0x08)
105
+REG32(COMPARE0, 0x0c)
106
+REG32(COMPARE1, 0x10)
107
+REG32(COMPARE2, 0x14)
108
+REG32(COMPARE3, 0x18)
109
+
110
+static void bcm2835_systmr_update_irq(BCM2835SystemTimerState *s)
111
+{
112
+ bool enable = !!s->reg.status;
113
+
114
+ trace_bcm2835_systmr_irq(enable);
115
+ qemu_set_irq(s->irq, enable);
116
+}
117
+
118
+static void bcm2835_systmr_update_compare(BCM2835SystemTimerState *s,
119
+ unsigned timer_index)
120
+{
121
+ /* TODO fow now, since neither Linux nor U-boot use these timers. */
122
+ qemu_log_mask(LOG_UNIMP, "COMPARE register %u not implemented\n",
123
+ timer_index);
124
+}
125
+
126
+static uint64_t bcm2835_systmr_read(void *opaque, hwaddr offset,
127
+ unsigned size)
128
+{
129
+ BCM2835SystemTimerState *s = BCM2835_SYSTIMER(opaque);
130
+ uint64_t r = 0;
131
+
132
+ switch (offset) {
133
+ case A_CTRL_STATUS:
134
+ r = s->reg.status;
135
+ break;
136
+ case A_COMPARE0 ... A_COMPARE3:
137
+ r = s->reg.compare[(offset - A_COMPARE0) >> 2];
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;
146
+ default:
147
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: bad offset 0x%" HWADDR_PRIx "\n",
148
+ __func__, offset);
149
+ break;
150
+ }
151
+ trace_bcm2835_systmr_read(offset, r);
152
+
153
+ return r;
154
+}
155
+
156
+static void bcm2835_systmr_write(void *opaque, hwaddr offset,
157
+ uint64_t value, unsigned size)
158
+{
159
+ BCM2835SystemTimerState *s = BCM2835_SYSTIMER(opaque);
160
+
161
+ trace_bcm2835_systmr_write(offset, value);
162
+ switch (offset) {
163
+ case A_CTRL_STATUS:
164
+ s->reg.status &= ~value; /* Ack */
165
+ bcm2835_systmr_update_irq(s);
166
+ break;
167
+ case A_COMPARE0 ... A_COMPARE3:
168
+ s->reg.compare[(offset - A_COMPARE0) >> 2] = value;
169
+ bcm2835_systmr_update_compare(s, (offset - A_COMPARE0) >> 2);
170
+ break;
171
+ case A_COUNTER_LOW:
172
+ case A_COUNTER_HIGH:
173
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: read-only ofs 0x%" HWADDR_PRIx "\n",
174
+ __func__, offset);
175
+ break;
176
+ default:
177
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: bad offset 0x%" HWADDR_PRIx "\n",
178
+ __func__, offset);
179
+ break;
180
+ }
181
+}
182
+
183
+static const MemoryRegionOps bcm2835_systmr_ops = {
184
+ .read = bcm2835_systmr_read,
185
+ .write = bcm2835_systmr_write,
186
+ .endianness = DEVICE_LITTLE_ENDIAN,
187
+ .impl = {
188
+ .min_access_size = 4,
189
+ .max_access_size = 4,
190
+ },
191
+};
192
+
193
+static void bcm2835_systmr_reset(DeviceState *dev)
194
+{
195
+ BCM2835SystemTimerState *s = BCM2835_SYSTIMER(dev);
196
+
197
+ memset(&s->reg, 0, sizeof(s->reg));
198
+}
199
+
200
+static void bcm2835_systmr_realize(DeviceState *dev, Error **errp)
201
+{
202
+ BCM2835SystemTimerState *s = BCM2835_SYSTIMER(dev);
203
+
204
+ memory_region_init_io(&s->iomem, OBJECT(dev), &bcm2835_systmr_ops,
205
+ s, "bcm2835-sys-timer", 0x20);
206
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
207
+ sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq);
208
+}
209
+
210
+static const VMStateDescription bcm2835_systmr_vmstate = {
211
+ .name = "bcm2835_sys_timer",
212
+ .version_id = 1,
213
+ .minimum_version_id = 1,
214
+ .fields = (VMStateField[]) {
215
+ VMSTATE_UINT32(reg.status, BCM2835SystemTimerState),
216
+ VMSTATE_UINT32_ARRAY(reg.compare, BCM2835SystemTimerState, 4),
217
+ VMSTATE_END_OF_LIST()
218
+ }
219
+};
220
+
221
+static void bcm2835_systmr_class_init(ObjectClass *klass, void *data)
222
+{
223
+ DeviceClass *dc = DEVICE_CLASS(klass);
224
+
225
+ dc->realize = bcm2835_systmr_realize;
226
+ dc->reset = bcm2835_systmr_reset;
227
+ dc->vmsd = &bcm2835_systmr_vmstate;
228
+}
229
+
230
+static const TypeInfo bcm2835_systmr_info = {
231
+ .name = TYPE_BCM2835_SYSTIMER,
232
+ .parent = TYPE_SYS_BUS_DEVICE,
233
+ .instance_size = sizeof(BCM2835SystemTimerState),
234
+ .class_init = bcm2835_systmr_class_init,
235
+};
236
+
237
+static void bcm2835_systmr_register_types(void)
238
+{
239
+ type_register_static(&bcm2835_systmr_info);
240
+}
241
+
242
+type_init(bcm2835_systmr_register_types);
243
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
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
--
257
2.20.1
258
259
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
Connect the recently added SYS_timer.
4
Now U-Boot does not hang anymore polling a free running counter
5
stuck at 0.
6
This timer is also used by the Linux kernel thermal subsystem.
7
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
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
19
--- a/include/hw/arm/bcm2835_peripherals.h
20
+++ b/include/hw/arm/bcm2835_peripherals.h
21
@@ -XXX,XX +XXX,XX @@
22
#include "hw/sd/sdhci.h"
23
#include "hw/sd/bcm2835_sdhost.h"
24
#include "hw/gpio/bcm2835_gpio.h"
25
+#include "hw/timer/bcm2835_systmr.h"
26
#include "hw/misc/unimp.h"
27
28
#define TYPE_BCM2835_PERIPHERALS "bcm2835-peripherals"
29
@@ -XXX,XX +XXX,XX @@ typedef struct BCM2835PeripheralState {
30
MemoryRegion ram_alias[4];
31
qemu_irq irq, fiq;
32
33
- UnimplementedDeviceState systmr;
34
+ BCM2835SystemTimerState systmr;
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;
62
+ }
63
+ memory_region_add_subregion(&s->peri_mr, ST_OFFSET,
64
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->systmr), 0));
65
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->systmr), 0,
66
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_ARM_IRQ,
67
+ INTERRUPT_ARM_TIMER));
68
+
69
/* UART0 */
70
qdev_prop_set_chr(DEVICE(&s->uart0), "chardev", serial_hd(0));
71
object_property_set_bool(OBJECT(&s->uart0), true, "realized", &err);
72
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
73
}
74
75
create_unimp(s, &s->armtmr, "bcm2835-sp804", ARMCTRL_TIMER0_1_OFFSET, 0x40);
76
- create_unimp(s, &s->systmr, "bcm2835-systimer", ST_OFFSET, 0x20);
77
create_unimp(s, &s->cprman, "bcm2835-cprman", CPRMAN_OFFSET, 0x1000);
78
create_unimp(s, &s->a2w, "bcm2835-a2w", A2W_OFFSET, 0x1000);
79
create_unimp(s, &s->i2s, "bcm2835-i2s", I2S_OFFSET, 0x100);
80
--
81
2.20.1
82
83
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
This file creates the BCM2836/BCM2837 blocks.
4
The biggest differences with the BCM2838 we are going to add, are
5
the base addresses of the interrupt controller and the peripherals.
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
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>
15
---
16
hw/arm/bcm2836.c | 18 +++++++++---------
17
1 file changed, 9 insertions(+), 9 deletions(-)
18
19
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/arm/bcm2836.c
22
+++ b/hw/arm/bcm2836.c
23
@@ -XXX,XX +XXX,XX @@
24
#include "hw/arm/raspi_platform.h"
25
#include "hw/sysbus.h"
26
27
-/* Peripheral base address seen by the CPU */
28
-#define BCM2836_PERI_BASE 0x3F000000
29
-
30
-/* "QA7" (Pi2) interrupt controller and mailboxes etc. */
31
-#define BCM2836_CONTROL_BASE 0x40000000
32
-
33
struct BCM283XInfo {
34
const char *name;
35
const char *cpu_type;
36
+ hwaddr peri_base; /* Peripheral base address seen by the CPU */
37
+ hwaddr ctrl_base; /* Interrupt controller and mailboxes etc. */
38
int clusterid;
39
};
40
41
@@ -XXX,XX +XXX,XX @@ static const BCM283XInfo bcm283x_socs[] = {
42
{
43
.name = TYPE_BCM2836,
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;
69
}
70
71
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->control), 0, BCM2836_CONTROL_BASE);
72
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->control), 0, info->ctrl_base);
73
74
sysbus_connect_irq(SYS_BUS_DEVICE(&s->peripherals), 0,
75
qdev_get_gpio_in_named(DEVICE(&s->control), "gpu-irq", 0));
76
@@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
77
78
/* set periphbase/CBAR value for CPU-local registers */
79
object_property_set_int(OBJECT(&s->cpus[n]),
80
- BCM2836_PERI_BASE + MSYNC_OFFSET,
81
+ info->peri_base,
82
"reset-cbar", &err);
83
if (err) {
84
error_propagate(errp, err);
85
--
86
2.20.1
87
88
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
write_secondary_boot() is used in SMP configurations where the
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>
13
---
14
hw/arm/highbank.c | 3 ++-
15
1 file changed, 2 insertions(+), 1 deletion(-)
16
17
diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/highbank.c
20
+++ b/hw/arm/highbank.c
21
@@ -XXX,XX +XXX,XX @@ static void hb_write_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
22
for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
23
smpboot[n] = tswap32(smpboot[n]);
24
}
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
--
32
2.20.1
33
34
diff view generated by jsdifflib