1
target-arm queue: the big things in here are SVE in system
1
The following changes since commit 7e7eb9f852a46b51a71ae9d82590b2e4d28827ee:
2
emulation mode, and v8M stack limit checking; there are
3
also a handful of smaller fixes.
4
2
5
thanks
3
Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2021-01-28' into staging (2021-01-28 22:43:18 +0000)
6
-- PMM
7
8
The following changes since commit 079911cb6e26898e16f5bb56ef4f9d33cf92d32d:
9
10
Merge remote-tracking branch 'remotes/rth/tags/pull-fpu-20181005' into staging (2018-10-08 12:44:35 +0100)
11
4
12
are available in the Git repository at:
5
are available in the Git repository at:
13
6
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20181008
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210129
15
8
16
for you to fetch changes up to 74e2e59b8d0a68be0956310fc349179c89fd7be0:
9
for you to fetch changes up to 11749122e1a86866591306d43603d2795a3dea1a:
17
10
18
hw/display/bcm2835_fb: Silence Coverity warning about multiply overflow (2018-10-08 14:55:05 +0100)
11
hw/arm/stellaris: Remove board-creation reset of STELLARIS_SYS (2021-01-29 10:47:29 +0000)
19
12
20
----------------------------------------------------------------
13
----------------------------------------------------------------
21
target-arm queue:
14
target-arm queue:
22
* target/arm: fix error in a code comment
15
* Implement ID_PFR2
23
* virt: Suppress external aborts on virt-2.10 and earlier
16
* Conditionalize DBGDIDR
24
* target/arm: Correct condition for v8M callee stack push
17
* rename xlnx-zcu102.canbusN properties
25
* target/arm: Don't read r4 from v8M exception stackframe twice
18
* provide powerdown/reset mechanism for secure firmware on 'virt' board
26
* target/arm: Support SVE in system emulation mode
19
* hw/misc: Fix arith overflow in NPCM7XX PWM module
27
* target/arm: Implement v8M hardware stack limit checking
20
* target/arm: Replace magic value by MMU_DATA_LOAD definition
28
* hw/display/bcm2835_fb: Silence Coverity warning about multiply overflow
21
* configure: fix preadv errors on Catalina macOS with new XCode
22
* Various configure and other cleanups in preparation for iOS support
23
* hvf: Add hypervisor entitlement to output binaries (needed for Big Sur)
24
* Implement pvpanic-pci device
25
* Convert the CMSDK timer devices to the Clock framework
29
26
30
----------------------------------------------------------------
27
----------------------------------------------------------------
31
Dongjiu Geng (1):
28
Alexander Graf (1):
32
target/arm: fix code comments error
29
hvf: Add hypervisor entitlement to output binaries
33
30
34
Peter Maydell (17):
31
Hao Wu (1):
35
virt: Suppress external aborts on virt-2.10 and earlier
32
hw/misc: Fix arith overflow in NPCM7XX PWM module
36
target/arm: Correct condition for v8M callee stack push
37
target/arm: Don't read r4 from v8M exception stackframe twice
38
target/arm: Define new TBFLAG for v8M stack checking
39
target/arm: Define new EXCP type for v8M stack overflows
40
target/arm: Move v7m_using_psp() to internals.h
41
target/arm: Add v8M stack checks on ADD/SUB/MOV of SP
42
target/arm: Add some comments in Thumb decode
43
target/arm: Add v8M stack checks on exception entry
44
target/arm: Add v8M stack limit checks on NS function calls
45
target/arm: Add v8M stack checks for LDRD/STRD (imm)
46
target/arm: Add v8M stack checks for Thumb2 LDM/STM
47
target/arm: Add v8M stack checks for T32 load/store single
48
target/arm: Add v8M stack checks for Thumb push/pop
49
target/arm: Add v8M stack checks for VLDM/VSTM
50
target/arm: Add v8M stack checks for MSR to SP_NS
51
hw/display/bcm2835_fb: Silence Coverity warning about multiply overflow
52
33
53
Richard Henderson (15):
34
Joelle van Dyne (7):
54
target/arm: Define ID_AA64ZFR0_EL1
35
configure: cross-compiling with empty cross_prefix
55
target/arm: Adjust sve_exception_el
36
osdep: build with non-working system() function
56
target/arm: Pass in current_el to fp and sve_exception_el
37
darwin: remove redundant dependency declaration
57
target/arm: Handle SVE vector length changes in system mode
38
darwin: fix cross-compiling for Darwin
58
target/arm: Adjust aarch64_cpu_dump_state for system mode SVE
39
configure: cross compile should use x86_64 cpu_family
59
target/arm: Clear unused predicate bits for LD1RQ
40
darwin: detect CoreAudio for build
60
target/arm: Rewrite helper_sve_ld1*_r using pages
41
darwin: remove 64-bit build detection on 32-bit OS
61
target/arm: Rewrite helper_sve_ld[234]*_r
62
target/arm: Rewrite helper_sve_st[1234]*_r
63
target/arm: Split contiguous loads for endianness
64
target/arm: Split contiguous stores for endianness
65
target/arm: Rewrite vector gather loads
66
target/arm: Rewrite vector gather stores
67
target/arm: Rewrite vector gather first-fault loads
68
target/arm: Pass TCGMemOpIdx to sve memory helpers
69
42
70
target/arm/cpu.h | 17 +
43
Maxim Uvarov (3):
71
target/arm/helper-sve.h | 385 ++++++---
44
hw: gpio: implement gpio-pwr driver for qemu reset/poweroff
72
target/arm/helper.h | 2 +
45
arm-virt: refactor gpios creation
73
target/arm/internals.h | 44 +
46
arm-virt: add secure pl061 for reset/power down
74
target/arm/kvm_arm.h | 4 +-
75
target/arm/translate.h | 1 +
76
hw/arm/virt.c | 2 +
77
hw/display/bcm2835_fb.c | 2 +-
78
target/arm/cpu64.c | 42 -
79
target/arm/helper.c | 345 +++++---
80
target/arm/kvm.c | 2 +-
81
target/arm/op_helper.c | 24 +-
82
target/arm/sve_helper.c | 1961 ++++++++++++++++++++++++++++++--------------
83
target/arm/translate-a64.c | 8 +-
84
target/arm/translate-sve.c | 670 ++++++++++-----
85
target/arm/translate.c | 198 ++++-
86
16 files changed, 2611 insertions(+), 1096 deletions(-)
87
47
48
Mihai Carabas (4):
49
hw/misc/pvpanic: split-out generic and bus dependent code
50
hw/misc/pvpanic: add PCI interface support
51
pvpanic : update pvpanic spec document
52
tests/qtest: add a test case for pvpanic-pci
53
54
Paolo Bonzini (1):
55
arm: rename xlnx-zcu102.canbusN properties
56
57
Peter Maydell (26):
58
configure: Move preadv check to meson.build
59
ptimer: Add new ptimer_set_period_from_clock() function
60
clock: Add new clock_has_source() function
61
tests: Add a simple test of the CMSDK APB timer
62
tests: Add a simple test of the CMSDK APB watchdog
63
tests: Add a simple test of the CMSDK APB dual timer
64
hw/timer/cmsdk-apb-timer: Rename CMSDKAPBTIMER struct to CMSDKAPBTimer
65
hw/timer/cmsdk-apb-timer: Add Clock input
66
hw/timer/cmsdk-apb-dualtimer: Add Clock input
67
hw/watchdog/cmsdk-apb-watchdog: Add Clock input
68
hw/arm/armsse: Rename "MAINCLK" property to "MAINCLK_FRQ"
69
hw/arm/armsse: Wire up clocks
70
hw/arm/mps2: Inline CMSDK_APB_TIMER creation
71
hw/arm/mps2: Create and connect SYSCLK Clock
72
hw/arm/mps2-tz: Create and connect ARMSSE Clocks
73
hw/arm/musca: Create and connect ARMSSE Clocks
74
hw/arm/stellaris: Convert SSYS to QOM device
75
hw/arm/stellaris: Create Clock input for watchdog
76
hw/timer/cmsdk-apb-timer: Convert to use Clock input
77
hw/timer/cmsdk-apb-dualtimer: Convert to use Clock input
78
hw/watchdog/cmsdk-apb-watchdog: Convert to use Clock input
79
tests/qtest/cmsdk-apb-watchdog-test: Test clock changes
80
hw/arm/armsse: Use Clock to set system_clock_scale
81
arm: Don't set freq properties on CMSDK timer, dualtimer, watchdog, ARMSSE
82
arm: Remove frq properties on CMSDK timer, dualtimer, watchdog, ARMSSE
83
hw/arm/stellaris: Remove board-creation reset of STELLARIS_SYS
84
85
Philippe Mathieu-Daudé (1):
86
target/arm: Replace magic value by MMU_DATA_LOAD definition
87
88
Richard Henderson (2):
89
target/arm: Implement ID_PFR2
90
target/arm: Conditionalize DBGDIDR
91
92
docs/devel/clocks.rst | 16 +++
93
docs/specs/pci-ids.txt | 1 +
94
docs/specs/pvpanic.txt | 13 ++-
95
docs/system/arm/virt.rst | 2 +
96
configure | 78 ++++++++------
97
meson.build | 34 ++++++-
98
include/hw/arm/armsse.h | 14 ++-
99
include/hw/arm/virt.h | 2 +
100
include/hw/clock.h | 15 +++
101
include/hw/misc/pvpanic.h | 24 ++++-
102
include/hw/pci/pci.h | 1 +
103
include/hw/ptimer.h | 22 ++++
104
include/hw/timer/cmsdk-apb-dualtimer.h | 5 +-
105
include/hw/timer/cmsdk-apb-timer.h | 34 ++-----
106
include/hw/watchdog/cmsdk-apb-watchdog.h | 5 +-
107
include/qemu/osdep.h | 12 +++
108
include/qemu/typedefs.h | 1 +
109
target/arm/cpu.h | 1 +
110
hw/arm/armsse.c | 48 ++++++---
111
hw/arm/mps2-tz.c | 14 ++-
112
hw/arm/mps2.c | 28 ++++-
113
hw/arm/musca.c | 13 ++-
114
hw/arm/stellaris.c | 170 +++++++++++++++++++++++--------
115
hw/arm/virt.c | 111 ++++++++++++++++----
116
hw/arm/xlnx-zcu102.c | 4 +-
117
hw/core/ptimer.c | 34 +++++++
118
hw/gpio/gpio_pwr.c | 70 +++++++++++++
119
hw/misc/npcm7xx_pwm.c | 23 ++++-
120
hw/misc/pvpanic-isa.c | 94 +++++++++++++++++
121
hw/misc/pvpanic-pci.c | 94 +++++++++++++++++
122
hw/misc/pvpanic.c | 85 ++--------------
123
hw/timer/cmsdk-apb-dualtimer.c | 53 +++++++---
124
hw/timer/cmsdk-apb-timer.c | 55 +++++-----
125
hw/watchdog/cmsdk-apb-watchdog.c | 29 ++++--
126
target/arm/helper.c | 27 +++--
127
target/arm/kvm64.c | 2 +
128
tests/qtest/cmsdk-apb-dualtimer-test.c | 130 +++++++++++++++++++++++
129
tests/qtest/cmsdk-apb-timer-test.c | 75 ++++++++++++++
130
tests/qtest/cmsdk-apb-watchdog-test.c | 131 ++++++++++++++++++++++++
131
tests/qtest/npcm7xx_pwm-test.c | 4 +-
132
tests/qtest/pvpanic-pci-test.c | 94 +++++++++++++++++
133
tests/qtest/xlnx-can-test.c | 30 +++---
134
MAINTAINERS | 3 +
135
accel/hvf/entitlements.plist | 8 ++
136
hw/arm/Kconfig | 1 +
137
hw/gpio/Kconfig | 3 +
138
hw/gpio/meson.build | 1 +
139
hw/i386/Kconfig | 2 +-
140
hw/misc/Kconfig | 12 ++-
141
hw/misc/meson.build | 4 +-
142
scripts/entitlement.sh | 13 +++
143
tests/qtest/meson.build | 6 +-
144
52 files changed, 1432 insertions(+), 319 deletions(-)
145
create mode 100644 hw/gpio/gpio_pwr.c
146
create mode 100644 hw/misc/pvpanic-isa.c
147
create mode 100644 hw/misc/pvpanic-pci.c
148
create mode 100644 tests/qtest/cmsdk-apb-dualtimer-test.c
149
create mode 100644 tests/qtest/cmsdk-apb-timer-test.c
150
create mode 100644 tests/qtest/cmsdk-apb-watchdog-test.c
151
create mode 100644 tests/qtest/pvpanic-pci-test.c
152
create mode 100644 accel/hvf/entitlements.plist
153
create mode 100755 scripts/entitlement.sh
154
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Use the existing helpers to determine if (1) the fpu is enabled,
3
This was defined at some point before ARMv8.4, and will
4
(2) sve state is enabled, and (3) the current sve vector length.
4
shortly be used by new processor descriptions.
5
5
6
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20181005175350.30752-6-richard.henderson@linaro.org
8
Message-id: 20210120204400.1056582-1-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
10
---
12
target/arm/cpu.h | 4 ++++
11
target/arm/cpu.h | 1 +
13
target/arm/helper.c | 6 +++---
12
target/arm/helper.c | 4 ++--
14
target/arm/translate-a64.c | 8 ++++++--
13
target/arm/kvm64.c | 2 ++
15
3 files changed, 13 insertions(+), 5 deletions(-)
14
3 files changed, 5 insertions(+), 2 deletions(-)
16
15
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
18
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/cpu.h
18
--- a/target/arm/cpu.h
20
+++ b/target/arm/cpu.h
19
+++ b/target/arm/cpu.h
21
@@ -XXX,XX +XXX,XX @@ target_ulong do_arm_semihosting(CPUARMState *env);
20
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
22
void aarch64_sync_32_to_64(CPUARMState *env);
21
uint32_t id_mmfr4;
23
void aarch64_sync_64_to_32(CPUARMState *env);
22
uint32_t id_pfr0;
24
23
uint32_t id_pfr1;
25
+int fp_exception_el(CPUARMState *env, int cur_el);
24
+ uint32_t id_pfr2;
26
+int sve_exception_el(CPUARMState *env, int cur_el);
25
uint32_t mvfr0;
27
+uint32_t sve_zcr_len_for_el(CPUARMState *env, int el);
26
uint32_t mvfr1;
28
+
27
uint32_t mvfr2;
29
static inline bool is_a64(CPUARMState *env)
30
{
31
return env->aarch64;
32
diff --git a/target/arm/helper.c b/target/arm/helper.c
28
diff --git a/target/arm/helper.c b/target/arm/helper.c
33
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/helper.c
30
--- a/target/arm/helper.c
35
+++ b/target/arm/helper.c
31
+++ b/target/arm/helper.c
36
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo debug_lpae_cp_reginfo[] = {
32
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
37
* take care of raising that exception.
33
.access = PL1_R, .type = ARM_CP_CONST,
38
* C.f. the ARM pseudocode function CheckSVEEnabled.
34
.accessfn = access_aa64_tid3,
39
*/
35
.resetvalue = 0 },
40
-static int sve_exception_el(CPUARMState *env, int el)
36
- { .name = "MVFR4_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
41
+int sve_exception_el(CPUARMState *env, int el)
37
+ { .name = "ID_PFR2", .state = ARM_CP_STATE_BOTH,
42
{
38
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 4,
43
#ifndef CONFIG_USER_ONLY
39
.access = PL1_R, .type = ARM_CP_CONST,
44
if (el <= 1) {
40
.accessfn = access_aa64_tid3,
45
@@ -XXX,XX +XXX,XX @@ static int sve_exception_el(CPUARMState *env, int el)
41
- .resetvalue = 0 },
46
/*
42
+ .resetvalue = cpu->isar.id_pfr2 },
47
* Given that SVE is enabled, return the vector length for EL.
43
{ .name = "MVFR5_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
48
*/
44
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 5,
49
-static uint32_t sve_zcr_len_for_el(CPUARMState *env, int el)
45
.access = PL1_R, .type = ARM_CP_CONST,
50
+uint32_t sve_zcr_len_for_el(CPUARMState *env, int el)
46
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
51
{
52
ARMCPU *cpu = arm_env_get_cpu(env);
53
uint32_t zcr_len = cpu->sve_max_vq - 1;
54
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(crc32c)(uint32_t acc, uint32_t val, uint32_t bytes)
55
/* Return the exception level to which FP-disabled exceptions should
56
* be taken, or 0 if FP is enabled.
57
*/
58
-static int fp_exception_el(CPUARMState *env, int cur_el)
59
+int fp_exception_el(CPUARMState *env, int cur_el)
60
{
61
#ifndef CONFIG_USER_ONLY
62
int fpen;
63
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
64
index XXXXXXX..XXXXXXX 100644
47
index XXXXXXX..XXXXXXX 100644
65
--- a/target/arm/translate-a64.c
48
--- a/target/arm/kvm64.c
66
+++ b/target/arm/translate-a64.c
49
+++ b/target/arm/kvm64.c
67
@@ -XXX,XX +XXX,XX @@ void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
50
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
68
cpu_fprintf(f, "\n");
51
ARM64_SYS_REG(3, 0, 0, 1, 0));
69
return;
52
err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_pfr1,
70
}
53
ARM64_SYS_REG(3, 0, 0, 1, 1));
71
+ if (fp_exception_el(env, el) != 0) {
54
+ err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_pfr2,
72
+ cpu_fprintf(f, " FPU disabled\n");
55
+ ARM64_SYS_REG(3, 0, 0, 3, 4));
73
+ return;
56
err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_dfr0,
74
+ }
57
ARM64_SYS_REG(3, 0, 0, 1, 2));
75
cpu_fprintf(f, " FPCR=%08x FPSR=%08x\n",
58
err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr0,
76
vfp_get_fpcr(env), vfp_get_fpsr(env));
77
78
- if (arm_feature(env, ARM_FEATURE_SVE)) {
79
- int j, zcr_len = env->vfp.zcr_el[1] & 0xf; /* fix for system mode */
80
+ if (arm_feature(env, ARM_FEATURE_SVE) && sve_exception_el(env, el) == 0) {
81
+ int j, zcr_len = sve_zcr_len_for_el(env, el);
82
83
for (i = 0; i <= FFR_PRED_NUM; i++) {
84
bool eol;
85
--
59
--
86
2.19.0
60
2.20.1
87
61
88
62
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
We are going to want to determine whether sve is enabled
3
Only define the register if it exists for the cpu.
4
for EL other than current.
5
4
6
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20210120031656.737646-1-richard.henderson@linaro.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20181005175350.30752-4-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
9
---
12
target/arm/helper.c | 21 +++++++++------------
10
target/arm/helper.c | 21 +++++++++++++++------
13
1 file changed, 9 insertions(+), 12 deletions(-)
11
1 file changed, 15 insertions(+), 6 deletions(-)
14
12
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.c
15
--- a/target/arm/helper.c
18
+++ b/target/arm/helper.c
16
+++ b/target/arm/helper.c
19
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo debug_lpae_cp_reginfo[] = {
17
@@ -XXX,XX +XXX,XX @@ static void define_debug_regs(ARMCPU *cpu)
20
* take care of raising that exception.
21
* C.f. the ARM pseudocode function CheckSVEEnabled.
22
*/
23
-static int sve_exception_el(CPUARMState *env)
24
+static int sve_exception_el(CPUARMState *env, int el)
25
{
26
#ifndef CONFIG_USER_ONLY
27
- unsigned current_el = arm_current_el(env);
28
-
29
- if (current_el <= 1) {
30
+ if (el <= 1) {
31
bool disabled = false;
32
33
/* The CPACR.ZEN controls traps to EL1:
34
@@ -XXX,XX +XXX,XX @@ static int sve_exception_el(CPUARMState *env)
35
if (!extract32(env->cp15.cpacr_el1, 16, 1)) {
36
disabled = true;
37
} else if (!extract32(env->cp15.cpacr_el1, 17, 1)) {
38
- disabled = current_el == 0;
39
+ disabled = el == 0;
40
}
41
if (disabled) {
42
/* route_to_el2 */
43
@@ -XXX,XX +XXX,XX @@ static int sve_exception_el(CPUARMState *env)
44
if (!extract32(env->cp15.cpacr_el1, 20, 1)) {
45
disabled = true;
46
} else if (!extract32(env->cp15.cpacr_el1, 21, 1)) {
47
- disabled = current_el == 0;
48
+ disabled = el == 0;
49
}
50
if (disabled) {
51
return 0;
52
@@ -XXX,XX +XXX,XX @@ static int sve_exception_el(CPUARMState *env)
53
/* CPTR_EL2. Since TZ and TFP are positive,
54
* they will be zero when EL2 is not present.
55
*/
18
*/
56
- if (current_el <= 2 && !arm_is_secure_below_el3(env)) {
19
int i;
57
+ if (el <= 2 && !arm_is_secure_below_el3(env)) {
20
int wrps, brps, ctx_cmps;
58
if (env->cp15.cptr_el[2] & CPTR_TZ) {
21
- ARMCPRegInfo dbgdidr = {
59
return 2;
22
- .name = "DBGDIDR", .cp = 14, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 0,
60
}
23
- .access = PL0_R, .accessfn = access_tda,
61
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(crc32c)(uint32_t acc, uint32_t val, uint32_t bytes)
24
- .type = ARM_CP_CONST, .resetvalue = cpu->isar.dbgdidr,
62
/* Return the exception level to which FP-disabled exceptions should
25
- };
63
* be taken, or 0 if FP is enabled.
26
+
64
*/
27
+ /*
65
-static inline int fp_exception_el(CPUARMState *env)
28
+ * The Arm ARM says DBGDIDR is optional and deprecated if EL1 cannot
66
+static int fp_exception_el(CPUARMState *env, int cur_el)
29
+ * use AArch32. Given that bit 15 is RES1, if the value is 0 then
67
{
30
+ * the register must not exist for this cpu.
68
#ifndef CONFIG_USER_ONLY
31
+ */
69
int fpen;
32
+ if (cpu->isar.dbgdidr != 0) {
70
- int cur_el = arm_current_el(env);
33
+ ARMCPRegInfo dbgdidr = {
71
34
+ .name = "DBGDIDR", .cp = 14, .crn = 0, .crm = 0,
72
/* CPACR and the CPTR registers don't exist before v6, so FP is
35
+ .opc1 = 0, .opc2 = 0,
73
* always accessible
36
+ .access = PL0_R, .accessfn = access_tda,
74
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
37
+ .type = ARM_CP_CONST, .resetvalue = cpu->isar.dbgdidr,
75
target_ulong *cs_base, uint32_t *pflags)
38
+ };
76
{
39
+ define_one_arm_cp_reg(cpu, &dbgdidr);
77
ARMMMUIdx mmu_idx = core_to_arm_mmu_idx(env, cpu_mmu_index(env, false));
40
+ }
78
- int fp_el = fp_exception_el(env);
41
79
+ int current_el = arm_current_el(env);
42
/* Note that all these register fields hold "number of Xs minus 1". */
80
+ int fp_el = fp_exception_el(env, current_el);
43
brps = arm_num_brps(cpu);
81
uint32_t flags;
44
@@ -XXX,XX +XXX,XX @@ static void define_debug_regs(ARMCPU *cpu)
82
45
83
if (is_a64(env)) {
46
assert(ctx_cmps <= brps);
84
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
47
85
flags |= (arm_regime_tbi1(env, mmu_idx) << ARM_TBFLAG_TBI1_SHIFT);
48
- define_one_arm_cp_reg(cpu, &dbgdidr);
86
49
define_arm_cp_regs(cpu, debug_cp_reginfo);
87
if (arm_feature(env, ARM_FEATURE_SVE)) {
50
88
- int sve_el = sve_exception_el(env);
51
if (arm_feature(&cpu->env, ARM_FEATURE_LPAE)) {
89
+ int sve_el = sve_exception_el(env, current_el);
90
uint32_t zcr_len;
91
92
/* If SVE is disabled, but FP is enabled,
93
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
94
if (sve_el != 0 && fp_el == 0) {
95
zcr_len = 0;
96
} else {
97
- int current_el = arm_current_el(env);
98
ARMCPU *cpu = arm_env_get_cpu(env);
99
100
zcr_len = cpu->sve_max_vq - 1;
101
--
52
--
102
2.19.0
53
2.20.1
103
54
104
55
diff view generated by jsdifflib
New patch
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
2
3
The properties to attach a CANBUS object to the xlnx-zcu102 machine have
4
a period in them. We want to use periods in properties for compound QAPI types,
5
and besides the "xlnx-zcu102." prefix is both unnecessary and different
6
from any other machine property name. Remove it.
7
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
9
Message-id: 20210118162537.779542-1-pbonzini@redhat.com
10
Reviewed-by: Vikram Garhwal <fnu.vikram@xilinx.com>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
hw/arm/xlnx-zcu102.c | 4 ++--
14
tests/qtest/xlnx-can-test.c | 30 +++++++++++++++---------------
15
2 files changed, 17 insertions(+), 17 deletions(-)
16
17
diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/xlnx-zcu102.c
20
+++ b/hw/arm/xlnx-zcu102.c
21
@@ -XXX,XX +XXX,XX @@ static void xlnx_zcu102_machine_instance_init(Object *obj)
22
s->secure = false;
23
/* Default to virt (EL2) being disabled */
24
s->virt = false;
25
- object_property_add_link(obj, "xlnx-zcu102.canbus0", TYPE_CAN_BUS,
26
+ object_property_add_link(obj, "canbus0", TYPE_CAN_BUS,
27
(Object **)&s->canbus[0],
28
object_property_allow_set_link,
29
0);
30
31
- object_property_add_link(obj, "xlnx-zcu102.canbus1", TYPE_CAN_BUS,
32
+ object_property_add_link(obj, "canbus1", TYPE_CAN_BUS,
33
(Object **)&s->canbus[1],
34
object_property_allow_set_link,
35
0);
36
diff --git a/tests/qtest/xlnx-can-test.c b/tests/qtest/xlnx-can-test.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/tests/qtest/xlnx-can-test.c
39
+++ b/tests/qtest/xlnx-can-test.c
40
@@ -XXX,XX +XXX,XX @@ static void test_can_bus(void)
41
uint8_t can_timestamp = 1;
42
43
QTestState *qts = qtest_init("-machine xlnx-zcu102"
44
- " -object can-bus,id=canbus0"
45
- " -machine xlnx-zcu102.canbus0=canbus0"
46
- " -machine xlnx-zcu102.canbus1=canbus0"
47
+ " -object can-bus,id=canbus"
48
+ " -machine canbus0=canbus"
49
+ " -machine canbus1=canbus"
50
);
51
52
/* Configure the CAN0 and CAN1. */
53
@@ -XXX,XX +XXX,XX @@ static void test_can_loopback(void)
54
uint32_t status = 0;
55
56
QTestState *qts = qtest_init("-machine xlnx-zcu102"
57
- " -object can-bus,id=canbus0"
58
- " -machine xlnx-zcu102.canbus0=canbus0"
59
- " -machine xlnx-zcu102.canbus1=canbus0"
60
+ " -object can-bus,id=canbus"
61
+ " -machine canbus0=canbus"
62
+ " -machine canbus1=canbus"
63
);
64
65
/* Configure the CAN0 in loopback mode. */
66
@@ -XXX,XX +XXX,XX @@ static void test_can_filter(void)
67
uint8_t can_timestamp = 1;
68
69
QTestState *qts = qtest_init("-machine xlnx-zcu102"
70
- " -object can-bus,id=canbus0"
71
- " -machine xlnx-zcu102.canbus0=canbus0"
72
- " -machine xlnx-zcu102.canbus1=canbus0"
73
+ " -object can-bus,id=canbus"
74
+ " -machine canbus0=canbus"
75
+ " -machine canbus1=canbus"
76
);
77
78
/* Configure the CAN0 and CAN1. */
79
@@ -XXX,XX +XXX,XX @@ static void test_can_sleepmode(void)
80
uint8_t can_timestamp = 1;
81
82
QTestState *qts = qtest_init("-machine xlnx-zcu102"
83
- " -object can-bus,id=canbus0"
84
- " -machine xlnx-zcu102.canbus0=canbus0"
85
- " -machine xlnx-zcu102.canbus1=canbus0"
86
+ " -object can-bus,id=canbus"
87
+ " -machine canbus0=canbus"
88
+ " -machine canbus1=canbus"
89
);
90
91
/* Configure the CAN0. */
92
@@ -XXX,XX +XXX,XX @@ static void test_can_snoopmode(void)
93
uint8_t can_timestamp = 1;
94
95
QTestState *qts = qtest_init("-machine xlnx-zcu102"
96
- " -object can-bus,id=canbus0"
97
- " -machine xlnx-zcu102.canbus0=canbus0"
98
- " -machine xlnx-zcu102.canbus1=canbus0"
99
+ " -object can-bus,id=canbus"
100
+ " -machine canbus0=canbus"
101
+ " -machine canbus1=canbus"
102
);
103
104
/* Configure the CAN0. */
105
--
106
2.20.1
107
108
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Maxim Uvarov <maxim.uvarov@linaro.org>
2
2
3
This implements the feature for softmmu, and moves the
3
Implement gpio-pwr driver to allow reboot and poweroff machine.
4
main loop out of a macro and into a function.
4
This is simple driver with just 2 gpios lines. Current use case
5
is to reboot and poweroff virt machine in secure mode. Secure
6
pl066 gpio chip is needed for that.
5
7
8
Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
9
Reviewed-by: Hao Wu <wuhaotsh@google.com>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20181005175350.30752-15-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
---
12
target/arm/helper-sve.h | 84 ++++++++---
13
hw/gpio/gpio_pwr.c | 70 +++++++++++++++++++++++++++++++++++++++++++++
13
target/arm/sve_helper.c | 290 +++++++++++++++++++++++++++----------
14
hw/gpio/Kconfig | 3 ++
14
target/arm/translate-sve.c | 84 +++++------
15
hw/gpio/meson.build | 1 +
15
3 files changed, 321 insertions(+), 137 deletions(-)
16
3 files changed, 74 insertions(+)
17
create mode 100644 hw/gpio/gpio_pwr.c
16
18
17
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
19
diff --git a/hw/gpio/gpio_pwr.c b/hw/gpio/gpio_pwr.c
18
index XXXXXXX..XXXXXXX 100644
20
new file mode 100644
19
--- a/target/arm/helper-sve.h
21
index XXXXXXX..XXXXXXX
20
+++ b/target/arm/helper-sve.h
22
--- /dev/null
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_6(sve_ldsds_be_zd, TCG_CALL_NO_WG,
23
+++ b/hw/gpio/gpio_pwr.c
22
24
@@ -XXX,XX +XXX,XX @@
23
DEF_HELPER_FLAGS_6(sve_ldffbsu_zsu, TCG_CALL_NO_WG,
25
+/*
24
void, env, ptr, ptr, ptr, tl, i32)
26
+ * GPIO qemu power controller
25
-DEF_HELPER_FLAGS_6(sve_ldffhsu_zsu, TCG_CALL_NO_WG,
27
+ *
26
+DEF_HELPER_FLAGS_6(sve_ldffhsu_le_zsu, TCG_CALL_NO_WG,
28
+ * Copyright (c) 2020 Linaro Limited
27
void, env, ptr, ptr, ptr, tl, i32)
29
+ *
28
-DEF_HELPER_FLAGS_6(sve_ldffssu_zsu, TCG_CALL_NO_WG,
30
+ * Author: Maxim Uvarov <maxim.uvarov@linaro.org>
29
+DEF_HELPER_FLAGS_6(sve_ldffhsu_be_zsu, TCG_CALL_NO_WG,
31
+ *
30
+ void, env, ptr, ptr, ptr, tl, i32)
32
+ * Virtual gpio driver which can be used on top of pl061
31
+DEF_HELPER_FLAGS_6(sve_ldffss_le_zsu, TCG_CALL_NO_WG,
33
+ * to reboot and shutdown qemu virtual machine. One of use
32
+ void, env, ptr, ptr, ptr, tl, i32)
34
+ * case is gpio driver for secure world application (ARM
33
+DEF_HELPER_FLAGS_6(sve_ldffss_be_zsu, TCG_CALL_NO_WG,
35
+ * Trusted Firmware.).
34
void, env, ptr, ptr, ptr, tl, i32)
36
+ *
35
DEF_HELPER_FLAGS_6(sve_ldffbss_zsu, TCG_CALL_NO_WG,
37
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
36
void, env, ptr, ptr, ptr, tl, i32)
38
+ * See the COPYING file in the top-level directory.
37
-DEF_HELPER_FLAGS_6(sve_ldffhss_zsu, TCG_CALL_NO_WG,
39
+ * SPDX-License-Identifier: GPL-2.0-or-later
38
+DEF_HELPER_FLAGS_6(sve_ldffhss_le_zsu, TCG_CALL_NO_WG,
39
+ void, env, ptr, ptr, ptr, tl, i32)
40
+DEF_HELPER_FLAGS_6(sve_ldffhss_be_zsu, TCG_CALL_NO_WG,
41
void, env, ptr, ptr, ptr, tl, i32)
42
43
DEF_HELPER_FLAGS_6(sve_ldffbsu_zss, TCG_CALL_NO_WG,
44
void, env, ptr, ptr, ptr, tl, i32)
45
-DEF_HELPER_FLAGS_6(sve_ldffhsu_zss, TCG_CALL_NO_WG,
46
+DEF_HELPER_FLAGS_6(sve_ldffhsu_le_zss, TCG_CALL_NO_WG,
47
void, env, ptr, ptr, ptr, tl, i32)
48
-DEF_HELPER_FLAGS_6(sve_ldffssu_zss, TCG_CALL_NO_WG,
49
+DEF_HELPER_FLAGS_6(sve_ldffhsu_be_zss, TCG_CALL_NO_WG,
50
+ void, env, ptr, ptr, ptr, tl, i32)
51
+DEF_HELPER_FLAGS_6(sve_ldffss_le_zss, TCG_CALL_NO_WG,
52
+ void, env, ptr, ptr, ptr, tl, i32)
53
+DEF_HELPER_FLAGS_6(sve_ldffss_be_zss, TCG_CALL_NO_WG,
54
void, env, ptr, ptr, ptr, tl, i32)
55
DEF_HELPER_FLAGS_6(sve_ldffbss_zss, TCG_CALL_NO_WG,
56
void, env, ptr, ptr, ptr, tl, i32)
57
-DEF_HELPER_FLAGS_6(sve_ldffhss_zss, TCG_CALL_NO_WG,
58
+DEF_HELPER_FLAGS_6(sve_ldffhss_le_zss, TCG_CALL_NO_WG,
59
+ void, env, ptr, ptr, ptr, tl, i32)
60
+DEF_HELPER_FLAGS_6(sve_ldffhss_be_zss, TCG_CALL_NO_WG,
61
void, env, ptr, ptr, ptr, tl, i32)
62
63
DEF_HELPER_FLAGS_6(sve_ldffbdu_zsu, TCG_CALL_NO_WG,
64
void, env, ptr, ptr, ptr, tl, i32)
65
-DEF_HELPER_FLAGS_6(sve_ldffhdu_zsu, TCG_CALL_NO_WG,
66
+DEF_HELPER_FLAGS_6(sve_ldffhdu_le_zsu, TCG_CALL_NO_WG,
67
void, env, ptr, ptr, ptr, tl, i32)
68
-DEF_HELPER_FLAGS_6(sve_ldffsdu_zsu, TCG_CALL_NO_WG,
69
+DEF_HELPER_FLAGS_6(sve_ldffhdu_be_zsu, TCG_CALL_NO_WG,
70
void, env, ptr, ptr, ptr, tl, i32)
71
-DEF_HELPER_FLAGS_6(sve_ldffddu_zsu, TCG_CALL_NO_WG,
72
+DEF_HELPER_FLAGS_6(sve_ldffsdu_le_zsu, TCG_CALL_NO_WG,
73
+ void, env, ptr, ptr, ptr, tl, i32)
74
+DEF_HELPER_FLAGS_6(sve_ldffsdu_be_zsu, TCG_CALL_NO_WG,
75
+ void, env, ptr, ptr, ptr, tl, i32)
76
+DEF_HELPER_FLAGS_6(sve_ldffdd_le_zsu, TCG_CALL_NO_WG,
77
+ void, env, ptr, ptr, ptr, tl, i32)
78
+DEF_HELPER_FLAGS_6(sve_ldffdd_be_zsu, TCG_CALL_NO_WG,
79
void, env, ptr, ptr, ptr, tl, i32)
80
DEF_HELPER_FLAGS_6(sve_ldffbds_zsu, TCG_CALL_NO_WG,
81
void, env, ptr, ptr, ptr, tl, i32)
82
-DEF_HELPER_FLAGS_6(sve_ldffhds_zsu, TCG_CALL_NO_WG,
83
+DEF_HELPER_FLAGS_6(sve_ldffhds_le_zsu, TCG_CALL_NO_WG,
84
void, env, ptr, ptr, ptr, tl, i32)
85
-DEF_HELPER_FLAGS_6(sve_ldffsds_zsu, TCG_CALL_NO_WG,
86
+DEF_HELPER_FLAGS_6(sve_ldffhds_be_zsu, TCG_CALL_NO_WG,
87
+ void, env, ptr, ptr, ptr, tl, i32)
88
+DEF_HELPER_FLAGS_6(sve_ldffsds_le_zsu, TCG_CALL_NO_WG,
89
+ void, env, ptr, ptr, ptr, tl, i32)
90
+DEF_HELPER_FLAGS_6(sve_ldffsds_be_zsu, TCG_CALL_NO_WG,
91
void, env, ptr, ptr, ptr, tl, i32)
92
93
DEF_HELPER_FLAGS_6(sve_ldffbdu_zss, TCG_CALL_NO_WG,
94
void, env, ptr, ptr, ptr, tl, i32)
95
-DEF_HELPER_FLAGS_6(sve_ldffhdu_zss, TCG_CALL_NO_WG,
96
+DEF_HELPER_FLAGS_6(sve_ldffhdu_le_zss, TCG_CALL_NO_WG,
97
void, env, ptr, ptr, ptr, tl, i32)
98
-DEF_HELPER_FLAGS_6(sve_ldffsdu_zss, TCG_CALL_NO_WG,
99
+DEF_HELPER_FLAGS_6(sve_ldffhdu_be_zss, TCG_CALL_NO_WG,
100
void, env, ptr, ptr, ptr, tl, i32)
101
-DEF_HELPER_FLAGS_6(sve_ldffddu_zss, TCG_CALL_NO_WG,
102
+DEF_HELPER_FLAGS_6(sve_ldffsdu_le_zss, TCG_CALL_NO_WG,
103
+ void, env, ptr, ptr, ptr, tl, i32)
104
+DEF_HELPER_FLAGS_6(sve_ldffsdu_be_zss, TCG_CALL_NO_WG,
105
+ void, env, ptr, ptr, ptr, tl, i32)
106
+DEF_HELPER_FLAGS_6(sve_ldffdd_le_zss, TCG_CALL_NO_WG,
107
+ void, env, ptr, ptr, ptr, tl, i32)
108
+DEF_HELPER_FLAGS_6(sve_ldffdd_be_zss, TCG_CALL_NO_WG,
109
void, env, ptr, ptr, ptr, tl, i32)
110
DEF_HELPER_FLAGS_6(sve_ldffbds_zss, TCG_CALL_NO_WG,
111
void, env, ptr, ptr, ptr, tl, i32)
112
-DEF_HELPER_FLAGS_6(sve_ldffhds_zss, TCG_CALL_NO_WG,
113
+DEF_HELPER_FLAGS_6(sve_ldffhds_le_zss, TCG_CALL_NO_WG,
114
void, env, ptr, ptr, ptr, tl, i32)
115
-DEF_HELPER_FLAGS_6(sve_ldffsds_zss, TCG_CALL_NO_WG,
116
+DEF_HELPER_FLAGS_6(sve_ldffhds_be_zss, TCG_CALL_NO_WG,
117
+ void, env, ptr, ptr, ptr, tl, i32)
118
+DEF_HELPER_FLAGS_6(sve_ldffsds_le_zss, TCG_CALL_NO_WG,
119
+ void, env, ptr, ptr, ptr, tl, i32)
120
+DEF_HELPER_FLAGS_6(sve_ldffsds_be_zss, TCG_CALL_NO_WG,
121
void, env, ptr, ptr, ptr, tl, i32)
122
123
DEF_HELPER_FLAGS_6(sve_ldffbdu_zd, TCG_CALL_NO_WG,
124
void, env, ptr, ptr, ptr, tl, i32)
125
-DEF_HELPER_FLAGS_6(sve_ldffhdu_zd, TCG_CALL_NO_WG,
126
+DEF_HELPER_FLAGS_6(sve_ldffhdu_le_zd, TCG_CALL_NO_WG,
127
void, env, ptr, ptr, ptr, tl, i32)
128
-DEF_HELPER_FLAGS_6(sve_ldffsdu_zd, TCG_CALL_NO_WG,
129
+DEF_HELPER_FLAGS_6(sve_ldffhdu_be_zd, TCG_CALL_NO_WG,
130
void, env, ptr, ptr, ptr, tl, i32)
131
-DEF_HELPER_FLAGS_6(sve_ldffddu_zd, TCG_CALL_NO_WG,
132
+DEF_HELPER_FLAGS_6(sve_ldffsdu_le_zd, TCG_CALL_NO_WG,
133
+ void, env, ptr, ptr, ptr, tl, i32)
134
+DEF_HELPER_FLAGS_6(sve_ldffsdu_be_zd, TCG_CALL_NO_WG,
135
+ void, env, ptr, ptr, ptr, tl, i32)
136
+DEF_HELPER_FLAGS_6(sve_ldffdd_le_zd, TCG_CALL_NO_WG,
137
+ void, env, ptr, ptr, ptr, tl, i32)
138
+DEF_HELPER_FLAGS_6(sve_ldffdd_be_zd, TCG_CALL_NO_WG,
139
void, env, ptr, ptr, ptr, tl, i32)
140
DEF_HELPER_FLAGS_6(sve_ldffbds_zd, TCG_CALL_NO_WG,
141
void, env, ptr, ptr, ptr, tl, i32)
142
-DEF_HELPER_FLAGS_6(sve_ldffhds_zd, TCG_CALL_NO_WG,
143
+DEF_HELPER_FLAGS_6(sve_ldffhds_le_zd, TCG_CALL_NO_WG,
144
void, env, ptr, ptr, ptr, tl, i32)
145
-DEF_HELPER_FLAGS_6(sve_ldffsds_zd, TCG_CALL_NO_WG,
146
+DEF_HELPER_FLAGS_6(sve_ldffhds_be_zd, TCG_CALL_NO_WG,
147
+ void, env, ptr, ptr, ptr, tl, i32)
148
+DEF_HELPER_FLAGS_6(sve_ldffsds_le_zd, TCG_CALL_NO_WG,
149
+ void, env, ptr, ptr, ptr, tl, i32)
150
+DEF_HELPER_FLAGS_6(sve_ldffsds_be_zd, TCG_CALL_NO_WG,
151
void, env, ptr, ptr, ptr, tl, i32)
152
153
DEF_HELPER_FLAGS_6(sve_stbs_zsu, TCG_CALL_NO_WG,
154
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
155
index XXXXXXX..XXXXXXX 100644
156
--- a/target/arm/sve_helper.c
157
+++ b/target/arm/sve_helper.c
158
@@ -XXX,XX +XXX,XX @@ DO_LD1_ZPZ_D(dd_be, zd)
159
160
/* First fault loads with a vector index. */
161
162
-#ifdef CONFIG_USER_ONLY
163
+/* Load one element into VD+REG_OFF from (ENV,VADDR) without faulting.
164
+ * The controlling predicate is known to be true. Return true if the
165
+ * load was successful.
166
+ */
40
+ */
167
+typedef bool sve_ld1_nf_fn(CPUARMState *env, void *vd, intptr_t reg_off,
41
+
168
+ target_ulong vaddr, int mmu_idx);
169
170
-#define DO_LDFF1_ZPZ(NAME, TYPEE, TYPEI, TYPEM, FN, H) \
171
-void HELPER(NAME)(CPUARMState *env, void *vd, void *vg, void *vm, \
172
- target_ulong base, uint32_t desc) \
173
-{ \
174
- intptr_t i, oprsz = simd_oprsz(desc); \
175
- unsigned scale = simd_data(desc); \
176
- uintptr_t ra = GETPC(); \
177
- bool first = true; \
178
- mmap_lock(); \
179
- for (i = 0; i < oprsz; ) { \
180
- uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
181
- do { \
182
- TYPEM m = 0; \
183
- if (pg & 1) { \
184
- target_ulong off = *(TYPEI *)(vm + H(i)); \
185
- target_ulong addr = base + (off << scale); \
186
- if (!first && \
187
- page_check_range(addr, sizeof(TYPEM), PAGE_READ)) { \
188
- record_fault(env, i, oprsz); \
189
- goto exit; \
190
- } \
191
- m = FN(env, addr, ra); \
192
- first = false; \
193
- } \
194
- *(TYPEE *)(vd + H(i)) = m; \
195
- i += sizeof(TYPEE), pg >>= sizeof(TYPEE); \
196
- } while (i & 15); \
197
- } \
198
- exit: \
199
- mmap_unlock(); \
200
+#ifdef CONFIG_SOFTMMU
201
+#define DO_LD_NF(NAME, H, TYPEE, TYPEM, HOST) \
202
+static bool sve_ld##NAME##_nf(CPUARMState *env, void *vd, intptr_t reg_off, \
203
+ target_ulong addr, int mmu_idx) \
204
+{ \
205
+ target_ulong next_page = -(addr | TARGET_PAGE_MASK); \
206
+ if (likely(next_page - addr >= sizeof(TYPEM))) { \
207
+ void *host = tlb_vaddr_to_host(env, addr, MMU_DATA_LOAD, mmu_idx); \
208
+ if (likely(host)) { \
209
+ TYPEM val = HOST(host); \
210
+ *(TYPEE *)(vd + H(reg_off)) = val; \
211
+ return true; \
212
+ } \
213
+ } \
214
+ return false; \
215
}
216
-
217
#else
218
-
219
-#define DO_LDFF1_ZPZ(NAME, TYPEE, TYPEI, TYPEM, FN, H) \
220
-void HELPER(NAME)(CPUARMState *env, void *vd, void *vg, void *vm, \
221
- target_ulong base, uint32_t desc) \
222
-{ \
223
- g_assert_not_reached(); \
224
+#define DO_LD_NF(NAME, H, TYPEE, TYPEM, HOST) \
225
+static bool sve_ld##NAME##_nf(CPUARMState *env, void *vd, intptr_t reg_off, \
226
+ target_ulong addr, int mmu_idx) \
227
+{ \
228
+ if (likely(page_check_range(addr, sizeof(TYPEM), PAGE_READ))) { \
229
+ TYPEM val = HOST(g2h(addr)); \
230
+ *(TYPEE *)(vd + H(reg_off)) = val; \
231
+ return true; \
232
+ } \
233
+ return false; \
234
}
235
-
236
#endif
237
238
-#define DO_LDFF1_ZPZ_S(NAME, TYPEI, TYPEM, FN) \
239
- DO_LDFF1_ZPZ(NAME, uint32_t, TYPEI, TYPEM, FN, H1_4)
240
-#define DO_LDFF1_ZPZ_D(NAME, TYPEI, TYPEM, FN) \
241
- DO_LDFF1_ZPZ(NAME, uint64_t, TYPEI, TYPEM, FN, )
242
+DO_LD_NF(bsu, H1_4, uint32_t, uint8_t, ldub_p)
243
+DO_LD_NF(bss, H1_4, uint32_t, int8_t, ldsb_p)
244
+DO_LD_NF(bdu, , uint64_t, uint8_t, ldub_p)
245
+DO_LD_NF(bds, , uint64_t, int8_t, ldsb_p)
246
247
-DO_LDFF1_ZPZ_S(sve_ldffbsu_zsu, uint32_t, uint8_t, cpu_ldub_data_ra)
248
-DO_LDFF1_ZPZ_S(sve_ldffhsu_zsu, uint32_t, uint16_t, cpu_lduw_data_ra)
249
-DO_LDFF1_ZPZ_S(sve_ldffssu_zsu, uint32_t, uint32_t, cpu_ldl_data_ra)
250
-DO_LDFF1_ZPZ_S(sve_ldffbss_zsu, uint32_t, int8_t, cpu_ldub_data_ra)
251
-DO_LDFF1_ZPZ_S(sve_ldffhss_zsu, uint32_t, int16_t, cpu_lduw_data_ra)
252
+DO_LD_NF(hsu_le, H1_4, uint32_t, uint16_t, lduw_le_p)
253
+DO_LD_NF(hss_le, H1_4, uint32_t, int16_t, ldsw_le_p)
254
+DO_LD_NF(hsu_be, H1_4, uint32_t, uint16_t, lduw_be_p)
255
+DO_LD_NF(hss_be, H1_4, uint32_t, int16_t, ldsw_be_p)
256
+DO_LD_NF(hdu_le, , uint64_t, uint16_t, lduw_le_p)
257
+DO_LD_NF(hds_le, , uint64_t, int16_t, ldsw_le_p)
258
+DO_LD_NF(hdu_be, , uint64_t, uint16_t, lduw_be_p)
259
+DO_LD_NF(hds_be, , uint64_t, int16_t, ldsw_be_p)
260
261
-DO_LDFF1_ZPZ_S(sve_ldffbsu_zss, int32_t, uint8_t, cpu_ldub_data_ra)
262
-DO_LDFF1_ZPZ_S(sve_ldffhsu_zss, int32_t, uint16_t, cpu_lduw_data_ra)
263
-DO_LDFF1_ZPZ_S(sve_ldffssu_zss, int32_t, uint32_t, cpu_ldl_data_ra)
264
-DO_LDFF1_ZPZ_S(sve_ldffbss_zss, int32_t, int8_t, cpu_ldub_data_ra)
265
-DO_LDFF1_ZPZ_S(sve_ldffhss_zss, int32_t, int16_t, cpu_lduw_data_ra)
266
+DO_LD_NF(ss_le, H1_4, uint32_t, uint32_t, ldl_le_p)
267
+DO_LD_NF(ss_be, H1_4, uint32_t, uint32_t, ldl_be_p)
268
+DO_LD_NF(sdu_le, , uint64_t, uint32_t, ldl_le_p)
269
+DO_LD_NF(sds_le, , uint64_t, int32_t, ldl_le_p)
270
+DO_LD_NF(sdu_be, , uint64_t, uint32_t, ldl_be_p)
271
+DO_LD_NF(sds_be, , uint64_t, int32_t, ldl_be_p)
272
273
-DO_LDFF1_ZPZ_D(sve_ldffbdu_zsu, uint32_t, uint8_t, cpu_ldub_data_ra)
274
-DO_LDFF1_ZPZ_D(sve_ldffhdu_zsu, uint32_t, uint16_t, cpu_lduw_data_ra)
275
-DO_LDFF1_ZPZ_D(sve_ldffsdu_zsu, uint32_t, uint32_t, cpu_ldl_data_ra)
276
-DO_LDFF1_ZPZ_D(sve_ldffddu_zsu, uint32_t, uint64_t, cpu_ldq_data_ra)
277
-DO_LDFF1_ZPZ_D(sve_ldffbds_zsu, uint32_t, int8_t, cpu_ldub_data_ra)
278
-DO_LDFF1_ZPZ_D(sve_ldffhds_zsu, uint32_t, int16_t, cpu_lduw_data_ra)
279
-DO_LDFF1_ZPZ_D(sve_ldffsds_zsu, uint32_t, int32_t, cpu_ldl_data_ra)
280
+DO_LD_NF(dd_le, , uint64_t, uint64_t, ldq_le_p)
281
+DO_LD_NF(dd_be, , uint64_t, uint64_t, ldq_be_p)
282
283
-DO_LDFF1_ZPZ_D(sve_ldffbdu_zss, int32_t, uint8_t, cpu_ldub_data_ra)
284
-DO_LDFF1_ZPZ_D(sve_ldffhdu_zss, int32_t, uint16_t, cpu_lduw_data_ra)
285
-DO_LDFF1_ZPZ_D(sve_ldffsdu_zss, int32_t, uint32_t, cpu_ldl_data_ra)
286
-DO_LDFF1_ZPZ_D(sve_ldffddu_zss, int32_t, uint64_t, cpu_ldq_data_ra)
287
-DO_LDFF1_ZPZ_D(sve_ldffbds_zss, int32_t, int8_t, cpu_ldub_data_ra)
288
-DO_LDFF1_ZPZ_D(sve_ldffhds_zss, int32_t, int16_t, cpu_lduw_data_ra)
289
-DO_LDFF1_ZPZ_D(sve_ldffsds_zss, int32_t, int32_t, cpu_ldl_data_ra)
290
+/*
42
+/*
291
+ * Common helper for all gather first-faulting loads.
43
+ * QEMU interface:
44
+ * two named input GPIO lines:
45
+ * 'reset' : when asserted, trigger system reset
46
+ * 'shutdown' : when asserted, trigger system shutdown
292
+ */
47
+ */
293
+static inline void sve_ldff1_zs(CPUARMState *env, void *vd, void *vg, void *vm,
48
+
294
+ target_ulong base, uint32_t desc, uintptr_t ra,
49
+#include "qemu/osdep.h"
295
+ zreg_off_fn *off_fn, sve_ld1_tlb_fn *tlb_fn,
50
+#include "hw/sysbus.h"
296
+ sve_ld1_nf_fn *nonfault_fn)
51
+#include "sysemu/runstate.h"
52
+
53
+#define TYPE_GPIOPWR "gpio-pwr"
54
+OBJECT_DECLARE_SIMPLE_TYPE(GPIO_PWR_State, GPIOPWR)
55
+
56
+struct GPIO_PWR_State {
57
+ SysBusDevice parent_obj;
58
+};
59
+
60
+static void gpio_pwr_reset(void *opaque, int n, int level)
297
+{
61
+{
298
+ const int mmu_idx = cpu_mmu_index(env, false);
62
+ if (level) {
299
+ intptr_t reg_off, reg_max = simd_oprsz(desc);
63
+ qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
300
+ unsigned scale = simd_data(desc);
301
+ target_ulong addr;
302
303
-DO_LDFF1_ZPZ_D(sve_ldffbdu_zd, uint64_t, uint8_t, cpu_ldub_data_ra)
304
-DO_LDFF1_ZPZ_D(sve_ldffhdu_zd, uint64_t, uint16_t, cpu_lduw_data_ra)
305
-DO_LDFF1_ZPZ_D(sve_ldffsdu_zd, uint64_t, uint32_t, cpu_ldl_data_ra)
306
-DO_LDFF1_ZPZ_D(sve_ldffddu_zd, uint64_t, uint64_t, cpu_ldq_data_ra)
307
-DO_LDFF1_ZPZ_D(sve_ldffbds_zd, uint64_t, int8_t, cpu_ldub_data_ra)
308
-DO_LDFF1_ZPZ_D(sve_ldffhds_zd, uint64_t, int16_t, cpu_lduw_data_ra)
309
-DO_LDFF1_ZPZ_D(sve_ldffsds_zd, uint64_t, int32_t, cpu_ldl_data_ra)
310
+ /* Skip to the first true predicate. */
311
+ reg_off = find_next_active(vg, 0, reg_max, MO_32);
312
+ if (likely(reg_off < reg_max)) {
313
+ /* Perform one normal read, which will fault or not. */
314
+ set_helper_retaddr(ra);
315
+ addr = off_fn(vm, reg_off);
316
+ addr = base + (addr << scale);
317
+ tlb_fn(env, vd, reg_off, addr, mmu_idx, ra);
318
+
319
+ /* The rest of the reads will be non-faulting. */
320
+ set_helper_retaddr(0);
321
+ }
322
+
323
+ /* After any fault, zero the leading predicated false elements. */
324
+ swap_memzero(vd, reg_off);
325
+
326
+ while (likely((reg_off += 4) < reg_max)) {
327
+ uint64_t pg = *(uint64_t *)(vg + (reg_off >> 6) * 8);
328
+ if (likely((pg >> (reg_off & 63)) & 1)) {
329
+ addr = off_fn(vm, reg_off);
330
+ addr = base + (addr << scale);
331
+ if (!nonfault_fn(env, vd, reg_off, addr, mmu_idx)) {
332
+ record_fault(env, reg_off, reg_max);
333
+ break;
334
+ }
335
+ } else {
336
+ *(uint32_t *)(vd + H1_4(reg_off)) = 0;
337
+ }
338
+ }
64
+ }
339
+}
65
+}
340
+
66
+
341
+static inline void sve_ldff1_zd(CPUARMState *env, void *vd, void *vg, void *vm,
67
+static void gpio_pwr_shutdown(void *opaque, int n, int level)
342
+ target_ulong base, uint32_t desc, uintptr_t ra,
343
+ zreg_off_fn *off_fn, sve_ld1_tlb_fn *tlb_fn,
344
+ sve_ld1_nf_fn *nonfault_fn)
345
+{
68
+{
346
+ const int mmu_idx = cpu_mmu_index(env, false);
69
+ if (level) {
347
+ intptr_t reg_off, reg_max = simd_oprsz(desc);
70
+ qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
348
+ unsigned scale = simd_data(desc);
349
+ target_ulong addr;
350
+
351
+ /* Skip to the first true predicate. */
352
+ reg_off = find_next_active(vg, 0, reg_max, MO_64);
353
+ if (likely(reg_off < reg_max)) {
354
+ /* Perform one normal read, which will fault or not. */
355
+ set_helper_retaddr(ra);
356
+ addr = off_fn(vm, reg_off);
357
+ addr = base + (addr << scale);
358
+ tlb_fn(env, vd, reg_off, addr, mmu_idx, ra);
359
+
360
+ /* The rest of the reads will be non-faulting. */
361
+ set_helper_retaddr(0);
362
+ }
363
+
364
+ /* After any fault, zero the leading predicated false elements. */
365
+ swap_memzero(vd, reg_off);
366
+
367
+ while (likely((reg_off += 8) < reg_max)) {
368
+ uint8_t pg = *(uint8_t *)(vg + H1(reg_off >> 3));
369
+ if (likely(pg & 1)) {
370
+ addr = off_fn(vm, reg_off);
371
+ addr = base + (addr << scale);
372
+ if (!nonfault_fn(env, vd, reg_off, addr, mmu_idx)) {
373
+ record_fault(env, reg_off, reg_max);
374
+ break;
375
+ }
376
+ } else {
377
+ *(uint64_t *)(vd + reg_off) = 0;
378
+ }
379
+ }
71
+ }
380
+}
72
+}
381
+
73
+
382
+#define DO_LDFF1_ZPZ_S(MEM, OFS) \
74
+static void gpio_pwr_init(Object *obj)
383
+void HELPER(sve_ldff##MEM##_##OFS) \
75
+{
384
+ (CPUARMState *env, void *vd, void *vg, void *vm, \
76
+ DeviceState *dev = DEVICE(obj);
385
+ target_ulong base, uint32_t desc) \
77
+
386
+{ \
78
+ qdev_init_gpio_in_named(dev, gpio_pwr_reset, "reset", 1);
387
+ sve_ldff1_zs(env, vd, vg, vm, base, desc, GETPC(), \
79
+ qdev_init_gpio_in_named(dev, gpio_pwr_shutdown, "shutdown", 1);
388
+ off_##OFS##_s, sve_ld1##MEM##_tlb, sve_ld##MEM##_nf); \
389
+}
80
+}
390
+
81
+
391
+#define DO_LDFF1_ZPZ_D(MEM, OFS) \
82
+static const TypeInfo gpio_pwr_info = {
392
+void HELPER(sve_ldff##MEM##_##OFS) \
83
+ .name = TYPE_GPIOPWR,
393
+ (CPUARMState *env, void *vd, void *vg, void *vm, \
84
+ .parent = TYPE_SYS_BUS_DEVICE,
394
+ target_ulong base, uint32_t desc) \
85
+ .instance_size = sizeof(GPIO_PWR_State),
395
+{ \
86
+ .instance_init = gpio_pwr_init,
396
+ sve_ldff1_zd(env, vd, vg, vm, base, desc, GETPC(), \
87
+};
397
+ off_##OFS##_d, sve_ld1##MEM##_tlb, sve_ld##MEM##_nf); \
88
+
89
+static void gpio_pwr_register_types(void)
90
+{
91
+ type_register_static(&gpio_pwr_info);
398
+}
92
+}
399
+
93
+
400
+DO_LDFF1_ZPZ_S(bsu, zsu)
94
+type_init(gpio_pwr_register_types)
401
+DO_LDFF1_ZPZ_S(bsu, zss)
95
diff --git a/hw/gpio/Kconfig b/hw/gpio/Kconfig
402
+DO_LDFF1_ZPZ_D(bdu, zsu)
96
index XXXXXXX..XXXXXXX 100644
403
+DO_LDFF1_ZPZ_D(bdu, zss)
97
--- a/hw/gpio/Kconfig
404
+DO_LDFF1_ZPZ_D(bdu, zd)
98
+++ b/hw/gpio/Kconfig
99
@@ -XXX,XX +XXX,XX @@ config PL061
100
config GPIO_KEY
101
bool
102
103
+config GPIO_PWR
104
+ bool
405
+
105
+
406
+DO_LDFF1_ZPZ_S(bss, zsu)
106
config SIFIVE_GPIO
407
+DO_LDFF1_ZPZ_S(bss, zss)
107
bool
408
+DO_LDFF1_ZPZ_D(bds, zsu)
108
diff --git a/hw/gpio/meson.build b/hw/gpio/meson.build
409
+DO_LDFF1_ZPZ_D(bds, zss)
410
+DO_LDFF1_ZPZ_D(bds, zd)
411
+
412
+DO_LDFF1_ZPZ_S(hsu_le, zsu)
413
+DO_LDFF1_ZPZ_S(hsu_le, zss)
414
+DO_LDFF1_ZPZ_D(hdu_le, zsu)
415
+DO_LDFF1_ZPZ_D(hdu_le, zss)
416
+DO_LDFF1_ZPZ_D(hdu_le, zd)
417
+
418
+DO_LDFF1_ZPZ_S(hsu_be, zsu)
419
+DO_LDFF1_ZPZ_S(hsu_be, zss)
420
+DO_LDFF1_ZPZ_D(hdu_be, zsu)
421
+DO_LDFF1_ZPZ_D(hdu_be, zss)
422
+DO_LDFF1_ZPZ_D(hdu_be, zd)
423
+
424
+DO_LDFF1_ZPZ_S(hss_le, zsu)
425
+DO_LDFF1_ZPZ_S(hss_le, zss)
426
+DO_LDFF1_ZPZ_D(hds_le, zsu)
427
+DO_LDFF1_ZPZ_D(hds_le, zss)
428
+DO_LDFF1_ZPZ_D(hds_le, zd)
429
+
430
+DO_LDFF1_ZPZ_S(hss_be, zsu)
431
+DO_LDFF1_ZPZ_S(hss_be, zss)
432
+DO_LDFF1_ZPZ_D(hds_be, zsu)
433
+DO_LDFF1_ZPZ_D(hds_be, zss)
434
+DO_LDFF1_ZPZ_D(hds_be, zd)
435
+
436
+DO_LDFF1_ZPZ_S(ss_le, zsu)
437
+DO_LDFF1_ZPZ_S(ss_le, zss)
438
+DO_LDFF1_ZPZ_D(sdu_le, zsu)
439
+DO_LDFF1_ZPZ_D(sdu_le, zss)
440
+DO_LDFF1_ZPZ_D(sdu_le, zd)
441
+
442
+DO_LDFF1_ZPZ_S(ss_be, zsu)
443
+DO_LDFF1_ZPZ_S(ss_be, zss)
444
+DO_LDFF1_ZPZ_D(sdu_be, zsu)
445
+DO_LDFF1_ZPZ_D(sdu_be, zss)
446
+DO_LDFF1_ZPZ_D(sdu_be, zd)
447
+
448
+DO_LDFF1_ZPZ_D(sds_le, zsu)
449
+DO_LDFF1_ZPZ_D(sds_le, zss)
450
+DO_LDFF1_ZPZ_D(sds_le, zd)
451
+
452
+DO_LDFF1_ZPZ_D(sds_be, zsu)
453
+DO_LDFF1_ZPZ_D(sds_be, zss)
454
+DO_LDFF1_ZPZ_D(sds_be, zd)
455
+
456
+DO_LDFF1_ZPZ_D(dd_le, zsu)
457
+DO_LDFF1_ZPZ_D(dd_le, zss)
458
+DO_LDFF1_ZPZ_D(dd_le, zd)
459
+
460
+DO_LDFF1_ZPZ_D(dd_be, zsu)
461
+DO_LDFF1_ZPZ_D(dd_be, zss)
462
+DO_LDFF1_ZPZ_D(dd_be, zd)
463
464
/* Stores with a vector index. */
465
466
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
467
index XXXXXXX..XXXXXXX 100644
109
index XXXXXXX..XXXXXXX 100644
468
--- a/target/arm/translate-sve.c
110
--- a/hw/gpio/meson.build
469
+++ b/target/arm/translate-sve.c
111
+++ b/hw/gpio/meson.build
470
@@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_mem_scatter * const gather_load_fn32[2][2][2][2][3] = {
112
@@ -XXX,XX +XXX,XX @@
471
113
softmmu_ss.add(when: 'CONFIG_E500', if_true: files('mpc8xxx.c'))
472
/* First-fault */
114
softmmu_ss.add(when: 'CONFIG_GPIO_KEY', if_true: files('gpio_key.c'))
473
{ { { gen_helper_sve_ldffbss_zsu,
115
+softmmu_ss.add(when: 'CONFIG_GPIO_PWR', if_true: files('gpio_pwr.c'))
474
- gen_helper_sve_ldffhss_zsu,
116
softmmu_ss.add(when: 'CONFIG_MAX7310', if_true: files('max7310.c'))
475
+ gen_helper_sve_ldffhss_le_zsu,
117
softmmu_ss.add(when: 'CONFIG_PL061', if_true: files('pl061.c'))
476
NULL, },
118
softmmu_ss.add(when: 'CONFIG_PUV3', if_true: files('puv3_gpio.c'))
477
{ gen_helper_sve_ldffbsu_zsu,
478
- gen_helper_sve_ldffhsu_zsu,
479
- gen_helper_sve_ldffssu_zsu, } },
480
+ gen_helper_sve_ldffhsu_le_zsu,
481
+ gen_helper_sve_ldffss_le_zsu, } },
482
{ { gen_helper_sve_ldffbss_zss,
483
- gen_helper_sve_ldffhss_zss,
484
+ gen_helper_sve_ldffhss_le_zss,
485
NULL, },
486
{ gen_helper_sve_ldffbsu_zss,
487
- gen_helper_sve_ldffhsu_zss,
488
- gen_helper_sve_ldffssu_zss, } } } },
489
+ gen_helper_sve_ldffhsu_le_zss,
490
+ gen_helper_sve_ldffss_le_zss, } } } },
491
492
/* Big-endian */
493
{ { { { gen_helper_sve_ldbss_zsu,
494
@@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_mem_scatter * const gather_load_fn32[2][2][2][2][3] = {
495
496
/* First-fault */
497
{ { { gen_helper_sve_ldffbss_zsu,
498
- gen_helper_sve_ldffhss_zsu,
499
+ gen_helper_sve_ldffhss_be_zsu,
500
NULL, },
501
{ gen_helper_sve_ldffbsu_zsu,
502
- gen_helper_sve_ldffhsu_zsu,
503
- gen_helper_sve_ldffssu_zsu, } },
504
+ gen_helper_sve_ldffhsu_be_zsu,
505
+ gen_helper_sve_ldffss_be_zsu, } },
506
{ { gen_helper_sve_ldffbss_zss,
507
- gen_helper_sve_ldffhss_zss,
508
+ gen_helper_sve_ldffhss_be_zss,
509
NULL, },
510
{ gen_helper_sve_ldffbsu_zss,
511
- gen_helper_sve_ldffhsu_zss,
512
- gen_helper_sve_ldffssu_zss, } } } },
513
+ gen_helper_sve_ldffhsu_be_zss,
514
+ gen_helper_sve_ldffss_be_zss, } } } },
515
};
516
517
/* Note that we overload xs=2 to indicate 64-bit offset. */
518
@@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_mem_scatter * const gather_load_fn64[2][2][3][2][4] = {
519
520
/* First-fault */
521
{ { { gen_helper_sve_ldffbds_zsu,
522
- gen_helper_sve_ldffhds_zsu,
523
- gen_helper_sve_ldffsds_zsu,
524
+ gen_helper_sve_ldffhds_le_zsu,
525
+ gen_helper_sve_ldffsds_le_zsu,
526
NULL, },
527
{ gen_helper_sve_ldffbdu_zsu,
528
- gen_helper_sve_ldffhdu_zsu,
529
- gen_helper_sve_ldffsdu_zsu,
530
- gen_helper_sve_ldffddu_zsu, } },
531
+ gen_helper_sve_ldffhdu_le_zsu,
532
+ gen_helper_sve_ldffsdu_le_zsu,
533
+ gen_helper_sve_ldffdd_le_zsu, } },
534
{ { gen_helper_sve_ldffbds_zss,
535
- gen_helper_sve_ldffhds_zss,
536
- gen_helper_sve_ldffsds_zss,
537
+ gen_helper_sve_ldffhds_le_zss,
538
+ gen_helper_sve_ldffsds_le_zss,
539
NULL, },
540
{ gen_helper_sve_ldffbdu_zss,
541
- gen_helper_sve_ldffhdu_zss,
542
- gen_helper_sve_ldffsdu_zss,
543
- gen_helper_sve_ldffddu_zss, } },
544
+ gen_helper_sve_ldffhdu_le_zss,
545
+ gen_helper_sve_ldffsdu_le_zss,
546
+ gen_helper_sve_ldffdd_le_zss, } },
547
{ { gen_helper_sve_ldffbds_zd,
548
- gen_helper_sve_ldffhds_zd,
549
- gen_helper_sve_ldffsds_zd,
550
+ gen_helper_sve_ldffhds_le_zd,
551
+ gen_helper_sve_ldffsds_le_zd,
552
NULL, },
553
{ gen_helper_sve_ldffbdu_zd,
554
- gen_helper_sve_ldffhdu_zd,
555
- gen_helper_sve_ldffsdu_zd,
556
- gen_helper_sve_ldffddu_zd, } } } },
557
+ gen_helper_sve_ldffhdu_le_zd,
558
+ gen_helper_sve_ldffsdu_le_zd,
559
+ gen_helper_sve_ldffdd_le_zd, } } } },
560
561
/* Big-endian */
562
{ { { { gen_helper_sve_ldbds_zsu,
563
@@ -XXX,XX +XXX,XX @@ static gen_helper_gvec_mem_scatter * const gather_load_fn64[2][2][3][2][4] = {
564
565
/* First-fault */
566
{ { { gen_helper_sve_ldffbds_zsu,
567
- gen_helper_sve_ldffhds_zsu,
568
- gen_helper_sve_ldffsds_zsu,
569
+ gen_helper_sve_ldffhds_be_zsu,
570
+ gen_helper_sve_ldffsds_be_zsu,
571
NULL, },
572
{ gen_helper_sve_ldffbdu_zsu,
573
- gen_helper_sve_ldffhdu_zsu,
574
- gen_helper_sve_ldffsdu_zsu,
575
- gen_helper_sve_ldffddu_zsu, } },
576
+ gen_helper_sve_ldffhdu_be_zsu,
577
+ gen_helper_sve_ldffsdu_be_zsu,
578
+ gen_helper_sve_ldffdd_be_zsu, } },
579
{ { gen_helper_sve_ldffbds_zss,
580
- gen_helper_sve_ldffhds_zss,
581
- gen_helper_sve_ldffsds_zss,
582
+ gen_helper_sve_ldffhds_be_zss,
583
+ gen_helper_sve_ldffsds_be_zss,
584
NULL, },
585
{ gen_helper_sve_ldffbdu_zss,
586
- gen_helper_sve_ldffhdu_zss,
587
- gen_helper_sve_ldffsdu_zss,
588
- gen_helper_sve_ldffddu_zss, } },
589
+ gen_helper_sve_ldffhdu_be_zss,
590
+ gen_helper_sve_ldffsdu_be_zss,
591
+ gen_helper_sve_ldffdd_be_zss, } },
592
{ { gen_helper_sve_ldffbds_zd,
593
- gen_helper_sve_ldffhds_zd,
594
- gen_helper_sve_ldffsds_zd,
595
+ gen_helper_sve_ldffhds_be_zd,
596
+ gen_helper_sve_ldffsds_be_zd,
597
NULL, },
598
{ gen_helper_sve_ldffbdu_zd,
599
- gen_helper_sve_ldffhdu_zd,
600
- gen_helper_sve_ldffsdu_zd,
601
- gen_helper_sve_ldffddu_zd, } } } },
602
+ gen_helper_sve_ldffhdu_be_zd,
603
+ gen_helper_sve_ldffsdu_be_zd,
604
+ gen_helper_sve_ldffdd_be_zd, } } } },
605
};
606
607
static bool trans_LD1_zprz(DisasContext *s, arg_LD1_zprz *a, uint32_t insn)
608
--
119
--
609
2.19.0
120
2.20.1
610
121
611
122
diff view generated by jsdifflib
1
In commit c79c0a314c43b78 we enabled emulation of external aborts
1
From: Maxim Uvarov <maxim.uvarov@linaro.org>
2
when the guest attempts to access a physical address with no
3
mapped device. In commit 4672cbd7bed88dc6 we suppress this for
4
most legacy boards to prevent breakage of previously working
5
guests, but we didn't suppress it in the 'virt' board, with
6
the rationale "we know that guests won't try to prod devices
7
that we don't describe in the device tree or ACPI tables". This
8
is mostly true, but we've had a report of a Linux guest image
9
that this did break. The problem seems to be that the guest
10
is (incorrectly) configured with a DEBUG_UART_PHYS value that
11
tells it there is a uart at 0x10009000 (which is true for
12
vexpress but not for virt), so in early bootup the kernel
13
probes this bogus address.
14
2
15
This is a misconfigured guest, so we don't need to worry
3
No functional change. Just refactor code to better
16
about it too much, but we can arrange that guests that ran
4
support secure and normal world gpios.
17
on QEMU v2.10 (before c79c0a314c43b78) will still run on
18
the "virt-2.10" board model, by suppressing external aborts
19
only for that version and earlier. This seems a reasonable
20
compromise: "virt-2.10" is supposed to behave the same way
21
that "virt" did in the 2.10 release, and making it do that
22
provides a usable workaround for guests with bugs like this.
23
5
24
Cc: qemu-stable@nongnu.org
6
Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
7
Reviewed-by: Andrew Jones <drjones@redhat.com>
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
Message-id: 20180925144127.31965-1-peter.maydell@linaro.org
27
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
28
---
9
---
29
hw/arm/virt.c | 2 ++
10
hw/arm/virt.c | 57 ++++++++++++++++++++++++++++++++-------------------
30
1 file changed, 2 insertions(+)
11
1 file changed, 36 insertions(+), 21 deletions(-)
31
12
32
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
13
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
33
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
34
--- a/hw/arm/virt.c
15
--- a/hw/arm/virt.c
35
+++ b/hw/arm/virt.c
16
+++ b/hw/arm/virt.c
36
@@ -XXX,XX +XXX,XX @@ static void virt_machine_2_10_options(MachineClass *mc)
17
@@ -XXX,XX +XXX,XX @@ static void virt_powerdown_req(Notifier *n, void *opaque)
18
}
19
}
20
21
-static void create_gpio(const VirtMachineState *vms)
22
+static void create_gpio_keys(const VirtMachineState *vms,
23
+ DeviceState *pl061_dev,
24
+ uint32_t phandle)
25
+{
26
+ gpio_key_dev = sysbus_create_simple("gpio-key", -1,
27
+ qdev_get_gpio_in(pl061_dev, 3));
28
+
29
+ qemu_fdt_add_subnode(vms->fdt, "/gpio-keys");
30
+ qemu_fdt_setprop_string(vms->fdt, "/gpio-keys", "compatible", "gpio-keys");
31
+ qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys", "#size-cells", 0);
32
+ qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys", "#address-cells", 1);
33
+
34
+ qemu_fdt_add_subnode(vms->fdt, "/gpio-keys/poweroff");
35
+ qemu_fdt_setprop_string(vms->fdt, "/gpio-keys/poweroff",
36
+ "label", "GPIO Key Poweroff");
37
+ qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys/poweroff", "linux,code",
38
+ KEY_POWER);
39
+ qemu_fdt_setprop_cells(vms->fdt, "/gpio-keys/poweroff",
40
+ "gpios", phandle, 3, 0);
41
+}
42
+
43
+static void create_gpio_devices(const VirtMachineState *vms, int gpio,
44
+ MemoryRegion *mem)
37
{
45
{
38
virt_machine_2_11_options(mc);
46
char *nodename;
39
SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_10);
47
DeviceState *pl061_dev;
40
+ /* before 2.11 we never faulted accesses to bad addresses */
48
- hwaddr base = vms->memmap[VIRT_GPIO].base;
41
+ mc->ignore_memory_transaction_failures = true;
49
- hwaddr size = vms->memmap[VIRT_GPIO].size;
50
- int irq = vms->irqmap[VIRT_GPIO];
51
+ hwaddr base = vms->memmap[gpio].base;
52
+ hwaddr size = vms->memmap[gpio].size;
53
+ int irq = vms->irqmap[gpio];
54
const char compat[] = "arm,pl061\0arm,primecell";
55
+ SysBusDevice *s;
56
57
- pl061_dev = sysbus_create_simple("pl061", base,
58
- qdev_get_gpio_in(vms->gic, irq));
59
+ pl061_dev = qdev_new("pl061");
60
+ s = SYS_BUS_DEVICE(pl061_dev);
61
+ sysbus_realize_and_unref(s, &error_fatal);
62
+ memory_region_add_subregion(mem, base, sysbus_mmio_get_region(s, 0));
63
+ sysbus_connect_irq(s, 0, qdev_get_gpio_in(vms->gic, irq));
64
65
uint32_t phandle = qemu_fdt_alloc_phandle(vms->fdt);
66
nodename = g_strdup_printf("/pl061@%" PRIx64, base);
67
@@ -XXX,XX +XXX,XX @@ static void create_gpio(const VirtMachineState *vms)
68
qemu_fdt_setprop_string(vms->fdt, nodename, "clock-names", "apb_pclk");
69
qemu_fdt_setprop_cell(vms->fdt, nodename, "phandle", phandle);
70
71
- gpio_key_dev = sysbus_create_simple("gpio-key", -1,
72
- qdev_get_gpio_in(pl061_dev, 3));
73
- qemu_fdt_add_subnode(vms->fdt, "/gpio-keys");
74
- qemu_fdt_setprop_string(vms->fdt, "/gpio-keys", "compatible", "gpio-keys");
75
- qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys", "#size-cells", 0);
76
- qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys", "#address-cells", 1);
77
-
78
- qemu_fdt_add_subnode(vms->fdt, "/gpio-keys/poweroff");
79
- qemu_fdt_setprop_string(vms->fdt, "/gpio-keys/poweroff",
80
- "label", "GPIO Key Poweroff");
81
- qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys/poweroff", "linux,code",
82
- KEY_POWER);
83
- qemu_fdt_setprop_cells(vms->fdt, "/gpio-keys/poweroff",
84
- "gpios", phandle, 3, 0);
85
g_free(nodename);
86
+
87
+ /* Child gpio devices */
88
+ create_gpio_keys(vms, pl061_dev, phandle);
42
}
89
}
43
DEFINE_VIRT_MACHINE(2, 10)
90
44
91
static void create_virtio_devices(const VirtMachineState *vms)
92
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
93
if (has_ged && aarch64 && firmware_loaded && virt_is_acpi_enabled(vms)) {
94
vms->acpi_dev = create_acpi_ged(vms);
95
} else {
96
- create_gpio(vms);
97
+ create_gpio_devices(vms, VIRT_GPIO, sysmem);
98
}
99
100
/* connect powerdown request */
45
--
101
--
46
2.19.0
102
2.20.1
47
103
48
104
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Maxim Uvarov <maxim.uvarov@linaro.org>
2
2
3
SVE vector length can change when changing EL, or when writing
3
Add secure pl061 for reset/power down machine from
4
to one of the ZCR_ELn registers.
4
the secure world (Arm Trusted Firmware). Connect it
5
with gpio-pwr driver.
5
6
6
For correctness, our implementation requires that predicate bits
7
Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
7
that are inaccessible are never set. Which means noticing length
8
Reviewed-by: Andrew Jones <drjones@redhat.com>
8
changes and zeroing the appropriate register bits.
9
[PMM: Added mention of the new device to the documentation]
9
10
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20181005175350.30752-5-richard.henderson@linaro.org
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
11
---
16
target/arm/cpu.h | 4 ++
12
docs/system/arm/virt.rst | 2 ++
17
target/arm/cpu64.c | 42 -------------
13
include/hw/arm/virt.h | 2 ++
18
target/arm/helper.c | 133 +++++++++++++++++++++++++++++++++++++----
14
hw/arm/virt.c | 56 +++++++++++++++++++++++++++++++++++++++-
19
target/arm/op_helper.c | 1 +
15
hw/arm/Kconfig | 1 +
20
4 files changed, 125 insertions(+), 55 deletions(-)
16
4 files changed, 60 insertions(+), 1 deletion(-)
21
17
22
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
18
diff --git a/docs/system/arm/virt.rst b/docs/system/arm/virt.rst
23
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/cpu.h
20
--- a/docs/system/arm/virt.rst
25
+++ b/target/arm/cpu.h
21
+++ b/docs/system/arm/virt.rst
26
@@ -XXX,XX +XXX,XX @@ int arm_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
22
@@ -XXX,XX +XXX,XX @@ The virt board supports:
27
int aarch64_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
23
- Secure-World-only devices if the CPU has TrustZone:
28
int aarch64_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
24
29
void aarch64_sve_narrow_vq(CPUARMState *env, unsigned vq);
25
- A second PL011 UART
30
+void aarch64_sve_change_el(CPUARMState *env, int old_el, int new_el);
26
+ - A second PL061 GPIO controller, with GPIO lines for triggering
31
+#else
27
+ a system reset or system poweroff
32
+static inline void aarch64_sve_narrow_vq(CPUARMState *env, unsigned vq) { }
28
- A secure flash memory
33
+static inline void aarch64_sve_change_el(CPUARMState *env, int o, int n) { }
29
- 16MB of secure RAM
34
#endif
30
35
31
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
36
target_ulong do_arm_semihosting(CPUARMState *env);
37
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
38
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
39
--- a/target/arm/cpu64.c
33
--- a/include/hw/arm/virt.h
40
+++ b/target/arm/cpu64.c
34
+++ b/include/hw/arm/virt.h
41
@@ -XXX,XX +XXX,XX @@ static void aarch64_cpu_register_types(void)
35
@@ -XXX,XX +XXX,XX @@ enum {
36
VIRT_GPIO,
37
VIRT_SECURE_UART,
38
VIRT_SECURE_MEM,
39
+ VIRT_SECURE_GPIO,
40
VIRT_PCDIMM_ACPI,
41
VIRT_ACPI_GED,
42
VIRT_NVDIMM_ACPI,
43
@@ -XXX,XX +XXX,XX @@ struct VirtMachineClass {
44
bool kvm_no_adjvtime;
45
bool no_kvm_steal_time;
46
bool acpi_expose_flash;
47
+ bool no_secure_gpio;
48
};
49
50
struct VirtMachineState {
51
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/hw/arm/virt.c
54
+++ b/hw/arm/virt.c
55
@@ -XXX,XX +XXX,XX @@ static const MemMapEntry base_memmap[] = {
56
[VIRT_ACPI_GED] = { 0x09080000, ACPI_GED_EVT_SEL_LEN },
57
[VIRT_NVDIMM_ACPI] = { 0x09090000, NVDIMM_ACPI_IO_LEN},
58
[VIRT_PVTIME] = { 0x090a0000, 0x00010000 },
59
+ [VIRT_SECURE_GPIO] = { 0x090b0000, 0x00001000 },
60
[VIRT_MMIO] = { 0x0a000000, 0x00000200 },
61
/* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
62
[VIRT_PLATFORM_BUS] = { 0x0c000000, 0x02000000 },
63
@@ -XXX,XX +XXX,XX @@ static void create_gpio_keys(const VirtMachineState *vms,
64
"gpios", phandle, 3, 0);
42
}
65
}
43
66
44
type_init(aarch64_cpu_register_types)
67
+#define SECURE_GPIO_POWEROFF 0
45
-
68
+#define SECURE_GPIO_RESET 1
46
-/* The manual says that when SVE is enabled and VQ is widened the
69
+
47
- * implementation is allowed to zero the previously inaccessible
70
+static void create_secure_gpio_pwr(const VirtMachineState *vms,
48
- * portion of the registers. The corollary to that is that when
71
+ DeviceState *pl061_dev,
49
- * SVE is enabled and VQ is narrowed we are also allowed to zero
72
+ uint32_t phandle)
50
- * the now inaccessible portion of the registers.
51
- *
52
- * The intent of this is that no predicate bit beyond VQ is ever set.
53
- * Which means that some operations on predicate registers themselves
54
- * may operate on full uint64_t or even unrolled across the maximum
55
- * uint64_t[4]. Performing 4 bits of host arithmetic unconditionally
56
- * may well be cheaper than conditionals to restrict the operation
57
- * to the relevant portion of a uint16_t[16].
58
- *
59
- * TODO: Need to call this for changes to the real system registers
60
- * and EL state changes.
61
- */
62
-void aarch64_sve_narrow_vq(CPUARMState *env, unsigned vq)
63
-{
64
- int i, j;
65
- uint64_t pmask;
66
-
67
- assert(vq >= 1 && vq <= ARM_MAX_VQ);
68
- assert(vq <= arm_env_get_cpu(env)->sve_max_vq);
69
-
70
- /* Zap the high bits of the zregs. */
71
- for (i = 0; i < 32; i++) {
72
- memset(&env->vfp.zregs[i].d[2 * vq], 0, 16 * (ARM_MAX_VQ - vq));
73
- }
74
-
75
- /* Zap the high bits of the pregs and ffr. */
76
- pmask = 0;
77
- if (vq & 3) {
78
- pmask = ~(-1ULL << (16 * (vq & 3)));
79
- }
80
- for (j = vq / 4; j < ARM_MAX_VQ / 4; j++) {
81
- for (i = 0; i < 17; ++i) {
82
- env->vfp.pregs[i].p[j] &= pmask;
83
- }
84
- pmask = 0;
85
- }
86
-}
87
diff --git a/target/arm/helper.c b/target/arm/helper.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/target/arm/helper.c
90
+++ b/target/arm/helper.c
91
@@ -XXX,XX +XXX,XX @@ static int sve_exception_el(CPUARMState *env, int el)
92
return 0;
93
}
94
95
+/*
96
+ * Given that SVE is enabled, return the vector length for EL.
97
+ */
98
+static uint32_t sve_zcr_len_for_el(CPUARMState *env, int el)
99
+{
73
+{
100
+ ARMCPU *cpu = arm_env_get_cpu(env);
74
+ DeviceState *gpio_pwr_dev;
101
+ uint32_t zcr_len = cpu->sve_max_vq - 1;
102
+
75
+
103
+ if (el <= 1) {
76
+ /* gpio-pwr */
104
+ zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[1]);
77
+ gpio_pwr_dev = sysbus_create_simple("gpio-pwr", -1, NULL);
105
+ }
78
+
106
+ if (el < 2 && arm_feature(env, ARM_FEATURE_EL2)) {
79
+ /* connect secure pl061 to gpio-pwr */
107
+ zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[2]);
80
+ qdev_connect_gpio_out(pl061_dev, SECURE_GPIO_RESET,
108
+ }
81
+ qdev_get_gpio_in_named(gpio_pwr_dev, "reset", 0));
109
+ if (el < 3 && arm_feature(env, ARM_FEATURE_EL3)) {
82
+ qdev_connect_gpio_out(pl061_dev, SECURE_GPIO_POWEROFF,
110
+ zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[3]);
83
+ qdev_get_gpio_in_named(gpio_pwr_dev, "shutdown", 0));
111
+ }
84
+
112
+ return zcr_len;
85
+ qemu_fdt_add_subnode(vms->fdt, "/gpio-poweroff");
86
+ qemu_fdt_setprop_string(vms->fdt, "/gpio-poweroff", "compatible",
87
+ "gpio-poweroff");
88
+ qemu_fdt_setprop_cells(vms->fdt, "/gpio-poweroff",
89
+ "gpios", phandle, SECURE_GPIO_POWEROFF, 0);
90
+ qemu_fdt_setprop_string(vms->fdt, "/gpio-poweroff", "status", "disabled");
91
+ qemu_fdt_setprop_string(vms->fdt, "/gpio-poweroff", "secure-status",
92
+ "okay");
93
+
94
+ qemu_fdt_add_subnode(vms->fdt, "/gpio-restart");
95
+ qemu_fdt_setprop_string(vms->fdt, "/gpio-restart", "compatible",
96
+ "gpio-restart");
97
+ qemu_fdt_setprop_cells(vms->fdt, "/gpio-restart",
98
+ "gpios", phandle, SECURE_GPIO_RESET, 0);
99
+ qemu_fdt_setprop_string(vms->fdt, "/gpio-restart", "status", "disabled");
100
+ qemu_fdt_setprop_string(vms->fdt, "/gpio-restart", "secure-status",
101
+ "okay");
113
+}
102
+}
114
+
103
+
115
static void zcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
104
static void create_gpio_devices(const VirtMachineState *vms, int gpio,
116
uint64_t value)
105
MemoryRegion *mem)
117
{
106
{
118
+ int cur_el = arm_current_el(env);
107
@@ -XXX,XX +XXX,XX @@ static void create_gpio_devices(const VirtMachineState *vms, int gpio,
119
+ int old_len = sve_zcr_len_for_el(env, cur_el);
108
qemu_fdt_setprop_string(vms->fdt, nodename, "clock-names", "apb_pclk");
120
+ int new_len;
109
qemu_fdt_setprop_cell(vms->fdt, nodename, "phandle", phandle);
121
+
110
122
/* Bits other than [3:0] are RAZ/WI. */
111
+ if (gpio != VIRT_GPIO) {
123
raw_write(env, ri, value & 0xf);
112
+ /* Mark as not usable by the normal world */
124
+
113
+ qemu_fdt_setprop_string(vms->fdt, nodename, "status", "disabled");
125
+ /*
114
+ qemu_fdt_setprop_string(vms->fdt, nodename, "secure-status", "okay");
126
+ * Because we arrived here, we know both FP and SVE are enabled;
115
+ }
127
+ * otherwise we would have trapped access to the ZCR_ELn register.
116
g_free(nodename);
128
+ */
117
129
+ new_len = sve_zcr_len_for_el(env, cur_el);
118
/* Child gpio devices */
130
+ if (new_len < old_len) {
119
- create_gpio_keys(vms, pl061_dev, phandle);
131
+ aarch64_sve_narrow_vq(env, new_len + 1);
120
+ if (gpio == VIRT_GPIO) {
121
+ create_gpio_keys(vms, pl061_dev, phandle);
122
+ } else {
123
+ create_secure_gpio_pwr(vms, pl061_dev, phandle);
132
+ }
124
+ }
133
}
125
}
134
126
135
static const ARMCPRegInfo zcr_el1_reginfo = {
127
static void create_virtio_devices(const VirtMachineState *vms)
136
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
128
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
137
unsigned int new_el = env->exception.target_el;
129
create_gpio_devices(vms, VIRT_GPIO, sysmem);
138
target_ulong addr = env->cp15.vbar_el[new_el];
130
}
139
unsigned int new_mode = aarch64_pstate_mode(new_el, true);
131
140
+ unsigned int cur_el = arm_current_el(env);
132
+ if (vms->secure && !vmc->no_secure_gpio) {
141
133
+ create_gpio_devices(vms, VIRT_SECURE_GPIO, secure_sysmem);
142
- if (arm_current_el(env) < new_el) {
143
+ aarch64_sve_change_el(env, cur_el, new_el);
144
+
145
+ if (cur_el < new_el) {
146
/* Entry vector offset depends on whether the implemented EL
147
* immediately lower than the target level is using AArch32 or AArch64
148
*/
149
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
150
if (sve_el != 0 && fp_el == 0) {
151
zcr_len = 0;
152
} else {
153
- ARMCPU *cpu = arm_env_get_cpu(env);
154
-
155
- zcr_len = cpu->sve_max_vq - 1;
156
- if (current_el <= 1) {
157
- zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[1]);
158
- }
159
- if (current_el < 2 && arm_feature(env, ARM_FEATURE_EL2)) {
160
- zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[2]);
161
- }
162
- if (current_el < 3 && arm_feature(env, ARM_FEATURE_EL3)) {
163
- zcr_len = MIN(zcr_len, 0xf & (uint32_t)env->vfp.zcr_el[3]);
164
- }
165
+ zcr_len = sve_zcr_len_for_el(env, current_el);
166
}
167
flags |= sve_el << ARM_TBFLAG_SVEEXC_EL_SHIFT;
168
flags |= zcr_len << ARM_TBFLAG_ZCR_LEN_SHIFT;
169
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
170
*pflags = flags;
171
*cs_base = 0;
172
}
173
+
174
+#ifdef TARGET_AARCH64
175
+/*
176
+ * The manual says that when SVE is enabled and VQ is widened the
177
+ * implementation is allowed to zero the previously inaccessible
178
+ * portion of the registers. The corollary to that is that when
179
+ * SVE is enabled and VQ is narrowed we are also allowed to zero
180
+ * the now inaccessible portion of the registers.
181
+ *
182
+ * The intent of this is that no predicate bit beyond VQ is ever set.
183
+ * Which means that some operations on predicate registers themselves
184
+ * may operate on full uint64_t or even unrolled across the maximum
185
+ * uint64_t[4]. Performing 4 bits of host arithmetic unconditionally
186
+ * may well be cheaper than conditionals to restrict the operation
187
+ * to the relevant portion of a uint16_t[16].
188
+ */
189
+void aarch64_sve_narrow_vq(CPUARMState *env, unsigned vq)
190
+{
191
+ int i, j;
192
+ uint64_t pmask;
193
+
194
+ assert(vq >= 1 && vq <= ARM_MAX_VQ);
195
+ assert(vq <= arm_env_get_cpu(env)->sve_max_vq);
196
+
197
+ /* Zap the high bits of the zregs. */
198
+ for (i = 0; i < 32; i++) {
199
+ memset(&env->vfp.zregs[i].d[2 * vq], 0, 16 * (ARM_MAX_VQ - vq));
200
+ }
134
+ }
201
+
135
+
202
+ /* Zap the high bits of the pregs and ffr. */
136
/* connect powerdown request */
203
+ pmask = 0;
137
vms->powerdown_notifier.notify = virt_powerdown_req;
204
+ if (vq & 3) {
138
qemu_register_powerdown_notifier(&vms->powerdown_notifier);
205
+ pmask = ~(-1ULL << (16 * (vq & 3)));
139
@@ -XXX,XX +XXX,XX @@ DEFINE_VIRT_MACHINE_AS_LATEST(6, 0)
206
+ }
140
207
+ for (j = vq / 4; j < ARM_MAX_VQ / 4; j++) {
141
static void virt_machine_5_2_options(MachineClass *mc)
208
+ for (i = 0; i < 17; ++i) {
142
{
209
+ env->vfp.pregs[i].p[j] &= pmask;
143
+ VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
210
+ }
211
+ pmask = 0;
212
+ }
213
+}
214
+
144
+
215
+/*
145
virt_machine_6_0_options(mc);
216
+ * Notice a change in SVE vector size when changing EL.
146
compat_props_add(mc->compat_props, hw_compat_5_2, hw_compat_5_2_len);
217
+ */
147
+ vmc->no_secure_gpio = true;
218
+void aarch64_sve_change_el(CPUARMState *env, int old_el, int new_el)
148
}
219
+{
149
DEFINE_VIRT_MACHINE(5, 2)
220
+ int old_len, new_len;
150
221
+
151
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
222
+ /* Nothing to do if no SVE. */
223
+ if (!arm_feature(env, ARM_FEATURE_SVE)) {
224
+ return;
225
+ }
226
+
227
+ /* Nothing to do if FP is disabled in either EL. */
228
+ if (fp_exception_el(env, old_el) || fp_exception_el(env, new_el)) {
229
+ return;
230
+ }
231
+
232
+ /*
233
+ * DDI0584A.d sec 3.2: "If SVE instructions are disabled or trapped
234
+ * at ELx, or not available because the EL is in AArch32 state, then
235
+ * for all purposes other than a direct read, the ZCR_ELx.LEN field
236
+ * has an effective value of 0".
237
+ *
238
+ * Consider EL2 (aa64, vq=4) -> EL0 (aa32) -> EL1 (aa64, vq=0).
239
+ * If we ignore aa32 state, we would fail to see the vq4->vq0 transition
240
+ * from EL2->EL1. Thus we go ahead and narrow when entering aa32 so that
241
+ * we already have the correct register contents when encountering the
242
+ * vq0->vq0 transition between EL0->EL1.
243
+ */
244
+ old_len = (arm_el_is_aa64(env, old_el) && !sve_exception_el(env, old_el)
245
+ ? sve_zcr_len_for_el(env, old_el) : 0);
246
+ new_len = (arm_el_is_aa64(env, new_el) && !sve_exception_el(env, new_el)
247
+ ? sve_zcr_len_for_el(env, new_el) : 0);
248
+
249
+ /* When changing vector length, clear inaccessible state. */
250
+ if (new_len < old_len) {
251
+ aarch64_sve_narrow_vq(env, new_len + 1);
252
+ }
253
+}
254
+#endif
255
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
256
index XXXXXXX..XXXXXXX 100644
152
index XXXXXXX..XXXXXXX 100644
257
--- a/target/arm/op_helper.c
153
--- a/hw/arm/Kconfig
258
+++ b/target/arm/op_helper.c
154
+++ b/hw/arm/Kconfig
259
@@ -XXX,XX +XXX,XX @@ void HELPER(exception_return)(CPUARMState *env)
155
@@ -XXX,XX +XXX,XX @@ config ARM_VIRT
260
"AArch64 EL%d PC 0x%" PRIx64 "\n",
156
select PL011 # UART
261
cur_el, new_el, env->pc);
157
select PL031 # RTC
262
}
158
select PL061 # GPIO
263
+ aarch64_sve_change_el(env, cur_el, new_el);
159
+ select GPIO_PWR
264
160
select PLATFORM_BUS
265
qemu_mutex_lock_iothread();
161
select SMBIOS
266
arm_call_el_change_hook(arm_env_get_cpu(env));
162
select VIRTIO_MMIO
267
--
163
--
268
2.19.0
164
2.20.1
269
165
270
166
diff view generated by jsdifflib
New patch
1
From: Hao Wu <wuhaotsh@google.com>
1
2
3
Fix potential overflow problem when calculating pwm_duty.
4
1. Ensure p->cmr and p->cnr to be from [0,65535], according to the
5
hardware specification.
6
2. Changed duty to uint32_t. However, since MAX_DUTY * (p->cmr+1)
7
can excceed UINT32_MAX, we convert them to uint64_t in computation
8
and converted them back to uint32_t.
9
(duty is guaranteed to be <= MAX_DUTY so it won't overflow.)
10
11
Fixes: CID 1442342
12
Suggested-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Doug Evans <dje@google.com>
14
Signed-off-by: Hao Wu <wuhaotsh@google.com>
15
Message-id: 20210127011142.2122790-1-wuhaotsh@google.com
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
19
hw/misc/npcm7xx_pwm.c | 23 +++++++++++++++++++----
20
tests/qtest/npcm7xx_pwm-test.c | 4 ++--
21
2 files changed, 21 insertions(+), 6 deletions(-)
22
23
diff --git a/hw/misc/npcm7xx_pwm.c b/hw/misc/npcm7xx_pwm.c
24
index XXXXXXX..XXXXXXX 100644
25
--- a/hw/misc/npcm7xx_pwm.c
26
+++ b/hw/misc/npcm7xx_pwm.c
27
@@ -XXX,XX +XXX,XX @@ REG32(NPCM7XX_PWM_PWDR3, 0x50);
28
#define NPCM7XX_CH_INV BIT(2)
29
#define NPCM7XX_CH_MOD BIT(3)
30
31
+#define NPCM7XX_MAX_CMR 65535
32
+#define NPCM7XX_MAX_CNR 65535
33
+
34
/* Offset of each PWM channel's prescaler in the PPR register. */
35
static const int npcm7xx_ppr_base[] = { 0, 0, 8, 8 };
36
/* Offset of each PWM channel's clock selector in the CSR register. */
37
@@ -XXX,XX +XXX,XX @@ static uint32_t npcm7xx_pwm_calculate_freq(NPCM7xxPWM *p)
38
39
static uint32_t npcm7xx_pwm_calculate_duty(NPCM7xxPWM *p)
40
{
41
- uint64_t duty;
42
+ uint32_t duty;
43
44
if (p->running) {
45
if (p->cnr == 0) {
46
@@ -XXX,XX +XXX,XX @@ static uint32_t npcm7xx_pwm_calculate_duty(NPCM7xxPWM *p)
47
} else if (p->cmr >= p->cnr) {
48
duty = NPCM7XX_PWM_MAX_DUTY;
49
} else {
50
- duty = NPCM7XX_PWM_MAX_DUTY * (p->cmr + 1) / (p->cnr + 1);
51
+ duty = (uint64_t)NPCM7XX_PWM_MAX_DUTY * (p->cmr + 1) / (p->cnr + 1);
52
}
53
} else {
54
duty = 0;
55
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_pwm_write(void *opaque, hwaddr offset,
56
case A_NPCM7XX_PWM_CNR2:
57
case A_NPCM7XX_PWM_CNR3:
58
p = &s->pwm[npcm7xx_cnr_index(offset)];
59
- p->cnr = value;
60
+ if (value > NPCM7XX_MAX_CNR) {
61
+ qemu_log_mask(LOG_GUEST_ERROR,
62
+ "%s: invalid cnr value: %u", __func__, value);
63
+ p->cnr = NPCM7XX_MAX_CNR;
64
+ } else {
65
+ p->cnr = value;
66
+ }
67
npcm7xx_pwm_update_output(p);
68
break;
69
70
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_pwm_write(void *opaque, hwaddr offset,
71
case A_NPCM7XX_PWM_CMR2:
72
case A_NPCM7XX_PWM_CMR3:
73
p = &s->pwm[npcm7xx_cmr_index(offset)];
74
- p->cmr = value;
75
+ if (value > NPCM7XX_MAX_CMR) {
76
+ qemu_log_mask(LOG_GUEST_ERROR,
77
+ "%s: invalid cmr value: %u", __func__, value);
78
+ p->cmr = NPCM7XX_MAX_CMR;
79
+ } else {
80
+ p->cmr = value;
81
+ }
82
npcm7xx_pwm_update_output(p);
83
break;
84
85
diff --git a/tests/qtest/npcm7xx_pwm-test.c b/tests/qtest/npcm7xx_pwm-test.c
86
index XXXXXXX..XXXXXXX 100644
87
--- a/tests/qtest/npcm7xx_pwm-test.c
88
+++ b/tests/qtest/npcm7xx_pwm-test.c
89
@@ -XXX,XX +XXX,XX @@ static uint64_t pwm_compute_freq(QTestState *qts, uint32_t ppr, uint32_t csr,
90
91
static uint64_t pwm_compute_duty(uint32_t cnr, uint32_t cmr, bool inverted)
92
{
93
- uint64_t duty;
94
+ uint32_t duty;
95
96
if (cnr == 0) {
97
/* PWM is stopped. */
98
@@ -XXX,XX +XXX,XX @@ static uint64_t pwm_compute_duty(uint32_t cnr, uint32_t cmr, bool inverted)
99
} else if (cmr >= cnr) {
100
duty = MAX_DUTY;
101
} else {
102
- duty = MAX_DUTY * (cmr + 1) / (cnr + 1);
103
+ duty = (uint64_t)MAX_DUTY * (cmr + 1) / (cnr + 1);
104
}
105
106
if (inverted) {
107
--
108
2.20.1
109
110
diff view generated by jsdifflib
1
In v7m_exception_taken() we were incorrectly using a
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
"LR bit EXCRET.ES is 1" check when it should be 0
3
(compare the pseudocode ExceptionTaken() function).
4
This meant we didn't stack the callee-saved registers
5
when tailchaining from a NonSecure to a Secure exception.
6
2
7
Cc: qemu-stable@nongnu.org
3
cpu_get_phys_page_debug() uses 'DATA LOAD' MMU access type.
4
5
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Message-id: 20210127232822.3530782-1-f4bug@amsat.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
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: 20181002145940.30931-1-peter.maydell@linaro.org
11
---
9
---
12
target/arm/helper.c | 2 +-
10
target/arm/helper.c | 2 +-
13
1 file changed, 1 insertion(+), 1 deletion(-)
11
1 file changed, 1 insertion(+), 1 deletion(-)
14
12
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.c
15
--- a/target/arm/helper.c
18
+++ b/target/arm/helper.c
16
+++ b/target/arm/helper.c
19
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
17
@@ -XXX,XX +XXX,XX @@ hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState *cs, vaddr addr,
20
* not already saved.
18
21
*/
19
*attrs = (MemTxAttrs) {};
22
if (lr & R_V7M_EXCRET_DCRS_MASK &&
20
23
- !(dotailchain && (lr & R_V7M_EXCRET_ES_MASK))) {
21
- ret = get_phys_addr(env, addr, 0, mmu_idx, &phys_addr,
24
+ !(dotailchain && !(lr & R_V7M_EXCRET_ES_MASK))) {
22
+ ret = get_phys_addr(env, addr, MMU_DATA_LOAD, mmu_idx, &phys_addr,
25
push_failed = v7m_push_callee_stack(cpu, lr, dotailchain,
23
attrs, &prot, &page_size, &fi, &cacheattrs);
26
ignore_stackfaults);
24
27
}
25
if (ret) {
28
--
26
--
29
2.19.0
27
2.20.1
30
28
31
29
diff view generated by jsdifflib
New patch
1
Move the preadv availability check to meson.build. This is what we
2
want to be doing for host-OS-feature-checks anyway, but it also fixes
3
a problem with building for macOS with the most recent XCode SDK on a
4
Catalina host.
1
5
6
On that configuration, 'preadv()' is provided as a weak symbol, so
7
that programs can be built with optional support for it and make a
8
runtime availability check to see whether the preadv() they have is a
9
working one or one which they must not call because it will
10
runtime-assert. QEMU's configure test passes (unless you're building
11
with --enable-werror) because the test program using preadv()
12
compiles, but then QEMU crashes at runtime when preadv() is called,
13
with errors like:
14
15
dyld: lazy symbol binding failed: Symbol not found: _preadv
16
Referenced from: /Users/pm215/src/qemu/./build/x86/tests/test-replication
17
Expected in: /usr/lib/libSystem.B.dylib
18
19
dyld: Symbol not found: _preadv
20
Referenced from: /Users/pm215/src/qemu/./build/x86/tests/test-replication
21
Expected in: /usr/lib/libSystem.B.dylib
22
23
Meson's own function availability check has a special case for macOS
24
which adds '-Wl,-no_weak_imports' to the compiler flags, which forces
25
the test to require the real function, not the macOS-version-too-old
26
stub.
27
28
So this commit fixes the bug where macOS builds on Catalina currently
29
require --disable-werror.
30
31
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
32
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
33
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
34
Message-id: 20210126155846.17109-1-peter.maydell@linaro.org
35
---
36
configure | 16 ----------------
37
meson.build | 4 +++-
38
2 files changed, 3 insertions(+), 17 deletions(-)
39
40
diff --git a/configure b/configure
41
index XXXXXXX..XXXXXXX 100755
42
--- a/configure
43
+++ b/configure
44
@@ -XXX,XX +XXX,XX @@ if compile_prog "" "" ; then
45
iovec=yes
46
fi
47
48
-##########################################
49
-# preadv probe
50
-cat > $TMPC <<EOF
51
-#include <sys/types.h>
52
-#include <sys/uio.h>
53
-#include <unistd.h>
54
-int main(void) { return preadv(0, 0, 0, 0); }
55
-EOF
56
-preadv=no
57
-if compile_prog "" "" ; then
58
- preadv=yes
59
-fi
60
-
61
##########################################
62
# fdt probe
63
64
@@ -XXX,XX +XXX,XX @@ fi
65
if test "$iovec" = "yes" ; then
66
echo "CONFIG_IOVEC=y" >> $config_host_mak
67
fi
68
-if test "$preadv" = "yes" ; then
69
- echo "CONFIG_PREADV=y" >> $config_host_mak
70
-fi
71
if test "$membarrier" = "yes" ; then
72
echo "CONFIG_MEMBARRIER=y" >> $config_host_mak
73
fi
74
diff --git a/meson.build b/meson.build
75
index XXXXXXX..XXXXXXX 100644
76
--- a/meson.build
77
+++ b/meson.build
78
@@ -XXX,XX +XXX,XX @@ config_host_data.set('HAVE_PTY_H', cc.has_header('pty.h'))
79
config_host_data.set('HAVE_SYS_IOCCOM_H', cc.has_header('sys/ioccom.h'))
80
config_host_data.set('HAVE_SYS_KCOV_H', cc.has_header('sys/kcov.h'))
81
82
+config_host_data.set('CONFIG_PREADV', cc.has_function('preadv', prefix: '#include <sys/uio.h>'))
83
+
84
ignored = ['CONFIG_QEMU_INTERP_PREFIX'] # actually per-target
85
arrays = ['CONFIG_AUDIO_DRIVERS', 'CONFIG_BDRV_RW_WHITELIST', 'CONFIG_BDRV_RO_WHITELIST']
86
strings = ['HOST_DSOSUF', 'CONFIG_IASL']
87
@@ -XXX,XX +XXX,XX @@ summary_info += {'PIE': get_option('b_pie')}
88
summary_info += {'static build': config_host.has_key('CONFIG_STATIC')}
89
summary_info += {'malloc trim support': has_malloc_trim}
90
summary_info += {'membarrier': config_host.has_key('CONFIG_MEMBARRIER')}
91
-summary_info += {'preadv support': config_host.has_key('CONFIG_PREADV')}
92
+summary_info += {'preadv support': config_host_data.get('CONFIG_PREADV')}
93
summary_info += {'fdatasync': config_host.has_key('CONFIG_FDATASYNC')}
94
summary_info += {'madvise': config_host.has_key('CONFIG_MADVISE')}
95
summary_info += {'posix_madvise': config_host.has_key('CONFIG_POSIX_MADVISE')}
96
--
97
2.20.1
98
99
diff view generated by jsdifflib
New patch
1
From: Joelle van Dyne <j@getutm.app>
1
2
3
The iOS toolchain does not use the host prefix naming convention. So we
4
need to enable cross-compile options while allowing the PREFIX to be
5
blank.
6
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Signed-off-by: Joelle van Dyne <j@getutm.app>
9
Message-id: 20210126012457.39046-3-j@getutm.app
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
configure | 6 ++++--
13
1 file changed, 4 insertions(+), 2 deletions(-)
14
15
diff --git a/configure b/configure
16
index XXXXXXX..XXXXXXX 100755
17
--- a/configure
18
+++ b/configure
19
@@ -XXX,XX +XXX,XX @@ cpu=""
20
iasl="iasl"
21
interp_prefix="/usr/gnemul/qemu-%M"
22
static="no"
23
+cross_compile="no"
24
cross_prefix=""
25
audio_drv_list=""
26
block_drv_rw_whitelist=""
27
@@ -XXX,XX +XXX,XX @@ for opt do
28
optarg=$(expr "x$opt" : 'x[^=]*=\(.*\)')
29
case "$opt" in
30
--cross-prefix=*) cross_prefix="$optarg"
31
+ cross_compile="yes"
32
;;
33
--cc=*) CC="$optarg"
34
;;
35
@@ -XXX,XX +XXX,XX @@ $(echo Deprecated targets: $deprecated_targets_list | \
36
--target-list-exclude=LIST exclude a set of targets from the default target-list
37
38
Advanced options (experts only):
39
- --cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix]
40
+ --cross-prefix=PREFIX use PREFIX for compile tools, PREFIX can be blank [$cross_prefix]
41
--cc=CC use C compiler CC [$cc]
42
--iasl=IASL use ACPI compiler IASL [$iasl]
43
--host-cc=CC use C compiler CC [$host_cc] for code run at
44
@@ -XXX,XX +XXX,XX @@ if has $sdl2_config; then
45
fi
46
echo "strip = [$(meson_quote $strip)]" >> $cross
47
echo "windres = [$(meson_quote $windres)]" >> $cross
48
-if test -n "$cross_prefix"; then
49
+if test "$cross_compile" = "yes"; then
50
cross_arg="--cross-file config-meson.cross"
51
echo "[host_machine]" >> $cross
52
if test "$mingw32" = "yes" ; then
53
--
54
2.20.1
55
56
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Joelle van Dyne <j@getutm.app>
2
2
3
Check for EL3 before testing CPTR_EL3.EZ. Return 0 when the exception
3
Build without error on hosts without a working system(). If system()
4
should be routed via AdvSIMDFPAccessTrap. Mirror the structure of
4
is called, return -1 with ENOSYS.
5
CheckSVEEnabled more closely.
6
5
7
Fixes: 5be5e8eda78
6
Signed-off-by: Joelle van Dyne <j@getutm.app>
7
Message-id: 20210126012457.39046-6-j@getutm.app
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20181005175350.30752-3-richard.henderson@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
10
---
14
target/arm/helper.c | 96 ++++++++++++++++++++++-----------------------
11
meson.build | 1 +
15
1 file changed, 46 insertions(+), 50 deletions(-)
12
include/qemu/osdep.h | 12 ++++++++++++
13
2 files changed, 13 insertions(+)
16
14
17
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
diff --git a/meson.build b/meson.build
18
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper.c
17
--- a/meson.build
20
+++ b/target/arm/helper.c
18
+++ b/meson.build
21
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo debug_lpae_cp_reginfo[] = {
19
@@ -XXX,XX +XXX,XX @@ config_host_data.set('HAVE_DRM_H', cc.has_header('libdrm/drm.h'))
22
REGINFO_SENTINEL
20
config_host_data.set('HAVE_PTY_H', cc.has_header('pty.h'))
23
};
21
config_host_data.set('HAVE_SYS_IOCCOM_H', cc.has_header('sys/ioccom.h'))
24
22
config_host_data.set('HAVE_SYS_KCOV_H', cc.has_header('sys/kcov.h'))
25
-/* Return the exception level to which SVE-disabled exceptions should
23
+config_host_data.set('HAVE_SYSTEM_FUNCTION', cc.has_function('system', prefix: '#include <stdlib.h>'))
26
- * be taken, or 0 if SVE is enabled.
24
27
+/* Return the exception level to which exceptions should be taken
25
config_host_data.set('CONFIG_PREADV', cc.has_function('preadv', prefix: '#include <sys/uio.h>'))
28
+ * via SVEAccessTrap. If an exception should be routed through
26
29
+ * AArch64.AdvSIMDFPAccessTrap, return 0; fp_exception_el should
27
diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
30
+ * take care of raising that exception.
28
index XXXXXXX..XXXXXXX 100644
31
+ * C.f. the ARM pseudocode function CheckSVEEnabled.
29
--- a/include/qemu/osdep.h
32
*/
30
+++ b/include/qemu/osdep.h
33
static int sve_exception_el(CPUARMState *env)
31
@@ -XXX,XX +XXX,XX @@ static inline void qemu_thread_jit_write(void) {}
34
{
32
static inline void qemu_thread_jit_execute(void) {}
35
#ifndef CONFIG_USER_ONLY
33
#endif
36
unsigned current_el = arm_current_el(env);
34
37
35
+/**
38
- /* The CPACR.ZEN controls traps to EL1:
36
+ * Platforms which do not support system() return ENOSYS
39
- * 0, 2 : trap EL0 and EL1 accesses
37
+ */
40
- * 1 : trap only EL0 accesses
38
+#ifndef HAVE_SYSTEM_FUNCTION
41
- * 3 : trap no accesses
39
+#define system platform_does_not_support_system
42
+ if (current_el <= 1) {
40
+static inline int platform_does_not_support_system(const char *command)
43
+ bool disabled = false;
41
+{
42
+ errno = ENOSYS;
43
+ return -1;
44
+}
45
+#endif /* !HAVE_SYSTEM_FUNCTION */
44
+
46
+
45
+ /* The CPACR.ZEN controls traps to EL1:
46
+ * 0, 2 : trap EL0 and EL1 accesses
47
+ * 1 : trap only EL0 accesses
48
+ * 3 : trap no accesses
49
+ */
50
+ if (!extract32(env->cp15.cpacr_el1, 16, 1)) {
51
+ disabled = true;
52
+ } else if (!extract32(env->cp15.cpacr_el1, 17, 1)) {
53
+ disabled = current_el == 0;
54
+ }
55
+ if (disabled) {
56
+ /* route_to_el2 */
57
+ return (arm_feature(env, ARM_FEATURE_EL2)
58
+ && !arm_is_secure(env)
59
+ && (env->cp15.hcr_el2 & HCR_TGE) ? 2 : 1);
60
+ }
61
+
62
+ /* Check CPACR.FPEN. */
63
+ if (!extract32(env->cp15.cpacr_el1, 20, 1)) {
64
+ disabled = true;
65
+ } else if (!extract32(env->cp15.cpacr_el1, 21, 1)) {
66
+ disabled = current_el == 0;
67
+ }
68
+ if (disabled) {
69
+ return 0;
70
+ }
71
+ }
72
+
73
+ /* CPTR_EL2. Since TZ and TFP are positive,
74
+ * they will be zero when EL2 is not present.
75
*/
76
- switch (extract32(env->cp15.cpacr_el1, 16, 2)) {
77
- default:
78
- if (current_el <= 1) {
79
- /* Trap to PL1, which might be EL1 or EL3 */
80
- if (arm_is_secure(env) && !arm_el_is_aa64(env, 3)) {
81
- return 3;
82
- }
83
- return 1;
84
+ if (current_el <= 2 && !arm_is_secure_below_el3(env)) {
85
+ if (env->cp15.cptr_el[2] & CPTR_TZ) {
86
+ return 2;
87
}
88
- break;
89
- case 1:
90
- if (current_el == 0) {
91
- return 1;
92
+ if (env->cp15.cptr_el[2] & CPTR_TFP) {
93
+ return 0;
94
}
95
- break;
96
- case 3:
97
- break;
98
}
99
100
- /* Similarly for CPACR.FPEN, after having checked ZEN. */
101
- switch (extract32(env->cp15.cpacr_el1, 20, 2)) {
102
- default:
103
- if (current_el <= 1) {
104
- if (arm_is_secure(env) && !arm_el_is_aa64(env, 3)) {
105
- return 3;
106
- }
107
- return 1;
108
- }
109
- break;
110
- case 1:
111
- if (current_el == 0) {
112
- return 1;
113
- }
114
- break;
115
- case 3:
116
- break;
117
- }
118
-
119
- /* CPTR_EL2. Check both TZ and TFP. */
120
- if (current_el <= 2
121
- && (env->cp15.cptr_el[2] & (CPTR_TFP | CPTR_TZ))
122
- && !arm_is_secure_below_el3(env)) {
123
- return 2;
124
- }
125
-
126
- /* CPTR_EL3. Check both EZ and TFP. */
127
- if (!(env->cp15.cptr_el[3] & CPTR_EZ)
128
- || (env->cp15.cptr_el[3] & CPTR_TFP)) {
129
+ /* CPTR_EL3. Since EZ is negative we must check for EL3. */
130
+ if (arm_feature(env, ARM_FEATURE_EL3)
131
+ && !(env->cp15.cptr_el[3] & CPTR_EZ)) {
132
return 3;
133
}
134
#endif
47
#endif
135
--
48
--
136
2.19.0
49
2.20.1
137
50
138
51
diff view generated by jsdifflib
New patch
1
From: Joelle van Dyne <j@getutm.app>
1
2
3
Meson will find CoreFoundation, IOKit, and Cocoa as needed.
4
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Joelle van Dyne <j@getutm.app>
7
Message-id: 20210126012457.39046-7-j@getutm.app
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
configure | 1 -
11
1 file changed, 1 deletion(-)
12
13
diff --git a/configure b/configure
14
index XXXXXXX..XXXXXXX 100755
15
--- a/configure
16
+++ b/configure
17
@@ -XXX,XX +XXX,XX @@ Darwin)
18
fi
19
audio_drv_list="coreaudio try-sdl"
20
audio_possible_drivers="coreaudio sdl"
21
- QEMU_LDFLAGS="-framework CoreFoundation -framework IOKit $QEMU_LDFLAGS"
22
# Disable attempts to use ObjectiveC features in os/object.h since they
23
# won't work when we're compiling with gcc as a C compiler.
24
QEMU_CFLAGS="-DOS_OBJECT_USE_OBJC=0 $QEMU_CFLAGS"
25
--
26
2.20.1
27
28
diff view generated by jsdifflib
New patch
1
From: Joelle van Dyne <j@getutm.app>
1
2
3
Add objc to the Meson cross file as well as detection of Darwin.
4
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Joelle van Dyne <j@getutm.app>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20210126012457.39046-8-j@getutm.app
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
configure | 4 ++++
12
1 file changed, 4 insertions(+)
13
14
diff --git a/configure b/configure
15
index XXXXXXX..XXXXXXX 100755
16
--- a/configure
17
+++ b/configure
18
@@ -XXX,XX +XXX,XX @@ echo "cpp_link_args = [${LDFLAGS:+$(meson_quote $LDFLAGS)}]" >> $cross
19
echo "[binaries]" >> $cross
20
echo "c = [$(meson_quote $cc)]" >> $cross
21
test -n "$cxx" && echo "cpp = [$(meson_quote $cxx)]" >> $cross
22
+test -n "$objcc" && echo "objc = [$(meson_quote $objcc)]" >> $cross
23
echo "ar = [$(meson_quote $ar)]" >> $cross
24
echo "nm = [$(meson_quote $nm)]" >> $cross
25
echo "pkgconfig = [$(meson_quote $pkg_config_exe)]" >> $cross
26
@@ -XXX,XX +XXX,XX @@ if test "$cross_compile" = "yes"; then
27
if test "$linux" = "yes" ; then
28
echo "system = 'linux'" >> $cross
29
fi
30
+ if test "$darwin" = "yes" ; then
31
+ echo "system = 'darwin'" >> $cross
32
+ fi
33
case "$ARCH" in
34
i386|x86_64)
35
echo "cpu_family = 'x86'" >> $cross
36
--
37
2.20.1
38
39
diff view generated by jsdifflib
New patch
1
From: Joelle van Dyne <j@getutm.app>
1
2
3
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
4
Signed-off-by: Joelle van Dyne <j@getutm.app>
5
Message-id: 20210126012457.39046-9-j@getutm.app
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
8
configure | 5 ++++-
9
1 file changed, 4 insertions(+), 1 deletion(-)
10
11
diff --git a/configure b/configure
12
index XXXXXXX..XXXXXXX 100755
13
--- a/configure
14
+++ b/configure
15
@@ -XXX,XX +XXX,XX @@ if test "$cross_compile" = "yes"; then
16
echo "system = 'darwin'" >> $cross
17
fi
18
case "$ARCH" in
19
- i386|x86_64)
20
+ i386)
21
echo "cpu_family = 'x86'" >> $cross
22
;;
23
+ x86_64)
24
+ echo "cpu_family = 'x86_64'" >> $cross
25
+ ;;
26
ppc64le)
27
echo "cpu_family = 'ppc64'" >> $cross
28
;;
29
--
30
2.20.1
31
32
diff view generated by jsdifflib
New patch
1
From: Joelle van Dyne <j@getutm.app>
1
2
3
On iOS there is no CoreAudio, so we should not assume Darwin always
4
has it.
5
6
Signed-off-by: Joelle van Dyne <j@getutm.app>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20210126012457.39046-11-j@getutm.app
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
configure | 35 +++++++++++++++++++++++++++++++++--
12
1 file changed, 33 insertions(+), 2 deletions(-)
13
14
diff --git a/configure b/configure
15
index XXXXXXX..XXXXXXX 100755
16
--- a/configure
17
+++ b/configure
18
@@ -XXX,XX +XXX,XX @@ fdt="auto"
19
netmap="no"
20
sdl="auto"
21
sdl_image="auto"
22
+coreaudio="auto"
23
virtiofsd="auto"
24
virtfs="auto"
25
libudev="auto"
26
@@ -XXX,XX +XXX,XX @@ Darwin)
27
QEMU_CFLAGS="-arch x86_64 $QEMU_CFLAGS"
28
QEMU_LDFLAGS="-arch x86_64 $QEMU_LDFLAGS"
29
fi
30
- audio_drv_list="coreaudio try-sdl"
31
+ audio_drv_list="try-coreaudio try-sdl"
32
audio_possible_drivers="coreaudio sdl"
33
# Disable attempts to use ObjectiveC features in os/object.h since they
34
# won't work when we're compiling with gcc as a C compiler.
35
@@ -XXX,XX +XXX,XX @@ EOF
36
fi
37
fi
38
39
+##########################################
40
+# detect CoreAudio
41
+if test "$coreaudio" != "no" ; then
42
+ coreaudio_libs="-framework CoreAudio"
43
+ cat > $TMPC << EOF
44
+#include <CoreAudio/CoreAudio.h>
45
+int main(void)
46
+{
47
+ return (int)AudioGetCurrentHostTime();
48
+}
49
+EOF
50
+ if compile_prog "" "$coreaudio_libs" ; then
51
+ coreaudio=yes
52
+ else
53
+ coreaudio=no
54
+ fi
55
+fi
56
+
57
##########################################
58
# Sound support libraries probe
59
60
@@ -XXX,XX +XXX,XX @@ for drv in $audio_drv_list; do
61
fi
62
;;
63
64
- coreaudio)
65
+ coreaudio | try-coreaudio)
66
+ if test "$coreaudio" = "no"; then
67
+ if test "$drv" = "try-coreaudio"; then
68
+ audio_drv_list=$(echo "$audio_drv_list" | sed -e 's/try-coreaudio//')
69
+ else
70
+ error_exit "$drv check failed" \
71
+ "Make sure to have the $drv is available."
72
+ fi
73
+ else
74
coreaudio_libs="-framework CoreAudio"
75
+ if test "$drv" = "try-coreaudio"; then
76
+ audio_drv_list=$(echo "$audio_drv_list" | sed -e 's/try-coreaudio/coreaudio/')
77
+ fi
78
+ fi
79
;;
80
81
dsound)
82
--
83
2.20.1
84
85
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Joelle van Dyne <j@getutm.app>
2
2
3
Given that the only field defined for this new register may only
3
A workaround added in early days of 64-bit OSX forced x86_64 if the
4
be 0, we don't actually need to change anything except the name.
4
host machine had 64-bit support. This creates issues when cross-
5
compiling for ARM64. Additionally, the user can always use --cpu=* to
6
manually set the host CPU and therefore this workaround should be
7
removed.
5
8
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
10
Signed-off-by: Joelle van Dyne <j@getutm.app>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20210126012457.39046-12-j@getutm.app
9
Message-id: 20181005175350.30752-2-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
13
---
12
target/arm/helper.c | 3 ++-
14
configure | 11 -----------
13
1 file changed, 2 insertions(+), 1 deletion(-)
15
1 file changed, 11 deletions(-)
14
16
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
17
diff --git a/configure b/configure
16
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100755
17
--- a/target/arm/helper.c
19
--- a/configure
18
+++ b/target/arm/helper.c
20
+++ b/configure
19
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
21
@@ -XXX,XX +XXX,XX @@ fi
20
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 3,
22
# the correct CPU with the --cpu option.
21
.access = PL1_R, .type = ARM_CP_CONST,
23
case $targetos in
22
.resetvalue = 0 },
24
Darwin)
23
- { .name = "ID_AA64PFR4_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
25
- # on Leopard most of the system is 32-bit, so we have to ask the kernel if we can
24
+ { .name = "ID_AA64ZFR0_EL1", .state = ARM_CP_STATE_AA64,
26
- # run 64-bit userspace code.
25
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 4,
27
- # If the user didn't specify a CPU explicitly and the kernel says this is
26
.access = PL1_R, .type = ARM_CP_CONST,
28
- # 64 bit hw, then assume x86_64. Otherwise fall through to the usual detection code.
27
+ /* At present, only SVEver == 0 is defined anyway. */
29
- if test -z "$cpu" && test "$(sysctl -n hw.optional.x86_64)" = "1"; then
28
.resetvalue = 0 },
30
- cpu="x86_64"
29
{ .name = "ID_AA64PFR5_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
31
- fi
30
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 5,
32
HOST_DSOSUF=".dylib"
33
;;
34
SunOS)
35
@@ -XXX,XX +XXX,XX @@ OpenBSD)
36
Darwin)
37
bsd="yes"
38
darwin="yes"
39
- if [ "$cpu" = "x86_64" ] ; then
40
- QEMU_CFLAGS="-arch x86_64 $QEMU_CFLAGS"
41
- QEMU_LDFLAGS="-arch x86_64 $QEMU_LDFLAGS"
42
- fi
43
audio_drv_list="try-coreaudio try-sdl"
44
audio_possible_drivers="coreaudio sdl"
45
# Disable attempts to use ObjectiveC features in os/object.h since they
31
--
46
--
32
2.19.0
47
2.20.1
33
48
34
49
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Alexander Graf <agraf@csgraf.de>
2
2
3
The 16-byte load only uses 16 predicate bits. But while
3
In macOS 11, QEMU only gets access to Hypervisor.framework if it has the
4
reusing the other load infrastructure, we find other bits
4
respective entitlement. Add an entitlement template and automatically self
5
that are set and trigger an assert. To avoid this and
5
sign and apply the entitlement in the build.
6
retain the assert, zero-extend the predicate that we pass
7
to the LD1 helper.
8
6
9
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
7
Signed-off-by: Alexander Graf <agraf@csgraf.de>
10
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
8
Reviewed-by: Roman Bolshakov <r.bolshakov@yadro.com>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Tested-by: Roman Bolshakov <r.bolshakov@yadro.com>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20181005175350.30752-7-richard.henderson@linaro.org
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
11
---
16
target/arm/translate-sve.c | 25 +++++++++++++++++++++++--
12
meson.build | 29 +++++++++++++++++++++++++----
17
1 file changed, 23 insertions(+), 2 deletions(-)
13
accel/hvf/entitlements.plist | 8 ++++++++
14
scripts/entitlement.sh | 13 +++++++++++++
15
3 files changed, 46 insertions(+), 4 deletions(-)
16
create mode 100644 accel/hvf/entitlements.plist
17
create mode 100755 scripts/entitlement.sh
18
18
19
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
19
diff --git a/meson.build b/meson.build
20
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/translate-sve.c
21
--- a/meson.build
22
+++ b/target/arm/translate-sve.c
22
+++ b/meson.build
23
@@ -XXX,XX +XXX,XX @@ static void do_ldrq(DisasContext *s, int zt, int pg, TCGv_i64 addr, int msz)
23
@@ -XXX,XX +XXX,XX @@ foreach target : target_dirs
24
unsigned vsz = vec_full_reg_size(s);
24
}]
25
TCGv_ptr t_pg;
25
endif
26
TCGv_i32 desc;
26
foreach exe: execs
27
+ int poff;
27
- emulators += {exe['name']:
28
28
- executable(exe['name'], exe['sources'],
29
/* Load the first quadword using the normal predicated load helpers. */
29
- install: true,
30
desc = tcg_const_i32(simd_desc(16, 16, zt));
30
+ exe_name = exe['name']
31
- t_pg = tcg_temp_new_ptr();
31
+ exe_sign = 'CONFIG_HVF' in config_target
32
32
+ if exe_sign
33
- tcg_gen_addi_ptr(t_pg, cpu_env, pred_full_reg_offset(s, pg));
33
+ exe_name += '-unsigned'
34
+ poff = pred_full_reg_offset(s, pg);
34
+ endif
35
+ if (vsz > 16) {
36
+ /*
37
+ * Zero-extend the first 16 bits of the predicate into a temporary.
38
+ * This avoids triggering an assert making sure we don't have bits
39
+ * set within a predicate beyond VQ, but we have lowered VQ to 1
40
+ * for this load operation.
41
+ */
42
+ TCGv_i64 tmp = tcg_temp_new_i64();
43
+#ifdef HOST_WORDS_BIGENDIAN
44
+ poff += 6;
45
+#endif
46
+ tcg_gen_ld16u_i64(tmp, cpu_env, poff);
47
+
35
+
48
+ poff = offsetof(CPUARMState, vfp.preg_tmp);
36
+ emulator = executable(exe_name, exe['sources'],
49
+ tcg_gen_st_i64(tmp, cpu_env, poff);
37
+ install: not exe_sign,
50
+ tcg_temp_free_i64(tmp);
38
c_args: c_args,
51
+ }
39
dependencies: arch_deps + deps + exe['dependencies'],
40
objects: lib.extract_all_objects(recursive: true),
41
@@ -XXX,XX +XXX,XX @@ foreach target : target_dirs
42
link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
43
link_args: link_args,
44
gui_app: exe['gui'])
45
- }
52
+
46
+
53
+ t_pg = tcg_temp_new_ptr();
47
+ if exe_sign
54
+ tcg_gen_addi_ptr(t_pg, cpu_env, poff);
48
+ emulators += {exe['name'] : custom_target(exe['name'],
49
+ install: true,
50
+ install_dir: get_option('bindir'),
51
+ depends: emulator,
52
+ output: exe['name'],
53
+ command: [
54
+ meson.current_source_dir() / 'scripts/entitlement.sh',
55
+ meson.current_build_dir() / exe_name,
56
+ meson.current_build_dir() / exe['name'],
57
+ meson.current_source_dir() / 'accel/hvf/entitlements.plist'
58
+ ])
59
+ }
60
+ else
61
+ emulators += {exe['name']: emulator}
62
+ endif
63
64
if 'CONFIG_TRACE_SYSTEMTAP' in config_host
65
foreach stp: [
66
diff --git a/accel/hvf/entitlements.plist b/accel/hvf/entitlements.plist
67
new file mode 100644
68
index XXXXXXX..XXXXXXX
69
--- /dev/null
70
+++ b/accel/hvf/entitlements.plist
71
@@ -XXX,XX +XXX,XX @@
72
+<?xml version="1.0" encoding="UTF-8"?>
73
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
74
+<plist version="1.0">
75
+<dict>
76
+ <key>com.apple.security.hypervisor</key>
77
+ <true/>
78
+</dict>
79
+</plist>
80
diff --git a/scripts/entitlement.sh b/scripts/entitlement.sh
81
new file mode 100755
82
index XXXXXXX..XXXXXXX
83
--- /dev/null
84
+++ b/scripts/entitlement.sh
85
@@ -XXX,XX +XXX,XX @@
86
+#!/bin/sh -e
87
+#
88
+# Helper script for the build process to apply entitlements
55
+
89
+
56
fns[msz](cpu_env, t_pg, addr, desc);
90
+SRC="$1"
57
91
+DST="$2"
58
tcg_temp_free_ptr(t_pg);
92
+ENTITLEMENT="$3"
93
+
94
+trap 'rm "$DST.tmp"' exit
95
+cp -af "$SRC" "$DST.tmp"
96
+codesign --entitlements "$ENTITLEMENT" --force -s - "$DST.tmp"
97
+mv "$DST.tmp" "$DST"
98
+trap '' exit
59
--
99
--
60
2.19.0
100
2.20.1
61
101
62
102
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Mihai Carabas <mihai.carabas@oracle.com>
2
2
3
Uses tlb_vaddr_to_host for correct operation with softmmu.
3
To ease the PCI device addition in next patches, split the code as follows:
4
Optimize for accesses within a single page or pair of pages.
4
- generic code (read/write/setup) is being kept in pvpanic.c
5
5
- ISA dependent code moved to pvpanic-isa.c
6
7
Also, rename:
8
- ISA_PVPANIC_DEVICE -> PVPANIC_ISA_DEVICE.
9
- TYPE_PVPANIC -> TYPE_PVPANIC_ISA.
10
- MemoryRegion io -> mr.
11
- pvpanic_ioport_* in pvpanic_*.
12
13
Update the build system with the new files and config structure.
14
15
Signed-off-by: Mihai Carabas <mihai.carabas@oracle.com>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20181005175350.30752-8-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
18
---
11
target/arm/sve_helper.c | 731 +++++++++++++++++++++++++++++++---------
19
include/hw/misc/pvpanic.h | 23 +++++++++-
12
1 file changed, 569 insertions(+), 162 deletions(-)
20
hw/misc/pvpanic-isa.c | 94 +++++++++++++++++++++++++++++++++++++++
13
21
hw/misc/pvpanic.c | 85 +++--------------------------------
14
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
22
hw/i386/Kconfig | 2 +-
15
index XXXXXXX..XXXXXXX 100644
23
hw/misc/Kconfig | 6 ++-
16
--- a/target/arm/sve_helper.c
24
hw/misc/meson.build | 3 +-
17
+++ b/target/arm/sve_helper.c
25
tests/qtest/meson.build | 2 +-
18
@@ -XXX,XX +XXX,XX @@ static void swap_memmove(void *vd, void *vs, size_t n)
26
7 files changed, 130 insertions(+), 85 deletions(-)
27
create mode 100644 hw/misc/pvpanic-isa.c
28
29
diff --git a/include/hw/misc/pvpanic.h b/include/hw/misc/pvpanic.h
30
index XXXXXXX..XXXXXXX 100644
31
--- a/include/hw/misc/pvpanic.h
32
+++ b/include/hw/misc/pvpanic.h
33
@@ -XXX,XX +XXX,XX @@
34
35
#include "qom/object.h"
36
37
-#define TYPE_PVPANIC "pvpanic"
38
+#define TYPE_PVPANIC_ISA_DEVICE "pvpanic"
39
40
#define PVPANIC_IOPORT_PROP "ioport"
41
42
+/* The bit of supported pv event, TODO: include uapi header and remove this */
43
+#define PVPANIC_F_PANICKED 0
44
+#define PVPANIC_F_CRASHLOADED 1
45
+
46
+/* The pv event value */
47
+#define PVPANIC_PANICKED (1 << PVPANIC_F_PANICKED)
48
+#define PVPANIC_CRASHLOADED (1 << PVPANIC_F_CRASHLOADED)
49
+
50
+/*
51
+ * PVPanicState for any device type
52
+ */
53
+typedef struct PVPanicState PVPanicState;
54
+struct PVPanicState {
55
+ MemoryRegion mr;
56
+ uint8_t events;
57
+};
58
+
59
+void pvpanic_setup_io(PVPanicState *s, DeviceState *dev, unsigned size);
60
+
61
static inline uint16_t pvpanic_port(void)
62
{
63
- Object *o = object_resolve_path_type("", TYPE_PVPANIC, NULL);
64
+ Object *o = object_resolve_path_type("", TYPE_PVPANIC_ISA_DEVICE, NULL);
65
if (!o) {
66
return 0;
67
}
68
diff --git a/hw/misc/pvpanic-isa.c b/hw/misc/pvpanic-isa.c
69
new file mode 100644
70
index XXXXXXX..XXXXXXX
71
--- /dev/null
72
+++ b/hw/misc/pvpanic-isa.c
73
@@ -XXX,XX +XXX,XX @@
74
+/*
75
+ * QEMU simulated pvpanic device.
76
+ *
77
+ * Copyright Fujitsu, Corp. 2013
78
+ *
79
+ * Authors:
80
+ * Wen Congyang <wency@cn.fujitsu.com>
81
+ * Hu Tao <hutao@cn.fujitsu.com>
82
+ *
83
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
84
+ * See the COPYING file in the top-level directory.
85
+ *
86
+ */
87
+
88
+#include "qemu/osdep.h"
89
+#include "qemu/log.h"
90
+#include "qemu/module.h"
91
+#include "sysemu/runstate.h"
92
+
93
+#include "hw/nvram/fw_cfg.h"
94
+#include "hw/qdev-properties.h"
95
+#include "hw/misc/pvpanic.h"
96
+#include "qom/object.h"
97
+#include "hw/isa/isa.h"
98
+
99
+OBJECT_DECLARE_SIMPLE_TYPE(PVPanicISAState, PVPANIC_ISA_DEVICE)
100
+
101
+/*
102
+ * PVPanicISAState for ISA device and
103
+ * use ioport.
104
+ */
105
+struct PVPanicISAState {
106
+ ISADevice parent_obj;
107
+
108
+ uint16_t ioport;
109
+ PVPanicState pvpanic;
110
+};
111
+
112
+static void pvpanic_isa_initfn(Object *obj)
113
+{
114
+ PVPanicISAState *s = PVPANIC_ISA_DEVICE(obj);
115
+
116
+ pvpanic_setup_io(&s->pvpanic, DEVICE(s), 1);
117
+}
118
+
119
+static void pvpanic_isa_realizefn(DeviceState *dev, Error **errp)
120
+{
121
+ ISADevice *d = ISA_DEVICE(dev);
122
+ PVPanicISAState *s = PVPANIC_ISA_DEVICE(dev);
123
+ PVPanicState *ps = &s->pvpanic;
124
+ FWCfgState *fw_cfg = fw_cfg_find();
125
+ uint16_t *pvpanic_port;
126
+
127
+ if (!fw_cfg) {
128
+ return;
129
+ }
130
+
131
+ pvpanic_port = g_malloc(sizeof(*pvpanic_port));
132
+ *pvpanic_port = cpu_to_le16(s->ioport);
133
+ fw_cfg_add_file(fw_cfg, "etc/pvpanic-port", pvpanic_port,
134
+ sizeof(*pvpanic_port));
135
+
136
+ isa_register_ioport(d, &ps->mr, s->ioport);
137
+}
138
+
139
+static Property pvpanic_isa_properties[] = {
140
+ DEFINE_PROP_UINT16(PVPANIC_IOPORT_PROP, PVPanicISAState, ioport, 0x505),
141
+ DEFINE_PROP_UINT8("events", PVPanicISAState, pvpanic.events, PVPANIC_PANICKED | PVPANIC_CRASHLOADED),
142
+ DEFINE_PROP_END_OF_LIST(),
143
+};
144
+
145
+static void pvpanic_isa_class_init(ObjectClass *klass, void *data)
146
+{
147
+ DeviceClass *dc = DEVICE_CLASS(klass);
148
+
149
+ dc->realize = pvpanic_isa_realizefn;
150
+ device_class_set_props(dc, pvpanic_isa_properties);
151
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
152
+}
153
+
154
+static TypeInfo pvpanic_isa_info = {
155
+ .name = TYPE_PVPANIC_ISA_DEVICE,
156
+ .parent = TYPE_ISA_DEVICE,
157
+ .instance_size = sizeof(PVPanicISAState),
158
+ .instance_init = pvpanic_isa_initfn,
159
+ .class_init = pvpanic_isa_class_init,
160
+};
161
+
162
+static void pvpanic_register_types(void)
163
+{
164
+ type_register_static(&pvpanic_isa_info);
165
+}
166
+
167
+type_init(pvpanic_register_types)
168
diff --git a/hw/misc/pvpanic.c b/hw/misc/pvpanic.c
169
index XXXXXXX..XXXXXXX 100644
170
--- a/hw/misc/pvpanic.c
171
+++ b/hw/misc/pvpanic.c
172
@@ -XXX,XX +XXX,XX @@
173
#include "hw/misc/pvpanic.h"
174
#include "qom/object.h"
175
176
-/* The bit of supported pv event, TODO: include uapi header and remove this */
177
-#define PVPANIC_F_PANICKED 0
178
-#define PVPANIC_F_CRASHLOADED 1
179
-
180
-/* The pv event value */
181
-#define PVPANIC_PANICKED (1 << PVPANIC_F_PANICKED)
182
-#define PVPANIC_CRASHLOADED (1 << PVPANIC_F_CRASHLOADED)
183
-
184
-typedef struct PVPanicState PVPanicState;
185
-DECLARE_INSTANCE_CHECKER(PVPanicState, ISA_PVPANIC_DEVICE,
186
- TYPE_PVPANIC)
187
-
188
static void handle_event(int event)
189
{
190
static bool logged;
191
@@ -XXX,XX +XXX,XX @@ static void handle_event(int event)
19
}
192
}
20
}
193
}
21
194
22
+/* Similarly for memset of 0. */
195
-#include "hw/isa/isa.h"
23
+static void swap_memzero(void *vd, size_t n)
196
-
24
+{
197
-struct PVPanicState {
25
+ uintptr_t d = (uintptr_t)vd;
198
- ISADevice parent_obj;
26
+ uintptr_t o = (d | n) & 7;
199
-
27
+ size_t i;
200
- MemoryRegion io;
28
+
201
- uint16_t ioport;
29
+ /* Usually, the first bit of a predicate is set, so N is 0. */
202
- uint8_t events;
30
+ if (likely(n == 0)) {
203
-};
31
+ return;
204
-
32
+ }
205
/* return supported events on read */
33
+
206
-static uint64_t pvpanic_ioport_read(void *opaque, hwaddr addr, unsigned size)
34
+#ifndef HOST_WORDS_BIGENDIAN
207
+static uint64_t pvpanic_read(void *opaque, hwaddr addr, unsigned size)
35
+ o = 0;
208
{
36
+#endif
209
PVPanicState *pvp = opaque;
37
+ switch (o) {
210
return pvp->events;
38
+ case 0:
39
+ memset(vd, 0, n);
40
+ break;
41
+
42
+ case 4:
43
+ for (i = 0; i < n; i += 4) {
44
+ *(uint32_t *)H1_4(d + i) = 0;
45
+ }
46
+ break;
47
+
48
+ case 2:
49
+ case 6:
50
+ for (i = 0; i < n; i += 2) {
51
+ *(uint16_t *)H1_2(d + i) = 0;
52
+ }
53
+ break;
54
+
55
+ default:
56
+ for (i = 0; i < n; i++) {
57
+ *(uint8_t *)H1(d + i) = 0;
58
+ }
59
+ break;
60
+ }
61
+}
62
+
63
void HELPER(sve_ext)(void *vd, void *vn, void *vm, uint32_t desc)
64
{
65
intptr_t opr_sz = simd_oprsz(desc);
66
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_fcmla_zpzzz_d)(CPUARMState *env, void *vg, uint32_t desc)
67
/*
68
* Load contiguous data, protected by a governing predicate.
69
*/
70
-#define DO_LD1(NAME, FN, TYPEE, TYPEM, H) \
71
-static void do_##NAME(CPUARMState *env, void *vd, void *vg, \
72
- target_ulong addr, intptr_t oprsz, \
73
- uintptr_t ra) \
74
-{ \
75
- intptr_t i = 0; \
76
- do { \
77
- uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
78
- do { \
79
- TYPEM m = 0; \
80
- if (pg & 1) { \
81
- m = FN(env, addr, ra); \
82
- } \
83
- *(TYPEE *)(vd + H(i)) = m; \
84
- i += sizeof(TYPEE), pg >>= sizeof(TYPEE); \
85
- addr += sizeof(TYPEM); \
86
- } while (i & 15); \
87
- } while (i < oprsz); \
88
-} \
89
-void HELPER(NAME)(CPUARMState *env, void *vg, \
90
- target_ulong addr, uint32_t desc) \
91
-{ \
92
- do_##NAME(env, &env->vfp.zregs[simd_data(desc)], vg, \
93
- addr, simd_oprsz(desc), GETPC()); \
94
+
95
+/*
96
+ * Load elements into @vd, controlled by @vg, from @host + @mem_ofs.
97
+ * Memory is valid through @host + @mem_max. The register element
98
+ * indicies are inferred from @mem_ofs, as modified by the types for
99
+ * which the helper is built. Return the @mem_ofs of the first element
100
+ * not loaded (which is @mem_max if they are all loaded).
101
+ *
102
+ * For softmmu, we have fully validated the guest page. For user-only,
103
+ * we cannot fully validate without taking the mmap lock, but since we
104
+ * know the access is within one host page, if any access is valid they
105
+ * all must be valid. However, when @vg is all false, it may be that
106
+ * no access is valid.
107
+ */
108
+typedef intptr_t sve_ld1_host_fn(void *vd, void *vg, void *host,
109
+ intptr_t mem_ofs, intptr_t mem_max);
110
+
111
+/*
112
+ * Load one element into @vd + @reg_off from (@env, @vaddr, @ra).
113
+ * The controlling predicate is known to be true.
114
+ */
115
+typedef void sve_ld1_tlb_fn(CPUARMState *env, void *vd, intptr_t reg_off,
116
+ target_ulong vaddr, int mmu_idx, uintptr_t ra);
117
+
118
+/*
119
+ * Generate the above primitives.
120
+ */
121
+
122
+#define DO_LD_HOST(NAME, H, TYPEE, TYPEM, HOST) \
123
+static intptr_t sve_##NAME##_host(void *vd, void *vg, void *host, \
124
+ intptr_t mem_off, const intptr_t mem_max) \
125
+{ \
126
+ intptr_t reg_off = mem_off * (sizeof(TYPEE) / sizeof(TYPEM)); \
127
+ uint64_t *pg = vg; \
128
+ while (mem_off + sizeof(TYPEM) <= mem_max) { \
129
+ TYPEM val = 0; \
130
+ if (likely((pg[reg_off >> 6] >> (reg_off & 63)) & 1)) { \
131
+ val = HOST(host + mem_off); \
132
+ } \
133
+ *(TYPEE *)(vd + H(reg_off)) = val; \
134
+ mem_off += sizeof(TYPEM), reg_off += sizeof(TYPEE); \
135
+ } \
136
+ return mem_off; \
137
}
211
}
138
212
139
+#ifdef CONFIG_SOFTMMU
213
-static void pvpanic_ioport_write(void *opaque, hwaddr addr, uint64_t val,
140
+#define DO_LD_TLB(NAME, H, TYPEE, TYPEM, HOST, MOEND, TLB) \
214
+static void pvpanic_write(void *opaque, hwaddr addr, uint64_t val,
141
+static void sve_##NAME##_tlb(CPUARMState *env, void *vd, intptr_t reg_off, \
215
unsigned size)
142
+ target_ulong addr, int mmu_idx, uintptr_t ra) \
216
{
143
+{ \
217
handle_event(val);
144
+ TCGMemOpIdx oi = make_memop_idx(ctz32(sizeof(TYPEM)) | MOEND, mmu_idx); \
145
+ TYPEM val = TLB(env, addr, oi, ra); \
146
+ *(TYPEE *)(vd + H(reg_off)) = val; \
147
+}
148
+#else
149
+#define DO_LD_TLB(NAME, H, TYPEE, TYPEM, HOST, MOEND, TLB) \
150
+static void sve_##NAME##_tlb(CPUARMState *env, void *vd, intptr_t reg_off, \
151
+ target_ulong addr, int mmu_idx, uintptr_t ra) \
152
+{ \
153
+ TYPEM val = HOST(g2h(addr)); \
154
+ *(TYPEE *)(vd + H(reg_off)) = val; \
155
+}
156
+#endif
157
+
158
+#define DO_LD_PRIM_1(NAME, H, TE, TM) \
159
+ DO_LD_HOST(NAME, H, TE, TM, ldub_p) \
160
+ DO_LD_TLB(NAME, H, TE, TM, ldub_p, 0, helper_ret_ldub_mmu)
161
+
162
+DO_LD_PRIM_1(ld1bb, H1, uint8_t, uint8_t)
163
+DO_LD_PRIM_1(ld1bhu, H1_2, uint16_t, uint8_t)
164
+DO_LD_PRIM_1(ld1bhs, H1_2, uint16_t, int8_t)
165
+DO_LD_PRIM_1(ld1bsu, H1_4, uint32_t, uint8_t)
166
+DO_LD_PRIM_1(ld1bss, H1_4, uint32_t, int8_t)
167
+DO_LD_PRIM_1(ld1bdu, , uint64_t, uint8_t)
168
+DO_LD_PRIM_1(ld1bds, , uint64_t, int8_t)
169
+
170
+#define DO_LD_PRIM_2(NAME, end, MOEND, H, TE, TM, PH, PT) \
171
+ DO_LD_HOST(NAME##_##end, H, TE, TM, PH##_##end##_p) \
172
+ DO_LD_TLB(NAME##_##end, H, TE, TM, PH##_##end##_p, \
173
+ MOEND, helper_##end##_##PT##_mmu)
174
+
175
+DO_LD_PRIM_2(ld1hh, le, MO_LE, H1_2, uint16_t, uint16_t, lduw, lduw)
176
+DO_LD_PRIM_2(ld1hsu, le, MO_LE, H1_4, uint32_t, uint16_t, lduw, lduw)
177
+DO_LD_PRIM_2(ld1hss, le, MO_LE, H1_4, uint32_t, int16_t, lduw, lduw)
178
+DO_LD_PRIM_2(ld1hdu, le, MO_LE, , uint64_t, uint16_t, lduw, lduw)
179
+DO_LD_PRIM_2(ld1hds, le, MO_LE, , uint64_t, int16_t, lduw, lduw)
180
+
181
+DO_LD_PRIM_2(ld1ss, le, MO_LE, H1_4, uint32_t, uint32_t, ldl, ldul)
182
+DO_LD_PRIM_2(ld1sdu, le, MO_LE, , uint64_t, uint32_t, ldl, ldul)
183
+DO_LD_PRIM_2(ld1sds, le, MO_LE, , uint64_t, int32_t, ldl, ldul)
184
+
185
+DO_LD_PRIM_2(ld1dd, le, MO_LE, , uint64_t, uint64_t, ldq, ldq)
186
+
187
+DO_LD_PRIM_2(ld1hh, be, MO_BE, H1_2, uint16_t, uint16_t, lduw, lduw)
188
+DO_LD_PRIM_2(ld1hsu, be, MO_BE, H1_4, uint32_t, uint16_t, lduw, lduw)
189
+DO_LD_PRIM_2(ld1hss, be, MO_BE, H1_4, uint32_t, int16_t, lduw, lduw)
190
+DO_LD_PRIM_2(ld1hdu, be, MO_BE, , uint64_t, uint16_t, lduw, lduw)
191
+DO_LD_PRIM_2(ld1hds, be, MO_BE, , uint64_t, int16_t, lduw, lduw)
192
+
193
+DO_LD_PRIM_2(ld1ss, be, MO_BE, H1_4, uint32_t, uint32_t, ldl, ldul)
194
+DO_LD_PRIM_2(ld1sdu, be, MO_BE, , uint64_t, uint32_t, ldl, ldul)
195
+DO_LD_PRIM_2(ld1sds, be, MO_BE, , uint64_t, int32_t, ldl, ldul)
196
+
197
+DO_LD_PRIM_2(ld1dd, be, MO_BE, , uint64_t, uint64_t, ldq, ldq)
198
+
199
+#undef DO_LD_TLB
200
+#undef DO_LD_HOST
201
+#undef DO_LD_PRIM_1
202
+#undef DO_LD_PRIM_2
203
+
204
+/*
205
+ * Skip through a sequence of inactive elements in the guarding predicate @vg,
206
+ * beginning at @reg_off bounded by @reg_max. Return the offset of the active
207
+ * element >= @reg_off, or @reg_max if there were no active elements at all.
208
+ */
209
+static intptr_t find_next_active(uint64_t *vg, intptr_t reg_off,
210
+ intptr_t reg_max, int esz)
211
+{
212
+ uint64_t pg_mask = pred_esz_masks[esz];
213
+ uint64_t pg = (vg[reg_off >> 6] & pg_mask) >> (reg_off & 63);
214
+
215
+ /* In normal usage, the first element is active. */
216
+ if (likely(pg & 1)) {
217
+ return reg_off;
218
+ }
219
+
220
+ if (pg == 0) {
221
+ reg_off &= -64;
222
+ do {
223
+ reg_off += 64;
224
+ if (unlikely(reg_off >= reg_max)) {
225
+ /* The entire predicate was false. */
226
+ return reg_max;
227
+ }
228
+ pg = vg[reg_off >> 6] & pg_mask;
229
+ } while (pg == 0);
230
+ }
231
+ reg_off += ctz64(pg);
232
+
233
+ /* We should never see an out of range predicate bit set. */
234
+ tcg_debug_assert(reg_off < reg_max);
235
+ return reg_off;
236
+}
237
+
238
+/*
239
+ * Return the maximum offset <= @mem_max which is still within the page
240
+ * referenced by @base + @mem_off.
241
+ */
242
+static intptr_t max_for_page(target_ulong base, intptr_t mem_off,
243
+ intptr_t mem_max)
244
+{
245
+ target_ulong addr = base + mem_off;
246
+ intptr_t split = -(intptr_t)(addr | TARGET_PAGE_MASK);
247
+ return MIN(split, mem_max - mem_off) + mem_off;
248
+}
249
+
250
+static inline void set_helper_retaddr(uintptr_t ra)
251
+{
252
+#ifdef CONFIG_USER_ONLY
253
+ helper_retaddr = ra;
254
+#endif
255
+}
256
+
257
+/*
258
+ * The result of tlb_vaddr_to_host for user-only is just g2h(x),
259
+ * which is always non-null. Elide the useless test.
260
+ */
261
+static inline bool test_host_page(void *host)
262
+{
263
+#ifdef CONFIG_USER_ONLY
264
+ return true;
265
+#else
266
+ return likely(host != NULL);
267
+#endif
268
+}
269
+
270
+/*
271
+ * Common helper for all contiguous one-register predicated loads.
272
+ */
273
+static void sve_ld1_r(CPUARMState *env, void *vg, const target_ulong addr,
274
+ uint32_t desc, const uintptr_t retaddr,
275
+ const int esz, const int msz,
276
+ sve_ld1_host_fn *host_fn,
277
+ sve_ld1_tlb_fn *tlb_fn)
278
+{
279
+ void *vd = &env->vfp.zregs[simd_data(desc)];
280
+ const int diffsz = esz - msz;
281
+ const intptr_t reg_max = simd_oprsz(desc);
282
+ const intptr_t mem_max = reg_max >> diffsz;
283
+ const int mmu_idx = cpu_mmu_index(env, false);
284
+ ARMVectorReg scratch;
285
+ void *host;
286
+ intptr_t split, reg_off, mem_off;
287
+
288
+ /* Find the first active element. */
289
+ reg_off = find_next_active(vg, 0, reg_max, esz);
290
+ if (unlikely(reg_off == reg_max)) {
291
+ /* The entire predicate was false; no load occurs. */
292
+ memset(vd, 0, reg_max);
293
+ return;
294
+ }
295
+ mem_off = reg_off >> diffsz;
296
+ set_helper_retaddr(retaddr);
297
+
298
+ /*
299
+ * If the (remaining) load is entirely within a single page, then:
300
+ * For softmmu, and the tlb hits, then no faults will occur;
301
+ * For user-only, either the first load will fault or none will.
302
+ * We can thus perform the load directly to the destination and
303
+ * Vd will be unmodified on any exception path.
304
+ */
305
+ split = max_for_page(addr, mem_off, mem_max);
306
+ if (likely(split == mem_max)) {
307
+ host = tlb_vaddr_to_host(env, addr + mem_off, MMU_DATA_LOAD, mmu_idx);
308
+ if (test_host_page(host)) {
309
+ mem_off = host_fn(vd, vg, host - mem_off, mem_off, mem_max);
310
+ tcg_debug_assert(mem_off == mem_max);
311
+ set_helper_retaddr(0);
312
+ /* After having taken any fault, zero leading inactive elements. */
313
+ swap_memzero(vd, reg_off);
314
+ return;
315
+ }
316
+ }
317
+
318
+ /*
319
+ * Perform the predicated read into a temporary, thus ensuring
320
+ * if the load of the last element faults, Vd is not modified.
321
+ */
322
+#ifdef CONFIG_USER_ONLY
323
+ swap_memzero(&scratch, reg_off);
324
+ host_fn(&scratch, vg, g2h(addr), mem_off, mem_max);
325
+#else
326
+ memset(&scratch, 0, reg_max);
327
+ goto start;
328
+ while (1) {
329
+ reg_off = find_next_active(vg, reg_off, reg_max, esz);
330
+ if (reg_off >= reg_max) {
331
+ break;
332
+ }
333
+ mem_off = reg_off >> diffsz;
334
+ split = max_for_page(addr, mem_off, mem_max);
335
+
336
+ start:
337
+ if (split - mem_off >= (1 << msz)) {
338
+ /* At least one whole element on this page. */
339
+ host = tlb_vaddr_to_host(env, addr + mem_off,
340
+ MMU_DATA_LOAD, mmu_idx);
341
+ if (host) {
342
+ mem_off = host_fn(&scratch, vg, host - mem_off,
343
+ mem_off, split);
344
+ reg_off = mem_off << diffsz;
345
+ continue;
346
+ }
347
+ }
348
+
349
+ /*
350
+ * Perform one normal read. This may fault, longjmping out to the
351
+ * main loop in order to raise an exception. It may succeed, and
352
+ * as a side-effect load the TLB entry for the next round. Finally,
353
+ * in the extremely unlikely case we're performing this operation
354
+ * on I/O memory, it may succeed but not bring in the TLB entry.
355
+ * But even then we have still made forward progress.
356
+ */
357
+ tlb_fn(env, &scratch, reg_off, addr + mem_off, mmu_idx, retaddr);
358
+ reg_off += 1 << esz;
359
+ }
360
+#endif
361
+
362
+ set_helper_retaddr(0);
363
+ memcpy(vd, &scratch, reg_max);
364
+}
365
+
366
+#define DO_LD1_1(NAME, ESZ) \
367
+void HELPER(sve_##NAME##_r)(CPUARMState *env, void *vg, \
368
+ target_ulong addr, uint32_t desc) \
369
+{ \
370
+ sve_ld1_r(env, vg, addr, desc, GETPC(), ESZ, 0, \
371
+ sve_##NAME##_host, sve_##NAME##_tlb); \
372
+}
373
+
374
+/* TODO: Propagate the endian check back to the translator. */
375
+#define DO_LD1_2(NAME, ESZ, MSZ) \
376
+void HELPER(sve_##NAME##_r)(CPUARMState *env, void *vg, \
377
+ target_ulong addr, uint32_t desc) \
378
+{ \
379
+ if (arm_cpu_data_is_big_endian(env)) { \
380
+ sve_ld1_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, \
381
+ sve_##NAME##_be_host, sve_##NAME##_be_tlb); \
382
+ } else { \
383
+ sve_ld1_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, \
384
+ sve_##NAME##_le_host, sve_##NAME##_le_tlb); \
385
+ } \
386
+}
387
+
388
+DO_LD1_1(ld1bb, 0)
389
+DO_LD1_1(ld1bhu, 1)
390
+DO_LD1_1(ld1bhs, 1)
391
+DO_LD1_1(ld1bsu, 2)
392
+DO_LD1_1(ld1bss, 2)
393
+DO_LD1_1(ld1bdu, 3)
394
+DO_LD1_1(ld1bds, 3)
395
+
396
+DO_LD1_2(ld1hh, 1, 1)
397
+DO_LD1_2(ld1hsu, 2, 1)
398
+DO_LD1_2(ld1hss, 2, 1)
399
+DO_LD1_2(ld1hdu, 3, 1)
400
+DO_LD1_2(ld1hds, 3, 1)
401
+
402
+DO_LD1_2(ld1ss, 2, 2)
403
+DO_LD1_2(ld1sdu, 3, 2)
404
+DO_LD1_2(ld1sds, 3, 2)
405
+
406
+DO_LD1_2(ld1dd, 3, 3)
407
+
408
+#undef DO_LD1_1
409
+#undef DO_LD1_2
410
+
411
#define DO_LD2(NAME, FN, TYPEE, TYPEM, H) \
412
void HELPER(NAME)(CPUARMState *env, void *vg, \
413
target_ulong addr, uint32_t desc) \
414
@@ -XXX,XX +XXX,XX @@ void HELPER(NAME)(CPUARMState *env, void *vg, \
415
} \
416
}
218
}
417
219
418
-DO_LD1(sve_ld1bhu_r, cpu_ldub_data_ra, uint16_t, uint8_t, H1_2)
220
static const MemoryRegionOps pvpanic_ops = {
419
-DO_LD1(sve_ld1bhs_r, cpu_ldsb_data_ra, uint16_t, int8_t, H1_2)
221
- .read = pvpanic_ioport_read,
420
-DO_LD1(sve_ld1bsu_r, cpu_ldub_data_ra, uint32_t, uint8_t, H1_4)
222
- .write = pvpanic_ioport_write,
421
-DO_LD1(sve_ld1bss_r, cpu_ldsb_data_ra, uint32_t, int8_t, H1_4)
223
+ .read = pvpanic_read,
422
-DO_LD1(sve_ld1bdu_r, cpu_ldub_data_ra, uint64_t, uint8_t, )
224
+ .write = pvpanic_write,
423
-DO_LD1(sve_ld1bds_r, cpu_ldsb_data_ra, uint64_t, int8_t, )
225
.impl = {
424
-
226
.min_access_size = 1,
425
-DO_LD1(sve_ld1hsu_r, cpu_lduw_data_ra, uint32_t, uint16_t, H1_4)
227
.max_access_size = 1,
426
-DO_LD1(sve_ld1hss_r, cpu_ldsw_data_ra, uint32_t, int16_t, H1_4)
228
},
427
-DO_LD1(sve_ld1hdu_r, cpu_lduw_data_ra, uint64_t, uint16_t, )
229
};
428
-DO_LD1(sve_ld1hds_r, cpu_ldsw_data_ra, uint64_t, int16_t, )
230
429
-
231
-static void pvpanic_isa_initfn(Object *obj)
430
-DO_LD1(sve_ld1sdu_r, cpu_ldl_data_ra, uint64_t, uint32_t, )
232
+void pvpanic_setup_io(PVPanicState *s, DeviceState *dev, unsigned size)
431
-DO_LD1(sve_ld1sds_r, cpu_ldl_data_ra, uint64_t, int32_t, )
233
{
432
-
234
- PVPanicState *s = ISA_PVPANIC_DEVICE(obj);
433
-DO_LD1(sve_ld1bb_r, cpu_ldub_data_ra, uint8_t, uint8_t, H1)
235
-
434
DO_LD2(sve_ld2bb_r, cpu_ldub_data_ra, uint8_t, uint8_t, H1)
236
- memory_region_init_io(&s->io, OBJECT(s), &pvpanic_ops, s, "pvpanic", 1);
435
DO_LD3(sve_ld3bb_r, cpu_ldub_data_ra, uint8_t, uint8_t, H1)
237
+ memory_region_init_io(&s->mr, OBJECT(dev), &pvpanic_ops, s, "pvpanic", size);
436
DO_LD4(sve_ld4bb_r, cpu_ldub_data_ra, uint8_t, uint8_t, H1)
437
438
-DO_LD1(sve_ld1hh_r, cpu_lduw_data_ra, uint16_t, uint16_t, H1_2)
439
DO_LD2(sve_ld2hh_r, cpu_lduw_data_ra, uint16_t, uint16_t, H1_2)
440
DO_LD3(sve_ld3hh_r, cpu_lduw_data_ra, uint16_t, uint16_t, H1_2)
441
DO_LD4(sve_ld4hh_r, cpu_lduw_data_ra, uint16_t, uint16_t, H1_2)
442
443
-DO_LD1(sve_ld1ss_r, cpu_ldl_data_ra, uint32_t, uint32_t, H1_4)
444
DO_LD2(sve_ld2ss_r, cpu_ldl_data_ra, uint32_t, uint32_t, H1_4)
445
DO_LD3(sve_ld3ss_r, cpu_ldl_data_ra, uint32_t, uint32_t, H1_4)
446
DO_LD4(sve_ld4ss_r, cpu_ldl_data_ra, uint32_t, uint32_t, H1_4)
447
448
-DO_LD1(sve_ld1dd_r, cpu_ldq_data_ra, uint64_t, uint64_t, )
449
DO_LD2(sve_ld2dd_r, cpu_ldq_data_ra, uint64_t, uint64_t, )
450
DO_LD3(sve_ld3dd_r, cpu_ldq_data_ra, uint64_t, uint64_t, )
451
DO_LD4(sve_ld4dd_r, cpu_ldq_data_ra, uint64_t, uint64_t, )
452
453
-#undef DO_LD1
454
#undef DO_LD2
455
#undef DO_LD3
456
#undef DO_LD4
457
458
/*
459
* Load contiguous data, first-fault and no-fault.
460
+ *
461
+ * For user-only, one could argue that we should hold the mmap_lock during
462
+ * the operation so that there is no race between page_check_range and the
463
+ * load operation. However, unmapping pages out from under a running thread
464
+ * is extraordinarily unlikely. This theoretical race condition also affects
465
+ * linux-user/ in its get_user/put_user macros.
466
+ *
467
+ * TODO: Construct some helpers, written in assembly, that interact with
468
+ * handle_cpu_signal to produce memory ops which can properly report errors
469
+ * without racing.
470
*/
471
472
-#ifdef CONFIG_USER_ONLY
473
-
474
/* Fault on byte I. All bits in FFR from I are cleared. The vector
475
* result from I is CONSTRAINED UNPREDICTABLE; we choose the MERGE
476
* option, which leaves subsequent data unchanged.
477
@@ -XXX,XX +XXX,XX @@ static void record_fault(CPUARMState *env, uintptr_t i, uintptr_t oprsz)
478
}
479
}
238
}
480
239
-
481
-/* Hold the mmap lock during the operation so that there is no race
240
-static void pvpanic_isa_realizefn(DeviceState *dev, Error **errp)
482
- * between page_check_range and the load operation. We expect the
241
-{
483
- * usual case to have no faults at all, so we check the whole range
242
- ISADevice *d = ISA_DEVICE(dev);
484
- * first and if successful defer to the normal load operation.
243
- PVPanicState *s = ISA_PVPANIC_DEVICE(dev);
485
- *
244
- FWCfgState *fw_cfg = fw_cfg_find();
486
- * TODO: Change mmap_lock to a rwlock so that multiple readers
245
- uint16_t *pvpanic_port;
487
- * can run simultaneously. This will probably help other uses
246
-
488
- * within QEMU as well.
247
- if (!fw_cfg) {
489
+/*
248
- return;
490
+ * Common helper for all contiguous first-fault loads.
249
- }
491
*/
250
-
492
-#define DO_LDFF1(PART, FN, TYPEE, TYPEM, H) \
251
- pvpanic_port = g_malloc(sizeof(*pvpanic_port));
493
-static void do_sve_ldff1##PART(CPUARMState *env, void *vd, void *vg, \
252
- *pvpanic_port = cpu_to_le16(s->ioport);
494
- target_ulong addr, intptr_t oprsz, \
253
- fw_cfg_add_file(fw_cfg, "etc/pvpanic-port", pvpanic_port,
495
- bool first, uintptr_t ra) \
254
- sizeof(*pvpanic_port));
496
-{ \
255
-
497
- intptr_t i = 0; \
256
- isa_register_ioport(d, &s->io, s->ioport);
498
- do { \
499
- uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
500
- do { \
501
- TYPEM m = 0; \
502
- if (pg & 1) { \
503
- if (!first && \
504
- unlikely(page_check_range(addr, sizeof(TYPEM), \
505
- PAGE_READ))) { \
506
- record_fault(env, i, oprsz); \
507
- return; \
508
- } \
509
- m = FN(env, addr, ra); \
510
- first = false; \
511
- } \
512
- *(TYPEE *)(vd + H(i)) = m; \
513
- i += sizeof(TYPEE), pg >>= sizeof(TYPEE); \
514
- addr += sizeof(TYPEM); \
515
- } while (i & 15); \
516
- } while (i < oprsz); \
517
-} \
518
-void HELPER(sve_ldff1##PART)(CPUARMState *env, void *vg, \
519
- target_ulong addr, uint32_t desc) \
520
-{ \
521
- intptr_t oprsz = simd_oprsz(desc); \
522
- unsigned rd = simd_data(desc); \
523
- void *vd = &env->vfp.zregs[rd]; \
524
- mmap_lock(); \
525
- if (likely(page_check_range(addr, oprsz, PAGE_READ) == 0)) { \
526
- do_sve_ld1##PART(env, vd, vg, addr, oprsz, GETPC()); \
527
- } else { \
528
- do_sve_ldff1##PART(env, vd, vg, addr, oprsz, true, GETPC()); \
529
- } \
530
- mmap_unlock(); \
531
-}
257
-}
532
+static void sve_ldff1_r(CPUARMState *env, void *vg, const target_ulong addr,
258
-
533
+ uint32_t desc, const uintptr_t retaddr,
259
-static Property pvpanic_isa_properties[] = {
534
+ const int esz, const int msz,
260
- DEFINE_PROP_UINT16(PVPANIC_IOPORT_PROP, PVPanicState, ioport, 0x505),
535
+ sve_ld1_host_fn *host_fn,
261
- DEFINE_PROP_UINT8("events", PVPanicState, events, PVPANIC_PANICKED | PVPANIC_CRASHLOADED),
536
+ sve_ld1_tlb_fn *tlb_fn)
262
- DEFINE_PROP_END_OF_LIST(),
537
+{
263
-};
538
+ void *vd = &env->vfp.zregs[simd_data(desc)];
264
-
539
+ const int diffsz = esz - msz;
265
-static void pvpanic_isa_class_init(ObjectClass *klass, void *data)
540
+ const intptr_t reg_max = simd_oprsz(desc);
266
-{
541
+ const intptr_t mem_max = reg_max >> diffsz;
267
- DeviceClass *dc = DEVICE_CLASS(klass);
542
+ const int mmu_idx = cpu_mmu_index(env, false);
268
-
543
+ intptr_t split, reg_off, mem_off;
269
- dc->realize = pvpanic_isa_realizefn;
544
+ void *host;
270
- device_class_set_props(dc, pvpanic_isa_properties);
545
271
- set_bit(DEVICE_CATEGORY_MISC, dc->categories);
546
-/* No-fault loads are like first-fault loads without the
547
- * first faulting special case.
548
- */
549
-#define DO_LDNF1(PART) \
550
-void HELPER(sve_ldnf1##PART)(CPUARMState *env, void *vg, \
551
- target_ulong addr, uint32_t desc) \
552
-{ \
553
- intptr_t oprsz = simd_oprsz(desc); \
554
- unsigned rd = simd_data(desc); \
555
- void *vd = &env->vfp.zregs[rd]; \
556
- mmap_lock(); \
557
- if (likely(page_check_range(addr, oprsz, PAGE_READ) == 0)) { \
558
- do_sve_ld1##PART(env, vd, vg, addr, oprsz, GETPC()); \
559
- } else { \
560
- do_sve_ldff1##PART(env, vd, vg, addr, oprsz, false, GETPC()); \
561
- } \
562
- mmap_unlock(); \
563
-}
272
-}
564
+ /* Skip to the first active element. */
273
-
565
+ reg_off = find_next_active(vg, 0, reg_max, esz);
274
-static TypeInfo pvpanic_isa_info = {
566
+ if (unlikely(reg_off == reg_max)) {
275
- .name = TYPE_PVPANIC,
567
+ /* The entire predicate was false; no load occurs. */
276
- .parent = TYPE_ISA_DEVICE,
568
+ memset(vd, 0, reg_max);
277
- .instance_size = sizeof(PVPanicState),
569
+ return;
278
- .instance_init = pvpanic_isa_initfn,
570
+ }
279
- .class_init = pvpanic_isa_class_init,
571
+ mem_off = reg_off >> diffsz;
280
-};
572
+ set_helper_retaddr(retaddr);
281
-
573
282
-static void pvpanic_register_types(void)
574
+ /*
283
-{
575
+ * If the (remaining) load is entirely within a single page, then:
284
- type_register_static(&pvpanic_isa_info);
576
+ * For softmmu, and the tlb hits, then no faults will occur;
577
+ * For user-only, either the first load will fault or none will.
578
+ * We can thus perform the load directly to the destination and
579
+ * Vd will be unmodified on any exception path.
580
+ */
581
+ split = max_for_page(addr, mem_off, mem_max);
582
+ if (likely(split == mem_max)) {
583
+ host = tlb_vaddr_to_host(env, addr + mem_off, MMU_DATA_LOAD, mmu_idx);
584
+ if (test_host_page(host)) {
585
+ mem_off = host_fn(vd, vg, host - mem_off, mem_off, mem_max);
586
+ tcg_debug_assert(mem_off == mem_max);
587
+ set_helper_retaddr(0);
588
+ /* After any fault, zero any leading inactive elements. */
589
+ swap_memzero(vd, reg_off);
590
+ return;
591
+ }
592
+ }
593
+
594
+#ifdef CONFIG_USER_ONLY
595
+ /*
596
+ * The page(s) containing this first element at ADDR+MEM_OFF must
597
+ * be valid. Considering that this first element may be misaligned
598
+ * and cross a page boundary itself, take the rest of the page from
599
+ * the last byte of the element.
600
+ */
601
+ split = max_for_page(addr, mem_off + (1 << msz) - 1, mem_max);
602
+ mem_off = host_fn(vd, vg, g2h(addr), mem_off, split);
603
+
604
+ /* After any fault, zero any leading inactive elements. */
605
+ swap_memzero(vd, reg_off);
606
+ reg_off = mem_off << diffsz;
607
#else
608
+ /*
609
+ * Perform one normal read, which will fault or not.
610
+ * But it is likely to bring the page into the tlb.
611
+ */
612
+ tlb_fn(env, vd, reg_off, addr + mem_off, mmu_idx, retaddr);
613
614
-/* TODO: System mode is not yet supported.
615
- * This would probably use tlb_vaddr_to_host.
616
- */
617
-#define DO_LDFF1(PART, FN, TYPEE, TYPEM, H) \
618
-void HELPER(sve_ldff1##PART)(CPUARMState *env, void *vg, \
619
- target_ulong addr, uint32_t desc) \
620
-{ \
621
- g_assert_not_reached(); \
622
-}
285
-}
623
-
286
-
624
-#define DO_LDNF1(PART) \
287
-type_init(pvpanic_register_types)
625
-void HELPER(sve_ldnf1##PART)(CPUARMState *env, void *vg, \
288
diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig
626
- target_ulong addr, uint32_t desc) \
289
index XXXXXXX..XXXXXXX 100644
627
-{ \
290
--- a/hw/i386/Kconfig
628
- g_assert_not_reached(); \
291
+++ b/hw/i386/Kconfig
629
-}
292
@@ -XXX,XX +XXX,XX @@ config PC
630
+ /* After any fault, zero any leading predicated false elts. */
293
imply ISA_DEBUG
631
+ swap_memzero(vd, reg_off);
294
imply PARALLEL
632
+ mem_off += 1 << msz;
295
imply PCI_DEVICES
633
+ reg_off += 1 << esz;
296
- imply PVPANIC
634
297
+ imply PVPANIC_ISA
635
+ /* Try again to read the balance of the page. */
298
imply QXL
636
+ split = max_for_page(addr, mem_off - 1, mem_max);
299
imply SEV
637
+ if (split >= (1 << msz)) {
300
imply SGA
638
+ host = tlb_vaddr_to_host(env, addr + mem_off, MMU_DATA_LOAD, mmu_idx);
301
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
639
+ if (host) {
302
index XXXXXXX..XXXXXXX 100644
640
+ mem_off = host_fn(vd, vg, host - mem_off, mem_off, split);
303
--- a/hw/misc/Kconfig
641
+ reg_off = mem_off << diffsz;
304
+++ b/hw/misc/Kconfig
642
+ }
305
@@ -XXX,XX +XXX,XX @@ config IOTKIT_SYSCTL
643
+ }
306
config IOTKIT_SYSINFO
644
#endif
307
bool
645
308
646
-DO_LDFF1(bb_r, cpu_ldub_data_ra, uint8_t, uint8_t, H1)
309
-config PVPANIC
647
-DO_LDFF1(bhu_r, cpu_ldub_data_ra, uint16_t, uint8_t, H1_2)
310
+config PVPANIC_COMMON
648
-DO_LDFF1(bhs_r, cpu_ldsb_data_ra, uint16_t, int8_t, H1_2)
311
+ bool
649
-DO_LDFF1(bsu_r, cpu_ldub_data_ra, uint32_t, uint8_t, H1_4)
312
+
650
-DO_LDFF1(bss_r, cpu_ldsb_data_ra, uint32_t, int8_t, H1_4)
313
+config PVPANIC_ISA
651
-DO_LDFF1(bdu_r, cpu_ldub_data_ra, uint64_t, uint8_t, )
314
bool
652
-DO_LDFF1(bds_r, cpu_ldsb_data_ra, uint64_t, int8_t, )
315
depends on ISA_BUS
653
+ set_helper_retaddr(0);
316
+ select PVPANIC_COMMON
654
+ record_fault(env, reg_off, reg_max);
317
655
+}
318
config AUX
656
319
bool
657
-DO_LDFF1(hh_r, cpu_lduw_data_ra, uint16_t, uint16_t, H1_2)
320
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
658
-DO_LDFF1(hsu_r, cpu_lduw_data_ra, uint32_t, uint16_t, H1_4)
321
index XXXXXXX..XXXXXXX 100644
659
-DO_LDFF1(hss_r, cpu_ldsw_data_ra, uint32_t, int8_t, H1_4)
322
--- a/hw/misc/meson.build
660
-DO_LDFF1(hdu_r, cpu_lduw_data_ra, uint64_t, uint16_t, )
323
+++ b/hw/misc/meson.build
661
-DO_LDFF1(hds_r, cpu_ldsw_data_ra, uint64_t, int16_t, )
324
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_EMC141X', if_true: files('emc141x.c'))
662
+/*
325
softmmu_ss.add(when: 'CONFIG_UNIMP', if_true: files('unimp.c'))
663
+ * Common helper for all contiguous no-fault loads.
326
softmmu_ss.add(when: 'CONFIG_EMPTY_SLOT', if_true: files('empty_slot.c'))
664
+ */
327
softmmu_ss.add(when: 'CONFIG_LED', if_true: files('led.c'))
665
+static void sve_ldnf1_r(CPUARMState *env, void *vg, const target_ulong addr,
328
+softmmu_ss.add(when: 'CONFIG_PVPANIC_COMMON', if_true: files('pvpanic.c'))
666
+ uint32_t desc, const int esz, const int msz,
329
667
+ sve_ld1_host_fn *host_fn)
330
# ARM devices
668
+{
331
softmmu_ss.add(when: 'CONFIG_PL310', if_true: files('arm_l2x0.c'))
669
+ void *vd = &env->vfp.zregs[simd_data(desc)];
332
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_IOTKIT_SYSINFO', if_true: files('iotkit-sysinfo.c')
670
+ const int diffsz = esz - msz;
333
softmmu_ss.add(when: 'CONFIG_ARMSSE_CPUID', if_true: files('armsse-cpuid.c'))
671
+ const intptr_t reg_max = simd_oprsz(desc);
334
softmmu_ss.add(when: 'CONFIG_ARMSSE_MHU', if_true: files('armsse-mhu.c'))
672
+ const intptr_t mem_max = reg_max >> diffsz;
335
673
+ const int mmu_idx = cpu_mmu_index(env, false);
336
-softmmu_ss.add(when: 'CONFIG_PVPANIC', if_true: files('pvpanic.c'))
674
+ intptr_t split, reg_off, mem_off;
337
+softmmu_ss.add(when: 'CONFIG_PVPANIC_ISA', if_true: files('pvpanic-isa.c'))
675
+ void *host;
338
softmmu_ss.add(when: 'CONFIG_AUX', if_true: files('auxbus.c'))
676
339
softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_scu.c', 'aspeed_sdmc.c', 'aspeed_xdma.c'))
677
-DO_LDFF1(ss_r, cpu_ldl_data_ra, uint32_t, uint32_t, H1_4)
340
softmmu_ss.add(when: 'CONFIG_MSF2', if_true: files('msf2-sysreg.c'))
678
-DO_LDFF1(sdu_r, cpu_ldl_data_ra, uint64_t, uint32_t, )
341
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
679
-DO_LDFF1(sds_r, cpu_ldl_data_ra, uint64_t, int32_t, )
342
index XXXXXXX..XXXXXXX 100644
680
+#ifdef CONFIG_USER_ONLY
343
--- a/tests/qtest/meson.build
681
+ host = tlb_vaddr_to_host(env, addr, MMU_DATA_LOAD, mmu_idx);
344
+++ b/tests/qtest/meson.build
682
+ if (likely(page_check_range(addr, mem_max, PAGE_READ) == 0)) {
345
@@ -XXX,XX +XXX,XX @@ qtests_i386 = \
683
+ /* The entire operation is valid and will not fault. */
346
(config_host.has_key('CONFIG_LINUX') and \
684
+ host_fn(vd, vg, host, 0, mem_max);
347
config_all_devices.has_key('CONFIG_ISA_IPMI_BT') ? ['ipmi-bt-test'] : []) + \
685
+ return;
348
(config_all_devices.has_key('CONFIG_WDT_IB700') ? ['wdt_ib700-test'] : []) + \
686
+ }
349
- (config_all_devices.has_key('CONFIG_PVPANIC') ? ['pvpanic-test'] : []) + \
687
+#endif
350
+ (config_all_devices.has_key('CONFIG_PVPANIC_ISA') ? ['pvpanic-test'] : []) + \
688
351
(config_all_devices.has_key('CONFIG_HDA') ? ['intel-hda-test'] : []) + \
689
-DO_LDFF1(dd_r, cpu_ldq_data_ra, uint64_t, uint64_t, )
352
(config_all_devices.has_key('CONFIG_I82801B11') ? ['i82801b11-test'] : []) + \
690
+ /* There will be no fault, so we may modify in advance. */
353
(config_all_devices.has_key('CONFIG_IOH3420') ? ['ioh3420-test'] : []) + \
691
+ memset(vd, 0, reg_max);
692
693
-#undef DO_LDFF1
694
+ /* Skip to the first active element. */
695
+ reg_off = find_next_active(vg, 0, reg_max, esz);
696
+ if (unlikely(reg_off == reg_max)) {
697
+ /* The entire predicate was false; no load occurs. */
698
+ return;
699
+ }
700
+ mem_off = reg_off >> diffsz;
701
702
-DO_LDNF1(bb_r)
703
-DO_LDNF1(bhu_r)
704
-DO_LDNF1(bhs_r)
705
-DO_LDNF1(bsu_r)
706
-DO_LDNF1(bss_r)
707
-DO_LDNF1(bdu_r)
708
-DO_LDNF1(bds_r)
709
+#ifdef CONFIG_USER_ONLY
710
+ if (page_check_range(addr + mem_off, 1 << msz, PAGE_READ) == 0) {
711
+ /* At least one load is valid; take the rest of the page. */
712
+ split = max_for_page(addr, mem_off + (1 << msz) - 1, mem_max);
713
+ mem_off = host_fn(vd, vg, host, mem_off, split);
714
+ reg_off = mem_off << diffsz;
715
+ }
716
+#else
717
+ /*
718
+ * If the address is not in the TLB, we have no way to bring the
719
+ * entry into the TLB without also risking a fault. Note that
720
+ * the corollary is that we never load from an address not in RAM.
721
+ *
722
+ * This last is out of spec, in a weird corner case.
723
+ * Per the MemNF/MemSingleNF pseudocode, a NF load from Device memory
724
+ * must not actually hit the bus -- it returns UNKNOWN data instead.
725
+ * But if you map non-RAM with Normal memory attributes and do a NF
726
+ * load then it should access the bus. (Nobody ought actually do this
727
+ * in the real world, obviously.)
728
+ *
729
+ * Then there are the annoying special cases with watchpoints...
730
+ *
731
+ * TODO: Add a form of tlb_fill that does not raise an exception,
732
+ * with a form of tlb_vaddr_to_host and a set of loads to match.
733
+ * The non_fault_vaddr_to_host would handle everything, usually,
734
+ * and the loads would handle the iomem path for watchpoints.
735
+ */
736
+ host = tlb_vaddr_to_host(env, addr + mem_off, MMU_DATA_LOAD, mmu_idx);
737
+ split = max_for_page(addr, mem_off, mem_max);
738
+ if (host && split >= (1 << msz)) {
739
+ mem_off = host_fn(vd, vg, host - mem_off, mem_off, split);
740
+ reg_off = mem_off << diffsz;
741
+ }
742
+#endif
743
744
-DO_LDNF1(hh_r)
745
-DO_LDNF1(hsu_r)
746
-DO_LDNF1(hss_r)
747
-DO_LDNF1(hdu_r)
748
-DO_LDNF1(hds_r)
749
+ record_fault(env, reg_off, reg_max);
750
+}
751
752
-DO_LDNF1(ss_r)
753
-DO_LDNF1(sdu_r)
754
-DO_LDNF1(sds_r)
755
+#define DO_LDFF1_LDNF1_1(PART, ESZ) \
756
+void HELPER(sve_ldff1##PART##_r)(CPUARMState *env, void *vg, \
757
+ target_ulong addr, uint32_t desc) \
758
+{ \
759
+ sve_ldff1_r(env, vg, addr, desc, GETPC(), ESZ, 0, \
760
+ sve_ld1##PART##_host, sve_ld1##PART##_tlb); \
761
+} \
762
+void HELPER(sve_ldnf1##PART##_r)(CPUARMState *env, void *vg, \
763
+ target_ulong addr, uint32_t desc) \
764
+{ \
765
+ sve_ldnf1_r(env, vg, addr, desc, ESZ, 0, sve_ld1##PART##_host); \
766
+}
767
768
-DO_LDNF1(dd_r)
769
+/* TODO: Propagate the endian check back to the translator. */
770
+#define DO_LDFF1_LDNF1_2(PART, ESZ, MSZ) \
771
+void HELPER(sve_ldff1##PART##_r)(CPUARMState *env, void *vg, \
772
+ target_ulong addr, uint32_t desc) \
773
+{ \
774
+ if (arm_cpu_data_is_big_endian(env)) { \
775
+ sve_ldff1_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, \
776
+ sve_ld1##PART##_be_host, sve_ld1##PART##_be_tlb); \
777
+ } else { \
778
+ sve_ldff1_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, \
779
+ sve_ld1##PART##_le_host, sve_ld1##PART##_le_tlb); \
780
+ } \
781
+} \
782
+void HELPER(sve_ldnf1##PART##_r)(CPUARMState *env, void *vg, \
783
+ target_ulong addr, uint32_t desc) \
784
+{ \
785
+ if (arm_cpu_data_is_big_endian(env)) { \
786
+ sve_ldnf1_r(env, vg, addr, desc, ESZ, MSZ, \
787
+ sve_ld1##PART##_be_host); \
788
+ } else { \
789
+ sve_ldnf1_r(env, vg, addr, desc, ESZ, MSZ, \
790
+ sve_ld1##PART##_le_host); \
791
+ } \
792
+}
793
794
-#undef DO_LDNF1
795
+DO_LDFF1_LDNF1_1(bb, 0)
796
+DO_LDFF1_LDNF1_1(bhu, 1)
797
+DO_LDFF1_LDNF1_1(bhs, 1)
798
+DO_LDFF1_LDNF1_1(bsu, 2)
799
+DO_LDFF1_LDNF1_1(bss, 2)
800
+DO_LDFF1_LDNF1_1(bdu, 3)
801
+DO_LDFF1_LDNF1_1(bds, 3)
802
+
803
+DO_LDFF1_LDNF1_2(hh, 1, 1)
804
+DO_LDFF1_LDNF1_2(hsu, 2, 1)
805
+DO_LDFF1_LDNF1_2(hss, 2, 1)
806
+DO_LDFF1_LDNF1_2(hdu, 3, 1)
807
+DO_LDFF1_LDNF1_2(hds, 3, 1)
808
+
809
+DO_LDFF1_LDNF1_2(ss, 2, 2)
810
+DO_LDFF1_LDNF1_2(sdu, 3, 2)
811
+DO_LDFF1_LDNF1_2(sds, 3, 2)
812
+
813
+DO_LDFF1_LDNF1_2(dd, 3, 3)
814
+
815
+#undef DO_LDFF1_LDNF1_1
816
+#undef DO_LDFF1_LDNF1_2
817
818
/*
819
* Store contiguous data, protected by a governing predicate.
820
--
354
--
821
2.19.0
355
2.20.1
822
356
823
357
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Mihai Carabas <mihai.carabas@oracle.com>
2
2
3
This fixes the endianness problem for softmmu, and moves the
3
Add PCI interface support for PVPANIC device. Create a new file pvpanic-pci.c
4
main loop out of a macro and into an inlined function.
4
where the PCI specific routines reside and update the build system with the new
5
files and config structure.
5
6
7
Signed-off-by: Mihai Carabas <mihai.carabas@oracle.com>
8
Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
10
Signed-off-by: Mihai Carabas <mihai.carabas@oracle.com>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20181005175350.30752-10-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
---
12
target/arm/sve_helper.c | 351 ++++++++++++++++++++--------------------
13
docs/specs/pci-ids.txt | 1 +
13
1 file changed, 172 insertions(+), 179 deletions(-)
14
include/hw/misc/pvpanic.h | 1 +
15
include/hw/pci/pci.h | 1 +
16
hw/misc/pvpanic-pci.c | 94 +++++++++++++++++++++++++++++++++++++++
17
hw/misc/Kconfig | 6 +++
18
hw/misc/meson.build | 1 +
19
6 files changed, 104 insertions(+)
20
create mode 100644 hw/misc/pvpanic-pci.c
14
21
15
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
22
diff --git a/docs/specs/pci-ids.txt b/docs/specs/pci-ids.txt
16
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/sve_helper.c
24
--- a/docs/specs/pci-ids.txt
18
+++ b/target/arm/sve_helper.c
25
+++ b/docs/specs/pci-ids.txt
19
@@ -XXX,XX +XXX,XX @@ typedef intptr_t sve_ld1_host_fn(void *vd, void *vg, void *host,
26
@@ -XXX,XX +XXX,XX @@ PCI devices (other than virtio):
20
*/
27
1b36:000d PCI xhci usb host adapter
21
typedef void sve_ld1_tlb_fn(CPUARMState *env, void *vd, intptr_t reg_off,
28
1b36:000f mdpy (mdev sample device), linux/samples/vfio-mdev/mdpy.c
22
target_ulong vaddr, int mmu_idx, uintptr_t ra);
29
1b36:0010 PCIe NVMe device (-device nvme)
23
+typedef sve_ld1_tlb_fn sve_st1_tlb_fn;
30
+1b36:0011 PCI PVPanic device (-device pvpanic-pci)
24
31
25
/*
32
All these devices are documented in docs/specs.
26
* Generate the above primitives.
33
27
@@ -XXX,XX +XXX,XX @@ DO_LDFF1_LDNF1_2(dd, 3, 3)
34
diff --git a/include/hw/misc/pvpanic.h b/include/hw/misc/pvpanic.h
28
/*
35
index XXXXXXX..XXXXXXX 100644
29
* Store contiguous data, protected by a governing predicate.
36
--- a/include/hw/misc/pvpanic.h
30
*/
37
+++ b/include/hw/misc/pvpanic.h
31
-#define DO_ST1(NAME, FN, TYPEE, TYPEM, H) \
38
@@ -XXX,XX +XXX,XX @@
32
-void HELPER(NAME)(CPUARMState *env, void *vg, \
39
#include "qom/object.h"
33
- target_ulong addr, uint32_t desc) \
40
34
-{ \
41
#define TYPE_PVPANIC_ISA_DEVICE "pvpanic"
35
- intptr_t i, oprsz = simd_oprsz(desc); \
42
+#define TYPE_PVPANIC_PCI_DEVICE "pvpanic-pci"
36
- intptr_t ra = GETPC(); \
43
37
- unsigned rd = simd_data(desc); \
44
#define PVPANIC_IOPORT_PROP "ioport"
38
- void *vd = &env->vfp.zregs[rd]; \
45
39
- for (i = 0; i < oprsz; ) { \
46
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
40
- uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
47
index XXXXXXX..XXXXXXX 100644
41
- do { \
48
--- a/include/hw/pci/pci.h
42
- if (pg & 1) { \
49
+++ b/include/hw/pci/pci.h
43
- TYPEM m = *(TYPEE *)(vd + H(i)); \
50
@@ -XXX,XX +XXX,XX @@ extern bool pci_available;
44
- FN(env, addr, m, ra); \
51
#define PCI_DEVICE_ID_REDHAT_PCIE_BRIDGE 0x000e
45
- } \
52
#define PCI_DEVICE_ID_REDHAT_MDPY 0x000f
46
- i += sizeof(TYPEE), pg >>= sizeof(TYPEE); \
53
#define PCI_DEVICE_ID_REDHAT_NVME 0x0010
47
- addr += sizeof(TYPEM); \
54
+#define PCI_DEVICE_ID_REDHAT_PVPANIC 0x0011
48
- } while (i & 15); \
55
#define PCI_DEVICE_ID_REDHAT_QXL 0x0100
49
- } \
56
57
#define FMT_PCIBUS PRIx64
58
diff --git a/hw/misc/pvpanic-pci.c b/hw/misc/pvpanic-pci.c
59
new file mode 100644
60
index XXXXXXX..XXXXXXX
61
--- /dev/null
62
+++ b/hw/misc/pvpanic-pci.c
63
@@ -XXX,XX +XXX,XX @@
64
+/*
65
+ * QEMU simulated PCI pvpanic device.
66
+ *
67
+ * Copyright (C) 2020 Oracle
68
+ *
69
+ * Authors:
70
+ * Mihai Carabas <mihai.carabas@oracle.com>
71
+ *
72
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
73
+ * See the COPYING file in the top-level directory.
74
+ *
75
+ */
50
+
76
+
51
+#ifdef CONFIG_SOFTMMU
77
+#include "qemu/osdep.h"
52
+#define DO_ST_TLB(NAME, H, TYPEM, HOST, MOEND, TLB) \
78
+#include "qemu/log.h"
53
+static void sve_##NAME##_tlb(CPUARMState *env, void *vd, intptr_t reg_off, \
79
+#include "qemu/module.h"
54
+ target_ulong addr, int mmu_idx, uintptr_t ra) \
80
+#include "sysemu/runstate.h"
55
+{ \
81
+
56
+ TCGMemOpIdx oi = make_memop_idx(ctz32(sizeof(TYPEM)) | MOEND, mmu_idx); \
82
+#include "hw/nvram/fw_cfg.h"
57
+ TLB(env, addr, *(TYPEM *)(vd + H(reg_off)), oi, ra); \
83
+#include "hw/qdev-properties.h"
58
}
84
+#include "migration/vmstate.h"
59
-
85
+#include "hw/misc/pvpanic.h"
60
-#define DO_ST1_D(NAME, FN, TYPEM) \
86
+#include "qom/object.h"
61
-void HELPER(NAME)(CPUARMState *env, void *vg, \
87
+#include "hw/pci/pci.h"
62
- target_ulong addr, uint32_t desc) \
88
+
63
-{ \
89
+OBJECT_DECLARE_SIMPLE_TYPE(PVPanicPCIState, PVPANIC_PCI_DEVICE)
64
- intptr_t i, oprsz = simd_oprsz(desc) / 8; \
90
+
65
- intptr_t ra = GETPC(); \
66
- unsigned rd = simd_data(desc); \
67
- uint64_t *d = &env->vfp.zregs[rd].d[0]; \
68
- uint8_t *pg = vg; \
69
- for (i = 0; i < oprsz; i += 1) { \
70
- if (pg[H1(i)] & 1) { \
71
- FN(env, addr, d[i], ra); \
72
- } \
73
- addr += sizeof(TYPEM); \
74
- } \
75
+#else
76
+#define DO_ST_TLB(NAME, H, TYPEM, HOST, MOEND, TLB) \
77
+static void sve_##NAME##_tlb(CPUARMState *env, void *vd, intptr_t reg_off, \
78
+ target_ulong addr, int mmu_idx, uintptr_t ra) \
79
+{ \
80
+ HOST(g2h(addr), *(TYPEM *)(vd + H(reg_off))); \
81
}
82
+#endif
83
84
-#define DO_ST2(NAME, FN, TYPEE, TYPEM, H) \
85
-void HELPER(NAME)(CPUARMState *env, void *vg, \
86
- target_ulong addr, uint32_t desc) \
87
-{ \
88
- intptr_t i, oprsz = simd_oprsz(desc); \
89
- intptr_t ra = GETPC(); \
90
- unsigned rd = simd_data(desc); \
91
- void *d1 = &env->vfp.zregs[rd]; \
92
- void *d2 = &env->vfp.zregs[(rd + 1) & 31]; \
93
- for (i = 0; i < oprsz; ) { \
94
- uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
95
- do { \
96
- if (pg & 1) { \
97
- TYPEM m1 = *(TYPEE *)(d1 + H(i)); \
98
- TYPEM m2 = *(TYPEE *)(d2 + H(i)); \
99
- FN(env, addr, m1, ra); \
100
- FN(env, addr + sizeof(TYPEM), m2, ra); \
101
- } \
102
- i += sizeof(TYPEE), pg >>= sizeof(TYPEE); \
103
- addr += 2 * sizeof(TYPEM); \
104
- } while (i & 15); \
105
- } \
106
-}
107
+DO_ST_TLB(st1bb, H1, uint8_t, stb_p, 0, helper_ret_stb_mmu)
108
+DO_ST_TLB(st1bh, H1_2, uint16_t, stb_p, 0, helper_ret_stb_mmu)
109
+DO_ST_TLB(st1bs, H1_4, uint32_t, stb_p, 0, helper_ret_stb_mmu)
110
+DO_ST_TLB(st1bd, , uint64_t, stb_p, 0, helper_ret_stb_mmu)
111
112
-#define DO_ST3(NAME, FN, TYPEE, TYPEM, H) \
113
-void HELPER(NAME)(CPUARMState *env, void *vg, \
114
- target_ulong addr, uint32_t desc) \
115
-{ \
116
- intptr_t i, oprsz = simd_oprsz(desc); \
117
- intptr_t ra = GETPC(); \
118
- unsigned rd = simd_data(desc); \
119
- void *d1 = &env->vfp.zregs[rd]; \
120
- void *d2 = &env->vfp.zregs[(rd + 1) & 31]; \
121
- void *d3 = &env->vfp.zregs[(rd + 2) & 31]; \
122
- for (i = 0; i < oprsz; ) { \
123
- uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
124
- do { \
125
- if (pg & 1) { \
126
- TYPEM m1 = *(TYPEE *)(d1 + H(i)); \
127
- TYPEM m2 = *(TYPEE *)(d2 + H(i)); \
128
- TYPEM m3 = *(TYPEE *)(d3 + H(i)); \
129
- FN(env, addr, m1, ra); \
130
- FN(env, addr + sizeof(TYPEM), m2, ra); \
131
- FN(env, addr + 2 * sizeof(TYPEM), m3, ra); \
132
- } \
133
- i += sizeof(TYPEE), pg >>= sizeof(TYPEE); \
134
- addr += 3 * sizeof(TYPEM); \
135
- } while (i & 15); \
136
- } \
137
-}
138
+DO_ST_TLB(st1hh_le, H1_2, uint16_t, stw_le_p, MO_LE, helper_le_stw_mmu)
139
+DO_ST_TLB(st1hs_le, H1_4, uint32_t, stw_le_p, MO_LE, helper_le_stw_mmu)
140
+DO_ST_TLB(st1hd_le, , uint64_t, stw_le_p, MO_LE, helper_le_stw_mmu)
141
142
-#define DO_ST4(NAME, FN, TYPEE, TYPEM, H) \
143
-void HELPER(NAME)(CPUARMState *env, void *vg, \
144
- target_ulong addr, uint32_t desc) \
145
-{ \
146
- intptr_t i, oprsz = simd_oprsz(desc); \
147
- intptr_t ra = GETPC(); \
148
- unsigned rd = simd_data(desc); \
149
- void *d1 = &env->vfp.zregs[rd]; \
150
- void *d2 = &env->vfp.zregs[(rd + 1) & 31]; \
151
- void *d3 = &env->vfp.zregs[(rd + 2) & 31]; \
152
- void *d4 = &env->vfp.zregs[(rd + 3) & 31]; \
153
- for (i = 0; i < oprsz; ) { \
154
- uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
155
- do { \
156
- if (pg & 1) { \
157
- TYPEM m1 = *(TYPEE *)(d1 + H(i)); \
158
- TYPEM m2 = *(TYPEE *)(d2 + H(i)); \
159
- TYPEM m3 = *(TYPEE *)(d3 + H(i)); \
160
- TYPEM m4 = *(TYPEE *)(d4 + H(i)); \
161
- FN(env, addr, m1, ra); \
162
- FN(env, addr + sizeof(TYPEM), m2, ra); \
163
- FN(env, addr + 2 * sizeof(TYPEM), m3, ra); \
164
- FN(env, addr + 3 * sizeof(TYPEM), m4, ra); \
165
- } \
166
- i += sizeof(TYPEE), pg >>= sizeof(TYPEE); \
167
- addr += 4 * sizeof(TYPEM); \
168
- } while (i & 15); \
169
- } \
170
-}
171
+DO_ST_TLB(st1ss_le, H1_4, uint32_t, stl_le_p, MO_LE, helper_le_stl_mmu)
172
+DO_ST_TLB(st1sd_le, , uint64_t, stl_le_p, MO_LE, helper_le_stl_mmu)
173
174
-DO_ST1(sve_st1bh_r, cpu_stb_data_ra, uint16_t, uint8_t, H1_2)
175
-DO_ST1(sve_st1bs_r, cpu_stb_data_ra, uint32_t, uint8_t, H1_4)
176
-DO_ST1_D(sve_st1bd_r, cpu_stb_data_ra, uint8_t)
177
+DO_ST_TLB(st1dd_le, , uint64_t, stq_le_p, MO_LE, helper_le_stq_mmu)
178
179
-DO_ST1(sve_st1hs_r, cpu_stw_data_ra, uint32_t, uint16_t, H1_4)
180
-DO_ST1_D(sve_st1hd_r, cpu_stw_data_ra, uint16_t)
181
+DO_ST_TLB(st1hh_be, H1_2, uint16_t, stw_be_p, MO_BE, helper_be_stw_mmu)
182
+DO_ST_TLB(st1hs_be, H1_4, uint32_t, stw_be_p, MO_BE, helper_be_stw_mmu)
183
+DO_ST_TLB(st1hd_be, , uint64_t, stw_be_p, MO_BE, helper_be_stw_mmu)
184
185
-DO_ST1_D(sve_st1sd_r, cpu_stl_data_ra, uint32_t)
186
+DO_ST_TLB(st1ss_be, H1_4, uint32_t, stl_be_p, MO_BE, helper_be_stl_mmu)
187
+DO_ST_TLB(st1sd_be, , uint64_t, stl_be_p, MO_BE, helper_be_stl_mmu)
188
189
-DO_ST1(sve_st1bb_r, cpu_stb_data_ra, uint8_t, uint8_t, H1)
190
-DO_ST2(sve_st2bb_r, cpu_stb_data_ra, uint8_t, uint8_t, H1)
191
-DO_ST3(sve_st3bb_r, cpu_stb_data_ra, uint8_t, uint8_t, H1)
192
-DO_ST4(sve_st4bb_r, cpu_stb_data_ra, uint8_t, uint8_t, H1)
193
+DO_ST_TLB(st1dd_be, , uint64_t, stq_be_p, MO_BE, helper_be_stq_mmu)
194
195
-DO_ST1(sve_st1hh_r, cpu_stw_data_ra, uint16_t, uint16_t, H1_2)
196
-DO_ST2(sve_st2hh_r, cpu_stw_data_ra, uint16_t, uint16_t, H1_2)
197
-DO_ST3(sve_st3hh_r, cpu_stw_data_ra, uint16_t, uint16_t, H1_2)
198
-DO_ST4(sve_st4hh_r, cpu_stw_data_ra, uint16_t, uint16_t, H1_2)
199
+#undef DO_ST_TLB
200
201
-DO_ST1(sve_st1ss_r, cpu_stl_data_ra, uint32_t, uint32_t, H1_4)
202
-DO_ST2(sve_st2ss_r, cpu_stl_data_ra, uint32_t, uint32_t, H1_4)
203
-DO_ST3(sve_st3ss_r, cpu_stl_data_ra, uint32_t, uint32_t, H1_4)
204
-DO_ST4(sve_st4ss_r, cpu_stl_data_ra, uint32_t, uint32_t, H1_4)
205
-
206
-DO_ST1_D(sve_st1dd_r, cpu_stq_data_ra, uint64_t)
207
-
208
-void HELPER(sve_st2dd_r)(CPUARMState *env, void *vg,
209
- target_ulong addr, uint32_t desc)
210
+/*
91
+/*
211
+ * Common helpers for all contiguous 1,2,3,4-register predicated stores.
92
+ * PVPanicPCIState for PCI device
212
+ */
93
+ */
213
+static void sve_st1_r(CPUARMState *env, void *vg, target_ulong addr,
94
+typedef struct PVPanicPCIState {
214
+ uint32_t desc, const uintptr_t ra,
95
+ PCIDevice dev;
215
+ const int esize, const int msize,
96
+ PVPanicState pvpanic;
216
+ sve_st1_tlb_fn *tlb_fn)
97
+} PVPanicPCIState;
217
{
98
+
218
- intptr_t i, oprsz = simd_oprsz(desc) / 8;
99
+static const VMStateDescription vmstate_pvpanic_pci = {
219
- intptr_t ra = GETPC();
100
+ .name = "pvpanic-pci",
220
+ const int mmu_idx = cpu_mmu_index(env, false);
101
+ .version_id = 1,
221
+ intptr_t i, oprsz = simd_oprsz(desc);
102
+ .minimum_version_id = 1,
222
unsigned rd = simd_data(desc);
103
+ .fields = (VMStateField[]) {
223
- uint64_t *d1 = &env->vfp.zregs[rd].d[0];
104
+ VMSTATE_PCI_DEVICE(dev, PVPanicPCIState),
224
- uint64_t *d2 = &env->vfp.zregs[(rd + 1) & 31].d[0];
105
+ VMSTATE_END_OF_LIST()
225
- uint8_t *pg = vg;
106
+ }
226
+ void *vd = &env->vfp.zregs[rd];
107
+};
227
108
+
228
- for (i = 0; i < oprsz; i += 1) {
109
+static void pvpanic_pci_realizefn(PCIDevice *dev, Error **errp)
229
- if (pg[H1(i)] & 1) {
230
- cpu_stq_data_ra(env, addr, d1[i], ra);
231
- cpu_stq_data_ra(env, addr + 8, d2[i], ra);
232
- }
233
- addr += 2 * 8;
234
+ set_helper_retaddr(ra);
235
+ for (i = 0; i < oprsz; ) {
236
+ uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));
237
+ do {
238
+ if (pg & 1) {
239
+ tlb_fn(env, vd, i, addr, mmu_idx, ra);
240
+ }
241
+ i += esize, pg >>= esize;
242
+ addr += msize;
243
+ } while (i & 15);
244
}
245
+ set_helper_retaddr(0);
246
}
247
248
-void HELPER(sve_st3dd_r)(CPUARMState *env, void *vg,
249
- target_ulong addr, uint32_t desc)
250
+static void sve_st2_r(CPUARMState *env, void *vg, target_ulong addr,
251
+ uint32_t desc, const uintptr_t ra,
252
+ const int esize, const int msize,
253
+ sve_st1_tlb_fn *tlb_fn)
254
{
255
- intptr_t i, oprsz = simd_oprsz(desc) / 8;
256
- intptr_t ra = GETPC();
257
+ const int mmu_idx = cpu_mmu_index(env, false);
258
+ intptr_t i, oprsz = simd_oprsz(desc);
259
unsigned rd = simd_data(desc);
260
- uint64_t *d1 = &env->vfp.zregs[rd].d[0];
261
- uint64_t *d2 = &env->vfp.zregs[(rd + 1) & 31].d[0];
262
- uint64_t *d3 = &env->vfp.zregs[(rd + 2) & 31].d[0];
263
- uint8_t *pg = vg;
264
+ void *d1 = &env->vfp.zregs[rd];
265
+ void *d2 = &env->vfp.zregs[(rd + 1) & 31];
266
267
- for (i = 0; i < oprsz; i += 1) {
268
- if (pg[H1(i)] & 1) {
269
- cpu_stq_data_ra(env, addr, d1[i], ra);
270
- cpu_stq_data_ra(env, addr + 8, d2[i], ra);
271
- cpu_stq_data_ra(env, addr + 16, d3[i], ra);
272
- }
273
- addr += 3 * 8;
274
+ set_helper_retaddr(ra);
275
+ for (i = 0; i < oprsz; ) {
276
+ uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));
277
+ do {
278
+ if (pg & 1) {
279
+ tlb_fn(env, d1, i, addr, mmu_idx, ra);
280
+ tlb_fn(env, d2, i, addr + msize, mmu_idx, ra);
281
+ }
282
+ i += esize, pg >>= esize;
283
+ addr += 2 * msize;
284
+ } while (i & 15);
285
}
286
+ set_helper_retaddr(0);
287
}
288
289
-void HELPER(sve_st4dd_r)(CPUARMState *env, void *vg,
290
- target_ulong addr, uint32_t desc)
291
+static void sve_st3_r(CPUARMState *env, void *vg, target_ulong addr,
292
+ uint32_t desc, const uintptr_t ra,
293
+ const int esize, const int msize,
294
+ sve_st1_tlb_fn *tlb_fn)
295
{
296
- intptr_t i, oprsz = simd_oprsz(desc) / 8;
297
- intptr_t ra = GETPC();
298
+ const int mmu_idx = cpu_mmu_index(env, false);
299
+ intptr_t i, oprsz = simd_oprsz(desc);
300
unsigned rd = simd_data(desc);
301
- uint64_t *d1 = &env->vfp.zregs[rd].d[0];
302
- uint64_t *d2 = &env->vfp.zregs[(rd + 1) & 31].d[0];
303
- uint64_t *d3 = &env->vfp.zregs[(rd + 2) & 31].d[0];
304
- uint64_t *d4 = &env->vfp.zregs[(rd + 3) & 31].d[0];
305
- uint8_t *pg = vg;
306
+ void *d1 = &env->vfp.zregs[rd];
307
+ void *d2 = &env->vfp.zregs[(rd + 1) & 31];
308
+ void *d3 = &env->vfp.zregs[(rd + 2) & 31];
309
310
- for (i = 0; i < oprsz; i += 1) {
311
- if (pg[H1(i)] & 1) {
312
- cpu_stq_data_ra(env, addr, d1[i], ra);
313
- cpu_stq_data_ra(env, addr + 8, d2[i], ra);
314
- cpu_stq_data_ra(env, addr + 16, d3[i], ra);
315
- cpu_stq_data_ra(env, addr + 24, d4[i], ra);
316
- }
317
- addr += 4 * 8;
318
+ set_helper_retaddr(ra);
319
+ for (i = 0; i < oprsz; ) {
320
+ uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));
321
+ do {
322
+ if (pg & 1) {
323
+ tlb_fn(env, d1, i, addr, mmu_idx, ra);
324
+ tlb_fn(env, d2, i, addr + msize, mmu_idx, ra);
325
+ tlb_fn(env, d3, i, addr + 2 * msize, mmu_idx, ra);
326
+ }
327
+ i += esize, pg >>= esize;
328
+ addr += 3 * msize;
329
+ } while (i & 15);
330
}
331
+ set_helper_retaddr(0);
332
}
333
334
+static void sve_st4_r(CPUARMState *env, void *vg, target_ulong addr,
335
+ uint32_t desc, const uintptr_t ra,
336
+ const int esize, const int msize,
337
+ sve_st1_tlb_fn *tlb_fn)
338
+{
110
+{
339
+ const int mmu_idx = cpu_mmu_index(env, false);
111
+ PVPanicPCIState *s = PVPANIC_PCI_DEVICE(dev);
340
+ intptr_t i, oprsz = simd_oprsz(desc);
112
+ PVPanicState *ps = &s->pvpanic;
341
+ unsigned rd = simd_data(desc);
342
+ void *d1 = &env->vfp.zregs[rd];
343
+ void *d2 = &env->vfp.zregs[(rd + 1) & 31];
344
+ void *d3 = &env->vfp.zregs[(rd + 2) & 31];
345
+ void *d4 = &env->vfp.zregs[(rd + 3) & 31];
346
+
113
+
347
+ set_helper_retaddr(ra);
114
+ pvpanic_setup_io(&s->pvpanic, DEVICE(s), 2);
348
+ for (i = 0; i < oprsz; ) {
115
+
349
+ uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));
116
+ pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &ps->mr);
350
+ do {
351
+ if (pg & 1) {
352
+ tlb_fn(env, d1, i, addr, mmu_idx, ra);
353
+ tlb_fn(env, d2, i, addr + msize, mmu_idx, ra);
354
+ tlb_fn(env, d3, i, addr + 2 * msize, mmu_idx, ra);
355
+ tlb_fn(env, d4, i, addr + 3 * msize, mmu_idx, ra);
356
+ }
357
+ i += esize, pg >>= esize;
358
+ addr += 4 * msize;
359
+ } while (i & 15);
360
+ }
361
+ set_helper_retaddr(0);
362
+}
117
+}
363
+
118
+
364
+#define DO_STN_1(N, NAME, ESIZE) \
119
+static Property pvpanic_pci_properties[] = {
365
+void __attribute__((flatten)) HELPER(sve_st##N##NAME##_r) \
120
+ DEFINE_PROP_UINT8("events", PVPanicPCIState, pvpanic.events, PVPANIC_PANICKED | PVPANIC_CRASHLOADED),
366
+ (CPUARMState *env, void *vg, target_ulong addr, uint32_t desc) \
121
+ DEFINE_PROP_END_OF_LIST(),
367
+{ \
122
+};
368
+ sve_st##N##_r(env, vg, addr, desc, GETPC(), ESIZE, 1, \
123
+
369
+ sve_st1##NAME##_tlb); \
124
+static void pvpanic_pci_class_init(ObjectClass *klass, void *data)
125
+{
126
+ DeviceClass *dc = DEVICE_CLASS(klass);
127
+ PCIDeviceClass *pc = PCI_DEVICE_CLASS(klass);
128
+
129
+ device_class_set_props(dc, pvpanic_pci_properties);
130
+
131
+ pc->realize = pvpanic_pci_realizefn;
132
+ pc->vendor_id = PCI_VENDOR_ID_REDHAT;
133
+ pc->device_id = PCI_DEVICE_ID_REDHAT_PVPANIC;
134
+ pc->revision = 1;
135
+ pc->class_id = PCI_CLASS_SYSTEM_OTHER;
136
+ dc->vmsd = &vmstate_pvpanic_pci;
137
+
138
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
370
+}
139
+}
371
+
140
+
372
+#define DO_STN_2(N, NAME, ESIZE, MSIZE) \
141
+static TypeInfo pvpanic_pci_info = {
373
+void __attribute__((flatten)) HELPER(sve_st##N##NAME##_r) \
142
+ .name = TYPE_PVPANIC_PCI_DEVICE,
374
+ (CPUARMState *env, void *vg, target_ulong addr, uint32_t desc) \
143
+ .parent = TYPE_PCI_DEVICE,
375
+{ \
144
+ .instance_size = sizeof(PVPanicPCIState),
376
+ sve_st##N##_r(env, vg, addr, desc, GETPC(), ESIZE, MSIZE, \
145
+ .class_init = pvpanic_pci_class_init,
377
+ arm_cpu_data_is_big_endian(env) \
146
+ .interfaces = (InterfaceInfo[]) {
378
+ ? sve_st1##NAME##_be_tlb : sve_st1##NAME##_le_tlb); \
147
+ { INTERFACE_CONVENTIONAL_PCI_DEVICE },
148
+ { }
149
+ }
150
+};
151
+
152
+static void pvpanic_register_types(void)
153
+{
154
+ type_register_static(&pvpanic_pci_info);
379
+}
155
+}
380
+
156
+
381
+DO_STN_1(1, bb, 1)
157
+type_init(pvpanic_register_types);
382
+DO_STN_1(1, bh, 2)
158
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
383
+DO_STN_1(1, bs, 4)
159
index XXXXXXX..XXXXXXX 100644
384
+DO_STN_1(1, bd, 8)
160
--- a/hw/misc/Kconfig
385
+DO_STN_1(2, bb, 1)
161
+++ b/hw/misc/Kconfig
386
+DO_STN_1(3, bb, 1)
162
@@ -XXX,XX +XXX,XX @@ config IOTKIT_SYSINFO
387
+DO_STN_1(4, bb, 1)
163
config PVPANIC_COMMON
164
bool
165
166
+config PVPANIC_PCI
167
+ bool
168
+ default y if PCI_DEVICES
169
+ depends on PCI
170
+ select PVPANIC_COMMON
388
+
171
+
389
+DO_STN_2(1, hh, 2, 2)
172
config PVPANIC_ISA
390
+DO_STN_2(1, hs, 4, 2)
173
bool
391
+DO_STN_2(1, hd, 8, 2)
174
depends on ISA_BUS
392
+DO_STN_2(2, hh, 2, 2)
175
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
393
+DO_STN_2(3, hh, 2, 2)
176
index XXXXXXX..XXXXXXX 100644
394
+DO_STN_2(4, hh, 2, 2)
177
--- a/hw/misc/meson.build
395
+
178
+++ b/hw/misc/meson.build
396
+DO_STN_2(1, ss, 4, 4)
179
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_ARMSSE_CPUID', if_true: files('armsse-cpuid.c'))
397
+DO_STN_2(1, sd, 8, 4)
180
softmmu_ss.add(when: 'CONFIG_ARMSSE_MHU', if_true: files('armsse-mhu.c'))
398
+DO_STN_2(2, ss, 4, 4)
181
399
+DO_STN_2(3, ss, 4, 4)
182
softmmu_ss.add(when: 'CONFIG_PVPANIC_ISA', if_true: files('pvpanic-isa.c'))
400
+DO_STN_2(4, ss, 4, 4)
183
+softmmu_ss.add(when: 'CONFIG_PVPANIC_PCI', if_true: files('pvpanic-pci.c'))
401
+
184
softmmu_ss.add(when: 'CONFIG_AUX', if_true: files('auxbus.c'))
402
+DO_STN_2(1, dd, 8, 8)
185
softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_scu.c', 'aspeed_sdmc.c', 'aspeed_xdma.c'))
403
+DO_STN_2(2, dd, 8, 8)
186
softmmu_ss.add(when: 'CONFIG_MSF2', if_true: files('msf2-sysreg.c'))
404
+DO_STN_2(3, dd, 8, 8)
405
+DO_STN_2(4, dd, 8, 8)
406
+
407
+#undef DO_STN_1
408
+#undef DO_STN_2
409
+
410
/* Loads with a vector index. */
411
412
#define DO_LD1_ZPZ_S(NAME, TYPEI, TYPEM, FN) \
413
--
187
--
414
2.19.0
188
2.20.1
415
189
416
190
diff view generated by jsdifflib
1
From: Dongjiu Geng <gengdongjiu@huawei.com>
1
From: Mihai Carabas <mihai.carabas@oracle.com>
2
2
3
The parameter of kvm_arm_init_cpreg_list() is ARMCPU instead of
3
Add pvpanic PCI device support details in docs/specs/pvpanic.txt.
4
CPUState, so correct the note to make it match the code.
5
4
6
Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
5
Signed-off-by: Mihai Carabas <mihai.carabas@oracle.com>
7
Message-id: 1538069046-5757-1-git-send-email-gengdongjiu@huawei.com
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
8
---
11
target/arm/kvm_arm.h | 4 ++--
9
docs/specs/pvpanic.txt | 13 ++++++++++++-
12
target/arm/kvm.c | 2 +-
10
1 file changed, 12 insertions(+), 1 deletion(-)
13
2 files changed, 3 insertions(+), 3 deletions(-)
14
11
15
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
12
diff --git a/docs/specs/pvpanic.txt b/docs/specs/pvpanic.txt
16
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/kvm_arm.h
14
--- a/docs/specs/pvpanic.txt
18
+++ b/target/arm/kvm_arm.h
15
+++ b/docs/specs/pvpanic.txt
19
@@ -XXX,XX +XXX,XX @@ void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid, uint64_t group,
16
@@ -XXX,XX +XXX,XX @@
20
17
PVPANIC DEVICE
21
/**
18
==============
22
* kvm_arm_init_cpreg_list:
19
23
- * @cs: CPUState
20
-pvpanic device is a simulated ISA device, through which a guest panic
24
+ * @cpu: ARMCPU
21
+pvpanic device is a simulated device, through which a guest panic
25
*
22
event is sent to qemu, and a QMP event is generated. This allows
26
- * Initialize the CPUState's cpreg list according to the kernel's
23
management apps (e.g. libvirt) to be notified and respond to the event.
27
+ * Initialize the ARMCPU cpreg list according to the kernel's
24
28
* definition of what CPU registers it knows about (and throw away
25
@@ -XXX,XX +XXX,XX @@ The management app has the option of waiting for GUEST_PANICKED events,
29
* the previous TCG-created cpreg list).
26
and/or polling for guest-panicked RunState, to learn when the pvpanic
30
*
27
device has fired a panic event.
31
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
28
32
index XXXXXXX..XXXXXXX 100644
29
+The pvpanic device can be implemented as an ISA device (using IOPORT) or as a
33
--- a/target/arm/kvm.c
30
+PCI device.
34
+++ b/target/arm/kvm.c
31
+
35
@@ -XXX,XX +XXX,XX @@ static int compare_u64(const void *a, const void *b)
32
ISA Interface
36
return 0;
33
-------------
37
}
34
38
35
@@ -XXX,XX +XXX,XX @@ bit 1: a guest panic has happened and will be handled by the guest;
39
-/* Initialize the CPUState's cpreg list according to the kernel's
36
the host should record it or report it, but should not affect
40
+/* Initialize the ARMCPU cpreg list according to the kernel's
37
the execution of the guest.
41
* definition of what CPU registers it knows about (and throw away
38
42
* the previous TCG-created cpreg list).
39
+PCI Interface
43
*/
40
+-------------
41
+
42
+The PCI interface is similar to the ISA interface except that it uses an MMIO
43
+address space provided by its BAR0, 1 byte long. Any machine with a PCI bus
44
+can enable a pvpanic device by adding '-device pvpanic-pci' to the command
45
+line.
46
+
47
ACPI Interface
48
--------------
49
44
--
50
--
45
2.19.0
51
2.20.1
46
52
47
53
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Mihai Carabas <mihai.carabas@oracle.com>
2
2
3
This fixes the endianness problem for softmmu, and moves
3
Add a test case for pvpanic-pci device. The scenario is the same as pvpanic
4
the main loop out of a macro and into an inlined function.
4
ISA device, but is using the PCI bus.
5
5
6
Signed-off-by: Mihai Carabas <mihai.carabas@oracle.com>
7
Acked-by: Thomas Huth <thuth@redhat.com>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
9
Signed-off-by: Mihai Carabas <mihai.carabas@oracle.com>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20181005175350.30752-13-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
11
---
12
target/arm/helper-sve.h | 84 +++++++++----
12
tests/qtest/pvpanic-pci-test.c | 94 ++++++++++++++++++++++++++++++++++
13
target/arm/sve_helper.c | 225 ++++++++++++++++++++++++----------
13
tests/qtest/meson.build | 1 +
14
target/arm/translate-sve.c | 244 +++++++++++++++++++++++++------------
14
2 files changed, 95 insertions(+)
15
3 files changed, 386 insertions(+), 167 deletions(-)
15
create mode 100644 tests/qtest/pvpanic-pci-test.c
16
16
17
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
17
diff --git a/tests/qtest/pvpanic-pci-test.c b/tests/qtest/pvpanic-pci-test.c
18
index XXXXXXX..XXXXXXX 100644
18
new file mode 100644
19
--- a/target/arm/helper-sve.h
19
index XXXXXXX..XXXXXXX
20
+++ b/target/arm/helper-sve.h
20
--- /dev/null
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(sve_st1sd_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
21
+++ b/tests/qtest/pvpanic-pci-test.c
22
22
@@ -XXX,XX +XXX,XX @@
23
DEF_HELPER_FLAGS_6(sve_ldbsu_zsu, TCG_CALL_NO_WG,
24
void, env, ptr, ptr, ptr, tl, i32)
25
-DEF_HELPER_FLAGS_6(sve_ldhsu_zsu, TCG_CALL_NO_WG,
26
+DEF_HELPER_FLAGS_6(sve_ldhsu_le_zsu, TCG_CALL_NO_WG,
27
void, env, ptr, ptr, ptr, tl, i32)
28
-DEF_HELPER_FLAGS_6(sve_ldssu_zsu, TCG_CALL_NO_WG,
29
+DEF_HELPER_FLAGS_6(sve_ldhsu_be_zsu, TCG_CALL_NO_WG,
30
+ void, env, ptr, ptr, ptr, tl, i32)
31
+DEF_HELPER_FLAGS_6(sve_ldss_le_zsu, TCG_CALL_NO_WG,
32
+ void, env, ptr, ptr, ptr, tl, i32)
33
+DEF_HELPER_FLAGS_6(sve_ldss_be_zsu, TCG_CALL_NO_WG,
34
void, env, ptr, ptr, ptr, tl, i32)
35
DEF_HELPER_FLAGS_6(sve_ldbss_zsu, TCG_CALL_NO_WG,
36
void, env, ptr, ptr, ptr, tl, i32)
37
-DEF_HELPER_FLAGS_6(sve_ldhss_zsu, TCG_CALL_NO_WG,
38
+DEF_HELPER_FLAGS_6(sve_ldhss_le_zsu, TCG_CALL_NO_WG,
39
+ void, env, ptr, ptr, ptr, tl, i32)
40
+DEF_HELPER_FLAGS_6(sve_ldhss_be_zsu, TCG_CALL_NO_WG,
41
void, env, ptr, ptr, ptr, tl, i32)
42
43
DEF_HELPER_FLAGS_6(sve_ldbsu_zss, TCG_CALL_NO_WG,
44
void, env, ptr, ptr, ptr, tl, i32)
45
-DEF_HELPER_FLAGS_6(sve_ldhsu_zss, TCG_CALL_NO_WG,
46
+DEF_HELPER_FLAGS_6(sve_ldhsu_le_zss, TCG_CALL_NO_WG,
47
void, env, ptr, ptr, ptr, tl, i32)
48
-DEF_HELPER_FLAGS_6(sve_ldssu_zss, TCG_CALL_NO_WG,
49
+DEF_HELPER_FLAGS_6(sve_ldhsu_be_zss, TCG_CALL_NO_WG,
50
+ void, env, ptr, ptr, ptr, tl, i32)
51
+DEF_HELPER_FLAGS_6(sve_ldss_le_zss, TCG_CALL_NO_WG,
52
+ void, env, ptr, ptr, ptr, tl, i32)
53
+DEF_HELPER_FLAGS_6(sve_ldss_be_zss, TCG_CALL_NO_WG,
54
void, env, ptr, ptr, ptr, tl, i32)
55
DEF_HELPER_FLAGS_6(sve_ldbss_zss, TCG_CALL_NO_WG,
56
void, env, ptr, ptr, ptr, tl, i32)
57
-DEF_HELPER_FLAGS_6(sve_ldhss_zss, TCG_CALL_NO_WG,
58
+DEF_HELPER_FLAGS_6(sve_ldhss_le_zss, TCG_CALL_NO_WG,
59
+ void, env, ptr, ptr, ptr, tl, i32)
60
+DEF_HELPER_FLAGS_6(sve_ldhss_be_zss, TCG_CALL_NO_WG,
61
void, env, ptr, ptr, ptr, tl, i32)
62
63
DEF_HELPER_FLAGS_6(sve_ldbdu_zsu, TCG_CALL_NO_WG,
64
void, env, ptr, ptr, ptr, tl, i32)
65
-DEF_HELPER_FLAGS_6(sve_ldhdu_zsu, TCG_CALL_NO_WG,
66
+DEF_HELPER_FLAGS_6(sve_ldhdu_le_zsu, TCG_CALL_NO_WG,
67
void, env, ptr, ptr, ptr, tl, i32)
68
-DEF_HELPER_FLAGS_6(sve_ldsdu_zsu, TCG_CALL_NO_WG,
69
+DEF_HELPER_FLAGS_6(sve_ldhdu_be_zsu, TCG_CALL_NO_WG,
70
void, env, ptr, ptr, ptr, tl, i32)
71
-DEF_HELPER_FLAGS_6(sve_ldddu_zsu, TCG_CALL_NO_WG,
72
+DEF_HELPER_FLAGS_6(sve_ldsdu_le_zsu, TCG_CALL_NO_WG,
73
+ void, env, ptr, ptr, ptr, tl, i32)
74
+DEF_HELPER_FLAGS_6(sve_ldsdu_be_zsu, TCG_CALL_NO_WG,
75
+ void, env, ptr, ptr, ptr, tl, i32)
76
+DEF_HELPER_FLAGS_6(sve_lddd_le_zsu, TCG_CALL_NO_WG,
77
+ void, env, ptr, ptr, ptr, tl, i32)
78
+DEF_HELPER_FLAGS_6(sve_lddd_be_zsu, TCG_CALL_NO_WG,
79
void, env, ptr, ptr, ptr, tl, i32)
80
DEF_HELPER_FLAGS_6(sve_ldbds_zsu, TCG_CALL_NO_WG,
81
void, env, ptr, ptr, ptr, tl, i32)
82
-DEF_HELPER_FLAGS_6(sve_ldhds_zsu, TCG_CALL_NO_WG,
83
+DEF_HELPER_FLAGS_6(sve_ldhds_le_zsu, TCG_CALL_NO_WG,
84
void, env, ptr, ptr, ptr, tl, i32)
85
-DEF_HELPER_FLAGS_6(sve_ldsds_zsu, TCG_CALL_NO_WG,
86
+DEF_HELPER_FLAGS_6(sve_ldhds_be_zsu, TCG_CALL_NO_WG,
87
+ void, env, ptr, ptr, ptr, tl, i32)
88
+DEF_HELPER_FLAGS_6(sve_ldsds_le_zsu, TCG_CALL_NO_WG,
89
+ void, env, ptr, ptr, ptr, tl, i32)
90
+DEF_HELPER_FLAGS_6(sve_ldsds_be_zsu, TCG_CALL_NO_WG,
91
void, env, ptr, ptr, ptr, tl, i32)
92
93
DEF_HELPER_FLAGS_6(sve_ldbdu_zss, TCG_CALL_NO_WG,
94
void, env, ptr, ptr, ptr, tl, i32)
95
-DEF_HELPER_FLAGS_6(sve_ldhdu_zss, TCG_CALL_NO_WG,
96
+DEF_HELPER_FLAGS_6(sve_ldhdu_le_zss, TCG_CALL_NO_WG,
97
void, env, ptr, ptr, ptr, tl, i32)
98
-DEF_HELPER_FLAGS_6(sve_ldsdu_zss, TCG_CALL_NO_WG,
99
+DEF_HELPER_FLAGS_6(sve_ldhdu_be_zss, TCG_CALL_NO_WG,
100
void, env, ptr, ptr, ptr, tl, i32)
101
-DEF_HELPER_FLAGS_6(sve_ldddu_zss, TCG_CALL_NO_WG,
102
+DEF_HELPER_FLAGS_6(sve_ldsdu_le_zss, TCG_CALL_NO_WG,
103
+ void, env, ptr, ptr, ptr, tl, i32)
104
+DEF_HELPER_FLAGS_6(sve_ldsdu_be_zss, TCG_CALL_NO_WG,
105
+ void, env, ptr, ptr, ptr, tl, i32)
106
+DEF_HELPER_FLAGS_6(sve_lddd_le_zss, TCG_CALL_NO_WG,
107
+ void, env, ptr, ptr, ptr, tl, i32)
108
+DEF_HELPER_FLAGS_6(sve_lddd_be_zss, TCG_CALL_NO_WG,
109
void, env, ptr, ptr, ptr, tl, i32)
110
DEF_HELPER_FLAGS_6(sve_ldbds_zss, TCG_CALL_NO_WG,
111
void, env, ptr, ptr, ptr, tl, i32)
112
-DEF_HELPER_FLAGS_6(sve_ldhds_zss, TCG_CALL_NO_WG,
113
+DEF_HELPER_FLAGS_6(sve_ldhds_le_zss, TCG_CALL_NO_WG,
114
void, env, ptr, ptr, ptr, tl, i32)
115
-DEF_HELPER_FLAGS_6(sve_ldsds_zss, TCG_CALL_NO_WG,
116
+DEF_HELPER_FLAGS_6(sve_ldhds_be_zss, TCG_CALL_NO_WG,
117
+ void, env, ptr, ptr, ptr, tl, i32)
118
+DEF_HELPER_FLAGS_6(sve_ldsds_le_zss, TCG_CALL_NO_WG,
119
+ void, env, ptr, ptr, ptr, tl, i32)
120
+DEF_HELPER_FLAGS_6(sve_ldsds_be_zss, TCG_CALL_NO_WG,
121
void, env, ptr, ptr, ptr, tl, i32)
122
123
DEF_HELPER_FLAGS_6(sve_ldbdu_zd, TCG_CALL_NO_WG,
124
void, env, ptr, ptr, ptr, tl, i32)
125
-DEF_HELPER_FLAGS_6(sve_ldhdu_zd, TCG_CALL_NO_WG,
126
+DEF_HELPER_FLAGS_6(sve_ldhdu_le_zd, TCG_CALL_NO_WG,
127
void, env, ptr, ptr, ptr, tl, i32)
128
-DEF_HELPER_FLAGS_6(sve_ldsdu_zd, TCG_CALL_NO_WG,
129
+DEF_HELPER_FLAGS_6(sve_ldhdu_be_zd, TCG_CALL_NO_WG,
130
void, env, ptr, ptr, ptr, tl, i32)
131
-DEF_HELPER_FLAGS_6(sve_ldddu_zd, TCG_CALL_NO_WG,
132
+DEF_HELPER_FLAGS_6(sve_ldsdu_le_zd, TCG_CALL_NO_WG,
133
+ void, env, ptr, ptr, ptr, tl, i32)
134
+DEF_HELPER_FLAGS_6(sve_ldsdu_be_zd, TCG_CALL_NO_WG,
135
+ void, env, ptr, ptr, ptr, tl, i32)
136
+DEF_HELPER_FLAGS_6(sve_lddd_le_zd, TCG_CALL_NO_WG,
137
+ void, env, ptr, ptr, ptr, tl, i32)
138
+DEF_HELPER_FLAGS_6(sve_lddd_be_zd, TCG_CALL_NO_WG,
139
void, env, ptr, ptr, ptr, tl, i32)
140
DEF_HELPER_FLAGS_6(sve_ldbds_zd, TCG_CALL_NO_WG,
141
void, env, ptr, ptr, ptr, tl, i32)
142
-DEF_HELPER_FLAGS_6(sve_ldhds_zd, TCG_CALL_NO_WG,
143
+DEF_HELPER_FLAGS_6(sve_ldhds_le_zd, TCG_CALL_NO_WG,
144
void, env, ptr, ptr, ptr, tl, i32)
145
-DEF_HELPER_FLAGS_6(sve_ldsds_zd, TCG_CALL_NO_WG,
146
+DEF_HELPER_FLAGS_6(sve_ldhds_be_zd, TCG_CALL_NO_WG,
147
+ void, env, ptr, ptr, ptr, tl, i32)
148
+DEF_HELPER_FLAGS_6(sve_ldsds_le_zd, TCG_CALL_NO_WG,
149
+ void, env, ptr, ptr, ptr, tl, i32)
150
+DEF_HELPER_FLAGS_6(sve_ldsds_be_zd, TCG_CALL_NO_WG,
151
void, env, ptr, ptr, ptr, tl, i32)
152
153
DEF_HELPER_FLAGS_6(sve_ldffbsu_zsu, TCG_CALL_NO_WG,
154
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
155
index XXXXXXX..XXXXXXX 100644
156
--- a/target/arm/sve_helper.c
157
+++ b/target/arm/sve_helper.c
158
@@ -XXX,XX +XXX,XX @@ DO_STN_2(4, dd, 8, 8)
159
#undef DO_STN_1
160
#undef DO_STN_2
161
162
-/* Loads with a vector index. */
163
+/*
23
+/*
164
+ * Loads with a vector index.
24
+ * QTest testcase for PV Panic PCI device
25
+ *
26
+ * Copyright (C) 2020 Oracle
27
+ *
28
+ * Authors:
29
+ * Mihai Carabas <mihai.carabas@oracle.com>
30
+ *
31
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
32
+ * See the COPYING file in the top-level directory.
33
+ *
165
+ */
34
+ */
166
167
-#define DO_LD1_ZPZ_S(NAME, TYPEI, TYPEM, FN) \
168
-void HELPER(NAME)(CPUARMState *env, void *vd, void *vg, void *vm, \
169
- target_ulong base, uint32_t desc) \
170
-{ \
171
- intptr_t i, oprsz = simd_oprsz(desc); \
172
- unsigned scale = simd_data(desc); \
173
- uintptr_t ra = GETPC(); \
174
- for (i = 0; i < oprsz; ) { \
175
- uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
176
- do { \
177
- TYPEM m = 0; \
178
- if (pg & 1) { \
179
- target_ulong off = *(TYPEI *)(vm + H1_4(i)); \
180
- m = FN(env, base + (off << scale), ra); \
181
- } \
182
- *(uint32_t *)(vd + H1_4(i)) = m; \
183
- i += 4, pg >>= 4; \
184
- } while (i & 15); \
185
- } \
186
+/*
187
+ * Load the element at @reg + @reg_ofs, sign or zero-extend as needed.
188
+ */
189
+typedef target_ulong zreg_off_fn(void *reg, intptr_t reg_ofs);
190
+
35
+
191
+static target_ulong off_zsu_s(void *reg, intptr_t reg_ofs)
36
+#include "qemu/osdep.h"
37
+#include "libqos/libqtest.h"
38
+#include "qapi/qmp/qdict.h"
39
+#include "libqos/pci.h"
40
+#include "libqos/pci-pc.h"
41
+#include "hw/pci/pci_regs.h"
42
+
43
+static void test_panic_nopause(void)
192
+{
44
+{
193
+ return *(uint32_t *)(reg + H1_4(reg_ofs));
45
+ uint8_t val;
194
}
46
+ QDict *response, *data;
195
47
+ QTestState *qts;
196
-#define DO_LD1_ZPZ_D(NAME, TYPEI, TYPEM, FN) \
48
+ QPCIBus *pcibus;
197
-void HELPER(NAME)(CPUARMState *env, void *vd, void *vg, void *vm, \
49
+ QPCIDevice *dev;
198
- target_ulong base, uint32_t desc) \
50
+ QPCIBar bar;
199
-{ \
200
- intptr_t i, oprsz = simd_oprsz(desc) / 8; \
201
- unsigned scale = simd_data(desc); \
202
- uintptr_t ra = GETPC(); \
203
- uint64_t *d = vd, *m = vm; uint8_t *pg = vg; \
204
- for (i = 0; i < oprsz; i++) { \
205
- TYPEM mm = 0; \
206
- if (pg[H1(i)] & 1) { \
207
- target_ulong off = (TYPEI)m[i]; \
208
- mm = FN(env, base + (off << scale), ra); \
209
- } \
210
- d[i] = mm; \
211
- } \
212
+static target_ulong off_zss_s(void *reg, intptr_t reg_ofs)
213
+{
214
+ return *(int32_t *)(reg + H1_4(reg_ofs));
215
}
216
217
-DO_LD1_ZPZ_S(sve_ldbsu_zsu, uint32_t, uint8_t, cpu_ldub_data_ra)
218
-DO_LD1_ZPZ_S(sve_ldhsu_zsu, uint32_t, uint16_t, cpu_lduw_data_ra)
219
-DO_LD1_ZPZ_S(sve_ldssu_zsu, uint32_t, uint32_t, cpu_ldl_data_ra)
220
-DO_LD1_ZPZ_S(sve_ldbss_zsu, uint32_t, int8_t, cpu_ldub_data_ra)
221
-DO_LD1_ZPZ_S(sve_ldhss_zsu, uint32_t, int16_t, cpu_lduw_data_ra)
222
+static target_ulong off_zsu_d(void *reg, intptr_t reg_ofs)
223
+{
224
+ return (uint32_t)*(uint64_t *)(reg + reg_ofs);
225
+}
226
227
-DO_LD1_ZPZ_S(sve_ldbsu_zss, int32_t, uint8_t, cpu_ldub_data_ra)
228
-DO_LD1_ZPZ_S(sve_ldhsu_zss, int32_t, uint16_t, cpu_lduw_data_ra)
229
-DO_LD1_ZPZ_S(sve_ldssu_zss, int32_t, uint32_t, cpu_ldl_data_ra)
230
-DO_LD1_ZPZ_S(sve_ldbss_zss, int32_t, int8_t, cpu_ldub_data_ra)
231
-DO_LD1_ZPZ_S(sve_ldhss_zss, int32_t, int16_t, cpu_lduw_data_ra)
232
+static target_ulong off_zss_d(void *reg, intptr_t reg_ofs)
233
+{
234
+ return (int32_t)*(uint64_t *)(reg + reg_ofs);
235
+}
236
237
-DO_LD1_ZPZ_D(sve_ldbdu_zsu, uint32_t, uint8_t, cpu_ldub_data_ra)
238
-DO_LD1_ZPZ_D(sve_ldhdu_zsu, uint32_t, uint16_t, cpu_lduw_data_ra)
239
-DO_LD1_ZPZ_D(sve_ldsdu_zsu, uint32_t, uint32_t, cpu_ldl_data_ra)
240
-DO_LD1_ZPZ_D(sve_ldddu_zsu, uint32_t, uint64_t, cpu_ldq_data_ra)
241
-DO_LD1_ZPZ_D(sve_ldbds_zsu, uint32_t, int8_t, cpu_ldub_data_ra)
242
-DO_LD1_ZPZ_D(sve_ldhds_zsu, uint32_t, int16_t, cpu_lduw_data_ra)
243
-DO_LD1_ZPZ_D(sve_ldsds_zsu, uint32_t, int32_t, cpu_ldl_data_ra)
244
+static target_ulong off_zd_d(void *reg, intptr_t reg_ofs)
245
+{
246
+ return *(uint64_t *)(reg + reg_ofs);
247
+}
248
249
-DO_LD1_ZPZ_D(sve_ldbdu_zss, int32_t, uint8_t, cpu_ldub_data_ra)
250
-DO_LD1_ZPZ_D(sve_ldhdu_zss, int32_t, uint16_t, cpu_lduw_data_ra)
251
-DO_LD1_ZPZ_D(sve_ldsdu_zss, int32_t, uint32_t, cpu_ldl_data_ra)
252
-DO_LD1_ZPZ_D(sve_ldddu_zss, int32_t, uint64_t, cpu_ldq_data_ra)
253
-DO_LD1_ZPZ_D(sve_ldbds_zss, int32_t, int8_t, cpu_ldub_data_ra)
254
-DO_LD1_ZPZ_D(sve_ldhds_zss, int32_t, int16_t, cpu_lduw_data_ra)
255
-DO_LD1_ZPZ_D(sve_ldsds_zss, int32_t, int32_t, cpu_ldl_data_ra)
256
+static void sve_ld1_zs(CPUARMState *env, void *vd, void *vg, void *vm,
257
+ target_ulong base, uint32_t desc, uintptr_t ra,
258
+ zreg_off_fn *off_fn, sve_ld1_tlb_fn *tlb_fn)
259
+{
260
+ const int mmu_idx = cpu_mmu_index(env, false);
261
+ intptr_t i, oprsz = simd_oprsz(desc);
262
+ unsigned scale = simd_data(desc);
263
+ ARMVectorReg scratch = { };
264
265
-DO_LD1_ZPZ_D(sve_ldbdu_zd, uint64_t, uint8_t, cpu_ldub_data_ra)
266
-DO_LD1_ZPZ_D(sve_ldhdu_zd, uint64_t, uint16_t, cpu_lduw_data_ra)
267
-DO_LD1_ZPZ_D(sve_ldsdu_zd, uint64_t, uint32_t, cpu_ldl_data_ra)
268
-DO_LD1_ZPZ_D(sve_ldddu_zd, uint64_t, uint64_t, cpu_ldq_data_ra)
269
-DO_LD1_ZPZ_D(sve_ldbds_zd, uint64_t, int8_t, cpu_ldub_data_ra)
270
-DO_LD1_ZPZ_D(sve_ldhds_zd, uint64_t, int16_t, cpu_lduw_data_ra)
271
-DO_LD1_ZPZ_D(sve_ldsds_zd, uint64_t, int32_t, cpu_ldl_data_ra)
272
+ set_helper_retaddr(ra);
273
+ for (i = 0; i < oprsz; ) {
274
+ uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));
275
+ do {
276
+ if (likely(pg & 1)) {
277
+ target_ulong off = off_fn(vm, i);
278
+ tlb_fn(env, &scratch, i, base + (off << scale), mmu_idx, ra);
279
+ }
280
+ i += 4, pg >>= 4;
281
+ } while (i & 15);
282
+ }
283
+ set_helper_retaddr(0);
284
+
51
+
285
+ /* Wait until all exceptions have been raised to write back. */
52
+ qts = qtest_init("-device pvpanic-pci,addr=04.0 -action panic=none");
286
+ memcpy(vd, &scratch, oprsz);
53
+ pcibus = qpci_new_pc(qts, NULL);
54
+ dev = qpci_device_find(pcibus, QPCI_DEVFN(0x4, 0x0));
55
+ qpci_device_enable(dev);
56
+ bar = qpci_iomap(dev, 0, NULL);
57
+
58
+ qpci_memread(dev, bar, 0, &val, sizeof(val));
59
+ g_assert_cmpuint(val, ==, 3);
60
+
61
+ val = 1;
62
+ qpci_memwrite(dev, bar, 0, &val, sizeof(val));
63
+
64
+ response = qtest_qmp_eventwait_ref(qts, "GUEST_PANICKED");
65
+ g_assert(qdict_haskey(response, "data"));
66
+ data = qdict_get_qdict(response, "data");
67
+ g_assert(qdict_haskey(data, "action"));
68
+ g_assert_cmpstr(qdict_get_str(data, "action"), ==, "run");
69
+ qobject_unref(response);
70
+
71
+ qtest_quit(qts);
287
+}
72
+}
288
+
73
+
289
+static void sve_ld1_zd(CPUARMState *env, void *vd, void *vg, void *vm,
74
+static void test_panic(void)
290
+ target_ulong base, uint32_t desc, uintptr_t ra,
291
+ zreg_off_fn *off_fn, sve_ld1_tlb_fn *tlb_fn)
292
+{
75
+{
293
+ const int mmu_idx = cpu_mmu_index(env, false);
76
+ uint8_t val;
294
+ intptr_t i, oprsz = simd_oprsz(desc) / 8;
77
+ QDict *response, *data;
295
+ unsigned scale = simd_data(desc);
78
+ QTestState *qts;
296
+ ARMVectorReg scratch = { };
79
+ QPCIBus *pcibus;
80
+ QPCIDevice *dev;
81
+ QPCIBar bar;
297
+
82
+
298
+ set_helper_retaddr(ra);
83
+ qts = qtest_init("-device pvpanic-pci,addr=04.0 -action panic=pause");
299
+ for (i = 0; i < oprsz; i++) {
84
+ pcibus = qpci_new_pc(qts, NULL);
300
+ uint8_t pg = *(uint8_t *)(vg + H1(i));
85
+ dev = qpci_device_find(pcibus, QPCI_DEVFN(0x4, 0x0));
301
+ if (likely(pg & 1)) {
86
+ qpci_device_enable(dev);
302
+ target_ulong off = off_fn(vm, i * 8);
87
+ bar = qpci_iomap(dev, 0, NULL);
303
+ tlb_fn(env, &scratch, i * 8, base + (off << scale), mmu_idx, ra);
304
+ }
305
+ }
306
+ set_helper_retaddr(0);
307
+
88
+
308
+ /* Wait until all exceptions have been raised to write back. */
89
+ qpci_memread(dev, bar, 0, &val, sizeof(val));
309
+ memcpy(vd, &scratch, oprsz * 8);
90
+ g_assert_cmpuint(val, ==, 3);
91
+
92
+ val = 1;
93
+ qpci_memwrite(dev, bar, 0, &val, sizeof(val));
94
+
95
+ response = qtest_qmp_eventwait_ref(qts, "GUEST_PANICKED");
96
+ g_assert(qdict_haskey(response, "data"));
97
+ data = qdict_get_qdict(response, "data");
98
+ g_assert(qdict_haskey(data, "action"));
99
+ g_assert_cmpstr(qdict_get_str(data, "action"), ==, "pause");
100
+ qobject_unref(response);
101
+
102
+ qtest_quit(qts);
310
+}
103
+}
311
+
104
+
312
+#define DO_LD1_ZPZ_S(MEM, OFS) \
105
+int main(int argc, char **argv)
313
+void __attribute__((flatten)) HELPER(sve_ld##MEM##_##OFS) \
106
+{
314
+ (CPUARMState *env, void *vd, void *vg, void *vm, \
107
+ int ret;
315
+ target_ulong base, uint32_t desc) \
108
+
316
+{ \
109
+ g_test_init(&argc, &argv, NULL);
317
+ sve_ld1_zs(env, vd, vg, vm, base, desc, GETPC(), \
110
+ qtest_add_func("/pvpanic-pci/panic", test_panic);
318
+ off_##OFS##_s, sve_ld1##MEM##_tlb); \
111
+ qtest_add_func("/pvpanic-pci/panic-nopause", test_panic_nopause);
112
+
113
+ ret = g_test_run();
114
+
115
+ return ret;
319
+}
116
+}
320
+
117
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
321
+#define DO_LD1_ZPZ_D(MEM, OFS) \
322
+void __attribute__((flatten)) HELPER(sve_ld##MEM##_##OFS) \
323
+ (CPUARMState *env, void *vd, void *vg, void *vm, \
324
+ target_ulong base, uint32_t desc) \
325
+{ \
326
+ sve_ld1_zd(env, vd, vg, vm, base, desc, GETPC(), \
327
+ off_##OFS##_d, sve_ld1##MEM##_tlb); \
328
+}
329
+
330
+DO_LD1_ZPZ_S(bsu, zsu)
331
+DO_LD1_ZPZ_S(bsu, zss)
332
+DO_LD1_ZPZ_D(bdu, zsu)
333
+DO_LD1_ZPZ_D(bdu, zss)
334
+DO_LD1_ZPZ_D(bdu, zd)
335
+
336
+DO_LD1_ZPZ_S(bss, zsu)
337
+DO_LD1_ZPZ_S(bss, zss)
338
+DO_LD1_ZPZ_D(bds, zsu)
339
+DO_LD1_ZPZ_D(bds, zss)
340
+DO_LD1_ZPZ_D(bds, zd)
341
+
342
+DO_LD1_ZPZ_S(hsu_le, zsu)
343
+DO_LD1_ZPZ_S(hsu_le, zss)
344
+DO_LD1_ZPZ_D(hdu_le, zsu)
345
+DO_LD1_ZPZ_D(hdu_le, zss)
346
+DO_LD1_ZPZ_D(hdu_le, zd)
347
+
348
+DO_LD1_ZPZ_S(hsu_be, zsu)
349
+DO_LD1_ZPZ_S(hsu_be, zss)
350
+DO_LD1_ZPZ_D(hdu_be, zsu)
351
+DO_LD1_ZPZ_D(hdu_be, zss)
352
+DO_LD1_ZPZ_D(hdu_be, zd)
353
+
354
+DO_LD1_ZPZ_S(hss_le, zsu)
355
+DO_LD1_ZPZ_S(hss_le, zss)
356
+DO_LD1_ZPZ_D(hds_le, zsu)
357
+DO_LD1_ZPZ_D(hds_le, zss)
358
+DO_LD1_ZPZ_D(hds_le, zd)
359
+
360
+DO_LD1_ZPZ_S(hss_be, zsu)
361
+DO_LD1_ZPZ_S(hss_be, zss)
362
+DO_LD1_ZPZ_D(hds_be, zsu)
363
+DO_LD1_ZPZ_D(hds_be, zss)
364
+DO_LD1_ZPZ_D(hds_be, zd)
365
+
366
+DO_LD1_ZPZ_S(ss_le, zsu)
367
+DO_LD1_ZPZ_S(ss_le, zss)
368
+DO_LD1_ZPZ_D(sdu_le, zsu)
369
+DO_LD1_ZPZ_D(sdu_le, zss)
370
+DO_LD1_ZPZ_D(sdu_le, zd)
371
+
372
+DO_LD1_ZPZ_S(ss_be, zsu)
373
+DO_LD1_ZPZ_S(ss_be, zss)
374
+DO_LD1_ZPZ_D(sdu_be, zsu)
375
+DO_LD1_ZPZ_D(sdu_be, zss)
376
+DO_LD1_ZPZ_D(sdu_be, zd)
377
+
378
+DO_LD1_ZPZ_D(sds_le, zsu)
379
+DO_LD1_ZPZ_D(sds_le, zss)
380
+DO_LD1_ZPZ_D(sds_le, zd)
381
+
382
+DO_LD1_ZPZ_D(sds_be, zsu)
383
+DO_LD1_ZPZ_D(sds_be, zss)
384
+DO_LD1_ZPZ_D(sds_be, zd)
385
+
386
+DO_LD1_ZPZ_D(dd_le, zsu)
387
+DO_LD1_ZPZ_D(dd_le, zss)
388
+DO_LD1_ZPZ_D(dd_le, zd)
389
+
390
+DO_LD1_ZPZ_D(dd_be, zsu)
391
+DO_LD1_ZPZ_D(dd_be, zss)
392
+DO_LD1_ZPZ_D(dd_be, zd)
393
+
394
+#undef DO_LD1_ZPZ_S
395
+#undef DO_LD1_ZPZ_D
396
397
/* First fault loads with a vector index. */
398
399
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
400
index XXXXXXX..XXXXXXX 100644
118
index XXXXXXX..XXXXXXX 100644
401
--- a/target/arm/translate-sve.c
119
--- a/tests/qtest/meson.build
402
+++ b/target/arm/translate-sve.c
120
+++ b/tests/qtest/meson.build
403
@@ -XXX,XX +XXX,XX @@ static void do_mem_zpz(DisasContext *s, int zt, int pg, int zm, int scale,
121
@@ -XXX,XX +XXX,XX @@ qtests_i386 = \
404
tcg_temp_free_i32(desc);
122
config_all_devices.has_key('CONFIG_ISA_IPMI_BT') ? ['ipmi-bt-test'] : []) + \
405
}
123
(config_all_devices.has_key('CONFIG_WDT_IB700') ? ['wdt_ib700-test'] : []) + \
406
124
(config_all_devices.has_key('CONFIG_PVPANIC_ISA') ? ['pvpanic-test'] : []) + \
407
-/* Indexed by [ff][xs][u][msz]. */
125
+ (config_all_devices.has_key('CONFIG_PVPANIC_PCI') ? ['pvpanic-pci-test'] : []) + \
408
-static gen_helper_gvec_mem_scatter * const gather_load_fn32[2][2][2][3] = {
126
(config_all_devices.has_key('CONFIG_HDA') ? ['intel-hda-test'] : []) + \
409
- { { { gen_helper_sve_ldbss_zsu,
127
(config_all_devices.has_key('CONFIG_I82801B11') ? ['i82801b11-test'] : []) + \
410
- gen_helper_sve_ldhss_zsu,
128
(config_all_devices.has_key('CONFIG_IOH3420') ? ['ioh3420-test'] : []) + \
411
- NULL, },
412
- { gen_helper_sve_ldbsu_zsu,
413
- gen_helper_sve_ldhsu_zsu,
414
- gen_helper_sve_ldssu_zsu, } },
415
- { { gen_helper_sve_ldbss_zss,
416
- gen_helper_sve_ldhss_zss,
417
- NULL, },
418
- { gen_helper_sve_ldbsu_zss,
419
- gen_helper_sve_ldhsu_zss,
420
- gen_helper_sve_ldssu_zss, } } },
421
+/* Indexed by [be][ff][xs][u][msz]. */
422
+static gen_helper_gvec_mem_scatter * const gather_load_fn32[2][2][2][2][3] = {
423
+ /* Little-endian */
424
+ { { { { gen_helper_sve_ldbss_zsu,
425
+ gen_helper_sve_ldhss_le_zsu,
426
+ NULL, },
427
+ { gen_helper_sve_ldbsu_zsu,
428
+ gen_helper_sve_ldhsu_le_zsu,
429
+ gen_helper_sve_ldss_le_zsu, } },
430
+ { { gen_helper_sve_ldbss_zss,
431
+ gen_helper_sve_ldhss_le_zss,
432
+ NULL, },
433
+ { gen_helper_sve_ldbsu_zss,
434
+ gen_helper_sve_ldhsu_le_zss,
435
+ gen_helper_sve_ldss_le_zss, } } },
436
437
- { { { gen_helper_sve_ldffbss_zsu,
438
- gen_helper_sve_ldffhss_zsu,
439
- NULL, },
440
- { gen_helper_sve_ldffbsu_zsu,
441
- gen_helper_sve_ldffhsu_zsu,
442
- gen_helper_sve_ldffssu_zsu, } },
443
- { { gen_helper_sve_ldffbss_zss,
444
- gen_helper_sve_ldffhss_zss,
445
- NULL, },
446
- { gen_helper_sve_ldffbsu_zss,
447
- gen_helper_sve_ldffhsu_zss,
448
- gen_helper_sve_ldffssu_zss, } } }
449
+ /* First-fault */
450
+ { { { gen_helper_sve_ldffbss_zsu,
451
+ gen_helper_sve_ldffhss_zsu,
452
+ NULL, },
453
+ { gen_helper_sve_ldffbsu_zsu,
454
+ gen_helper_sve_ldffhsu_zsu,
455
+ gen_helper_sve_ldffssu_zsu, } },
456
+ { { gen_helper_sve_ldffbss_zss,
457
+ gen_helper_sve_ldffhss_zss,
458
+ NULL, },
459
+ { gen_helper_sve_ldffbsu_zss,
460
+ gen_helper_sve_ldffhsu_zss,
461
+ gen_helper_sve_ldffssu_zss, } } } },
462
+
463
+ /* Big-endian */
464
+ { { { { gen_helper_sve_ldbss_zsu,
465
+ gen_helper_sve_ldhss_be_zsu,
466
+ NULL, },
467
+ { gen_helper_sve_ldbsu_zsu,
468
+ gen_helper_sve_ldhsu_be_zsu,
469
+ gen_helper_sve_ldss_be_zsu, } },
470
+ { { gen_helper_sve_ldbss_zss,
471
+ gen_helper_sve_ldhss_be_zss,
472
+ NULL, },
473
+ { gen_helper_sve_ldbsu_zss,
474
+ gen_helper_sve_ldhsu_be_zss,
475
+ gen_helper_sve_ldss_be_zss, } } },
476
+
477
+ /* First-fault */
478
+ { { { gen_helper_sve_ldffbss_zsu,
479
+ gen_helper_sve_ldffhss_zsu,
480
+ NULL, },
481
+ { gen_helper_sve_ldffbsu_zsu,
482
+ gen_helper_sve_ldffhsu_zsu,
483
+ gen_helper_sve_ldffssu_zsu, } },
484
+ { { gen_helper_sve_ldffbss_zss,
485
+ gen_helper_sve_ldffhss_zss,
486
+ NULL, },
487
+ { gen_helper_sve_ldffbsu_zss,
488
+ gen_helper_sve_ldffhsu_zss,
489
+ gen_helper_sve_ldffssu_zss, } } } },
490
};
491
492
/* Note that we overload xs=2 to indicate 64-bit offset. */
493
-static gen_helper_gvec_mem_scatter * const gather_load_fn64[2][3][2][4] = {
494
- { { { gen_helper_sve_ldbds_zsu,
495
- gen_helper_sve_ldhds_zsu,
496
- gen_helper_sve_ldsds_zsu,
497
- NULL, },
498
- { gen_helper_sve_ldbdu_zsu,
499
- gen_helper_sve_ldhdu_zsu,
500
- gen_helper_sve_ldsdu_zsu,
501
- gen_helper_sve_ldddu_zsu, } },
502
- { { gen_helper_sve_ldbds_zss,
503
- gen_helper_sve_ldhds_zss,
504
- gen_helper_sve_ldsds_zss,
505
- NULL, },
506
- { gen_helper_sve_ldbdu_zss,
507
- gen_helper_sve_ldhdu_zss,
508
- gen_helper_sve_ldsdu_zss,
509
- gen_helper_sve_ldddu_zss, } },
510
- { { gen_helper_sve_ldbds_zd,
511
- gen_helper_sve_ldhds_zd,
512
- gen_helper_sve_ldsds_zd,
513
- NULL, },
514
- { gen_helper_sve_ldbdu_zd,
515
- gen_helper_sve_ldhdu_zd,
516
- gen_helper_sve_ldsdu_zd,
517
- gen_helper_sve_ldddu_zd, } } },
518
+static gen_helper_gvec_mem_scatter * const gather_load_fn64[2][2][3][2][4] = {
519
+ /* Little-endian */
520
+ { { { { gen_helper_sve_ldbds_zsu,
521
+ gen_helper_sve_ldhds_le_zsu,
522
+ gen_helper_sve_ldsds_le_zsu,
523
+ NULL, },
524
+ { gen_helper_sve_ldbdu_zsu,
525
+ gen_helper_sve_ldhdu_le_zsu,
526
+ gen_helper_sve_ldsdu_le_zsu,
527
+ gen_helper_sve_lddd_le_zsu, } },
528
+ { { gen_helper_sve_ldbds_zss,
529
+ gen_helper_sve_ldhds_le_zss,
530
+ gen_helper_sve_ldsds_le_zss,
531
+ NULL, },
532
+ { gen_helper_sve_ldbdu_zss,
533
+ gen_helper_sve_ldhdu_le_zss,
534
+ gen_helper_sve_ldsdu_le_zss,
535
+ gen_helper_sve_lddd_le_zss, } },
536
+ { { gen_helper_sve_ldbds_zd,
537
+ gen_helper_sve_ldhds_le_zd,
538
+ gen_helper_sve_ldsds_le_zd,
539
+ NULL, },
540
+ { gen_helper_sve_ldbdu_zd,
541
+ gen_helper_sve_ldhdu_le_zd,
542
+ gen_helper_sve_ldsdu_le_zd,
543
+ gen_helper_sve_lddd_le_zd, } } },
544
545
- { { { gen_helper_sve_ldffbds_zsu,
546
- gen_helper_sve_ldffhds_zsu,
547
- gen_helper_sve_ldffsds_zsu,
548
- NULL, },
549
- { gen_helper_sve_ldffbdu_zsu,
550
- gen_helper_sve_ldffhdu_zsu,
551
- gen_helper_sve_ldffsdu_zsu,
552
- gen_helper_sve_ldffddu_zsu, } },
553
- { { gen_helper_sve_ldffbds_zss,
554
- gen_helper_sve_ldffhds_zss,
555
- gen_helper_sve_ldffsds_zss,
556
- NULL, },
557
- { gen_helper_sve_ldffbdu_zss,
558
- gen_helper_sve_ldffhdu_zss,
559
- gen_helper_sve_ldffsdu_zss,
560
- gen_helper_sve_ldffddu_zss, } },
561
- { { gen_helper_sve_ldffbds_zd,
562
- gen_helper_sve_ldffhds_zd,
563
- gen_helper_sve_ldffsds_zd,
564
- NULL, },
565
- { gen_helper_sve_ldffbdu_zd,
566
- gen_helper_sve_ldffhdu_zd,
567
- gen_helper_sve_ldffsdu_zd,
568
- gen_helper_sve_ldffddu_zd, } } }
569
+ /* First-fault */
570
+ { { { gen_helper_sve_ldffbds_zsu,
571
+ gen_helper_sve_ldffhds_zsu,
572
+ gen_helper_sve_ldffsds_zsu,
573
+ NULL, },
574
+ { gen_helper_sve_ldffbdu_zsu,
575
+ gen_helper_sve_ldffhdu_zsu,
576
+ gen_helper_sve_ldffsdu_zsu,
577
+ gen_helper_sve_ldffddu_zsu, } },
578
+ { { gen_helper_sve_ldffbds_zss,
579
+ gen_helper_sve_ldffhds_zss,
580
+ gen_helper_sve_ldffsds_zss,
581
+ NULL, },
582
+ { gen_helper_sve_ldffbdu_zss,
583
+ gen_helper_sve_ldffhdu_zss,
584
+ gen_helper_sve_ldffsdu_zss,
585
+ gen_helper_sve_ldffddu_zss, } },
586
+ { { gen_helper_sve_ldffbds_zd,
587
+ gen_helper_sve_ldffhds_zd,
588
+ gen_helper_sve_ldffsds_zd,
589
+ NULL, },
590
+ { gen_helper_sve_ldffbdu_zd,
591
+ gen_helper_sve_ldffhdu_zd,
592
+ gen_helper_sve_ldffsdu_zd,
593
+ gen_helper_sve_ldffddu_zd, } } } },
594
+
595
+ /* Big-endian */
596
+ { { { { gen_helper_sve_ldbds_zsu,
597
+ gen_helper_sve_ldhds_be_zsu,
598
+ gen_helper_sve_ldsds_be_zsu,
599
+ NULL, },
600
+ { gen_helper_sve_ldbdu_zsu,
601
+ gen_helper_sve_ldhdu_be_zsu,
602
+ gen_helper_sve_ldsdu_be_zsu,
603
+ gen_helper_sve_lddd_be_zsu, } },
604
+ { { gen_helper_sve_ldbds_zss,
605
+ gen_helper_sve_ldhds_be_zss,
606
+ gen_helper_sve_ldsds_be_zss,
607
+ NULL, },
608
+ { gen_helper_sve_ldbdu_zss,
609
+ gen_helper_sve_ldhdu_be_zss,
610
+ gen_helper_sve_ldsdu_be_zss,
611
+ gen_helper_sve_lddd_be_zss, } },
612
+ { { gen_helper_sve_ldbds_zd,
613
+ gen_helper_sve_ldhds_be_zd,
614
+ gen_helper_sve_ldsds_be_zd,
615
+ NULL, },
616
+ { gen_helper_sve_ldbdu_zd,
617
+ gen_helper_sve_ldhdu_be_zd,
618
+ gen_helper_sve_ldsdu_be_zd,
619
+ gen_helper_sve_lddd_be_zd, } } },
620
+
621
+ /* First-fault */
622
+ { { { gen_helper_sve_ldffbds_zsu,
623
+ gen_helper_sve_ldffhds_zsu,
624
+ gen_helper_sve_ldffsds_zsu,
625
+ NULL, },
626
+ { gen_helper_sve_ldffbdu_zsu,
627
+ gen_helper_sve_ldffhdu_zsu,
628
+ gen_helper_sve_ldffsdu_zsu,
629
+ gen_helper_sve_ldffddu_zsu, } },
630
+ { { gen_helper_sve_ldffbds_zss,
631
+ gen_helper_sve_ldffhds_zss,
632
+ gen_helper_sve_ldffsds_zss,
633
+ NULL, },
634
+ { gen_helper_sve_ldffbdu_zss,
635
+ gen_helper_sve_ldffhdu_zss,
636
+ gen_helper_sve_ldffsdu_zss,
637
+ gen_helper_sve_ldffddu_zss, } },
638
+ { { gen_helper_sve_ldffbds_zd,
639
+ gen_helper_sve_ldffhds_zd,
640
+ gen_helper_sve_ldffsds_zd,
641
+ NULL, },
642
+ { gen_helper_sve_ldffbdu_zd,
643
+ gen_helper_sve_ldffhdu_zd,
644
+ gen_helper_sve_ldffsdu_zd,
645
+ gen_helper_sve_ldffddu_zd, } } } },
646
};
647
648
static bool trans_LD1_zprz(DisasContext *s, arg_LD1_zprz *a, uint32_t insn)
649
{
650
gen_helper_gvec_mem_scatter *fn = NULL;
651
+ int be = s->be_data == MO_BE;
652
653
if (!sve_access_check(s)) {
654
return true;
655
@@ -XXX,XX +XXX,XX @@ static bool trans_LD1_zprz(DisasContext *s, arg_LD1_zprz *a, uint32_t insn)
656
657
switch (a->esz) {
658
case MO_32:
659
- fn = gather_load_fn32[a->ff][a->xs][a->u][a->msz];
660
+ fn = gather_load_fn32[be][a->ff][a->xs][a->u][a->msz];
661
break;
662
case MO_64:
663
- fn = gather_load_fn64[a->ff][a->xs][a->u][a->msz];
664
+ fn = gather_load_fn64[be][a->ff][a->xs][a->u][a->msz];
665
break;
666
}
667
assert(fn != NULL);
668
@@ -XXX,XX +XXX,XX @@ static bool trans_LD1_zprz(DisasContext *s, arg_LD1_zprz *a, uint32_t insn)
669
static bool trans_LD1_zpiz(DisasContext *s, arg_LD1_zpiz *a, uint32_t insn)
670
{
671
gen_helper_gvec_mem_scatter *fn = NULL;
672
+ int be = s->be_data == MO_BE;
673
TCGv_i64 imm;
674
675
if (a->esz < a->msz || (a->esz == a->msz && !a->u)) {
676
@@ -XXX,XX +XXX,XX @@ static bool trans_LD1_zpiz(DisasContext *s, arg_LD1_zpiz *a, uint32_t insn)
677
678
switch (a->esz) {
679
case MO_32:
680
- fn = gather_load_fn32[a->ff][0][a->u][a->msz];
681
+ fn = gather_load_fn32[be][a->ff][0][a->u][a->msz];
682
break;
683
case MO_64:
684
- fn = gather_load_fn64[a->ff][2][a->u][a->msz];
685
+ fn = gather_load_fn64[be][a->ff][2][a->u][a->msz];
686
break;
687
}
688
assert(fn != NULL);
689
--
129
--
690
2.19.0
130
2.20.1
691
131
692
132
diff view generated by jsdifflib
1
Updating the NS stack pointer via MSR to SP_NS should include
1
The ptimer API currently provides two methods for setting the period:
2
a check whether the new SP value is below the stack limit.
2
ptimer_set_period(), which takes a period in nanoseconds, and
3
No other kinds of update to the various stack pointer and
3
ptimer_set_freq(), which takes a frequency in Hz. Neither of these
4
limit registers via MSR should perform a check.
4
lines up nicely with the Clock API, because although both the Clock
5
and the ptimer track the frequency using a representation of whole
6
and fractional nanoseconds, conversion via either period-in-ns or
7
frequency-in-Hz will introduce a rounding error.
8
9
Add a new function ptimer_set_period_from_clock() which takes the
10
Clock object directly to avoid the rounding issues. This includes a
11
facility for the user to specify that there is a frequency divider
12
between the Clock proper and the timer, as some timer devices like
13
the CMSDK APB dualtimer need this.
14
15
To avoid having to drag in clock.h from ptimer.h we add the Clock
16
type to typedefs.h.
5
17
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
19
Reviewed-by: Luc Michel <luc@lmichel.fr>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20181002163556.10279-14-peter.maydell@linaro.org
21
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
22
Message-id: 20210128114145.20536-2-peter.maydell@linaro.org
23
Message-id: 20210121190622.22000-2-peter.maydell@linaro.org
10
---
24
---
11
target/arm/helper.c | 14 +++++++++++++-
25
include/hw/ptimer.h | 22 ++++++++++++++++++++++
12
1 file changed, 13 insertions(+), 1 deletion(-)
26
include/qemu/typedefs.h | 1 +
27
hw/core/ptimer.c | 34 ++++++++++++++++++++++++++++++++++
28
3 files changed, 57 insertions(+)
13
29
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
30
diff --git a/include/hw/ptimer.h b/include/hw/ptimer.h
15
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
32
--- a/include/hw/ptimer.h
17
+++ b/target/arm/helper.c
33
+++ b/include/hw/ptimer.h
18
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
34
@@ -XXX,XX +XXX,XX @@ void ptimer_transaction_commit(ptimer_state *s);
19
* currently in handler mode or not, using the NS CONTROL.SPSEL.
35
*/
20
*/
36
void ptimer_set_period(ptimer_state *s, int64_t period);
21
bool spsel = env->v7m.control[M_REG_NS] & R_V7M_CONTROL_SPSEL_MASK;
37
22
+ bool is_psp = !arm_v7m_is_handler_mode(env) && spsel;
38
+/**
23
+ uint32_t limit;
39
+ * ptimer_set_period_from_clock - Set counter increment from a Clock
24
40
+ * @s: ptimer to configure
25
if (!env->v7m.secure) {
41
+ * @clk: pointer to Clock object to take period from
26
return;
42
+ * @divisor: value to scale the clock frequency down by
27
}
43
+ *
28
- if (!arm_v7m_is_handler_mode(env) && spsel) {
44
+ * If the ptimer is being driven from a Clock, this is the preferred
45
+ * way to tell the ptimer about the period, because it avoids any
46
+ * possible rounding errors that might happen if the internal
47
+ * representation of the Clock period was converted to either a period
48
+ * in ns or a frequency in Hz.
49
+ *
50
+ * If the ptimer should run at the same frequency as the clock,
51
+ * pass 1 as the @divisor; if the ptimer should run at half the
52
+ * frequency, pass 2, and so on.
53
+ *
54
+ * This function will assert if it is called outside a
55
+ * ptimer_transaction_begin/commit block.
56
+ */
57
+void ptimer_set_period_from_clock(ptimer_state *s, const Clock *clock,
58
+ unsigned int divisor);
29
+
59
+
30
+ limit = is_psp ? env->v7m.psplim[false] : env->v7m.msplim[false];
60
/**
61
* ptimer_set_freq - Set counter frequency in Hz
62
* @s: ptimer to configure
63
diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
64
index XXXXXXX..XXXXXXX 100644
65
--- a/include/qemu/typedefs.h
66
+++ b/include/qemu/typedefs.h
67
@@ -XXX,XX +XXX,XX @@ typedef struct BlockDriverState BlockDriverState;
68
typedef struct BusClass BusClass;
69
typedef struct BusState BusState;
70
typedef struct Chardev Chardev;
71
+typedef struct Clock Clock;
72
typedef struct CompatProperty CompatProperty;
73
typedef struct CoMutex CoMutex;
74
typedef struct CPUAddressSpace CPUAddressSpace;
75
diff --git a/hw/core/ptimer.c b/hw/core/ptimer.c
76
index XXXXXXX..XXXXXXX 100644
77
--- a/hw/core/ptimer.c
78
+++ b/hw/core/ptimer.c
79
@@ -XXX,XX +XXX,XX @@
80
#include "sysemu/qtest.h"
81
#include "block/aio.h"
82
#include "sysemu/cpus.h"
83
+#include "hw/clock.h"
84
85
#define DELTA_ADJUST 1
86
#define DELTA_NO_ADJUST -1
87
@@ -XXX,XX +XXX,XX @@ void ptimer_set_period(ptimer_state *s, int64_t period)
88
}
89
}
90
91
+/* Set counter increment interval from a Clock */
92
+void ptimer_set_period_from_clock(ptimer_state *s, const Clock *clk,
93
+ unsigned int divisor)
94
+{
95
+ /*
96
+ * The raw clock period is a 64-bit value in units of 2^-32 ns;
97
+ * put another way it's a 32.32 fixed-point ns value. Our internal
98
+ * representation of the period is 64.32 fixed point ns, so
99
+ * the conversion is simple.
100
+ */
101
+ uint64_t raw_period = clock_get(clk);
102
+ uint64_t period_frac;
31
+
103
+
32
+ if (val < limit) {
104
+ assert(s->in_transaction);
33
+ CPUState *cs = CPU(arm_env_get_cpu(env));
105
+ s->delta = ptimer_get_count(s);
106
+ s->period = extract64(raw_period, 32, 32);
107
+ period_frac = extract64(raw_period, 0, 32);
108
+ /*
109
+ * divisor specifies a possible frequency divisor between the
110
+ * clock and the timer, so it is a multiplier on the period.
111
+ * We do the multiply after splitting the raw period out into
112
+ * period and frac to avoid having to do a 32*64->96 multiply.
113
+ */
114
+ s->period *= divisor;
115
+ period_frac *= divisor;
116
+ s->period += extract64(period_frac, 32, 32);
117
+ s->period_frac = (uint32_t)period_frac;
34
+
118
+
35
+ cpu_restore_state(cs, GETPC(), true);
119
+ if (s->enabled) {
36
+ raise_exception(env, EXCP_STKOF, 0, 1);
120
+ s->need_reload = true;
37
+ }
121
+ }
122
+}
38
+
123
+
39
+ if (is_psp) {
124
/* Set counter frequency in Hz. */
40
env->v7m.other_ss_psp = val;
125
void ptimer_set_freq(ptimer_state *s, uint32_t freq)
41
} else {
126
{
42
env->v7m.other_ss_msp = val;
43
--
127
--
44
2.19.0
128
2.20.1
45
129
46
130
diff view generated by jsdifflib
New patch
1
Add a function for checking whether a clock has a source. This is
2
useful for devices which have input clocks that must be wired up by
3
the board as it allows them to fail in realize rather than ploughing
4
on with a zero-period clock.
1
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Luc Michel <luc@lmichel.fr>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Message-id: 20210128114145.20536-3-peter.maydell@linaro.org
11
Message-id: 20210121190622.22000-3-peter.maydell@linaro.org
12
---
13
docs/devel/clocks.rst | 16 ++++++++++++++++
14
include/hw/clock.h | 15 +++++++++++++++
15
2 files changed, 31 insertions(+)
16
17
diff --git a/docs/devel/clocks.rst b/docs/devel/clocks.rst
18
index XXXXXXX..XXXXXXX 100644
19
--- a/docs/devel/clocks.rst
20
+++ b/docs/devel/clocks.rst
21
@@ -XXX,XX +XXX,XX @@ object during device instance init. For example:
22
/* set initial value to 10ns / 100MHz */
23
clock_set_ns(clk, 10);
24
25
+To enforce that the clock is wired up by the board code, you can
26
+call ``clock_has_source()`` in your device's realize method:
27
+
28
+.. code-block:: c
29
+
30
+ if (!clock_has_source(s->clk)) {
31
+ error_setg(errp, "MyDevice: clk input must be connected");
32
+ return;
33
+ }
34
+
35
+Note that this only checks that the clock has been wired up; it is
36
+still possible that the output clock connected to it is disabled
37
+or has not yet been configured, in which case the period will be
38
+zero. You should use the clock callback to find out when the clock
39
+period changes.
40
+
41
Fetching clock frequency/period
42
-------------------------------
43
44
diff --git a/include/hw/clock.h b/include/hw/clock.h
45
index XXXXXXX..XXXXXXX 100644
46
--- a/include/hw/clock.h
47
+++ b/include/hw/clock.h
48
@@ -XXX,XX +XXX,XX @@ void clock_clear_callback(Clock *clk);
49
*/
50
void clock_set_source(Clock *clk, Clock *src);
51
52
+/**
53
+ * clock_has_source:
54
+ * @clk: the clock
55
+ *
56
+ * Returns true if the clock has a source clock connected to it.
57
+ * This is useful for devices which have input clocks which must
58
+ * be connected by the board/SoC code which creates them. The
59
+ * device code can use this to check in its realize method that
60
+ * the clock has been connected.
61
+ */
62
+static inline bool clock_has_source(const Clock *clk)
63
+{
64
+ return clk->source != NULL;
65
+}
66
+
67
/**
68
* clock_set:
69
* @clk: the clock to initialize.
70
--
71
2.20.1
72
73
diff view generated by jsdifflib
New patch
1
Add a simple test of the CMSDK APB timer, since we're about to do
2
some refactoring of how it is clocked.
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Luc Michel <luc@lmichel.fr>
7
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20210128114145.20536-4-peter.maydell@linaro.org
9
Message-id: 20210121190622.22000-4-peter.maydell@linaro.org
10
---
11
tests/qtest/cmsdk-apb-timer-test.c | 75 ++++++++++++++++++++++++++++++
12
MAINTAINERS | 1 +
13
tests/qtest/meson.build | 1 +
14
3 files changed, 77 insertions(+)
15
create mode 100644 tests/qtest/cmsdk-apb-timer-test.c
16
17
diff --git a/tests/qtest/cmsdk-apb-timer-test.c b/tests/qtest/cmsdk-apb-timer-test.c
18
new file mode 100644
19
index XXXXXXX..XXXXXXX
20
--- /dev/null
21
+++ b/tests/qtest/cmsdk-apb-timer-test.c
22
@@ -XXX,XX +XXX,XX @@
23
+/*
24
+ * QTest testcase for the CMSDK APB timer device
25
+ *
26
+ * Copyright (c) 2021 Linaro Limited
27
+ *
28
+ * This program is free software; you can redistribute it and/or modify it
29
+ * under the terms of the GNU General Public License as published by the
30
+ * Free Software Foundation; either version 2 of the License, or
31
+ * (at your option) any later version.
32
+ *
33
+ * This program is distributed in the hope that it will be useful, but WITHOUT
34
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
35
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
36
+ * for more details.
37
+ */
38
+
39
+#include "qemu/osdep.h"
40
+#include "libqtest-single.h"
41
+
42
+/* IoTKit/ARMSSE-200 timer0; driven at 25MHz in mps2-an385, so 40ns per tick */
43
+#define TIMER_BASE 0x40000000
44
+
45
+#define CTRL 0
46
+#define VALUE 4
47
+#define RELOAD 8
48
+#define INTSTATUS 0xc
49
+
50
+static void test_timer(void)
51
+{
52
+ g_assert_true(readl(TIMER_BASE + INTSTATUS) == 0);
53
+
54
+ /* Start timer: will fire after 40 * 1000 == 40000 ns */
55
+ writel(TIMER_BASE + RELOAD, 1000);
56
+ writel(TIMER_BASE + CTRL, 9);
57
+
58
+ /* Step to just past the 500th tick and check VALUE */
59
+ clock_step(40 * 500 + 1);
60
+ g_assert_cmpuint(readl(TIMER_BASE + INTSTATUS), ==, 0);
61
+ g_assert_cmpuint(readl(TIMER_BASE + VALUE), ==, 500);
62
+
63
+ /* Just past the 1000th tick: timer should have fired */
64
+ clock_step(40 * 500);
65
+ g_assert_cmpuint(readl(TIMER_BASE + INTSTATUS), ==, 1);
66
+ g_assert_cmpuint(readl(TIMER_BASE + VALUE), ==, 0);
67
+
68
+ /* VALUE reloads at the following tick */
69
+ clock_step(40);
70
+ g_assert_cmpuint(readl(TIMER_BASE + VALUE), ==, 1000);
71
+
72
+ /* Check write-1-to-clear behaviour of INTSTATUS */
73
+ writel(TIMER_BASE + INTSTATUS, 0);
74
+ g_assert_cmpuint(readl(TIMER_BASE + INTSTATUS), ==, 1);
75
+ writel(TIMER_BASE + INTSTATUS, 1);
76
+ g_assert_cmpuint(readl(TIMER_BASE + INTSTATUS), ==, 0);
77
+
78
+ /* Turn off the timer */
79
+ writel(TIMER_BASE + CTRL, 0);
80
+}
81
+
82
+int main(int argc, char **argv)
83
+{
84
+ int r;
85
+
86
+ g_test_init(&argc, &argv, NULL);
87
+
88
+ qtest_start("-machine mps2-an385");
89
+
90
+ qtest_add_func("/cmsdk-apb-timer/timer", test_timer);
91
+
92
+ r = g_test_run();
93
+
94
+ qtest_end();
95
+
96
+ return r;
97
+}
98
diff --git a/MAINTAINERS b/MAINTAINERS
99
index XXXXXXX..XXXXXXX 100644
100
--- a/MAINTAINERS
101
+++ b/MAINTAINERS
102
@@ -XXX,XX +XXX,XX @@ F: include/hw/rtc/pl031.h
103
F: include/hw/arm/primecell.h
104
F: hw/timer/cmsdk-apb-timer.c
105
F: include/hw/timer/cmsdk-apb-timer.h
106
+F: tests/qtest/cmsdk-apb-timer-test.c
107
F: hw/timer/cmsdk-apb-dualtimer.c
108
F: include/hw/timer/cmsdk-apb-dualtimer.h
109
F: hw/char/cmsdk-apb-uart.c
110
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
111
index XXXXXXX..XXXXXXX 100644
112
--- a/tests/qtest/meson.build
113
+++ b/tests/qtest/meson.build
114
@@ -XXX,XX +XXX,XX @@ qtests_npcm7xx = \
115
'npcm7xx_timer-test',
116
'npcm7xx_watchdog_timer-test']
117
qtests_arm = \
118
+ (config_all_devices.has_key('CONFIG_CMSDK_APB_TIMER') ? ['cmsdk-apb-timer-test'] : []) + \
119
(config_all_devices.has_key('CONFIG_PFLASH_CFI02') ? ['pflash-cfi02-test'] : []) + \
120
(config_all_devices.has_key('CONFIG_NPCM7XX') ? qtests_npcm7xx : []) + \
121
['arm-cpu-features',
122
--
123
2.20.1
124
125
diff view generated by jsdifflib
New patch
1
Add a simple test of the CMSDK watchdog, since we're about to do some
2
refactoring of how it is clocked.
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Luc Michel <luc@lmichel.fr>
6
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20210128114145.20536-5-peter.maydell@linaro.org
9
Message-id: 20210121190622.22000-5-peter.maydell@linaro.org
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
---
12
tests/qtest/cmsdk-apb-watchdog-test.c | 79 +++++++++++++++++++++++++++
13
MAINTAINERS | 1 +
14
tests/qtest/meson.build | 1 +
15
3 files changed, 81 insertions(+)
16
create mode 100644 tests/qtest/cmsdk-apb-watchdog-test.c
17
18
diff --git a/tests/qtest/cmsdk-apb-watchdog-test.c b/tests/qtest/cmsdk-apb-watchdog-test.c
19
new file mode 100644
20
index XXXXXXX..XXXXXXX
21
--- /dev/null
22
+++ b/tests/qtest/cmsdk-apb-watchdog-test.c
23
@@ -XXX,XX +XXX,XX @@
24
+/*
25
+ * QTest testcase for the CMSDK APB watchdog device
26
+ *
27
+ * Copyright (c) 2021 Linaro Limited
28
+ *
29
+ * This program is free software; you can redistribute it and/or modify it
30
+ * under the terms of the GNU General Public License as published by the
31
+ * Free Software Foundation; either version 2 of the License, or
32
+ * (at your option) any later version.
33
+ *
34
+ * This program is distributed in the hope that it will be useful, but WITHOUT
35
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
36
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
37
+ * for more details.
38
+ */
39
+
40
+#include "qemu/osdep.h"
41
+#include "libqtest-single.h"
42
+
43
+/*
44
+ * lm3s811evb watchdog; at board startup this runs at 200MHz / 16 == 12.5MHz,
45
+ * which is 80ns per tick.
46
+ */
47
+#define WDOG_BASE 0x40000000
48
+
49
+#define WDOGLOAD 0
50
+#define WDOGVALUE 4
51
+#define WDOGCONTROL 8
52
+#define WDOGINTCLR 0xc
53
+#define WDOGRIS 0x10
54
+#define WDOGMIS 0x14
55
+#define WDOGLOCK 0xc00
56
+
57
+static void test_watchdog(void)
58
+{
59
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 0);
60
+
61
+ writel(WDOG_BASE + WDOGCONTROL, 1);
62
+ writel(WDOG_BASE + WDOGLOAD, 1000);
63
+
64
+ /* Step to just past the 500th tick */
65
+ clock_step(500 * 80 + 1);
66
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 0);
67
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 500);
68
+
69
+ /* Just past the 1000th tick: timer should have fired */
70
+ clock_step(500 * 80);
71
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 1);
72
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 0);
73
+
74
+ /* VALUE reloads at following tick */
75
+ clock_step(80);
76
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 1000);
77
+
78
+ /* Writing any value to WDOGINTCLR clears the interrupt and reloads */
79
+ clock_step(500 * 80);
80
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 500);
81
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 1);
82
+ writel(WDOG_BASE + WDOGINTCLR, 0);
83
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 1000);
84
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 0);
85
+}
86
+
87
+int main(int argc, char **argv)
88
+{
89
+ int r;
90
+
91
+ g_test_init(&argc, &argv, NULL);
92
+
93
+ qtest_start("-machine lm3s811evb");
94
+
95
+ qtest_add_func("/cmsdk-apb-watchdog/watchdog", test_watchdog);
96
+
97
+ r = g_test_run();
98
+
99
+ qtest_end();
100
+
101
+ return r;
102
+}
103
diff --git a/MAINTAINERS b/MAINTAINERS
104
index XXXXXXX..XXXXXXX 100644
105
--- a/MAINTAINERS
106
+++ b/MAINTAINERS
107
@@ -XXX,XX +XXX,XX @@ F: hw/char/cmsdk-apb-uart.c
108
F: include/hw/char/cmsdk-apb-uart.h
109
F: hw/watchdog/cmsdk-apb-watchdog.c
110
F: include/hw/watchdog/cmsdk-apb-watchdog.h
111
+F: tests/qtest/cmsdk-apb-watchdog-test.c
112
F: hw/misc/tz-ppc.c
113
F: include/hw/misc/tz-ppc.h
114
F: hw/misc/tz-mpc.c
115
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
116
index XXXXXXX..XXXXXXX 100644
117
--- a/tests/qtest/meson.build
118
+++ b/tests/qtest/meson.build
119
@@ -XXX,XX +XXX,XX @@ qtests_npcm7xx = \
120
'npcm7xx_watchdog_timer-test']
121
qtests_arm = \
122
(config_all_devices.has_key('CONFIG_CMSDK_APB_TIMER') ? ['cmsdk-apb-timer-test'] : []) + \
123
+ (config_all_devices.has_key('CONFIG_CMSDK_APB_WATCHDOG') ? ['cmsdk-apb-watchdog-test'] : []) + \
124
(config_all_devices.has_key('CONFIG_PFLASH_CFI02') ? ['pflash-cfi02-test'] : []) + \
125
(config_all_devices.has_key('CONFIG_NPCM7XX') ? qtests_npcm7xx : []) + \
126
['arm-cpu-features',
127
--
128
2.20.1
129
130
diff view generated by jsdifflib
1
Define EXCP_STKOF, and arrange for it to cause us to take
1
Add a simple test of the CMSDK dual timer, since we're about to do
2
a UsageFault with CFSR.STKOF set.
2
some refactoring of how it is clocked.
3
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
5
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20181002163556.10279-3-peter.maydell@linaro.org
7
Reviewed-by: Luc Michel <luc@lmichel.fr>
8
Message-id: 20210128114145.20536-6-peter.maydell@linaro.org
9
Message-id: 20210121190622.22000-6-peter.maydell@linaro.org
8
---
10
---
9
target/arm/cpu.h | 2 ++
11
tests/qtest/cmsdk-apb-dualtimer-test.c | 130 +++++++++++++++++++++++++
10
target/arm/helper.c | 5 +++++
12
MAINTAINERS | 1 +
11
2 files changed, 7 insertions(+)
13
tests/qtest/meson.build | 1 +
14
3 files changed, 132 insertions(+)
15
create mode 100644 tests/qtest/cmsdk-apb-dualtimer-test.c
12
16
13
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
diff --git a/tests/qtest/cmsdk-apb-dualtimer-test.c b/tests/qtest/cmsdk-apb-dualtimer-test.c
18
new file mode 100644
19
index XXXXXXX..XXXXXXX
20
--- /dev/null
21
+++ b/tests/qtest/cmsdk-apb-dualtimer-test.c
22
@@ -XXX,XX +XXX,XX @@
23
+/*
24
+ * QTest testcase for the CMSDK APB dualtimer device
25
+ *
26
+ * Copyright (c) 2021 Linaro Limited
27
+ *
28
+ * This program is free software; you can redistribute it and/or modify it
29
+ * under the terms of the GNU General Public License as published by the
30
+ * Free Software Foundation; either version 2 of the License, or
31
+ * (at your option) any later version.
32
+ *
33
+ * This program is distributed in the hope that it will be useful, but WITHOUT
34
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
35
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
36
+ * for more details.
37
+ */
38
+
39
+#include "qemu/osdep.h"
40
+#include "libqtest-single.h"
41
+
42
+/* IoTKit/ARMSSE dualtimer; driven at 25MHz in mps2-an385, so 40ns per tick */
43
+#define TIMER_BASE 0x40002000
44
+
45
+#define TIMER1LOAD 0
46
+#define TIMER1VALUE 4
47
+#define TIMER1CONTROL 8
48
+#define TIMER1INTCLR 0xc
49
+#define TIMER1RIS 0x10
50
+#define TIMER1MIS 0x14
51
+#define TIMER1BGLOAD 0x18
52
+
53
+#define TIMER2LOAD 0x20
54
+#define TIMER2VALUE 0x24
55
+#define TIMER2CONTROL 0x28
56
+#define TIMER2INTCLR 0x2c
57
+#define TIMER2RIS 0x30
58
+#define TIMER2MIS 0x34
59
+#define TIMER2BGLOAD 0x38
60
+
61
+#define CTRL_ENABLE (1 << 7)
62
+#define CTRL_PERIODIC (1 << 6)
63
+#define CTRL_INTEN (1 << 5)
64
+#define CTRL_PRESCALE_1 (0 << 2)
65
+#define CTRL_PRESCALE_16 (1 << 2)
66
+#define CTRL_PRESCALE_256 (2 << 2)
67
+#define CTRL_32BIT (1 << 1)
68
+#define CTRL_ONESHOT (1 << 0)
69
+
70
+static void test_dualtimer(void)
71
+{
72
+ g_assert_true(readl(TIMER_BASE + TIMER1RIS) == 0);
73
+
74
+ /* Start timer: will fire after 40000 ns */
75
+ writel(TIMER_BASE + TIMER1LOAD, 1000);
76
+ /* enable in free-running, wrapping, interrupt mode */
77
+ writel(TIMER_BASE + TIMER1CONTROL, CTRL_ENABLE | CTRL_INTEN);
78
+
79
+ /* Step to just past the 500th tick and check VALUE */
80
+ clock_step(500 * 40 + 1);
81
+ g_assert_cmpuint(readl(TIMER_BASE + TIMER1RIS), ==, 0);
82
+ g_assert_cmpuint(readl(TIMER_BASE + TIMER1VALUE), ==, 500);
83
+
84
+ /* Just past the 1000th tick: timer should have fired */
85
+ clock_step(500 * 40);
86
+ g_assert_cmpuint(readl(TIMER_BASE + TIMER1RIS), ==, 1);
87
+ g_assert_cmpuint(readl(TIMER_BASE + TIMER1VALUE), ==, 0);
88
+
89
+ /*
90
+ * We are in free-running wrapping 16-bit mode, so on the following
91
+ * tick VALUE should have wrapped round to 0xffff.
92
+ */
93
+ clock_step(40);
94
+ g_assert_cmpuint(readl(TIMER_BASE + TIMER1VALUE), ==, 0xffff);
95
+
96
+ /* Check that any write to INTCLR clears interrupt */
97
+ writel(TIMER_BASE + TIMER1INTCLR, 1);
98
+ g_assert_cmpuint(readl(TIMER_BASE + TIMER1RIS), ==, 0);
99
+
100
+ /* Turn off the timer */
101
+ writel(TIMER_BASE + TIMER1CONTROL, 0);
102
+}
103
+
104
+static void test_prescale(void)
105
+{
106
+ g_assert_true(readl(TIMER_BASE + TIMER2RIS) == 0);
107
+
108
+ /* Start timer: will fire after 40 * 256 * 1000 == 1024000 ns */
109
+ writel(TIMER_BASE + TIMER2LOAD, 1000);
110
+ /* enable in periodic, wrapping, interrupt mode, prescale 256 */
111
+ writel(TIMER_BASE + TIMER2CONTROL,
112
+ CTRL_ENABLE | CTRL_INTEN | CTRL_PERIODIC | CTRL_PRESCALE_256);
113
+
114
+ /* Step to just past the 500th tick and check VALUE */
115
+ clock_step(40 * 256 * 501);
116
+ g_assert_cmpuint(readl(TIMER_BASE + TIMER2RIS), ==, 0);
117
+ g_assert_cmpuint(readl(TIMER_BASE + TIMER2VALUE), ==, 500);
118
+
119
+ /* Just past the 1000th tick: timer should have fired */
120
+ clock_step(40 * 256 * 500);
121
+ g_assert_cmpuint(readl(TIMER_BASE + TIMER2RIS), ==, 1);
122
+ g_assert_cmpuint(readl(TIMER_BASE + TIMER2VALUE), ==, 0);
123
+
124
+ /* In periodic mode the tick VALUE now reloads */
125
+ clock_step(40 * 256);
126
+ g_assert_cmpuint(readl(TIMER_BASE + TIMER2VALUE), ==, 1000);
127
+
128
+ /* Check that any write to INTCLR clears interrupt */
129
+ writel(TIMER_BASE + TIMER2INTCLR, 1);
130
+ g_assert_cmpuint(readl(TIMER_BASE + TIMER2RIS), ==, 0);
131
+
132
+ /* Turn off the timer */
133
+ writel(TIMER_BASE + TIMER2CONTROL, 0);
134
+}
135
+
136
+int main(int argc, char **argv)
137
+{
138
+ int r;
139
+
140
+ g_test_init(&argc, &argv, NULL);
141
+
142
+ qtest_start("-machine mps2-an385");
143
+
144
+ qtest_add_func("/cmsdk-apb-dualtimer/dualtimer", test_dualtimer);
145
+ qtest_add_func("/cmsdk-apb-dualtimer/prescale", test_prescale);
146
+
147
+ r = g_test_run();
148
+
149
+ qtest_end();
150
+
151
+ return r;
152
+}
153
diff --git a/MAINTAINERS b/MAINTAINERS
14
index XXXXXXX..XXXXXXX 100644
154
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/cpu.h
155
--- a/MAINTAINERS
16
+++ b/target/arm/cpu.h
156
+++ b/MAINTAINERS
17
@@ -XXX,XX +XXX,XX @@
157
@@ -XXX,XX +XXX,XX @@ F: include/hw/timer/cmsdk-apb-timer.h
18
#define EXCP_SEMIHOST 16 /* semihosting call */
158
F: tests/qtest/cmsdk-apb-timer-test.c
19
#define EXCP_NOCP 17 /* v7M NOCP UsageFault */
159
F: hw/timer/cmsdk-apb-dualtimer.c
20
#define EXCP_INVSTATE 18 /* v7M INVSTATE UsageFault */
160
F: include/hw/timer/cmsdk-apb-dualtimer.h
21
+#define EXCP_STKOF 19 /* v8M STKOF UsageFault */
161
+F: tests/qtest/cmsdk-apb-dualtimer-test.c
22
/* NB: add new EXCP_ defines to the array in arm_log_exception() too */
162
F: hw/char/cmsdk-apb-uart.c
23
163
F: include/hw/char/cmsdk-apb-uart.h
24
#define ARMV7M_EXCP_RESET 1
164
F: hw/watchdog/cmsdk-apb-watchdog.c
25
@@ -XXX,XX +XXX,XX @@ FIELD(V7M_CFSR, UNDEFINSTR, 16 + 0, 1)
165
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
26
FIELD(V7M_CFSR, INVSTATE, 16 + 1, 1)
27
FIELD(V7M_CFSR, INVPC, 16 + 2, 1)
28
FIELD(V7M_CFSR, NOCP, 16 + 3, 1)
29
+FIELD(V7M_CFSR, STKOF, 16 + 4, 1)
30
FIELD(V7M_CFSR, UNALIGNED, 16 + 8, 1)
31
FIELD(V7M_CFSR, DIVBYZERO, 16 + 9, 1)
32
33
diff --git a/target/arm/helper.c b/target/arm/helper.c
34
index XXXXXXX..XXXXXXX 100644
166
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/helper.c
167
--- a/tests/qtest/meson.build
36
+++ b/target/arm/helper.c
168
+++ b/tests/qtest/meson.build
37
@@ -XXX,XX +XXX,XX @@ static void arm_log_exception(int idx)
169
@@ -XXX,XX +XXX,XX @@ qtests_npcm7xx = \
38
[EXCP_SEMIHOST] = "Semihosting call",
170
'npcm7xx_timer-test',
39
[EXCP_NOCP] = "v7M NOCP UsageFault",
171
'npcm7xx_watchdog_timer-test']
40
[EXCP_INVSTATE] = "v7M INVSTATE UsageFault",
172
qtests_arm = \
41
+ [EXCP_STKOF] = "v8M STKOF UsageFault",
173
+ (config_all_devices.has_key('CONFIG_CMSDK_APB_DUALTIMER') ? ['cmsdk-apb-dualtimer-test'] : []) + \
42
};
174
(config_all_devices.has_key('CONFIG_CMSDK_APB_TIMER') ? ['cmsdk-apb-timer-test'] : []) + \
43
175
(config_all_devices.has_key('CONFIG_CMSDK_APB_WATCHDOG') ? ['cmsdk-apb-watchdog-test'] : []) + \
44
if (idx >= 0 && idx < ARRAY_SIZE(excnames)) {
176
(config_all_devices.has_key('CONFIG_PFLASH_CFI02') ? ['pflash-cfi02-test'] : []) + \
45
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
46
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, env->v7m.secure);
47
env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_INVSTATE_MASK;
48
break;
49
+ case EXCP_STKOF:
50
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, env->v7m.secure);
51
+ env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_STKOF_MASK;
52
+ break;
53
case EXCP_SWI:
54
/* The PC already points to the next instruction. */
55
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SVC, env->v7m.secure);
56
--
177
--
57
2.19.0
178
2.20.1
58
179
59
180
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The state struct for the CMSDK APB timer device doesn't follow our
2
usual naming convention of camelcase -- "CMSDK" and "APB" are both
3
acronyms, but "TIMER" is not so should not be all-uppercase.
4
Globally rename the struct to "CMSDKAPBTimer" (bringing it into line
5
with CMSDKAPBWatchdog and CMSDKAPBDualTimer; CMSDKAPBUART remains
6
as-is because "UART" is an acronym).
2
7
3
This fixes the endianness problem for softmmu, and moves
8
Commit created with:
4
the main loop out of a macro and into an inlined function.
9
perl -p -i -e 's/CMSDKAPBTIMER/CMSDKAPBTimer/g' hw/timer/cmsdk-apb-timer.c include/hw/arm/armsse.h include/hw/timer/cmsdk-apb-timer.h
5
10
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20181005175350.30752-14-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: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Reviewed-by: Luc Michel <luc@lmichel.fr>
14
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Message-id: 20210128114145.20536-7-peter.maydell@linaro.org
16
Message-id: 20210121190622.22000-7-peter.maydell@linaro.org
11
---
17
---
12
target/arm/helper-sve.h | 52 ++++++++++----
18
include/hw/arm/armsse.h | 6 +++---
13
target/arm/sve_helper.c | 139 ++++++++++++++++++++++++-------------
19
include/hw/timer/cmsdk-apb-timer.h | 4 ++--
14
target/arm/translate-sve.c | 74 +++++++++++++-------
20
hw/timer/cmsdk-apb-timer.c | 28 ++++++++++++++--------------
15
3 files changed, 177 insertions(+), 88 deletions(-)
21
3 files changed, 19 insertions(+), 19 deletions(-)
16
22
17
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
23
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
18
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper-sve.h
25
--- a/include/hw/arm/armsse.h
20
+++ b/target/arm/helper-sve.h
26
+++ b/include/hw/arm/armsse.h
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_6(sve_ldffsds_zd, TCG_CALL_NO_WG,
27
@@ -XXX,XX +XXX,XX @@ struct ARMSSE {
22
28
TZPPC apb_ppc0;
23
DEF_HELPER_FLAGS_6(sve_stbs_zsu, TCG_CALL_NO_WG,
29
TZPPC apb_ppc1;
24
void, env, ptr, ptr, ptr, tl, i32)
30
TZMPC mpc[IOTS_NUM_MPC];
25
-DEF_HELPER_FLAGS_6(sve_sths_zsu, TCG_CALL_NO_WG,
31
- CMSDKAPBTIMER timer0;
26
+DEF_HELPER_FLAGS_6(sve_sths_le_zsu, TCG_CALL_NO_WG,
32
- CMSDKAPBTIMER timer1;
27
void, env, ptr, ptr, ptr, tl, i32)
33
- CMSDKAPBTIMER s32ktimer;
28
-DEF_HELPER_FLAGS_6(sve_stss_zsu, TCG_CALL_NO_WG,
34
+ CMSDKAPBTimer timer0;
29
+DEF_HELPER_FLAGS_6(sve_sths_be_zsu, TCG_CALL_NO_WG,
35
+ CMSDKAPBTimer timer1;
30
+ void, env, ptr, ptr, ptr, tl, i32)
36
+ CMSDKAPBTimer s32ktimer;
31
+DEF_HELPER_FLAGS_6(sve_stss_le_zsu, TCG_CALL_NO_WG,
37
qemu_or_irq ppc_irq_orgate;
32
+ void, env, ptr, ptr, ptr, tl, i32)
38
SplitIRQ sec_resp_splitter;
33
+DEF_HELPER_FLAGS_6(sve_stss_be_zsu, TCG_CALL_NO_WG,
39
SplitIRQ ppc_irq_splitter[NUM_PPCS];
34
void, env, ptr, ptr, ptr, tl, i32)
40
diff --git a/include/hw/timer/cmsdk-apb-timer.h b/include/hw/timer/cmsdk-apb-timer.h
35
36
DEF_HELPER_FLAGS_6(sve_stbs_zss, TCG_CALL_NO_WG,
37
void, env, ptr, ptr, ptr, tl, i32)
38
-DEF_HELPER_FLAGS_6(sve_sths_zss, TCG_CALL_NO_WG,
39
+DEF_HELPER_FLAGS_6(sve_sths_le_zss, TCG_CALL_NO_WG,
40
void, env, ptr, ptr, ptr, tl, i32)
41
-DEF_HELPER_FLAGS_6(sve_stss_zss, TCG_CALL_NO_WG,
42
+DEF_HELPER_FLAGS_6(sve_sths_be_zss, TCG_CALL_NO_WG,
43
+ void, env, ptr, ptr, ptr, tl, i32)
44
+DEF_HELPER_FLAGS_6(sve_stss_le_zss, TCG_CALL_NO_WG,
45
+ void, env, ptr, ptr, ptr, tl, i32)
46
+DEF_HELPER_FLAGS_6(sve_stss_be_zss, TCG_CALL_NO_WG,
47
void, env, ptr, ptr, ptr, tl, i32)
48
49
DEF_HELPER_FLAGS_6(sve_stbd_zsu, TCG_CALL_NO_WG,
50
void, env, ptr, ptr, ptr, tl, i32)
51
-DEF_HELPER_FLAGS_6(sve_sthd_zsu, TCG_CALL_NO_WG,
52
+DEF_HELPER_FLAGS_6(sve_sthd_le_zsu, TCG_CALL_NO_WG,
53
void, env, ptr, ptr, ptr, tl, i32)
54
-DEF_HELPER_FLAGS_6(sve_stsd_zsu, TCG_CALL_NO_WG,
55
+DEF_HELPER_FLAGS_6(sve_sthd_be_zsu, TCG_CALL_NO_WG,
56
void, env, ptr, ptr, ptr, tl, i32)
57
-DEF_HELPER_FLAGS_6(sve_stdd_zsu, TCG_CALL_NO_WG,
58
+DEF_HELPER_FLAGS_6(sve_stsd_le_zsu, TCG_CALL_NO_WG,
59
+ void, env, ptr, ptr, ptr, tl, i32)
60
+DEF_HELPER_FLAGS_6(sve_stsd_be_zsu, TCG_CALL_NO_WG,
61
+ void, env, ptr, ptr, ptr, tl, i32)
62
+DEF_HELPER_FLAGS_6(sve_stdd_le_zsu, TCG_CALL_NO_WG,
63
+ void, env, ptr, ptr, ptr, tl, i32)
64
+DEF_HELPER_FLAGS_6(sve_stdd_be_zsu, TCG_CALL_NO_WG,
65
void, env, ptr, ptr, ptr, tl, i32)
66
67
DEF_HELPER_FLAGS_6(sve_stbd_zss, TCG_CALL_NO_WG,
68
void, env, ptr, ptr, ptr, tl, i32)
69
-DEF_HELPER_FLAGS_6(sve_sthd_zss, TCG_CALL_NO_WG,
70
+DEF_HELPER_FLAGS_6(sve_sthd_le_zss, TCG_CALL_NO_WG,
71
void, env, ptr, ptr, ptr, tl, i32)
72
-DEF_HELPER_FLAGS_6(sve_stsd_zss, TCG_CALL_NO_WG,
73
+DEF_HELPER_FLAGS_6(sve_sthd_be_zss, TCG_CALL_NO_WG,
74
void, env, ptr, ptr, ptr, tl, i32)
75
-DEF_HELPER_FLAGS_6(sve_stdd_zss, TCG_CALL_NO_WG,
76
+DEF_HELPER_FLAGS_6(sve_stsd_le_zss, TCG_CALL_NO_WG,
77
+ void, env, ptr, ptr, ptr, tl, i32)
78
+DEF_HELPER_FLAGS_6(sve_stsd_be_zss, TCG_CALL_NO_WG,
79
+ void, env, ptr, ptr, ptr, tl, i32)
80
+DEF_HELPER_FLAGS_6(sve_stdd_le_zss, TCG_CALL_NO_WG,
81
+ void, env, ptr, ptr, ptr, tl, i32)
82
+DEF_HELPER_FLAGS_6(sve_stdd_be_zss, TCG_CALL_NO_WG,
83
void, env, ptr, ptr, ptr, tl, i32)
84
85
DEF_HELPER_FLAGS_6(sve_stbd_zd, TCG_CALL_NO_WG,
86
void, env, ptr, ptr, ptr, tl, i32)
87
-DEF_HELPER_FLAGS_6(sve_sthd_zd, TCG_CALL_NO_WG,
88
+DEF_HELPER_FLAGS_6(sve_sthd_le_zd, TCG_CALL_NO_WG,
89
void, env, ptr, ptr, ptr, tl, i32)
90
-DEF_HELPER_FLAGS_6(sve_stsd_zd, TCG_CALL_NO_WG,
91
+DEF_HELPER_FLAGS_6(sve_sthd_be_zd, TCG_CALL_NO_WG,
92
void, env, ptr, ptr, ptr, tl, i32)
93
-DEF_HELPER_FLAGS_6(sve_stdd_zd, TCG_CALL_NO_WG,
94
+DEF_HELPER_FLAGS_6(sve_stsd_le_zd, TCG_CALL_NO_WG,
95
+ void, env, ptr, ptr, ptr, tl, i32)
96
+DEF_HELPER_FLAGS_6(sve_stsd_be_zd, TCG_CALL_NO_WG,
97
+ void, env, ptr, ptr, ptr, tl, i32)
98
+DEF_HELPER_FLAGS_6(sve_stdd_le_zd, TCG_CALL_NO_WG,
99
+ void, env, ptr, ptr, ptr, tl, i32)
100
+DEF_HELPER_FLAGS_6(sve_stdd_be_zd, TCG_CALL_NO_WG,
101
void, env, ptr, ptr, ptr, tl, i32)
102
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
103
index XXXXXXX..XXXXXXX 100644
41
index XXXXXXX..XXXXXXX 100644
104
--- a/target/arm/sve_helper.c
42
--- a/include/hw/timer/cmsdk-apb-timer.h
105
+++ b/target/arm/sve_helper.c
43
+++ b/include/hw/timer/cmsdk-apb-timer.h
106
@@ -XXX,XX +XXX,XX @@ DO_LDFF1_ZPZ_D(sve_ldffsds_zd, uint64_t, int32_t, cpu_ldl_data_ra)
44
@@ -XXX,XX +XXX,XX @@
107
45
#include "qom/object.h"
108
/* Stores with a vector index. */
46
109
47
#define TYPE_CMSDK_APB_TIMER "cmsdk-apb-timer"
110
-#define DO_ST1_ZPZ_S(NAME, TYPEI, FN) \
48
-OBJECT_DECLARE_SIMPLE_TYPE(CMSDKAPBTIMER, CMSDK_APB_TIMER)
111
-void HELPER(NAME)(CPUARMState *env, void *vd, void *vg, void *vm, \
49
+OBJECT_DECLARE_SIMPLE_TYPE(CMSDKAPBTimer, CMSDK_APB_TIMER)
112
- target_ulong base, uint32_t desc) \
50
113
-{ \
51
-struct CMSDKAPBTIMER {
114
- intptr_t i, oprsz = simd_oprsz(desc); \
52
+struct CMSDKAPBTimer {
115
- unsigned scale = simd_data(desc); \
53
/*< private >*/
116
- uintptr_t ra = GETPC(); \
54
SysBusDevice parent_obj;
117
- for (i = 0; i < oprsz; ) { \
55
118
- uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
56
diff --git a/hw/timer/cmsdk-apb-timer.c b/hw/timer/cmsdk-apb-timer.c
119
- do { \
57
index XXXXXXX..XXXXXXX 100644
120
- if (likely(pg & 1)) { \
58
--- a/hw/timer/cmsdk-apb-timer.c
121
- target_ulong off = *(TYPEI *)(vm + H1_4(i)); \
59
+++ b/hw/timer/cmsdk-apb-timer.c
122
- uint32_t d = *(uint32_t *)(vd + H1_4(i)); \
60
@@ -XXX,XX +XXX,XX @@ static const int timer_id[] = {
123
- FN(env, base + (off << scale), d, ra); \
61
0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
124
- } \
62
};
125
- i += sizeof(uint32_t), pg >>= sizeof(uint32_t); \
63
126
- } while (i & 15); \
64
-static void cmsdk_apb_timer_update(CMSDKAPBTIMER *s)
127
- } \
65
+static void cmsdk_apb_timer_update(CMSDKAPBTimer *s)
128
+static void sve_st1_zs(CPUARMState *env, void *vd, void *vg, void *vm,
66
{
129
+ target_ulong base, uint32_t desc, uintptr_t ra,
67
qemu_set_irq(s->timerint, !!(s->intstatus & R_INTSTATUS_IRQ_MASK));
130
+ zreg_off_fn *off_fn, sve_ld1_tlb_fn *tlb_fn)
131
+{
132
+ const int mmu_idx = cpu_mmu_index(env, false);
133
+ intptr_t i, oprsz = simd_oprsz(desc);
134
+ unsigned scale = simd_data(desc);
135
+
136
+ set_helper_retaddr(ra);
137
+ for (i = 0; i < oprsz; ) {
138
+ uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));
139
+ do {
140
+ if (likely(pg & 1)) {
141
+ target_ulong off = off_fn(vm, i);
142
+ tlb_fn(env, vd, i, base + (off << scale), mmu_idx, ra);
143
+ }
144
+ i += 4, pg >>= 4;
145
+ } while (i & 15);
146
+ }
147
+ set_helper_retaddr(0);
148
}
68
}
149
69
150
-#define DO_ST1_ZPZ_D(NAME, TYPEI, FN) \
70
static uint64_t cmsdk_apb_timer_read(void *opaque, hwaddr offset, unsigned size)
151
-void HELPER(NAME)(CPUARMState *env, void *vd, void *vg, void *vm, \
71
{
152
- target_ulong base, uint32_t desc) \
72
- CMSDKAPBTIMER *s = CMSDK_APB_TIMER(opaque);
153
-{ \
73
+ CMSDKAPBTimer *s = CMSDK_APB_TIMER(opaque);
154
- intptr_t i, oprsz = simd_oprsz(desc) / 8; \
74
uint64_t r;
155
- unsigned scale = simd_data(desc); \
75
156
- uintptr_t ra = GETPC(); \
76
switch (offset) {
157
- uint64_t *d = vd, *m = vm; uint8_t *pg = vg; \
77
@@ -XXX,XX +XXX,XX @@ static uint64_t cmsdk_apb_timer_read(void *opaque, hwaddr offset, unsigned size)
158
- for (i = 0; i < oprsz; i++) { \
78
static void cmsdk_apb_timer_write(void *opaque, hwaddr offset, uint64_t value,
159
- if (likely(pg[H1(i)] & 1)) { \
79
unsigned size)
160
- target_ulong off = (target_ulong)(TYPEI)m[i] << scale; \
80
{
161
- FN(env, base + off, d[i], ra); \
81
- CMSDKAPBTIMER *s = CMSDK_APB_TIMER(opaque);
162
- } \
82
+ CMSDKAPBTimer *s = CMSDK_APB_TIMER(opaque);
163
- } \
83
164
+static void sve_st1_zd(CPUARMState *env, void *vd, void *vg, void *vm,
84
trace_cmsdk_apb_timer_write(offset, value, size);
165
+ target_ulong base, uint32_t desc, uintptr_t ra,
85
166
+ zreg_off_fn *off_fn, sve_ld1_tlb_fn *tlb_fn)
86
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps cmsdk_apb_timer_ops = {
167
+{
87
168
+ const int mmu_idx = cpu_mmu_index(env, false);
88
static void cmsdk_apb_timer_tick(void *opaque)
169
+ intptr_t i, oprsz = simd_oprsz(desc) / 8;
89
{
170
+ unsigned scale = simd_data(desc);
90
- CMSDKAPBTIMER *s = CMSDK_APB_TIMER(opaque);
171
+
91
+ CMSDKAPBTimer *s = CMSDK_APB_TIMER(opaque);
172
+ set_helper_retaddr(ra);
92
173
+ for (i = 0; i < oprsz; i++) {
93
if (s->ctrl & R_CTRL_IRQEN_MASK) {
174
+ uint8_t pg = *(uint8_t *)(vg + H1(i));
94
s->intstatus |= R_INTSTATUS_IRQ_MASK;
175
+ if (likely(pg & 1)) {
95
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_timer_tick(void *opaque)
176
+ target_ulong off = off_fn(vm, i * 8);
96
177
+ tlb_fn(env, vd, i * 8, base + (off << scale), mmu_idx, ra);
97
static void cmsdk_apb_timer_reset(DeviceState *dev)
178
+ }
98
{
179
+ }
99
- CMSDKAPBTIMER *s = CMSDK_APB_TIMER(dev);
180
+ set_helper_retaddr(0);
100
+ CMSDKAPBTimer *s = CMSDK_APB_TIMER(dev);
181
}
101
182
102
trace_cmsdk_apb_timer_reset();
183
-DO_ST1_ZPZ_S(sve_stbs_zsu, uint32_t, cpu_stb_data_ra)
103
s->ctrl = 0;
184
-DO_ST1_ZPZ_S(sve_sths_zsu, uint32_t, cpu_stw_data_ra)
104
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_timer_reset(DeviceState *dev)
185
-DO_ST1_ZPZ_S(sve_stss_zsu, uint32_t, cpu_stl_data_ra)
105
static void cmsdk_apb_timer_init(Object *obj)
186
+#define DO_ST1_ZPZ_S(MEM, OFS) \
106
{
187
+void __attribute__((flatten)) HELPER(sve_st##MEM##_##OFS) \
107
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
188
+ (CPUARMState *env, void *vd, void *vg, void *vm, \
108
- CMSDKAPBTIMER *s = CMSDK_APB_TIMER(obj);
189
+ target_ulong base, uint32_t desc) \
109
+ CMSDKAPBTimer *s = CMSDK_APB_TIMER(obj);
190
+{ \
110
191
+ sve_st1_zs(env, vd, vg, vm, base, desc, GETPC(), \
111
memory_region_init_io(&s->iomem, obj, &cmsdk_apb_timer_ops,
192
+ off_##OFS##_s, sve_st1##MEM##_tlb); \
112
s, "cmsdk-apb-timer", 0x1000);
193
+}
113
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_timer_init(Object *obj)
194
114
195
-DO_ST1_ZPZ_S(sve_stbs_zss, int32_t, cpu_stb_data_ra)
115
static void cmsdk_apb_timer_realize(DeviceState *dev, Error **errp)
196
-DO_ST1_ZPZ_S(sve_sths_zss, int32_t, cpu_stw_data_ra)
116
{
197
-DO_ST1_ZPZ_S(sve_stss_zss, int32_t, cpu_stl_data_ra)
117
- CMSDKAPBTIMER *s = CMSDK_APB_TIMER(dev);
198
+#define DO_ST1_ZPZ_D(MEM, OFS) \
118
+ CMSDKAPBTimer *s = CMSDK_APB_TIMER(dev);
199
+void __attribute__((flatten)) HELPER(sve_st##MEM##_##OFS) \
119
200
+ (CPUARMState *env, void *vd, void *vg, void *vm, \
120
if (s->pclk_frq == 0) {
201
+ target_ulong base, uint32_t desc) \
121
error_setg(errp, "CMSDK APB timer: pclk-frq property must be set");
202
+{ \
122
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription cmsdk_apb_timer_vmstate = {
203
+ sve_st1_zd(env, vd, vg, vm, base, desc, GETPC(), \
123
.version_id = 1,
204
+ off_##OFS##_d, sve_st1##MEM##_tlb); \
124
.minimum_version_id = 1,
205
+}
125
.fields = (VMStateField[]) {
206
126
- VMSTATE_PTIMER(timer, CMSDKAPBTIMER),
207
-DO_ST1_ZPZ_D(sve_stbd_zsu, uint32_t, cpu_stb_data_ra)
127
- VMSTATE_UINT32(ctrl, CMSDKAPBTIMER),
208
-DO_ST1_ZPZ_D(sve_sthd_zsu, uint32_t, cpu_stw_data_ra)
128
- VMSTATE_UINT32(value, CMSDKAPBTIMER),
209
-DO_ST1_ZPZ_D(sve_stsd_zsu, uint32_t, cpu_stl_data_ra)
129
- VMSTATE_UINT32(reload, CMSDKAPBTIMER),
210
-DO_ST1_ZPZ_D(sve_stdd_zsu, uint32_t, cpu_stq_data_ra)
130
- VMSTATE_UINT32(intstatus, CMSDKAPBTIMER),
211
+DO_ST1_ZPZ_S(bs, zsu)
131
+ VMSTATE_PTIMER(timer, CMSDKAPBTimer),
212
+DO_ST1_ZPZ_S(hs_le, zsu)
132
+ VMSTATE_UINT32(ctrl, CMSDKAPBTimer),
213
+DO_ST1_ZPZ_S(hs_be, zsu)
133
+ VMSTATE_UINT32(value, CMSDKAPBTimer),
214
+DO_ST1_ZPZ_S(ss_le, zsu)
134
+ VMSTATE_UINT32(reload, CMSDKAPBTimer),
215
+DO_ST1_ZPZ_S(ss_be, zsu)
135
+ VMSTATE_UINT32(intstatus, CMSDKAPBTimer),
216
136
VMSTATE_END_OF_LIST()
217
-DO_ST1_ZPZ_D(sve_stbd_zss, int32_t, cpu_stb_data_ra)
137
}
218
-DO_ST1_ZPZ_D(sve_sthd_zss, int32_t, cpu_stw_data_ra)
219
-DO_ST1_ZPZ_D(sve_stsd_zss, int32_t, cpu_stl_data_ra)
220
-DO_ST1_ZPZ_D(sve_stdd_zss, int32_t, cpu_stq_data_ra)
221
+DO_ST1_ZPZ_S(bs, zss)
222
+DO_ST1_ZPZ_S(hs_le, zss)
223
+DO_ST1_ZPZ_S(hs_be, zss)
224
+DO_ST1_ZPZ_S(ss_le, zss)
225
+DO_ST1_ZPZ_S(ss_be, zss)
226
227
-DO_ST1_ZPZ_D(sve_stbd_zd, uint64_t, cpu_stb_data_ra)
228
-DO_ST1_ZPZ_D(sve_sthd_zd, uint64_t, cpu_stw_data_ra)
229
-DO_ST1_ZPZ_D(sve_stsd_zd, uint64_t, cpu_stl_data_ra)
230
-DO_ST1_ZPZ_D(sve_stdd_zd, uint64_t, cpu_stq_data_ra)
231
+DO_ST1_ZPZ_D(bd, zsu)
232
+DO_ST1_ZPZ_D(hd_le, zsu)
233
+DO_ST1_ZPZ_D(hd_be, zsu)
234
+DO_ST1_ZPZ_D(sd_le, zsu)
235
+DO_ST1_ZPZ_D(sd_be, zsu)
236
+DO_ST1_ZPZ_D(dd_le, zsu)
237
+DO_ST1_ZPZ_D(dd_be, zsu)
238
+
239
+DO_ST1_ZPZ_D(bd, zss)
240
+DO_ST1_ZPZ_D(hd_le, zss)
241
+DO_ST1_ZPZ_D(hd_be, zss)
242
+DO_ST1_ZPZ_D(sd_le, zss)
243
+DO_ST1_ZPZ_D(sd_be, zss)
244
+DO_ST1_ZPZ_D(dd_le, zss)
245
+DO_ST1_ZPZ_D(dd_be, zss)
246
+
247
+DO_ST1_ZPZ_D(bd, zd)
248
+DO_ST1_ZPZ_D(hd_le, zd)
249
+DO_ST1_ZPZ_D(hd_be, zd)
250
+DO_ST1_ZPZ_D(sd_le, zd)
251
+DO_ST1_ZPZ_D(sd_be, zd)
252
+DO_ST1_ZPZ_D(dd_le, zd)
253
+DO_ST1_ZPZ_D(dd_be, zd)
254
+
255
+#undef DO_ST1_ZPZ_S
256
+#undef DO_ST1_ZPZ_D
257
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
258
index XXXXXXX..XXXXXXX 100644
259
--- a/target/arm/translate-sve.c
260
+++ b/target/arm/translate-sve.c
261
@@ -XXX,XX +XXX,XX @@ static bool trans_LD1_zpiz(DisasContext *s, arg_LD1_zpiz *a, uint32_t insn)
262
return true;
263
}
264
265
-/* Indexed by [xs][msz]. */
266
-static gen_helper_gvec_mem_scatter * const scatter_store_fn32[2][3] = {
267
- { gen_helper_sve_stbs_zsu,
268
- gen_helper_sve_sths_zsu,
269
- gen_helper_sve_stss_zsu, },
270
- { gen_helper_sve_stbs_zss,
271
- gen_helper_sve_sths_zss,
272
- gen_helper_sve_stss_zss, },
273
+/* Indexed by [be][xs][msz]. */
274
+static gen_helper_gvec_mem_scatter * const scatter_store_fn32[2][2][3] = {
275
+ /* Little-endian */
276
+ { { gen_helper_sve_stbs_zsu,
277
+ gen_helper_sve_sths_le_zsu,
278
+ gen_helper_sve_stss_le_zsu, },
279
+ { gen_helper_sve_stbs_zss,
280
+ gen_helper_sve_sths_le_zss,
281
+ gen_helper_sve_stss_le_zss, } },
282
+ /* Big-endian */
283
+ { { gen_helper_sve_stbs_zsu,
284
+ gen_helper_sve_sths_be_zsu,
285
+ gen_helper_sve_stss_be_zsu, },
286
+ { gen_helper_sve_stbs_zss,
287
+ gen_helper_sve_sths_be_zss,
288
+ gen_helper_sve_stss_be_zss, } },
289
};
138
};
290
139
291
/* Note that we overload xs=2 to indicate 64-bit offset. */
140
static Property cmsdk_apb_timer_properties[] = {
292
-static gen_helper_gvec_mem_scatter * const scatter_store_fn64[3][4] = {
141
- DEFINE_PROP_UINT32("pclk-frq", CMSDKAPBTIMER, pclk_frq, 0),
293
- { gen_helper_sve_stbd_zsu,
142
+ DEFINE_PROP_UINT32("pclk-frq", CMSDKAPBTimer, pclk_frq, 0),
294
- gen_helper_sve_sthd_zsu,
143
DEFINE_PROP_END_OF_LIST(),
295
- gen_helper_sve_stsd_zsu,
296
- gen_helper_sve_stdd_zsu, },
297
- { gen_helper_sve_stbd_zss,
298
- gen_helper_sve_sthd_zss,
299
- gen_helper_sve_stsd_zss,
300
- gen_helper_sve_stdd_zss, },
301
- { gen_helper_sve_stbd_zd,
302
- gen_helper_sve_sthd_zd,
303
- gen_helper_sve_stsd_zd,
304
- gen_helper_sve_stdd_zd, },
305
+static gen_helper_gvec_mem_scatter * const scatter_store_fn64[2][3][4] = {
306
+ /* Little-endian */
307
+ { { gen_helper_sve_stbd_zsu,
308
+ gen_helper_sve_sthd_le_zsu,
309
+ gen_helper_sve_stsd_le_zsu,
310
+ gen_helper_sve_stdd_le_zsu, },
311
+ { gen_helper_sve_stbd_zss,
312
+ gen_helper_sve_sthd_le_zss,
313
+ gen_helper_sve_stsd_le_zss,
314
+ gen_helper_sve_stdd_le_zss, },
315
+ { gen_helper_sve_stbd_zd,
316
+ gen_helper_sve_sthd_le_zd,
317
+ gen_helper_sve_stsd_le_zd,
318
+ gen_helper_sve_stdd_le_zd, } },
319
+ /* Big-endian */
320
+ { { gen_helper_sve_stbd_zsu,
321
+ gen_helper_sve_sthd_be_zsu,
322
+ gen_helper_sve_stsd_be_zsu,
323
+ gen_helper_sve_stdd_be_zsu, },
324
+ { gen_helper_sve_stbd_zss,
325
+ gen_helper_sve_sthd_be_zss,
326
+ gen_helper_sve_stsd_be_zss,
327
+ gen_helper_sve_stdd_be_zss, },
328
+ { gen_helper_sve_stbd_zd,
329
+ gen_helper_sve_sthd_be_zd,
330
+ gen_helper_sve_stsd_be_zd,
331
+ gen_helper_sve_stdd_be_zd, } },
332
};
144
};
333
145
334
static bool trans_ST1_zprz(DisasContext *s, arg_ST1_zprz *a, uint32_t insn)
146
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_timer_class_init(ObjectClass *klass, void *data)
335
{
147
static const TypeInfo cmsdk_apb_timer_info = {
336
gen_helper_gvec_mem_scatter *fn;
148
.name = TYPE_CMSDK_APB_TIMER,
337
+ int be = s->be_data == MO_BE;
149
.parent = TYPE_SYS_BUS_DEVICE,
338
150
- .instance_size = sizeof(CMSDKAPBTIMER),
339
if (a->esz < a->msz || (a->msz == 0 && a->scale)) {
151
+ .instance_size = sizeof(CMSDKAPBTimer),
340
return false;
152
.instance_init = cmsdk_apb_timer_init,
341
@@ -XXX,XX +XXX,XX @@ static bool trans_ST1_zprz(DisasContext *s, arg_ST1_zprz *a, uint32_t insn)
153
.class_init = cmsdk_apb_timer_class_init,
342
}
154
};
343
switch (a->esz) {
344
case MO_32:
345
- fn = scatter_store_fn32[a->xs][a->msz];
346
+ fn = scatter_store_fn32[be][a->xs][a->msz];
347
break;
348
case MO_64:
349
- fn = scatter_store_fn64[a->xs][a->msz];
350
+ fn = scatter_store_fn64[be][a->xs][a->msz];
351
break;
352
default:
353
g_assert_not_reached();
354
@@ -XXX,XX +XXX,XX @@ static bool trans_ST1_zprz(DisasContext *s, arg_ST1_zprz *a, uint32_t insn)
355
static bool trans_ST1_zpiz(DisasContext *s, arg_ST1_zpiz *a, uint32_t insn)
356
{
357
gen_helper_gvec_mem_scatter *fn = NULL;
358
+ int be = s->be_data == MO_BE;
359
TCGv_i64 imm;
360
361
if (a->esz < a->msz) {
362
@@ -XXX,XX +XXX,XX @@ static bool trans_ST1_zpiz(DisasContext *s, arg_ST1_zpiz *a, uint32_t insn)
363
364
switch (a->esz) {
365
case MO_32:
366
- fn = scatter_store_fn32[0][a->msz];
367
+ fn = scatter_store_fn32[be][0][a->msz];
368
break;
369
case MO_64:
370
- fn = scatter_store_fn64[2][a->msz];
371
+ fn = scatter_store_fn64[be][2][a->msz];
372
break;
373
}
374
assert(fn != NULL);
375
--
155
--
376
2.19.0
156
2.20.1
377
157
378
158
diff view generated by jsdifflib
New patch
1
As the first step in converting the CMSDK_APB_TIMER device to the
2
Clock framework, add a Clock input. For the moment we do nothing
3
with this clock; we will change the behaviour from using the pclk-frq
4
property to using the Clock once all the users of this device have
5
been converted to wire up the Clock.
1
6
7
Since the device doesn't already have a doc comment for its "QEMU
8
interface", we add one including the new Clock.
9
10
This is a migration compatibility break for machines mps2-an505,
11
mps2-an521, musca-a, musca-b1.
12
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Reviewed-by: Luc Michel <luc@lmichel.fr>
16
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Message-id: 20210128114145.20536-8-peter.maydell@linaro.org
18
Message-id: 20210121190622.22000-8-peter.maydell@linaro.org
19
---
20
include/hw/timer/cmsdk-apb-timer.h | 9 +++++++++
21
hw/timer/cmsdk-apb-timer.c | 7 +++++--
22
2 files changed, 14 insertions(+), 2 deletions(-)
23
24
diff --git a/include/hw/timer/cmsdk-apb-timer.h b/include/hw/timer/cmsdk-apb-timer.h
25
index XXXXXXX..XXXXXXX 100644
26
--- a/include/hw/timer/cmsdk-apb-timer.h
27
+++ b/include/hw/timer/cmsdk-apb-timer.h
28
@@ -XXX,XX +XXX,XX @@
29
#include "hw/qdev-properties.h"
30
#include "hw/sysbus.h"
31
#include "hw/ptimer.h"
32
+#include "hw/clock.h"
33
#include "qom/object.h"
34
35
#define TYPE_CMSDK_APB_TIMER "cmsdk-apb-timer"
36
OBJECT_DECLARE_SIMPLE_TYPE(CMSDKAPBTimer, CMSDK_APB_TIMER)
37
38
+/*
39
+ * QEMU interface:
40
+ * + QOM property "pclk-frq": frequency at which the timer is clocked
41
+ * + Clock input "pclk": clock for the timer
42
+ * + sysbus MMIO region 0: the register bank
43
+ * + sysbus IRQ 0: timer interrupt TIMERINT
44
+ */
45
struct CMSDKAPBTimer {
46
/*< private >*/
47
SysBusDevice parent_obj;
48
@@ -XXX,XX +XXX,XX @@ struct CMSDKAPBTimer {
49
qemu_irq timerint;
50
uint32_t pclk_frq;
51
struct ptimer_state *timer;
52
+ Clock *pclk;
53
54
uint32_t ctrl;
55
uint32_t value;
56
diff --git a/hw/timer/cmsdk-apb-timer.c b/hw/timer/cmsdk-apb-timer.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/hw/timer/cmsdk-apb-timer.c
59
+++ b/hw/timer/cmsdk-apb-timer.c
60
@@ -XXX,XX +XXX,XX @@
61
#include "hw/sysbus.h"
62
#include "hw/irq.h"
63
#include "hw/registerfields.h"
64
+#include "hw/qdev-clock.h"
65
#include "hw/timer/cmsdk-apb-timer.h"
66
#include "migration/vmstate.h"
67
68
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_timer_init(Object *obj)
69
s, "cmsdk-apb-timer", 0x1000);
70
sysbus_init_mmio(sbd, &s->iomem);
71
sysbus_init_irq(sbd, &s->timerint);
72
+ s->pclk = qdev_init_clock_in(DEVICE(s), "pclk", NULL, NULL);
73
}
74
75
static void cmsdk_apb_timer_realize(DeviceState *dev, Error **errp)
76
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_timer_realize(DeviceState *dev, Error **errp)
77
78
static const VMStateDescription cmsdk_apb_timer_vmstate = {
79
.name = "cmsdk-apb-timer",
80
- .version_id = 1,
81
- .minimum_version_id = 1,
82
+ .version_id = 2,
83
+ .minimum_version_id = 2,
84
.fields = (VMStateField[]) {
85
VMSTATE_PTIMER(timer, CMSDKAPBTimer),
86
+ VMSTATE_CLOCK(pclk, CMSDKAPBTimer),
87
VMSTATE_UINT32(ctrl, CMSDKAPBTimer),
88
VMSTATE_UINT32(value, CMSDKAPBTimer),
89
VMSTATE_UINT32(reload, CMSDKAPBTimer),
90
--
91
2.20.1
92
93
diff view generated by jsdifflib
1
A cut-and-paste error meant we were reading r4 from the v8M
1
As the first step in converting the CMSDK_APB_DUALTIMER device to the
2
callee-saves exception stack frame twice. This is harmless
2
Clock framework, add a Clock input. For the moment we do nothing
3
since it just meant we did two memory accesses to the same
3
with this clock; we will change the behaviour from using the pclk-frq
4
location, but it's unnecessary. Delete it.
4
property to using the Clock once all the users of this device have
5
been converted to wire up the Clock.
6
7
We take the opportunity to correct the name of the clock input to
8
match the hardware -- the dual timer names the clock which drives the
9
timers TIMCLK. (It does also have a 'pclk' input, which is used only
10
for the register and APB bus logic; on the SSE-200 these clocks are
11
both connected together.)
12
13
This is a migration compatibility break for machines mps2-an385,
14
mps2-an386, mps2-an500, mps2-an511, mps2-an505, mps2-an521, musca-a,
15
musca-b1.
5
16
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
18
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
Reviewed-by: Luc Michel <luc@lmichel.fr>
9
Message-id: 20181002150304.2287-1-peter.maydell@linaro.org
20
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
21
Message-id: 20210128114145.20536-9-peter.maydell@linaro.org
22
Message-id: 20210121190622.22000-9-peter.maydell@linaro.org
10
---
23
---
11
target/arm/helper.c | 1 -
24
include/hw/timer/cmsdk-apb-dualtimer.h | 3 +++
12
1 file changed, 1 deletion(-)
25
hw/timer/cmsdk-apb-dualtimer.c | 7 +++++--
26
2 files changed, 8 insertions(+), 2 deletions(-)
13
27
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
28
diff --git a/include/hw/timer/cmsdk-apb-dualtimer.h b/include/hw/timer/cmsdk-apb-dualtimer.h
15
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
30
--- a/include/hw/timer/cmsdk-apb-dualtimer.h
17
+++ b/target/arm/helper.c
31
+++ b/include/hw/timer/cmsdk-apb-dualtimer.h
18
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
32
@@ -XXX,XX +XXX,XX @@
19
}
33
*
20
34
* QEMU interface:
21
pop_ok = pop_ok &&
35
* + QOM property "pclk-frq": frequency at which the timer is clocked
22
- v7m_stack_read(cpu, &env->regs[4], frameptr + 0x8, mmu_idx) &&
36
+ * + Clock input "TIMCLK": clock (for both timers)
23
v7m_stack_read(cpu, &env->regs[4], frameptr + 0x8, mmu_idx) &&
37
* + sysbus MMIO region 0: the register bank
24
v7m_stack_read(cpu, &env->regs[5], frameptr + 0xc, mmu_idx) &&
38
* + sysbus IRQ 0: combined timer interrupt TIMINTC
25
v7m_stack_read(cpu, &env->regs[6], frameptr + 0x10, mmu_idx) &&
39
* + sysbus IRO 1: timer block 1 interrupt TIMINT1
40
@@ -XXX,XX +XXX,XX @@
41
42
#include "hw/sysbus.h"
43
#include "hw/ptimer.h"
44
+#include "hw/clock.h"
45
#include "qom/object.h"
46
47
#define TYPE_CMSDK_APB_DUALTIMER "cmsdk-apb-dualtimer"
48
@@ -XXX,XX +XXX,XX @@ struct CMSDKAPBDualTimer {
49
MemoryRegion iomem;
50
qemu_irq timerintc;
51
uint32_t pclk_frq;
52
+ Clock *timclk;
53
54
CMSDKAPBDualTimerModule timermod[CMSDK_APB_DUALTIMER_NUM_MODULES];
55
uint32_t timeritcr;
56
diff --git a/hw/timer/cmsdk-apb-dualtimer.c b/hw/timer/cmsdk-apb-dualtimer.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/hw/timer/cmsdk-apb-dualtimer.c
59
+++ b/hw/timer/cmsdk-apb-dualtimer.c
60
@@ -XXX,XX +XXX,XX @@
61
#include "hw/irq.h"
62
#include "hw/qdev-properties.h"
63
#include "hw/registerfields.h"
64
+#include "hw/qdev-clock.h"
65
#include "hw/timer/cmsdk-apb-dualtimer.h"
66
#include "migration/vmstate.h"
67
68
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_dualtimer_init(Object *obj)
69
for (i = 0; i < ARRAY_SIZE(s->timermod); i++) {
70
sysbus_init_irq(sbd, &s->timermod[i].timerint);
71
}
72
+ s->timclk = qdev_init_clock_in(DEVICE(s), "TIMCLK", NULL, NULL);
73
}
74
75
static void cmsdk_apb_dualtimer_realize(DeviceState *dev, Error **errp)
76
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription cmsdk_dualtimermod_vmstate = {
77
78
static const VMStateDescription cmsdk_apb_dualtimer_vmstate = {
79
.name = "cmsdk-apb-dualtimer",
80
- .version_id = 1,
81
- .minimum_version_id = 1,
82
+ .version_id = 2,
83
+ .minimum_version_id = 2,
84
.fields = (VMStateField[]) {
85
+ VMSTATE_CLOCK(timclk, CMSDKAPBDualTimer),
86
VMSTATE_STRUCT_ARRAY(timermod, CMSDKAPBDualTimer,
87
CMSDK_APB_DUALTIMER_NUM_MODULES,
88
1, cmsdk_dualtimermod_vmstate,
26
--
89
--
27
2.19.0
90
2.20.1
28
91
29
92
diff view generated by jsdifflib
1
Add v8M stack checks for the 16-bit Thumb push/pop
1
As the first step in converting the CMSDK_APB_TIMER device to the
2
encodings: STMDB, STMFD, LDM, LDMIA, LDMFD.
2
Clock framework, add a Clock input. For the moment we do nothing
3
with this clock; we will change the behaviour from using the
4
wdogclk-frq property to using the Clock once all the users of this
5
device have been converted to wire up the Clock.
6
7
This is a migration compatibility break for machines mps2-an385,
8
mps2-an386, mps2-an500, mps2-an511, mps2-an505, mps2-an521, musca-a,
9
musca-b1, lm3s811evb, lm3s6965evb.
3
10
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Reviewed-by: Luc Michel <luc@lmichel.fr>
7
Message-id: 20181002163556.10279-12-peter.maydell@linaro.org
14
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Message-id: 20210128114145.20536-10-peter.maydell@linaro.org
16
Message-id: 20210121190622.22000-10-peter.maydell@linaro.org
8
---
17
---
9
target/arm/translate.c | 16 +++++++++++++++-
18
include/hw/watchdog/cmsdk-apb-watchdog.h | 3 +++
10
1 file changed, 15 insertions(+), 1 deletion(-)
19
hw/watchdog/cmsdk-apb-watchdog.c | 7 +++++--
20
2 files changed, 8 insertions(+), 2 deletions(-)
11
21
12
diff --git a/target/arm/translate.c b/target/arm/translate.c
22
diff --git a/include/hw/watchdog/cmsdk-apb-watchdog.h b/include/hw/watchdog/cmsdk-apb-watchdog.h
13
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/translate.c
24
--- a/include/hw/watchdog/cmsdk-apb-watchdog.h
15
+++ b/target/arm/translate.c
25
+++ b/include/hw/watchdog/cmsdk-apb-watchdog.h
16
@@ -XXX,XX +XXX,XX @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
26
@@ -XXX,XX +XXX,XX @@
17
store_reg(s, rd, tmp);
27
*
18
break;
28
* QEMU interface:
19
case 4: case 5: case 0xc: case 0xd:
29
* + QOM property "wdogclk-frq": frequency at which the watchdog is clocked
20
- /* push/pop */
30
+ * + Clock input "WDOGCLK": clock for the watchdog's timer
21
+ /*
31
* + sysbus MMIO region 0: the register bank
22
+ * 0b1011_x10x_xxxx_xxxx
32
* + sysbus IRQ 0: watchdog interrupt
23
+ * - push/pop
33
*
24
+ */
34
@@ -XXX,XX +XXX,XX @@
25
addr = load_reg(s, 13);
35
26
if (insn & (1 << 8))
36
#include "hw/sysbus.h"
27
offset = 4;
37
#include "hw/ptimer.h"
28
@@ -XXX,XX +XXX,XX @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
38
+#include "hw/clock.h"
29
if ((insn & (1 << 11)) == 0) {
39
#include "qom/object.h"
30
tcg_gen_addi_i32(addr, addr, -offset);
40
31
}
41
#define TYPE_CMSDK_APB_WATCHDOG "cmsdk-apb-watchdog"
32
+
42
@@ -XXX,XX +XXX,XX @@ struct CMSDKAPBWatchdog {
33
+ if (s->v8m_stackcheck) {
43
uint32_t wdogclk_frq;
34
+ /*
44
bool is_luminary;
35
+ * Here 'addr' is the lower of "old SP" and "new SP";
45
struct ptimer_state *timer;
36
+ * if this is a pop that starts below the limit and ends
46
+ Clock *wdogclk;
37
+ * above it, it is UNKNOWN whether the limit check triggers;
47
38
+ * we choose to trigger.
48
uint32_t control;
39
+ */
49
uint32_t intstatus;
40
+ gen_helper_v8m_stackcheck(cpu_env, addr);
50
diff --git a/hw/watchdog/cmsdk-apb-watchdog.c b/hw/watchdog/cmsdk-apb-watchdog.c
41
+ }
51
index XXXXXXX..XXXXXXX 100644
42
+
52
--- a/hw/watchdog/cmsdk-apb-watchdog.c
43
for (i = 0; i < 8; i++) {
53
+++ b/hw/watchdog/cmsdk-apb-watchdog.c
44
if (insn & (1 << i)) {
54
@@ -XXX,XX +XXX,XX @@
45
if (insn & (1 << 11)) {
55
#include "hw/irq.h"
56
#include "hw/qdev-properties.h"
57
#include "hw/registerfields.h"
58
+#include "hw/qdev-clock.h"
59
#include "hw/watchdog/cmsdk-apb-watchdog.h"
60
#include "migration/vmstate.h"
61
62
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_watchdog_init(Object *obj)
63
s, "cmsdk-apb-watchdog", 0x1000);
64
sysbus_init_mmio(sbd, &s->iomem);
65
sysbus_init_irq(sbd, &s->wdogint);
66
+ s->wdogclk = qdev_init_clock_in(DEVICE(s), "WDOGCLK", NULL, NULL);
67
68
s->is_luminary = false;
69
s->id = cmsdk_apb_watchdog_id;
70
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_watchdog_realize(DeviceState *dev, Error **errp)
71
72
static const VMStateDescription cmsdk_apb_watchdog_vmstate = {
73
.name = "cmsdk-apb-watchdog",
74
- .version_id = 1,
75
- .minimum_version_id = 1,
76
+ .version_id = 2,
77
+ .minimum_version_id = 2,
78
.fields = (VMStateField[]) {
79
+ VMSTATE_CLOCK(wdogclk, CMSDKAPBWatchdog),
80
VMSTATE_PTIMER(timer, CMSDKAPBWatchdog),
81
VMSTATE_UINT32(control, CMSDKAPBWatchdog),
82
VMSTATE_UINT32(intstatus, CMSDKAPBWatchdog),
46
--
83
--
47
2.19.0
84
2.20.1
48
85
49
86
diff view generated by jsdifflib
1
Add v8M stack checks for the instructions in the T32
1
While we transition the ARMSSE code from integer properties
2
"load/store single" encoding class: these are the
2
specifying clock frequencies to Clock objects, we want to have the
3
"immediate pre-indexed" and "immediate, post-indexed"
3
device provide both at once. We want the final name of the main
4
LDR and STR instructions.
4
input Clock to be "MAINCLK", following the hardware name.
5
Unfortunately creating an input Clock with a name X creates an
6
under-the-hood QOM property X; for "MAINCLK" this clashes with the
7
existing UINT32 property of that name.
8
9
Rename the UINT32 property to MAINCLK_FRQ so it can coexist with the
10
MAINCLK Clock; once the transition is complete MAINCLK_FRQ will be
11
deleted.
12
13
Commit created with:
14
perl -p -i -e 's/MAINCLK/MAINCLK_FRQ/g' hw/arm/{armsse,mps2-tz,musca}.c include/hw/arm/armsse.h
5
15
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
17
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Reviewed-by: Luc Michel <luc@lmichel.fr>
9
Message-id: 20181002163556.10279-11-peter.maydell@linaro.org
19
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
20
Message-id: 20210128114145.20536-11-peter.maydell@linaro.org
21
Message-id: 20210121190622.22000-11-peter.maydell@linaro.org
10
---
22
---
11
target/arm/translate.c | 23 ++++++++++++++++++++++-
23
include/hw/arm/armsse.h | 2 +-
12
1 file changed, 22 insertions(+), 1 deletion(-)
24
hw/arm/armsse.c | 6 +++---
25
hw/arm/mps2-tz.c | 2 +-
26
hw/arm/musca.c | 2 +-
27
4 files changed, 6 insertions(+), 6 deletions(-)
13
28
14
diff --git a/target/arm/translate.c b/target/arm/translate.c
29
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
15
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/translate.c
31
--- a/include/hw/arm/armsse.h
17
+++ b/target/arm/translate.c
32
+++ b/include/hw/arm/armsse.h
18
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
33
@@ -XXX,XX +XXX,XX @@
19
imm = -imm;
34
* QEMU interface:
20
/* Fall through. */
35
* + QOM property "memory" is a MemoryRegion containing the devices provided
21
case 0xf: /* Pre-increment. */
36
* by the board model.
22
- tcg_gen_addi_i32(addr, addr, imm);
37
- * + QOM property "MAINCLK" is the frequency of the main system clock
23
writeback = 1;
38
+ * + QOM property "MAINCLK_FRQ" is the frequency of the main system clock
24
break;
39
* + QOM property "EXP_NUMIRQ" sets the number of expansion interrupts.
25
default:
40
* (In hardware, the SSE-200 permits the number of expansion interrupts
26
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
41
* for the two CPUs to be configured separately, but we restrict it to
27
42
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
28
issinfo = writeback ? ISSInvalid : rs;
43
index XXXXXXX..XXXXXXX 100644
29
44
--- a/hw/arm/armsse.c
30
+ if (s->v8m_stackcheck && rn == 13 && writeback) {
45
+++ b/hw/arm/armsse.c
31
+ /*
46
@@ -XXX,XX +XXX,XX @@ static Property iotkit_properties[] = {
32
+ * Stackcheck. Here we know 'addr' is the current SP;
47
DEFINE_PROP_LINK("memory", ARMSSE, board_memory, TYPE_MEMORY_REGION,
33
+ * if imm is +ve we're moving SP up, else down. It is
48
MemoryRegion *),
34
+ * UNKNOWN whether the limit check triggers when SP starts
49
DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
35
+ * below the limit and ends up above it; we chose to do so.
50
- DEFINE_PROP_UINT32("MAINCLK", ARMSSE, mainclk_frq, 0),
36
+ */
51
+ DEFINE_PROP_UINT32("MAINCLK_FRQ", ARMSSE, mainclk_frq, 0),
37
+ if ((int32_t)imm < 0) {
52
DEFINE_PROP_UINT32("SRAM_ADDR_WIDTH", ARMSSE, sram_addr_width, 15),
38
+ TCGv_i32 newsp = tcg_temp_new_i32();
53
DEFINE_PROP_UINT32("init-svtor", ARMSSE, init_svtor, 0x10000000),
39
+
54
DEFINE_PROP_BOOL("CPU0_FPU", ARMSSE, cpu_fpu[0], true),
40
+ tcg_gen_addi_i32(newsp, addr, imm);
55
@@ -XXX,XX +XXX,XX @@ static Property armsse_properties[] = {
41
+ gen_helper_v8m_stackcheck(cpu_env, newsp);
56
DEFINE_PROP_LINK("memory", ARMSSE, board_memory, TYPE_MEMORY_REGION,
42
+ tcg_temp_free_i32(newsp);
57
MemoryRegion *),
43
+ } else {
58
DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
44
+ gen_helper_v8m_stackcheck(cpu_env, addr);
59
- DEFINE_PROP_UINT32("MAINCLK", ARMSSE, mainclk_frq, 0),
45
+ }
60
+ DEFINE_PROP_UINT32("MAINCLK_FRQ", ARMSSE, mainclk_frq, 0),
46
+ }
61
DEFINE_PROP_UINT32("SRAM_ADDR_WIDTH", ARMSSE, sram_addr_width, 15),
47
+
62
DEFINE_PROP_UINT32("init-svtor", ARMSSE, init_svtor, 0x10000000),
48
+ if (writeback && !postinc) {
63
DEFINE_PROP_BOOL("CPU0_FPU", ARMSSE, cpu_fpu[0], false),
49
+ tcg_gen_addi_i32(addr, addr, imm);
64
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
50
+ }
65
}
51
+
66
52
if (insn & (1 << 20)) {
67
if (!s->mainclk_frq) {
53
/* Load. */
68
- error_setg(errp, "MAINCLK property was not set");
54
tmp = tcg_temp_new_i32();
69
+ error_setg(errp, "MAINCLK_FRQ property was not set");
70
return;
71
}
72
73
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
74
index XXXXXXX..XXXXXXX 100644
75
--- a/hw/arm/mps2-tz.c
76
+++ b/hw/arm/mps2-tz.c
77
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
78
object_property_set_link(OBJECT(&mms->iotkit), "memory",
79
OBJECT(system_memory), &error_abort);
80
qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", MPS2TZ_NUMIRQ);
81
- qdev_prop_set_uint32(iotkitdev, "MAINCLK", SYSCLK_FRQ);
82
+ qdev_prop_set_uint32(iotkitdev, "MAINCLK_FRQ", SYSCLK_FRQ);
83
sysbus_realize(SYS_BUS_DEVICE(&mms->iotkit), &error_fatal);
84
85
/*
86
diff --git a/hw/arm/musca.c b/hw/arm/musca.c
87
index XXXXXXX..XXXXXXX 100644
88
--- a/hw/arm/musca.c
89
+++ b/hw/arm/musca.c
90
@@ -XXX,XX +XXX,XX @@ static void musca_init(MachineState *machine)
91
qdev_prop_set_uint32(ssedev, "EXP_NUMIRQ", mmc->num_irqs);
92
qdev_prop_set_uint32(ssedev, "init-svtor", mmc->init_svtor);
93
qdev_prop_set_uint32(ssedev, "SRAM_ADDR_WIDTH", mmc->sram_addr_width);
94
- qdev_prop_set_uint32(ssedev, "MAINCLK", SYSCLK_FRQ);
95
+ qdev_prop_set_uint32(ssedev, "MAINCLK_FRQ", SYSCLK_FRQ);
96
/*
97
* Musca-A takes the default SSE-200 FPU/DSP settings (ie no for
98
* CPU0 and yes for CPU1); Musca-B1 explicitly enables them for CPU0.
55
--
99
--
56
2.19.0
100
2.20.1
57
101
58
102
diff view generated by jsdifflib
1
Add the v8M stack checks for:
1
Create two input clocks on the ARMSSE devices, one for the normal
2
* LDM (T2 encoding)
2
MAINCLK, and one for the 32KHz S32KCLK, and wire these up to the
3
* STM (T2 encoding)
3
appropriate devices. The old property-based clock frequency setting
4
will remain in place until conversion is complete.
4
5
5
This includes the 32-bit encodings of the instructions listed
6
This is a migration compatibility break for machines mps2-an505,
6
in v8M ARM ARM rule R_YVWT as
7
mps2-an521, musca-a, musca-b1.
7
* LDM, LDMIA, LDMFD
8
* LDMDB, LDMEA
9
* POP (multiple registers)
10
* PUSH (muliple registers)
11
* STM, STMIA, STMEA
12
* STMDB, STMFD
13
14
We perform the stack limit before doing any other part
15
of the load or store.
16
8
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Luc Michel <luc@lmichel.fr>
20
Message-id: 20181002163556.10279-10-peter.maydell@linaro.org
12
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Message-id: 20210128114145.20536-12-peter.maydell@linaro.org
14
Message-id: 20210121190622.22000-12-peter.maydell@linaro.org
21
---
15
---
22
target/arm/translate.c | 19 ++++++++++++++++++-
16
include/hw/arm/armsse.h | 6 ++++++
23
1 file changed, 18 insertions(+), 1 deletion(-)
17
hw/arm/armsse.c | 17 +++++++++++++++--
18
2 files changed, 21 insertions(+), 2 deletions(-)
24
19
25
diff --git a/target/arm/translate.c b/target/arm/translate.c
20
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
26
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
27
--- a/target/arm/translate.c
22
--- a/include/hw/arm/armsse.h
28
+++ b/target/arm/translate.c
23
+++ b/include/hw/arm/armsse.h
29
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
24
@@ -XXX,XX +XXX,XX @@
30
} else {
25
* per-CPU identity and control register blocks
31
int i, loaded_base = 0;
26
*
32
TCGv_i32 loaded_var;
27
* QEMU interface:
33
+ bool wback = extract32(insn, 21, 1);
28
+ * + Clock input "MAINCLK": clock for CPUs and most peripherals
34
/* Load/store multiple. */
29
+ * + Clock input "S32KCLK": slow 32KHz clock used for a few peripherals
35
addr = load_reg(s, rn);
30
* + QOM property "memory" is a MemoryRegion containing the devices provided
36
offset = 0;
31
* by the board model.
37
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
32
* + QOM property "MAINCLK_FRQ" is the frequency of the main system clock
38
if (insn & (1 << i))
33
@@ -XXX,XX +XXX,XX @@
39
offset += 4;
34
#include "hw/misc/armsse-mhu.h"
40
}
35
#include "hw/misc/unimp.h"
36
#include "hw/or-irq.h"
37
+#include "hw/clock.h"
38
#include "hw/core/split-irq.h"
39
#include "hw/cpu/cluster.h"
40
#include "qom/object.h"
41
@@ -XXX,XX +XXX,XX @@ struct ARMSSE {
42
43
uint32_t nsccfg;
44
45
+ Clock *mainclk;
46
+ Clock *s32kclk;
41
+
47
+
42
if (insn & (1 << 24)) {
48
/* Properties */
43
tcg_gen_addi_i32(addr, addr, -offset);
49
MemoryRegion *board_memory;
44
}
50
uint32_t exp_numirq;
45
51
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
46
+ if (s->v8m_stackcheck && rn == 13 && wback) {
52
index XXXXXXX..XXXXXXX 100644
47
+ /*
53
--- a/hw/arm/armsse.c
48
+ * If the writeback is incrementing SP rather than
54
+++ b/hw/arm/armsse.c
49
+ * decrementing it, and the initial SP is below the
55
@@ -XXX,XX +XXX,XX @@
50
+ * stack limit but the final written-back SP would
56
#include "hw/arm/armsse.h"
51
+ * be above, then then we must not perform any memory
57
#include "hw/arm/boot.h"
52
+ * accesses, but it is IMPDEF whether we generate
58
#include "hw/irq.h"
53
+ * an exception. We choose to do so in this case.
59
+#include "hw/qdev-clock.h"
54
+ * At this point 'addr' is the lowest address, so
60
55
+ * either the original SP (if incrementing) or our
61
/* Format of the System Information block SYS_CONFIG register */
56
+ * final SP (if decrementing), so that's what we check.
62
typedef enum SysConfigFormat {
57
+ */
63
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
58
+ gen_helper_v8m_stackcheck(cpu_env, addr);
64
assert(info->sram_banks <= MAX_SRAM_BANKS);
59
+ }
65
assert(info->num_cpus <= SSE_MAX_CPUS);
66
67
+ s->mainclk = qdev_init_clock_in(DEVICE(s), "MAINCLK", NULL, NULL);
68
+ s->s32kclk = qdev_init_clock_in(DEVICE(s), "S32KCLK", NULL, NULL);
60
+
69
+
61
loaded_var = NULL;
70
memory_region_init(&s->container, obj, "armsse-container", UINT64_MAX);
62
for (i = 0; i < 16; i++) {
71
63
if ((insn & (1 << i)) == 0)
72
for (i = 0; i < info->num_cpus; i++) {
64
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
73
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
65
if (loaded_base) {
74
* map its upstream ends to the right place in the container.
66
store_reg(s, rn, loaded_var);
75
*/
67
}
76
qdev_prop_set_uint32(DEVICE(&s->timer0), "pclk-frq", s->mainclk_frq);
68
- if (insn & (1 << 21)) {
77
+ qdev_connect_clock_in(DEVICE(&s->timer0), "pclk", s->mainclk);
69
+ if (wback) {
78
if (!sysbus_realize(SYS_BUS_DEVICE(&s->timer0), errp)) {
70
/* Base register writeback. */
79
return;
71
if (insn & (1 << 24)) {
80
}
72
tcg_gen_addi_i32(addr, addr, -offset);
81
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
82
&error_abort);
83
84
qdev_prop_set_uint32(DEVICE(&s->timer1), "pclk-frq", s->mainclk_frq);
85
+ qdev_connect_clock_in(DEVICE(&s->timer1), "pclk", s->mainclk);
86
if (!sysbus_realize(SYS_BUS_DEVICE(&s->timer1), errp)) {
87
return;
88
}
89
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
90
&error_abort);
91
92
qdev_prop_set_uint32(DEVICE(&s->dualtimer), "pclk-frq", s->mainclk_frq);
93
+ qdev_connect_clock_in(DEVICE(&s->dualtimer), "TIMCLK", s->mainclk);
94
if (!sysbus_realize(SYS_BUS_DEVICE(&s->dualtimer), errp)) {
95
return;
96
}
97
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
98
* 0x4002f000: S32K timer
99
*/
100
qdev_prop_set_uint32(DEVICE(&s->s32ktimer), "pclk-frq", S32KCLK);
101
+ qdev_connect_clock_in(DEVICE(&s->s32ktimer), "pclk", s->s32kclk);
102
if (!sysbus_realize(SYS_BUS_DEVICE(&s->s32ktimer), errp)) {
103
return;
104
}
105
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
106
qdev_get_gpio_in_named(DEVICE(&s->armv7m), "NMI", 0));
107
108
qdev_prop_set_uint32(DEVICE(&s->s32kwatchdog), "wdogclk-frq", S32KCLK);
109
+ qdev_connect_clock_in(DEVICE(&s->s32kwatchdog), "WDOGCLK", s->s32kclk);
110
if (!sysbus_realize(SYS_BUS_DEVICE(&s->s32kwatchdog), errp)) {
111
return;
112
}
113
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
114
/* 0x40080000 .. 0x4008ffff : ARMSSE second Base peripheral region */
115
116
qdev_prop_set_uint32(DEVICE(&s->nswatchdog), "wdogclk-frq", s->mainclk_frq);
117
+ qdev_connect_clock_in(DEVICE(&s->nswatchdog), "WDOGCLK", s->mainclk);
118
if (!sysbus_realize(SYS_BUS_DEVICE(&s->nswatchdog), errp)) {
119
return;
120
}
121
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
122
sysbus_mmio_map(SYS_BUS_DEVICE(&s->nswatchdog), 0, 0x40081000);
123
124
qdev_prop_set_uint32(DEVICE(&s->swatchdog), "wdogclk-frq", s->mainclk_frq);
125
+ qdev_connect_clock_in(DEVICE(&s->swatchdog), "WDOGCLK", s->mainclk);
126
if (!sysbus_realize(SYS_BUS_DEVICE(&s->swatchdog), errp)) {
127
return;
128
}
129
@@ -XXX,XX +XXX,XX @@ static void armsse_idau_check(IDAUInterface *ii, uint32_t address,
130
131
static const VMStateDescription armsse_vmstate = {
132
.name = "iotkit",
133
- .version_id = 1,
134
- .minimum_version_id = 1,
135
+ .version_id = 2,
136
+ .minimum_version_id = 2,
137
.fields = (VMStateField[]) {
138
+ VMSTATE_CLOCK(mainclk, ARMSSE),
139
+ VMSTATE_CLOCK(s32kclk, ARMSSE),
140
VMSTATE_UINT32(nsccfg, ARMSSE),
141
VMSTATE_END_OF_LIST()
142
}
73
--
143
--
74
2.19.0
144
2.20.1
75
145
76
146
diff view generated by jsdifflib
1
Add checks for breaches of the v8M stack limit when the
1
The old-style convenience function cmsdk_apb_timer_create() for
2
stack pointer is decremented to push the exception frame
2
creating CMSDK_APB_TIMER objects is used in only two places in
3
for exception entry.
3
mps2.c. Most of the rest of the code in that file uses the new
4
"initialize in place" coding style.
4
5
5
Note that the exception-entry case is unique in that the
6
We want to connect up a Clock object which should be done between the
6
stack pointer is updated to be the limit value if the limit
7
object creation and realization; rather than adding a Clock* argument
7
is hit (per rule R_ZLZG).
8
to the convenience function, convert the timer creation code in
9
mps2.c to the same style as is used already for the watchdog,
10
dualtimer and other devices, and delete the now-unused convenience
11
function.
8
12
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Reviewed-by: Luc Michel <luc@lmichel.fr>
12
Message-id: 20181002163556.10279-7-peter.maydell@linaro.org
16
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Message-id: 20210128114145.20536-13-peter.maydell@linaro.org
18
Message-id: 20210121190622.22000-13-peter.maydell@linaro.org
13
---
19
---
14
target/arm/helper.c | 54 ++++++++++++++++++++++++++++++++++++++-------
20
include/hw/timer/cmsdk-apb-timer.h | 21 ---------------------
15
1 file changed, 46 insertions(+), 8 deletions(-)
21
hw/arm/mps2.c | 18 ++++++++++++++++--
22
2 files changed, 16 insertions(+), 23 deletions(-)
16
23
17
diff --git a/target/arm/helper.c b/target/arm/helper.c
24
diff --git a/include/hw/timer/cmsdk-apb-timer.h b/include/hw/timer/cmsdk-apb-timer.h
18
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper.c
26
--- a/include/hw/timer/cmsdk-apb-timer.h
20
+++ b/target/arm/helper.c
27
+++ b/include/hw/timer/cmsdk-apb-timer.h
21
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain,
28
@@ -XXX,XX +XXX,XX @@ struct CMSDKAPBTimer {
22
uint32_t frameptr;
29
uint32_t intstatus;
23
ARMMMUIdx mmu_idx;
30
};
24
bool stacked_ok;
31
25
+ uint32_t limit;
32
-/**
26
+ bool want_psp;
33
- * cmsdk_apb_timer_create - convenience function to create TYPE_CMSDK_APB_TIMER
27
34
- * @addr: location in system memory to map registers
28
if (dotailchain) {
35
- * @pclk_frq: frequency in Hz of the PCLK clock (used for calculating baud rate)
29
bool mode = lr & R_V7M_EXCRET_MODE_MASK;
36
- */
30
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain,
37
-static inline DeviceState *cmsdk_apb_timer_create(hwaddr addr,
31
mmu_idx = arm_v7m_mmu_idx_for_secstate_and_priv(env, M_REG_S, priv);
38
- qemu_irq timerint,
32
frame_sp_p = get_v7m_sp_ptr(env, M_REG_S, mode,
39
- uint32_t pclk_frq)
33
lr & R_V7M_EXCRET_SPSEL_MASK);
40
-{
34
+ want_psp = mode && (lr & R_V7M_EXCRET_SPSEL_MASK);
41
- DeviceState *dev;
35
+ if (want_psp) {
42
- SysBusDevice *s;
36
+ limit = env->v7m.psplim[M_REG_S];
43
-
37
+ } else {
44
- dev = qdev_new(TYPE_CMSDK_APB_TIMER);
38
+ limit = env->v7m.msplim[M_REG_S];
45
- s = SYS_BUS_DEVICE(dev);
39
+ }
46
- qdev_prop_set_uint32(dev, "pclk-frq", pclk_frq);
40
} else {
47
- sysbus_realize_and_unref(s, &error_fatal);
41
mmu_idx = core_to_arm_mmu_idx(env, cpu_mmu_index(env, false));
48
- sysbus_mmio_map(s, 0, addr);
42
frame_sp_p = &env->regs[13];
49
- sysbus_connect_irq(s, 0, timerint);
43
+ limit = v7m_sp_limit(env);
50
- return dev;
51
-}
52
-
53
#endif
54
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
55
index XXXXXXX..XXXXXXX 100644
56
--- a/hw/arm/mps2.c
57
+++ b/hw/arm/mps2.c
58
@@ -XXX,XX +XXX,XX @@ struct MPS2MachineState {
59
/* CMSDK APB subsystem */
60
CMSDKAPBDualTimer dualtimer;
61
CMSDKAPBWatchdog watchdog;
62
+ CMSDKAPBTimer timer[2];
63
};
64
65
#define TYPE_MPS2_MACHINE "mps2"
66
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
44
}
67
}
45
68
46
frameptr = *frame_sp_p - 0x28;
69
/* CMSDK APB subsystem */
47
+ if (frameptr < limit) {
70
- cmsdk_apb_timer_create(0x40000000, qdev_get_gpio_in(armv7m, 8), SYSCLK_FRQ);
48
+ /*
71
- cmsdk_apb_timer_create(0x40001000, qdev_get_gpio_in(armv7m, 9), SYSCLK_FRQ);
49
+ * Stack limit failure: set SP to the limit value, and generate
72
+ for (i = 0; i < ARRAY_SIZE(mms->timer); i++) {
50
+ * STKOF UsageFault. Stack pushes below the limit must not be
73
+ g_autofree char *name = g_strdup_printf("timer%d", i);
51
+ * performed. It is IMPDEF whether pushes above the limit are
74
+ hwaddr base = 0x40000000 + i * 0x1000;
52
+ * performed; we choose not to.
75
+ int irqno = 8 + i;
53
+ */
76
+ SysBusDevice *sbd;
54
+ qemu_log_mask(CPU_LOG_INT,
55
+ "...STKOF during callee-saves register stacking\n");
56
+ env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_STKOF_MASK;
57
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE,
58
+ env->v7m.secure);
59
+ *frame_sp_p = limit;
60
+ return true;
61
+ }
62
63
/* Write as much of the stack frame as we can. A write failure may
64
* cause us to pend a derived exception.
65
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain,
66
v7m_stack_write(cpu, frameptr + 0x24, env->regs[11], mmu_idx,
67
ignore_faults);
68
69
- /* Update SP regardless of whether any of the stack accesses failed.
70
- * When we implement v8M stack limit checking then this attempt to
71
- * update SP might also fail and result in a derived exception.
72
- */
73
+ /* Update SP regardless of whether any of the stack accesses failed. */
74
*frame_sp_p = frameptr;
75
76
return !stacked_ok;
77
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_stack(ARMCPU *cpu)
78
79
frameptr -= 0x20;
80
81
+ if (arm_feature(env, ARM_FEATURE_V8)) {
82
+ uint32_t limit = v7m_sp_limit(env);
83
+
77
+
84
+ if (frameptr < limit) {
78
+ object_initialize_child(OBJECT(mms), name, &mms->timer[i],
85
+ /*
79
+ TYPE_CMSDK_APB_TIMER);
86
+ * Stack limit failure: set SP to the limit value, and generate
80
+ sbd = SYS_BUS_DEVICE(&mms->timer[i]);
87
+ * STKOF UsageFault. Stack pushes below the limit must not be
81
+ qdev_prop_set_uint32(DEVICE(&mms->timer[i]), "pclk-frq", SYSCLK_FRQ);
88
+ * performed. It is IMPDEF whether pushes above the limit are
82
+ sysbus_realize_and_unref(sbd, &error_fatal);
89
+ * performed; we choose not to.
83
+ sysbus_mmio_map(sbd, 0, base);
90
+ */
84
+ sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(armv7m, irqno));
91
+ qemu_log_mask(CPU_LOG_INT,
92
+ "...STKOF during stacking\n");
93
+ env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_STKOF_MASK;
94
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE,
95
+ env->v7m.secure);
96
+ env->regs[13] = limit;
97
+ return true;
98
+ }
99
+ }
85
+ }
100
+
86
+
101
/* Write as much of the stack frame as we can. If we fail a stack
87
object_initialize_child(OBJECT(mms), "dualtimer", &mms->dualtimer,
102
* write this will result in a derived exception being pended
88
TYPE_CMSDK_APB_DUALTIMER);
103
* (which may be taken in preference to the one we started with
89
qdev_prop_set_uint32(DEVICE(&mms->dualtimer), "pclk-frq", SYSCLK_FRQ);
104
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_stack(ARMCPU *cpu)
105
v7m_stack_write(cpu, frameptr + 24, env->regs[15], mmu_idx, false) &&
106
v7m_stack_write(cpu, frameptr + 28, xpsr, mmu_idx, false);
107
108
- /* Update SP regardless of whether any of the stack accesses failed.
109
- * When we implement v8M stack limit checking then this attempt to
110
- * update SP might also fail and result in a derived exception.
111
- */
112
+ /* Update SP regardless of whether any of the stack accesses failed. */
113
env->regs[13] = frameptr;
114
115
return !stacked_ok;
116
--
90
--
117
2.19.0
91
2.20.1
118
92
119
93
diff view generated by jsdifflib
1
Add the v8M stack checks for:
1
Create a fixed-frequency Clock object to be the SYSCLK, and wire it
2
* LDRD (immediate)
2
up to the devices that require it.
3
* STRD (immediate)
4
5
Loads and stores are more complicated than ADD/SUB/MOV, because we
6
must ensure that memory accesses below the stack limit are not
7
performed, so we can't simply do the check when we actually update
8
SP.
9
10
For these instructions, if the stack limit check triggers
11
we must not:
12
* perform any memory access below the SP limit
13
* update PC, SP or the load/store base register
14
but it is IMPDEF whether we:
15
* perform any accesses above or equal to the SP limit
16
* update destination registers for loads
17
18
For QEMU we choose to always check the limit before doing any other
19
part of the load or store, so we won't update any registers or
20
perform any memory accesses.
21
22
It is UNKNOWN whether the limit check triggers for a load or store
23
where the initial SP value is below the limit and one of the stores
24
would be below the limit, but the writeback moves SP to above the
25
limit. For QEMU we choose to trigger the check in this situation.
26
27
Note that limit checks happen only for loads and stores which update
28
SP via writeback; they do not happen for loads and stores which
29
simply use SP as a base register.
30
3
31
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
32
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
33
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Luc Michel <luc@lmichel.fr>
34
Message-id: 20181002163556.10279-9-peter.maydell@linaro.org
7
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20210128114145.20536-14-peter.maydell@linaro.org
9
Message-id: 20210121190622.22000-14-peter.maydell@linaro.org
35
---
10
---
36
target/arm/translate.c | 27 +++++++++++++++++++++++++--
11
hw/arm/mps2.c | 9 +++++++++
37
1 file changed, 25 insertions(+), 2 deletions(-)
12
1 file changed, 9 insertions(+)
38
13
39
diff --git a/target/arm/translate.c b/target/arm/translate.c
14
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
40
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
41
--- a/target/arm/translate.c
16
--- a/hw/arm/mps2.c
42
+++ b/target/arm/translate.c
17
+++ b/hw/arm/mps2.c
43
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
18
@@ -XXX,XX +XXX,XX @@
44
* 0b1111_1001_x11x_xxxx_xxxx_xxxx_xxxx_xxxx
19
#include "hw/net/lan9118.h"
45
* - load/store dual (pre-indexed)
20
#include "net/net.h"
46
*/
21
#include "hw/watchdog/cmsdk-apb-watchdog.h"
47
+ bool wback = extract32(insn, 21, 1);
22
+#include "hw/qdev-clock.h"
23
#include "qom/object.h"
24
25
typedef enum MPS2FPGAType {
26
@@ -XXX,XX +XXX,XX @@ struct MPS2MachineState {
27
CMSDKAPBDualTimer dualtimer;
28
CMSDKAPBWatchdog watchdog;
29
CMSDKAPBTimer timer[2];
30
+ Clock *sysclk;
31
};
32
33
#define TYPE_MPS2_MACHINE "mps2"
34
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
35
exit(EXIT_FAILURE);
36
}
37
38
+ /* This clock doesn't need migration because it is fixed-frequency */
39
+ mms->sysclk = clock_new(OBJECT(machine), "SYSCLK");
40
+ clock_set_hz(mms->sysclk, SYSCLK_FRQ);
48
+
41
+
49
if (rn == 15) {
42
/* The FPGA images have an odd combination of different RAMs,
50
if (insn & (1 << 21)) {
43
* because in hardware they are different implementations and
51
/* UNPREDICTABLE */
44
* connected to different buses, giving varying performance/size
52
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
45
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
53
addr = load_reg(s, rn);
46
TYPE_CMSDK_APB_TIMER);
54
}
47
sbd = SYS_BUS_DEVICE(&mms->timer[i]);
55
offset = (insn & 0xff) * 4;
48
qdev_prop_set_uint32(DEVICE(&mms->timer[i]), "pclk-frq", SYSCLK_FRQ);
56
- if ((insn & (1 << 23)) == 0)
49
+ qdev_connect_clock_in(DEVICE(&mms->timer[i]), "pclk", mms->sysclk);
57
+ if ((insn & (1 << 23)) == 0) {
50
sysbus_realize_and_unref(sbd, &error_fatal);
58
offset = -offset;
51
sysbus_mmio_map(sbd, 0, base);
59
+ }
52
sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(armv7m, irqno));
60
+
53
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
61
+ if (s->v8m_stackcheck && rn == 13 && wback) {
54
object_initialize_child(OBJECT(mms), "dualtimer", &mms->dualtimer,
62
+ /*
55
TYPE_CMSDK_APB_DUALTIMER);
63
+ * Here 'addr' is the current SP; if offset is +ve we're
56
qdev_prop_set_uint32(DEVICE(&mms->dualtimer), "pclk-frq", SYSCLK_FRQ);
64
+ * moving SP up, else down. It is UNKNOWN whether the limit
57
+ qdev_connect_clock_in(DEVICE(&mms->dualtimer), "TIMCLK", mms->sysclk);
65
+ * check triggers when SP starts below the limit and ends
58
sysbus_realize(SYS_BUS_DEVICE(&mms->dualtimer), &error_fatal);
66
+ * up above it; check whichever of the current and final
59
sysbus_connect_irq(SYS_BUS_DEVICE(&mms->dualtimer), 0,
67
+ * SP is lower, so QEMU will trigger in that situation.
60
qdev_get_gpio_in(armv7m, 10));
68
+ */
61
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
69
+ if ((int32_t)offset < 0) {
62
object_initialize_child(OBJECT(mms), "watchdog", &mms->watchdog,
70
+ TCGv_i32 newsp = tcg_temp_new_i32();
63
TYPE_CMSDK_APB_WATCHDOG);
71
+
64
qdev_prop_set_uint32(DEVICE(&mms->watchdog), "wdogclk-frq", SYSCLK_FRQ);
72
+ tcg_gen_addi_i32(newsp, addr, offset);
65
+ qdev_connect_clock_in(DEVICE(&mms->watchdog), "WDOGCLK", mms->sysclk);
73
+ gen_helper_v8m_stackcheck(cpu_env, newsp);
66
sysbus_realize(SYS_BUS_DEVICE(&mms->watchdog), &error_fatal);
74
+ tcg_temp_free_i32(newsp);
67
sysbus_connect_irq(SYS_BUS_DEVICE(&mms->watchdog), 0,
75
+ } else {
68
qdev_get_gpio_in_named(armv7m, "NMI", 0));
76
+ gen_helper_v8m_stackcheck(cpu_env, addr);
77
+ }
78
+ }
79
+
80
if (insn & (1 << 24)) {
81
tcg_gen_addi_i32(addr, addr, offset);
82
offset = 0;
83
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
84
gen_aa32_st32(s, tmp, addr, get_mem_index(s));
85
tcg_temp_free_i32(tmp);
86
}
87
- if (insn & (1 << 21)) {
88
+ if (wback) {
89
/* Base writeback. */
90
tcg_gen_addi_i32(addr, addr, offset - 4);
91
store_reg(s, rn, addr);
92
--
69
--
93
2.19.0
70
2.20.1
94
71
95
72
diff view generated by jsdifflib
1
Coverity complains (CID 1395628) that the multiply in the calculation
1
Create and connect the two clocks needed by the ARMSSE.
2
of the framebuffer base is performed as 32x32 but then used in a
3
context that takes a 64-bit hwaddr. This can't actually ever
4
overflow the 32-bit result, because of the constraints placed on
5
the s->config values in bcm2835_fb_validate_config(). But we
6
can placate Coverity anyway, by explicitly casting one of the
7
inputs to a hwaddr, so the whole expression is calculated with
8
64-bit arithmetic.
9
2
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Message-id: 20181005133012.26490-1-peter.maydell@linaro.org
5
Reviewed-by: Luc Michel <luc@lmichel.fr>
6
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20210128114145.20536-15-peter.maydell@linaro.org
8
Message-id: 20210121190622.22000-15-peter.maydell@linaro.org
13
---
9
---
14
hw/display/bcm2835_fb.c | 2 +-
10
hw/arm/mps2-tz.c | 13 +++++++++++++
15
1 file changed, 1 insertion(+), 1 deletion(-)
11
1 file changed, 13 insertions(+)
16
12
17
diff --git a/hw/display/bcm2835_fb.c b/hw/display/bcm2835_fb.c
13
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
18
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/display/bcm2835_fb.c
15
--- a/hw/arm/mps2-tz.c
20
+++ b/hw/display/bcm2835_fb.c
16
+++ b/hw/arm/mps2-tz.c
21
@@ -XXX,XX +XXX,XX @@ static void fb_update_display(void *opaque)
17
@@ -XXX,XX +XXX,XX @@
18
#include "hw/net/lan9118.h"
19
#include "net/net.h"
20
#include "hw/core/split-irq.h"
21
+#include "hw/qdev-clock.h"
22
#include "qom/object.h"
23
24
#define MPS2TZ_NUMIRQ 92
25
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
26
qemu_or_irq uart_irq_orgate;
27
DeviceState *lan9118;
28
SplitIRQ cpu_irq_splitter[MPS2TZ_NUMIRQ];
29
+ Clock *sysclk;
30
+ Clock *s32kclk;
31
};
32
33
#define TYPE_MPS2TZ_MACHINE "mps2tz"
34
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_TYPE(MPS2TZMachineState, MPS2TZMachineClass, MPS2TZ_MACHINE)
35
36
/* Main SYSCLK frequency in Hz */
37
#define SYSCLK_FRQ 20000000
38
+/* Slow 32Khz S32KCLK frequency in Hz */
39
+#define S32KCLK_FRQ (32 * 1000)
40
41
/* Create an alias of an entire original MemoryRegion @orig
42
* located at @base in the memory map.
43
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
44
exit(EXIT_FAILURE);
22
}
45
}
23
46
24
if (s->invalidate) {
47
+ /* These clocks don't need migration because they are fixed-frequency */
25
- hwaddr base = s->config.base + xoff + yoff * src_width;
48
+ mms->sysclk = clock_new(OBJECT(machine), "SYSCLK");
26
+ hwaddr base = s->config.base + xoff + (hwaddr)yoff * src_width;
49
+ clock_set_hz(mms->sysclk, SYSCLK_FRQ);
27
framebuffer_update_memory_section(&s->fbsection, s->dma_mr,
50
+ mms->s32kclk = clock_new(OBJECT(machine), "S32KCLK");
28
base,
51
+ clock_set_hz(mms->s32kclk, S32KCLK_FRQ);
29
s->config.yres, src_width);
52
+
53
object_initialize_child(OBJECT(machine), TYPE_IOTKIT, &mms->iotkit,
54
mmc->armsse_type);
55
iotkitdev = DEVICE(&mms->iotkit);
56
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
57
OBJECT(system_memory), &error_abort);
58
qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", MPS2TZ_NUMIRQ);
59
qdev_prop_set_uint32(iotkitdev, "MAINCLK_FRQ", SYSCLK_FRQ);
60
+ qdev_connect_clock_in(iotkitdev, "MAINCLK", mms->sysclk);
61
+ qdev_connect_clock_in(iotkitdev, "S32KCLK", mms->s32kclk);
62
sysbus_realize(SYS_BUS_DEVICE(&mms->iotkit), &error_fatal);
63
64
/*
30
--
65
--
31
2.19.0
66
2.20.1
32
67
33
68
diff view generated by jsdifflib
1
Add the v8M stack checks for the VLDM/VSTM
1
Create and connect the two clocks needed by the ARMSSE.
2
(aka VPUSH/VPOP) instructions. This code is currently
3
unreachable because we haven't yet implemented M profile
4
floating point support, but since the change is simple,
5
we add it now because otherwise we're likely to forget to
6
do it later.
7
2
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Luc Michel <luc@lmichel.fr>
11
Message-id: 20181002163556.10279-13-peter.maydell@linaro.org
6
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20210128114145.20536-16-peter.maydell@linaro.org
8
Message-id: 20210121190622.22000-16-peter.maydell@linaro.org
12
---
9
---
13
target/arm/translate.c | 12 ++++++++++++
10
hw/arm/musca.c | 12 ++++++++++++
14
1 file changed, 12 insertions(+)
11
1 file changed, 12 insertions(+)
15
12
16
diff --git a/target/arm/translate.c b/target/arm/translate.c
13
diff --git a/hw/arm/musca.c b/hw/arm/musca.c
17
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/translate.c
15
--- a/hw/arm/musca.c
19
+++ b/target/arm/translate.c
16
+++ b/hw/arm/musca.c
20
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
17
@@ -XXX,XX +XXX,XX @@
21
if (insn & (1 << 24)) /* pre-decrement */
18
#include "hw/misc/tz-ppc.h"
22
tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2));
19
#include "hw/misc/unimp.h"
23
20
#include "hw/rtc/pl031.h"
24
+ if (s->v8m_stackcheck && rn == 13 && w) {
21
+#include "hw/qdev-clock.h"
25
+ /*
22
#include "qom/object.h"
26
+ * Here 'addr' is the lowest address we will store to,
23
27
+ * and is either the old SP (if post-increment) or
24
#define MUSCA_NUMIRQ_MAX 96
28
+ * the new SP (if pre-decrement). For post-increment
25
@@ -XXX,XX +XXX,XX @@ struct MuscaMachineState {
29
+ * where the old value is below the limit and the new
26
UnimplementedDeviceState sdio;
30
+ * value is above, it is UNKNOWN whether the limit check
27
UnimplementedDeviceState gpio;
31
+ * triggers; we choose to trigger.
28
UnimplementedDeviceState cryptoisland;
32
+ */
29
+ Clock *sysclk;
33
+ gen_helper_v8m_stackcheck(cpu_env, addr);
30
+ Clock *s32kclk;
34
+ }
31
};
32
33
#define TYPE_MUSCA_MACHINE "musca"
34
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_TYPE(MuscaMachineState, MuscaMachineClass, MUSCA_MACHINE)
35
* don't model that in our SSE-200 model yet.
36
*/
37
#define SYSCLK_FRQ 40000000
38
+/* Slow 32Khz S32KCLK frequency in Hz */
39
+#define S32KCLK_FRQ (32 * 1000)
40
41
static qemu_irq get_sse_irq_in(MuscaMachineState *mms, int irqno)
42
{
43
@@ -XXX,XX +XXX,XX @@ static void musca_init(MachineState *machine)
44
exit(1);
45
}
46
47
+ mms->sysclk = clock_new(OBJECT(machine), "SYSCLK");
48
+ clock_set_hz(mms->sysclk, SYSCLK_FRQ);
49
+ mms->s32kclk = clock_new(OBJECT(machine), "S32KCLK");
50
+ clock_set_hz(mms->s32kclk, S32KCLK_FRQ);
35
+
51
+
36
if (dp)
52
object_initialize_child(OBJECT(machine), "sse-200", &mms->sse,
37
offset = 8;
53
TYPE_SSE200);
38
else
54
ssedev = DEVICE(&mms->sse);
55
@@ -XXX,XX +XXX,XX @@ static void musca_init(MachineState *machine)
56
qdev_prop_set_uint32(ssedev, "init-svtor", mmc->init_svtor);
57
qdev_prop_set_uint32(ssedev, "SRAM_ADDR_WIDTH", mmc->sram_addr_width);
58
qdev_prop_set_uint32(ssedev, "MAINCLK_FRQ", SYSCLK_FRQ);
59
+ qdev_connect_clock_in(ssedev, "MAINCLK", mms->sysclk);
60
+ qdev_connect_clock_in(ssedev, "S32KCLK", mms->s32kclk);
61
/*
62
* Musca-A takes the default SSE-200 FPU/DSP settings (ie no for
63
* CPU0 and yes for CPU1); Musca-B1 explicitly enables them for CPU0.
39
--
64
--
40
2.19.0
65
2.20.1
41
66
42
67
diff view generated by jsdifflib
New patch
1
1
Convert the SSYS code in the Stellaris boards (which encapsulates the
2
system registers) to a proper QOM device. This will provide us with
3
somewhere to put the output Clock whose frequency depends on the
4
setting of the PLL configuration registers.
5
6
This is a migration compatibility break for lm3s811evb, lm3s6965evb.
7
8
We use 3-phase reset here because the Clock will need to propagate
9
its value in the hold phase.
10
11
For the moment we reset the device during the board creation so that
12
the system_clock_scale global gets set; this will be removed in a
13
subsequent commit.
14
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Luc Michel <luc@lmichel.fr>
17
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
18
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
19
Message-id: 20210128114145.20536-17-peter.maydell@linaro.org
20
Message-id: 20210121190622.22000-17-peter.maydell@linaro.org
21
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
22
---
23
hw/arm/stellaris.c | 132 ++++++++++++++++++++++++++++++++++++---------
24
1 file changed, 107 insertions(+), 25 deletions(-)
25
26
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/arm/stellaris.c
29
+++ b/hw/arm/stellaris.c
30
@@ -XXX,XX +XXX,XX @@ static void stellaris_gptm_realize(DeviceState *dev, Error **errp)
31
32
/* System controller. */
33
34
-typedef struct {
35
+#define TYPE_STELLARIS_SYS "stellaris-sys"
36
+OBJECT_DECLARE_SIMPLE_TYPE(ssys_state, STELLARIS_SYS)
37
+
38
+struct ssys_state {
39
+ SysBusDevice parent_obj;
40
+
41
MemoryRegion iomem;
42
uint32_t pborctl;
43
uint32_t ldopctl;
44
@@ -XXX,XX +XXX,XX @@ typedef struct {
45
uint32_t dcgc[3];
46
uint32_t clkvclr;
47
uint32_t ldoarst;
48
+ qemu_irq irq;
49
+ /* Properties (all read-only registers) */
50
uint32_t user0;
51
uint32_t user1;
52
- qemu_irq irq;
53
- stellaris_board_info *board;
54
-} ssys_state;
55
+ uint32_t did0;
56
+ uint32_t did1;
57
+ uint32_t dc0;
58
+ uint32_t dc1;
59
+ uint32_t dc2;
60
+ uint32_t dc3;
61
+ uint32_t dc4;
62
+};
63
64
static void ssys_update(ssys_state *s)
65
{
66
@@ -XXX,XX +XXX,XX @@ static uint32_t pllcfg_fury[16] = {
67
68
static int ssys_board_class(const ssys_state *s)
69
{
70
- uint32_t did0 = s->board->did0;
71
+ uint32_t did0 = s->did0;
72
switch (did0 & DID0_VER_MASK) {
73
case DID0_VER_0:
74
return DID0_CLASS_SANDSTORM;
75
@@ -XXX,XX +XXX,XX @@ static uint64_t ssys_read(void *opaque, hwaddr offset,
76
77
switch (offset) {
78
case 0x000: /* DID0 */
79
- return s->board->did0;
80
+ return s->did0;
81
case 0x004: /* DID1 */
82
- return s->board->did1;
83
+ return s->did1;
84
case 0x008: /* DC0 */
85
- return s->board->dc0;
86
+ return s->dc0;
87
case 0x010: /* DC1 */
88
- return s->board->dc1;
89
+ return s->dc1;
90
case 0x014: /* DC2 */
91
- return s->board->dc2;
92
+ return s->dc2;
93
case 0x018: /* DC3 */
94
- return s->board->dc3;
95
+ return s->dc3;
96
case 0x01c: /* DC4 */
97
- return s->board->dc4;
98
+ return s->dc4;
99
case 0x030: /* PBORCTL */
100
return s->pborctl;
101
case 0x034: /* LDOPCTL */
102
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps ssys_ops = {
103
.endianness = DEVICE_NATIVE_ENDIAN,
104
};
105
106
-static void ssys_reset(void *opaque)
107
+static void stellaris_sys_reset_enter(Object *obj, ResetType type)
108
{
109
- ssys_state *s = (ssys_state *)opaque;
110
+ ssys_state *s = STELLARIS_SYS(obj);
111
112
s->pborctl = 0x7ffd;
113
s->rcc = 0x078e3ac0;
114
@@ -XXX,XX +XXX,XX @@ static void ssys_reset(void *opaque)
115
s->rcgc[0] = 1;
116
s->scgc[0] = 1;
117
s->dcgc[0] = 1;
118
+}
119
+
120
+static void stellaris_sys_reset_hold(Object *obj)
121
+{
122
+ ssys_state *s = STELLARIS_SYS(obj);
123
+
124
ssys_calculate_system_clock(s);
125
}
126
127
+static void stellaris_sys_reset_exit(Object *obj)
128
+{
129
+}
130
+
131
static int stellaris_sys_post_load(void *opaque, int version_id)
132
{
133
ssys_state *s = opaque;
134
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_stellaris_sys = {
135
}
136
};
137
138
+static Property stellaris_sys_properties[] = {
139
+ DEFINE_PROP_UINT32("user0", ssys_state, user0, 0),
140
+ DEFINE_PROP_UINT32("user1", ssys_state, user1, 0),
141
+ DEFINE_PROP_UINT32("did0", ssys_state, did0, 0),
142
+ DEFINE_PROP_UINT32("did1", ssys_state, did1, 0),
143
+ DEFINE_PROP_UINT32("dc0", ssys_state, dc0, 0),
144
+ DEFINE_PROP_UINT32("dc1", ssys_state, dc1, 0),
145
+ DEFINE_PROP_UINT32("dc2", ssys_state, dc2, 0),
146
+ DEFINE_PROP_UINT32("dc3", ssys_state, dc3, 0),
147
+ DEFINE_PROP_UINT32("dc4", ssys_state, dc4, 0),
148
+ DEFINE_PROP_END_OF_LIST()
149
+};
150
+
151
+static void stellaris_sys_instance_init(Object *obj)
152
+{
153
+ ssys_state *s = STELLARIS_SYS(obj);
154
+ SysBusDevice *sbd = SYS_BUS_DEVICE(s);
155
+
156
+ memory_region_init_io(&s->iomem, obj, &ssys_ops, s, "ssys", 0x00001000);
157
+ sysbus_init_mmio(sbd, &s->iomem);
158
+ sysbus_init_irq(sbd, &s->irq);
159
+}
160
+
161
static int stellaris_sys_init(uint32_t base, qemu_irq irq,
162
stellaris_board_info * board,
163
uint8_t *macaddr)
164
{
165
- ssys_state *s;
166
+ DeviceState *dev = qdev_new(TYPE_STELLARIS_SYS);
167
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
168
169
- s = g_new0(ssys_state, 1);
170
- s->irq = irq;
171
- s->board = board;
172
/* Most devices come preprogrammed with a MAC address in the user data. */
173
- s->user0 = macaddr[0] | (macaddr[1] << 8) | (macaddr[2] << 16);
174
- s->user1 = macaddr[3] | (macaddr[4] << 8) | (macaddr[5] << 16);
175
+ qdev_prop_set_uint32(dev, "user0",
176
+ macaddr[0] | (macaddr[1] << 8) | (macaddr[2] << 16));
177
+ qdev_prop_set_uint32(dev, "user1",
178
+ macaddr[3] | (macaddr[4] << 8) | (macaddr[5] << 16));
179
+ qdev_prop_set_uint32(dev, "did0", board->did0);
180
+ qdev_prop_set_uint32(dev, "did1", board->did1);
181
+ qdev_prop_set_uint32(dev, "dc0", board->dc0);
182
+ qdev_prop_set_uint32(dev, "dc1", board->dc1);
183
+ qdev_prop_set_uint32(dev, "dc2", board->dc2);
184
+ qdev_prop_set_uint32(dev, "dc3", board->dc3);
185
+ qdev_prop_set_uint32(dev, "dc4", board->dc4);
186
+
187
+ sysbus_realize_and_unref(sbd, &error_fatal);
188
+ sysbus_mmio_map(sbd, 0, base);
189
+ sysbus_connect_irq(sbd, 0, irq);
190
+
191
+ /*
192
+ * Normally we should not be resetting devices like this during
193
+ * board creation. For the moment we need to do so, because
194
+ * system_clock_scale will only get set when the STELLARIS_SYS
195
+ * device is reset, and we need its initial value to pass to
196
+ * the watchdog device. This hack can be removed once the
197
+ * watchdog has been converted to use a Clock input instead.
198
+ */
199
+ device_cold_reset(dev);
200
201
- memory_region_init_io(&s->iomem, NULL, &ssys_ops, s, "ssys", 0x00001000);
202
- memory_region_add_subregion(get_system_memory(), base, &s->iomem);
203
- ssys_reset(s);
204
- vmstate_register(NULL, VMSTATE_INSTANCE_ID_ANY, &vmstate_stellaris_sys, s);
205
return 0;
206
}
207
208
-
209
/* I2C controller. */
210
211
#define TYPE_STELLARIS_I2C "stellaris-i2c"
212
@@ -XXX,XX +XXX,XX @@ static const TypeInfo stellaris_adc_info = {
213
.class_init = stellaris_adc_class_init,
214
};
215
216
+static void stellaris_sys_class_init(ObjectClass *klass, void *data)
217
+{
218
+ DeviceClass *dc = DEVICE_CLASS(klass);
219
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
220
+
221
+ dc->vmsd = &vmstate_stellaris_sys;
222
+ rc->phases.enter = stellaris_sys_reset_enter;
223
+ rc->phases.hold = stellaris_sys_reset_hold;
224
+ rc->phases.exit = stellaris_sys_reset_exit;
225
+ device_class_set_props(dc, stellaris_sys_properties);
226
+}
227
+
228
+static const TypeInfo stellaris_sys_info = {
229
+ .name = TYPE_STELLARIS_SYS,
230
+ .parent = TYPE_SYS_BUS_DEVICE,
231
+ .instance_size = sizeof(ssys_state),
232
+ .instance_init = stellaris_sys_instance_init,
233
+ .class_init = stellaris_sys_class_init,
234
+};
235
+
236
static void stellaris_register_types(void)
237
{
238
type_register_static(&stellaris_i2c_info);
239
type_register_static(&stellaris_gptm_info);
240
type_register_static(&stellaris_adc_info);
241
+ type_register_static(&stellaris_sys_info);
242
}
243
244
type_init(stellaris_register_types)
245
--
246
2.20.1
247
248
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Create and connect the Clock input for the watchdog device on the
2
Stellaris boards. Because the Stellaris boards model the ability to
3
change the clock rate by programming PLL registers, we have to create
4
an output Clock on the ssys_state device and wire it up to the
5
watchdog.
2
6
3
We can choose the endianness at translation time, rather than
7
Note that the old comment on ssys_calculate_system_clock() got the
4
re-computing it at execution time.
8
units wrong -- system_clock_scale is in nanoseconds, not
9
milliseconds. Improve the commentary to clarify how we are
10
calculating the period.
5
11
6
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Luc Michel <luc@lmichel.fr>
14
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 20210128114145.20536-18-peter.maydell@linaro.org
9
Message-id: 20181005175350.30752-11-richard.henderson@linaro.org
17
Message-id: 20210121190622.22000-18-peter.maydell@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
---
19
---
12
target/arm/helper-sve.h | 117 +++++++++++++++-------
20
hw/arm/stellaris.c | 43 +++++++++++++++++++++++++++++++------------
13
target/arm/sve_helper.c | 70 ++++++-------
21
1 file changed, 31 insertions(+), 12 deletions(-)
14
target/arm/translate-sve.c | 196 +++++++++++++++++++++++++------------
15
3 files changed, 252 insertions(+), 131 deletions(-)
16
22
17
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
23
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
18
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper-sve.h
25
--- a/hw/arm/stellaris.c
20
+++ b/target/arm/helper-sve.h
26
+++ b/hw/arm/stellaris.c
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(sve_ld2bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
27
@@ -XXX,XX +XXX,XX @@
22
DEF_HELPER_FLAGS_4(sve_ld3bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
28
#include "hw/watchdog/cmsdk-apb-watchdog.h"
23
DEF_HELPER_FLAGS_4(sve_ld4bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
29
#include "migration/vmstate.h"
24
30
#include "hw/misc/unimp.h"
25
-DEF_HELPER_FLAGS_4(sve_ld1hh_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
31
+#include "hw/qdev-clock.h"
26
-DEF_HELPER_FLAGS_4(sve_ld2hh_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
32
#include "cpu.h"
27
-DEF_HELPER_FLAGS_4(sve_ld3hh_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
33
#include "qom/object.h"
28
-DEF_HELPER_FLAGS_4(sve_ld4hh_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
34
29
+DEF_HELPER_FLAGS_4(sve_ld1hh_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
35
@@ -XXX,XX +XXX,XX @@ struct ssys_state {
30
+DEF_HELPER_FLAGS_4(sve_ld2hh_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
36
uint32_t clkvclr;
31
+DEF_HELPER_FLAGS_4(sve_ld3hh_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
37
uint32_t ldoarst;
32
+DEF_HELPER_FLAGS_4(sve_ld4hh_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
38
qemu_irq irq;
33
39
+ Clock *sysclk;
34
-DEF_HELPER_FLAGS_4(sve_ld1ss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
40
/* Properties (all read-only registers) */
35
-DEF_HELPER_FLAGS_4(sve_ld2ss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
41
uint32_t user0;
36
-DEF_HELPER_FLAGS_4(sve_ld3ss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
42
uint32_t user1;
37
-DEF_HELPER_FLAGS_4(sve_ld4ss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
43
@@ -XXX,XX +XXX,XX @@ static bool ssys_use_rcc2(ssys_state *s)
38
+DEF_HELPER_FLAGS_4(sve_ld1hh_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
39
+DEF_HELPER_FLAGS_4(sve_ld2hh_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
40
+DEF_HELPER_FLAGS_4(sve_ld3hh_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
41
+DEF_HELPER_FLAGS_4(sve_ld4hh_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
42
43
-DEF_HELPER_FLAGS_4(sve_ld1dd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
44
-DEF_HELPER_FLAGS_4(sve_ld2dd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
45
-DEF_HELPER_FLAGS_4(sve_ld3dd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
46
-DEF_HELPER_FLAGS_4(sve_ld4dd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
47
+DEF_HELPER_FLAGS_4(sve_ld1ss_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
48
+DEF_HELPER_FLAGS_4(sve_ld2ss_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
49
+DEF_HELPER_FLAGS_4(sve_ld3ss_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
50
+DEF_HELPER_FLAGS_4(sve_ld4ss_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
51
+
52
+DEF_HELPER_FLAGS_4(sve_ld1ss_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
53
+DEF_HELPER_FLAGS_4(sve_ld2ss_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
54
+DEF_HELPER_FLAGS_4(sve_ld3ss_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
55
+DEF_HELPER_FLAGS_4(sve_ld4ss_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
56
+
57
+DEF_HELPER_FLAGS_4(sve_ld1dd_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
58
+DEF_HELPER_FLAGS_4(sve_ld2dd_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
59
+DEF_HELPER_FLAGS_4(sve_ld3dd_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
60
+DEF_HELPER_FLAGS_4(sve_ld4dd_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
61
+
62
+DEF_HELPER_FLAGS_4(sve_ld1dd_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
63
+DEF_HELPER_FLAGS_4(sve_ld2dd_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
64
+DEF_HELPER_FLAGS_4(sve_ld3dd_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
65
+DEF_HELPER_FLAGS_4(sve_ld4dd_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
66
67
DEF_HELPER_FLAGS_4(sve_ld1bhu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
68
DEF_HELPER_FLAGS_4(sve_ld1bsu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
69
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(sve_ld1bhs_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
70
DEF_HELPER_FLAGS_4(sve_ld1bss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
71
DEF_HELPER_FLAGS_4(sve_ld1bds_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
72
73
-DEF_HELPER_FLAGS_4(sve_ld1hsu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
74
-DEF_HELPER_FLAGS_4(sve_ld1hdu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
75
-DEF_HELPER_FLAGS_4(sve_ld1hss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
76
-DEF_HELPER_FLAGS_4(sve_ld1hds_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
77
+DEF_HELPER_FLAGS_4(sve_ld1hsu_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
78
+DEF_HELPER_FLAGS_4(sve_ld1hdu_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
79
+DEF_HELPER_FLAGS_4(sve_ld1hss_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
80
+DEF_HELPER_FLAGS_4(sve_ld1hds_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
81
82
-DEF_HELPER_FLAGS_4(sve_ld1sdu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
83
-DEF_HELPER_FLAGS_4(sve_ld1sds_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
84
+DEF_HELPER_FLAGS_4(sve_ld1hsu_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
85
+DEF_HELPER_FLAGS_4(sve_ld1hdu_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
86
+DEF_HELPER_FLAGS_4(sve_ld1hss_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
87
+DEF_HELPER_FLAGS_4(sve_ld1hds_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
88
+
89
+DEF_HELPER_FLAGS_4(sve_ld1sdu_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
90
+DEF_HELPER_FLAGS_4(sve_ld1sds_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
91
+
92
+DEF_HELPER_FLAGS_4(sve_ld1sdu_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
93
+DEF_HELPER_FLAGS_4(sve_ld1sds_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
94
95
DEF_HELPER_FLAGS_4(sve_ldff1bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
96
DEF_HELPER_FLAGS_4(sve_ldff1bhu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
97
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(sve_ldff1bhs_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
98
DEF_HELPER_FLAGS_4(sve_ldff1bss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
99
DEF_HELPER_FLAGS_4(sve_ldff1bds_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
100
101
-DEF_HELPER_FLAGS_4(sve_ldff1hh_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
102
-DEF_HELPER_FLAGS_4(sve_ldff1hsu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
103
-DEF_HELPER_FLAGS_4(sve_ldff1hdu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
104
-DEF_HELPER_FLAGS_4(sve_ldff1hss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
105
-DEF_HELPER_FLAGS_4(sve_ldff1hds_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
106
+DEF_HELPER_FLAGS_4(sve_ldff1hh_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
107
+DEF_HELPER_FLAGS_4(sve_ldff1hsu_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
108
+DEF_HELPER_FLAGS_4(sve_ldff1hdu_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
109
+DEF_HELPER_FLAGS_4(sve_ldff1hss_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
110
+DEF_HELPER_FLAGS_4(sve_ldff1hds_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
111
112
-DEF_HELPER_FLAGS_4(sve_ldff1ss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
113
-DEF_HELPER_FLAGS_4(sve_ldff1sdu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
114
-DEF_HELPER_FLAGS_4(sve_ldff1sds_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
115
+DEF_HELPER_FLAGS_4(sve_ldff1hh_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
116
+DEF_HELPER_FLAGS_4(sve_ldff1hsu_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
117
+DEF_HELPER_FLAGS_4(sve_ldff1hdu_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
118
+DEF_HELPER_FLAGS_4(sve_ldff1hss_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
119
+DEF_HELPER_FLAGS_4(sve_ldff1hds_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
120
121
-DEF_HELPER_FLAGS_4(sve_ldff1dd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
122
+DEF_HELPER_FLAGS_4(sve_ldff1ss_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
123
+DEF_HELPER_FLAGS_4(sve_ldff1sdu_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
124
+DEF_HELPER_FLAGS_4(sve_ldff1sds_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
125
+
126
+DEF_HELPER_FLAGS_4(sve_ldff1ss_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
127
+DEF_HELPER_FLAGS_4(sve_ldff1sdu_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
128
+DEF_HELPER_FLAGS_4(sve_ldff1sds_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
129
+
130
+DEF_HELPER_FLAGS_4(sve_ldff1dd_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
131
+DEF_HELPER_FLAGS_4(sve_ldff1dd_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
132
133
DEF_HELPER_FLAGS_4(sve_ldnf1bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
134
DEF_HELPER_FLAGS_4(sve_ldnf1bhu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
135
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(sve_ldnf1bhs_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
136
DEF_HELPER_FLAGS_4(sve_ldnf1bss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
137
DEF_HELPER_FLAGS_4(sve_ldnf1bds_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
138
139
-DEF_HELPER_FLAGS_4(sve_ldnf1hh_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
140
-DEF_HELPER_FLAGS_4(sve_ldnf1hsu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
141
-DEF_HELPER_FLAGS_4(sve_ldnf1hdu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
142
-DEF_HELPER_FLAGS_4(sve_ldnf1hss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
143
-DEF_HELPER_FLAGS_4(sve_ldnf1hds_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
144
+DEF_HELPER_FLAGS_4(sve_ldnf1hh_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
145
+DEF_HELPER_FLAGS_4(sve_ldnf1hsu_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
146
+DEF_HELPER_FLAGS_4(sve_ldnf1hdu_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
147
+DEF_HELPER_FLAGS_4(sve_ldnf1hss_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
148
+DEF_HELPER_FLAGS_4(sve_ldnf1hds_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
149
150
-DEF_HELPER_FLAGS_4(sve_ldnf1ss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
151
-DEF_HELPER_FLAGS_4(sve_ldnf1sdu_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
152
-DEF_HELPER_FLAGS_4(sve_ldnf1sds_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
153
+DEF_HELPER_FLAGS_4(sve_ldnf1hh_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
154
+DEF_HELPER_FLAGS_4(sve_ldnf1hsu_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
155
+DEF_HELPER_FLAGS_4(sve_ldnf1hdu_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
156
+DEF_HELPER_FLAGS_4(sve_ldnf1hss_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
157
+DEF_HELPER_FLAGS_4(sve_ldnf1hds_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
158
159
-DEF_HELPER_FLAGS_4(sve_ldnf1dd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
160
+DEF_HELPER_FLAGS_4(sve_ldnf1ss_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
161
+DEF_HELPER_FLAGS_4(sve_ldnf1sdu_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
162
+DEF_HELPER_FLAGS_4(sve_ldnf1sds_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
163
+
164
+DEF_HELPER_FLAGS_4(sve_ldnf1ss_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
165
+DEF_HELPER_FLAGS_4(sve_ldnf1sdu_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
166
+DEF_HELPER_FLAGS_4(sve_ldnf1sds_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
167
+
168
+DEF_HELPER_FLAGS_4(sve_ldnf1dd_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
169
+DEF_HELPER_FLAGS_4(sve_ldnf1dd_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
170
171
DEF_HELPER_FLAGS_4(sve_st1bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
172
DEF_HELPER_FLAGS_4(sve_st2bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
173
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
174
index XXXXXXX..XXXXXXX 100644
175
--- a/target/arm/sve_helper.c
176
+++ b/target/arm/sve_helper.c
177
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_##NAME##_r)(CPUARMState *env, void *vg, \
178
sve_##NAME##_host, sve_##NAME##_tlb); \
179
}
44
}
180
45
181
-/* TODO: Propagate the endian check back to the translator. */
46
/*
182
#define DO_LD1_2(NAME, ESZ, MSZ) \
47
- * Caculate the sys. clock period in ms.
183
-void HELPER(sve_##NAME##_r)(CPUARMState *env, void *vg, \
48
+ * Calculate the system clock period. We only want to propagate
184
- target_ulong addr, uint32_t desc) \
49
+ * this change to the rest of the system if we're not being called
185
-{ \
50
+ * from migration post-load.
186
- if (arm_cpu_data_is_big_endian(env)) { \
51
*/
187
- sve_ld1_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, \
52
-static void ssys_calculate_system_clock(ssys_state *s)
188
- sve_##NAME##_be_host, sve_##NAME##_be_tlb); \
53
+static void ssys_calculate_system_clock(ssys_state *s, bool propagate_clock)
189
- } else { \
54
{
190
- sve_ld1_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, \
55
+ /*
191
- sve_##NAME##_le_host, sve_##NAME##_le_tlb); \
56
+ * SYSDIV field specifies divisor: 0 == /1, 1 == /2, etc. Input
192
- } \
57
+ * clock is 200MHz, which is a period of 5 ns. Dividing the clock
193
+void HELPER(sve_##NAME##_le_r)(CPUARMState *env, void *vg, \
58
+ * frequency by X is the same as multiplying the period by X.
194
+ target_ulong addr, uint32_t desc) \
59
+ */
195
+{ \
60
if (ssys_use_rcc2(s)) {
196
+ sve_ld1_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, \
61
system_clock_scale = 5 * (((s->rcc2 >> 23) & 0x3f) + 1);
197
+ sve_##NAME##_le_host, sve_##NAME##_le_tlb); \
62
} else {
198
+} \
63
system_clock_scale = 5 * (((s->rcc >> 23) & 0xf) + 1);
199
+void HELPER(sve_##NAME##_be_r)(CPUARMState *env, void *vg, \
64
}
200
+ target_ulong addr, uint32_t desc) \
65
+ clock_set_ns(s->sysclk, system_clock_scale);
201
+{ \
66
+ if (propagate_clock) {
202
+ sve_ld1_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, \
67
+ clock_propagate(s->sysclk);
203
+ sve_##NAME##_be_host, sve_##NAME##_be_tlb); \
68
+ }
204
}
69
}
205
70
206
DO_LD1_1(ld1bb, 0)
71
static void ssys_write(void *opaque, hwaddr offset,
207
@@ -XXX,XX +XXX,XX @@ void __attribute__((flatten)) HELPER(sve_ld##N##bb_r) \
72
@@ -XXX,XX +XXX,XX @@ static void ssys_write(void *opaque, hwaddr offset,
73
s->int_status |= (1 << 6);
74
}
75
s->rcc = value;
76
- ssys_calculate_system_clock(s);
77
+ ssys_calculate_system_clock(s, true);
78
break;
79
case 0x070: /* RCC2 */
80
if (ssys_board_class(s) == DID0_CLASS_SANDSTORM) {
81
@@ -XXX,XX +XXX,XX @@ static void ssys_write(void *opaque, hwaddr offset,
82
s->int_status |= (1 << 6);
83
}
84
s->rcc2 = value;
85
- ssys_calculate_system_clock(s);
86
+ ssys_calculate_system_clock(s, true);
87
break;
88
case 0x100: /* RCGC0 */
89
s->rcgc[0] = value;
90
@@ -XXX,XX +XXX,XX @@ static void stellaris_sys_reset_hold(Object *obj)
91
{
92
ssys_state *s = STELLARIS_SYS(obj);
93
94
- ssys_calculate_system_clock(s);
95
+ /* OK to propagate clocks from the hold phase */
96
+ ssys_calculate_system_clock(s, true);
208
}
97
}
209
98
210
#define DO_LDN_2(N, SUFF, SIZE) \
99
static void stellaris_sys_reset_exit(Object *obj)
211
-void __attribute__((flatten)) HELPER(sve_ld##N##SUFF##_r) \
100
@@ -XXX,XX +XXX,XX @@ static int stellaris_sys_post_load(void *opaque, int version_id)
212
+void __attribute__((flatten)) HELPER(sve_ld##N##SUFF##_le_r) \
101
{
213
(CPUARMState *env, void *vg, target_ulong addr, uint32_t desc) \
102
ssys_state *s = opaque;
214
{ \
103
215
sve_ld##N##_r(env, vg, addr, desc, SIZE, GETPC(), \
104
- ssys_calculate_system_clock(s);
216
- arm_cpu_data_is_big_endian(env) \
105
+ ssys_calculate_system_clock(s, false);
217
- ? sve_ld1##SUFF##_be_tlb : sve_ld1##SUFF##_le_tlb); \
106
218
+ sve_ld1##SUFF##_le_tlb); \
107
return 0;
219
+} \
220
+void __attribute__((flatten)) HELPER(sve_ld##N##SUFF##_be_r) \
221
+ (CPUARMState *env, void *vg, target_ulong addr, uint32_t desc) \
222
+{ \
223
+ sve_ld##N##_r(env, vg, addr, desc, SIZE, GETPC(), \
224
+ sve_ld1##SUFF##_be_tlb); \
225
}
108
}
226
109
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_stellaris_sys = {
227
DO_LDN_1(2)
110
VMSTATE_UINT32_ARRAY(dcgc, ssys_state, 3),
228
@@ -XXX,XX +XXX,XX @@ void HELPER(sve_ldnf1##PART##_r)(CPUARMState *env, void *vg, \
111
VMSTATE_UINT32(clkvclr, ssys_state),
229
sve_ldnf1_r(env, vg, addr, desc, ESZ, 0, sve_ld1##PART##_host); \
112
VMSTATE_UINT32(ldoarst, ssys_state),
113
+ /* No field for sysclk -- handled in post-load instead */
114
VMSTATE_END_OF_LIST()
115
}
116
};
117
@@ -XXX,XX +XXX,XX @@ static void stellaris_sys_instance_init(Object *obj)
118
memory_region_init_io(&s->iomem, obj, &ssys_ops, s, "ssys", 0x00001000);
119
sysbus_init_mmio(sbd, &s->iomem);
120
sysbus_init_irq(sbd, &s->irq);
121
+ s->sysclk = qdev_init_clock_out(DEVICE(s), "SYSCLK");
230
}
122
}
231
123
232
-/* TODO: Propagate the endian check back to the translator. */
124
-static int stellaris_sys_init(uint32_t base, qemu_irq irq,
233
#define DO_LDFF1_LDNF1_2(PART, ESZ, MSZ) \
125
- stellaris_board_info * board,
234
-void HELPER(sve_ldff1##PART##_r)(CPUARMState *env, void *vg, \
126
- uint8_t *macaddr)
235
- target_ulong addr, uint32_t desc) \
127
+static DeviceState *stellaris_sys_init(uint32_t base, qemu_irq irq,
236
+void HELPER(sve_ldff1##PART##_le_r)(CPUARMState *env, void *vg, \
128
+ stellaris_board_info *board,
237
+ target_ulong addr, uint32_t desc) \
129
+ uint8_t *macaddr)
238
{ \
130
{
239
- if (arm_cpu_data_is_big_endian(env)) { \
131
DeviceState *dev = qdev_new(TYPE_STELLARIS_SYS);
240
- sve_ldff1_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, \
132
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
241
- sve_ld1##PART##_be_host, sve_ld1##PART##_be_tlb); \
133
@@ -XXX,XX +XXX,XX @@ static int stellaris_sys_init(uint32_t base, qemu_irq irq,
242
- } else { \
134
*/
243
- sve_ldff1_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, \
135
device_cold_reset(dev);
244
- sve_ld1##PART##_le_host, sve_ld1##PART##_le_tlb); \
136
245
- } \
137
- return 0;
246
+ sve_ldff1_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, \
138
+ return dev;
247
+ sve_ld1##PART##_le_host, sve_ld1##PART##_le_tlb); \
248
} \
249
-void HELPER(sve_ldnf1##PART##_r)(CPUARMState *env, void *vg, \
250
- target_ulong addr, uint32_t desc) \
251
+void HELPER(sve_ldnf1##PART##_le_r)(CPUARMState *env, void *vg, \
252
+ target_ulong addr, uint32_t desc) \
253
{ \
254
- if (arm_cpu_data_is_big_endian(env)) { \
255
- sve_ldnf1_r(env, vg, addr, desc, ESZ, MSZ, \
256
- sve_ld1##PART##_be_host); \
257
- } else { \
258
- sve_ldnf1_r(env, vg, addr, desc, ESZ, MSZ, \
259
- sve_ld1##PART##_le_host); \
260
- } \
261
+ sve_ldnf1_r(env, vg, addr, desc, ESZ, MSZ, sve_ld1##PART##_le_host); \
262
+} \
263
+void HELPER(sve_ldff1##PART##_be_r)(CPUARMState *env, void *vg, \
264
+ target_ulong addr, uint32_t desc) \
265
+{ \
266
+ sve_ldff1_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, \
267
+ sve_ld1##PART##_be_host, sve_ld1##PART##_be_tlb); \
268
+} \
269
+void HELPER(sve_ldnf1##PART##_be_r)(CPUARMState *env, void *vg, \
270
+ target_ulong addr, uint32_t desc) \
271
+{ \
272
+ sve_ldnf1_r(env, vg, addr, desc, ESZ, MSZ, sve_ld1##PART##_be_host); \
273
}
139
}
274
140
275
DO_LDFF1_LDNF1_1(bb, 0)
141
/* I2C controller. */
276
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
142
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
277
index XXXXXXX..XXXXXXX 100644
143
int flash_size;
278
--- a/target/arm/translate-sve.c
144
I2CBus *i2c;
279
+++ b/target/arm/translate-sve.c
145
DeviceState *dev;
280
@@ -XXX,XX +XXX,XX @@ static void do_mem_zpa(DisasContext *s, int zt, int pg, TCGv_i64 addr,
146
+ DeviceState *ssys_dev;
281
static void do_ld_zpa(DisasContext *s, int zt, int pg,
147
int i;
282
TCGv_i64 addr, int dtype, int nreg)
148
int j;
283
{
149
284
- static gen_helper_gvec_mem * const fns[16][4] = {
150
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
285
- { gen_helper_sve_ld1bb_r, gen_helper_sve_ld2bb_r,
151
}
286
- gen_helper_sve_ld3bb_r, gen_helper_sve_ld4bb_r },
287
- { gen_helper_sve_ld1bhu_r, NULL, NULL, NULL },
288
- { gen_helper_sve_ld1bsu_r, NULL, NULL, NULL },
289
- { gen_helper_sve_ld1bdu_r, NULL, NULL, NULL },
290
+ static gen_helper_gvec_mem * const fns[2][16][4] = {
291
+ /* Little-endian */
292
+ { { gen_helper_sve_ld1bb_r, gen_helper_sve_ld2bb_r,
293
+ gen_helper_sve_ld3bb_r, gen_helper_sve_ld4bb_r },
294
+ { gen_helper_sve_ld1bhu_r, NULL, NULL, NULL },
295
+ { gen_helper_sve_ld1bsu_r, NULL, NULL, NULL },
296
+ { gen_helper_sve_ld1bdu_r, NULL, NULL, NULL },
297
298
- { gen_helper_sve_ld1sds_r, NULL, NULL, NULL },
299
- { gen_helper_sve_ld1hh_r, gen_helper_sve_ld2hh_r,
300
- gen_helper_sve_ld3hh_r, gen_helper_sve_ld4hh_r },
301
- { gen_helper_sve_ld1hsu_r, NULL, NULL, NULL },
302
- { gen_helper_sve_ld1hdu_r, NULL, NULL, NULL },
303
+ { gen_helper_sve_ld1sds_le_r, NULL, NULL, NULL },
304
+ { gen_helper_sve_ld1hh_le_r, gen_helper_sve_ld2hh_le_r,
305
+ gen_helper_sve_ld3hh_le_r, gen_helper_sve_ld4hh_le_r },
306
+ { gen_helper_sve_ld1hsu_le_r, NULL, NULL, NULL },
307
+ { gen_helper_sve_ld1hdu_le_r, NULL, NULL, NULL },
308
309
- { gen_helper_sve_ld1hds_r, NULL, NULL, NULL },
310
- { gen_helper_sve_ld1hss_r, NULL, NULL, NULL },
311
- { gen_helper_sve_ld1ss_r, gen_helper_sve_ld2ss_r,
312
- gen_helper_sve_ld3ss_r, gen_helper_sve_ld4ss_r },
313
- { gen_helper_sve_ld1sdu_r, NULL, NULL, NULL },
314
+ { gen_helper_sve_ld1hds_le_r, NULL, NULL, NULL },
315
+ { gen_helper_sve_ld1hss_le_r, NULL, NULL, NULL },
316
+ { gen_helper_sve_ld1ss_le_r, gen_helper_sve_ld2ss_le_r,
317
+ gen_helper_sve_ld3ss_le_r, gen_helper_sve_ld4ss_le_r },
318
+ { gen_helper_sve_ld1sdu_le_r, NULL, NULL, NULL },
319
320
- { gen_helper_sve_ld1bds_r, NULL, NULL, NULL },
321
- { gen_helper_sve_ld1bss_r, NULL, NULL, NULL },
322
- { gen_helper_sve_ld1bhs_r, NULL, NULL, NULL },
323
- { gen_helper_sve_ld1dd_r, gen_helper_sve_ld2dd_r,
324
- gen_helper_sve_ld3dd_r, gen_helper_sve_ld4dd_r },
325
+ { gen_helper_sve_ld1bds_r, NULL, NULL, NULL },
326
+ { gen_helper_sve_ld1bss_r, NULL, NULL, NULL },
327
+ { gen_helper_sve_ld1bhs_r, NULL, NULL, NULL },
328
+ { gen_helper_sve_ld1dd_le_r, gen_helper_sve_ld2dd_le_r,
329
+ gen_helper_sve_ld3dd_le_r, gen_helper_sve_ld4dd_le_r } },
330
+
331
+ /* Big-endian */
332
+ { { gen_helper_sve_ld1bb_r, gen_helper_sve_ld2bb_r,
333
+ gen_helper_sve_ld3bb_r, gen_helper_sve_ld4bb_r },
334
+ { gen_helper_sve_ld1bhu_r, NULL, NULL, NULL },
335
+ { gen_helper_sve_ld1bsu_r, NULL, NULL, NULL },
336
+ { gen_helper_sve_ld1bdu_r, NULL, NULL, NULL },
337
+
338
+ { gen_helper_sve_ld1sds_be_r, NULL, NULL, NULL },
339
+ { gen_helper_sve_ld1hh_be_r, gen_helper_sve_ld2hh_be_r,
340
+ gen_helper_sve_ld3hh_be_r, gen_helper_sve_ld4hh_be_r },
341
+ { gen_helper_sve_ld1hsu_be_r, NULL, NULL, NULL },
342
+ { gen_helper_sve_ld1hdu_be_r, NULL, NULL, NULL },
343
+
344
+ { gen_helper_sve_ld1hds_be_r, NULL, NULL, NULL },
345
+ { gen_helper_sve_ld1hss_be_r, NULL, NULL, NULL },
346
+ { gen_helper_sve_ld1ss_be_r, gen_helper_sve_ld2ss_be_r,
347
+ gen_helper_sve_ld3ss_be_r, gen_helper_sve_ld4ss_be_r },
348
+ { gen_helper_sve_ld1sdu_be_r, NULL, NULL, NULL },
349
+
350
+ { gen_helper_sve_ld1bds_r, NULL, NULL, NULL },
351
+ { gen_helper_sve_ld1bss_r, NULL, NULL, NULL },
352
+ { gen_helper_sve_ld1bhs_r, NULL, NULL, NULL },
353
+ { gen_helper_sve_ld1dd_be_r, gen_helper_sve_ld2dd_be_r,
354
+ gen_helper_sve_ld3dd_be_r, gen_helper_sve_ld4dd_be_r } }
355
};
356
- gen_helper_gvec_mem *fn = fns[dtype][nreg];
357
+ gen_helper_gvec_mem *fn = fns[s->be_data == MO_BE][dtype][nreg];
358
359
/* While there are holes in the table, they are not
360
* accessible via the instruction encoding.
361
@@ -XXX,XX +XXX,XX @@ static bool trans_LD_zpri(DisasContext *s, arg_rpri_load *a, uint32_t insn)
362
363
static bool trans_LDFF1_zprr(DisasContext *s, arg_rprr_load *a, uint32_t insn)
364
{
365
- static gen_helper_gvec_mem * const fns[16] = {
366
- gen_helper_sve_ldff1bb_r,
367
- gen_helper_sve_ldff1bhu_r,
368
- gen_helper_sve_ldff1bsu_r,
369
- gen_helper_sve_ldff1bdu_r,
370
+ static gen_helper_gvec_mem * const fns[2][16] = {
371
+ /* Little-endian */
372
+ { gen_helper_sve_ldff1bb_r,
373
+ gen_helper_sve_ldff1bhu_r,
374
+ gen_helper_sve_ldff1bsu_r,
375
+ gen_helper_sve_ldff1bdu_r,
376
377
- gen_helper_sve_ldff1sds_r,
378
- gen_helper_sve_ldff1hh_r,
379
- gen_helper_sve_ldff1hsu_r,
380
- gen_helper_sve_ldff1hdu_r,
381
+ gen_helper_sve_ldff1sds_le_r,
382
+ gen_helper_sve_ldff1hh_le_r,
383
+ gen_helper_sve_ldff1hsu_le_r,
384
+ gen_helper_sve_ldff1hdu_le_r,
385
386
- gen_helper_sve_ldff1hds_r,
387
- gen_helper_sve_ldff1hss_r,
388
- gen_helper_sve_ldff1ss_r,
389
- gen_helper_sve_ldff1sdu_r,
390
+ gen_helper_sve_ldff1hds_le_r,
391
+ gen_helper_sve_ldff1hss_le_r,
392
+ gen_helper_sve_ldff1ss_le_r,
393
+ gen_helper_sve_ldff1sdu_le_r,
394
395
- gen_helper_sve_ldff1bds_r,
396
- gen_helper_sve_ldff1bss_r,
397
- gen_helper_sve_ldff1bhs_r,
398
- gen_helper_sve_ldff1dd_r,
399
+ gen_helper_sve_ldff1bds_r,
400
+ gen_helper_sve_ldff1bss_r,
401
+ gen_helper_sve_ldff1bhs_r,
402
+ gen_helper_sve_ldff1dd_le_r },
403
+
404
+ /* Big-endian */
405
+ { gen_helper_sve_ldff1bb_r,
406
+ gen_helper_sve_ldff1bhu_r,
407
+ gen_helper_sve_ldff1bsu_r,
408
+ gen_helper_sve_ldff1bdu_r,
409
+
410
+ gen_helper_sve_ldff1sds_be_r,
411
+ gen_helper_sve_ldff1hh_be_r,
412
+ gen_helper_sve_ldff1hsu_be_r,
413
+ gen_helper_sve_ldff1hdu_be_r,
414
+
415
+ gen_helper_sve_ldff1hds_be_r,
416
+ gen_helper_sve_ldff1hss_be_r,
417
+ gen_helper_sve_ldff1ss_be_r,
418
+ gen_helper_sve_ldff1sdu_be_r,
419
+
420
+ gen_helper_sve_ldff1bds_r,
421
+ gen_helper_sve_ldff1bss_r,
422
+ gen_helper_sve_ldff1bhs_r,
423
+ gen_helper_sve_ldff1dd_be_r },
424
};
425
426
if (sve_access_check(s)) {
427
TCGv_i64 addr = new_tmp_a64(s);
428
tcg_gen_shli_i64(addr, cpu_reg(s, a->rm), dtype_msz(a->dtype));
429
tcg_gen_add_i64(addr, addr, cpu_reg_sp(s, a->rn));
430
- do_mem_zpa(s, a->rd, a->pg, addr, fns[a->dtype]);
431
+ do_mem_zpa(s, a->rd, a->pg, addr, fns[s->be_data == MO_BE][a->dtype]);
432
}
152
}
433
return true;
153
434
}
154
- stellaris_sys_init(0x400fe000, qdev_get_gpio_in(nvic, 28),
435
155
- board, nd_table[0].macaddr.a);
436
static bool trans_LDNF1_zpri(DisasContext *s, arg_rpri_load *a, uint32_t insn)
156
+ ssys_dev = stellaris_sys_init(0x400fe000, qdev_get_gpio_in(nvic, 28),
437
{
157
+ board, nd_table[0].macaddr.a);
438
- static gen_helper_gvec_mem * const fns[16] = {
158
439
- gen_helper_sve_ldnf1bb_r,
159
440
- gen_helper_sve_ldnf1bhu_r,
160
if (board->dc1 & (1 << 3)) { /* watchdog present */
441
- gen_helper_sve_ldnf1bsu_r,
161
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
442
- gen_helper_sve_ldnf1bdu_r,
162
/* system_clock_scale is valid now */
443
+ static gen_helper_gvec_mem * const fns[2][16] = {
163
uint32_t mainclk = NANOSECONDS_PER_SECOND / system_clock_scale;
444
+ /* Little-endian */
164
qdev_prop_set_uint32(dev, "wdogclk-frq", mainclk);
445
+ { gen_helper_sve_ldnf1bb_r,
165
+ qdev_connect_clock_in(dev, "WDOGCLK",
446
+ gen_helper_sve_ldnf1bhu_r,
166
+ qdev_get_clock_out(ssys_dev, "SYSCLK"));
447
+ gen_helper_sve_ldnf1bsu_r,
167
448
+ gen_helper_sve_ldnf1bdu_r,
168
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
449
169
sysbus_mmio_map(SYS_BUS_DEVICE(dev),
450
- gen_helper_sve_ldnf1sds_r,
451
- gen_helper_sve_ldnf1hh_r,
452
- gen_helper_sve_ldnf1hsu_r,
453
- gen_helper_sve_ldnf1hdu_r,
454
+ gen_helper_sve_ldnf1sds_le_r,
455
+ gen_helper_sve_ldnf1hh_le_r,
456
+ gen_helper_sve_ldnf1hsu_le_r,
457
+ gen_helper_sve_ldnf1hdu_le_r,
458
459
- gen_helper_sve_ldnf1hds_r,
460
- gen_helper_sve_ldnf1hss_r,
461
- gen_helper_sve_ldnf1ss_r,
462
- gen_helper_sve_ldnf1sdu_r,
463
+ gen_helper_sve_ldnf1hds_le_r,
464
+ gen_helper_sve_ldnf1hss_le_r,
465
+ gen_helper_sve_ldnf1ss_le_r,
466
+ gen_helper_sve_ldnf1sdu_le_r,
467
468
- gen_helper_sve_ldnf1bds_r,
469
- gen_helper_sve_ldnf1bss_r,
470
- gen_helper_sve_ldnf1bhs_r,
471
- gen_helper_sve_ldnf1dd_r,
472
+ gen_helper_sve_ldnf1bds_r,
473
+ gen_helper_sve_ldnf1bss_r,
474
+ gen_helper_sve_ldnf1bhs_r,
475
+ gen_helper_sve_ldnf1dd_le_r },
476
+
477
+ /* Big-endian */
478
+ { gen_helper_sve_ldnf1bb_r,
479
+ gen_helper_sve_ldnf1bhu_r,
480
+ gen_helper_sve_ldnf1bsu_r,
481
+ gen_helper_sve_ldnf1bdu_r,
482
+
483
+ gen_helper_sve_ldnf1sds_be_r,
484
+ gen_helper_sve_ldnf1hh_be_r,
485
+ gen_helper_sve_ldnf1hsu_be_r,
486
+ gen_helper_sve_ldnf1hdu_be_r,
487
+
488
+ gen_helper_sve_ldnf1hds_be_r,
489
+ gen_helper_sve_ldnf1hss_be_r,
490
+ gen_helper_sve_ldnf1ss_be_r,
491
+ gen_helper_sve_ldnf1sdu_be_r,
492
+
493
+ gen_helper_sve_ldnf1bds_r,
494
+ gen_helper_sve_ldnf1bss_r,
495
+ gen_helper_sve_ldnf1bhs_r,
496
+ gen_helper_sve_ldnf1dd_be_r },
497
};
498
499
if (sve_access_check(s)) {
500
@@ -XXX,XX +XXX,XX @@ static bool trans_LDNF1_zpri(DisasContext *s, arg_rpri_load *a, uint32_t insn)
501
TCGv_i64 addr = new_tmp_a64(s);
502
503
tcg_gen_addi_i64(addr, cpu_reg_sp(s, a->rn), off);
504
- do_mem_zpa(s, a->rd, a->pg, addr, fns[a->dtype]);
505
+ do_mem_zpa(s, a->rd, a->pg, addr, fns[s->be_data == MO_BE][a->dtype]);
506
}
507
return true;
508
}
509
510
static void do_ldrq(DisasContext *s, int zt, int pg, TCGv_i64 addr, int msz)
511
{
512
- static gen_helper_gvec_mem * const fns[4] = {
513
- gen_helper_sve_ld1bb_r, gen_helper_sve_ld1hh_r,
514
- gen_helper_sve_ld1ss_r, gen_helper_sve_ld1dd_r,
515
+ static gen_helper_gvec_mem * const fns[2][4] = {
516
+ { gen_helper_sve_ld1bb_r, gen_helper_sve_ld1hh_le_r,
517
+ gen_helper_sve_ld1ss_le_r, gen_helper_sve_ld1dd_le_r },
518
+ { gen_helper_sve_ld1bb_r, gen_helper_sve_ld1hh_be_r,
519
+ gen_helper_sve_ld1ss_be_r, gen_helper_sve_ld1dd_be_r },
520
};
521
unsigned vsz = vec_full_reg_size(s);
522
TCGv_ptr t_pg;
523
@@ -XXX,XX +XXX,XX @@ static void do_ldrq(DisasContext *s, int zt, int pg, TCGv_i64 addr, int msz)
524
t_pg = tcg_temp_new_ptr();
525
tcg_gen_addi_ptr(t_pg, cpu_env, poff);
526
527
- fns[msz](cpu_env, t_pg, addr, desc);
528
+ fns[s->be_data == MO_BE][msz](cpu_env, t_pg, addr, desc);
529
530
tcg_temp_free_ptr(t_pg);
531
tcg_temp_free_i32(desc);
532
--
170
--
533
2.19.0
171
2.20.1
534
172
535
173
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Switch the CMSDK APB timer device over to using its Clock input; the
2
pclk-frq property is now ignored.
2
3
3
There is quite a lot of code required to compute cpu_mem_index,
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
or even put together the full TCGMemOpIdx. This can easily be
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
done at translation time.
6
Reviewed-by: Luc Michel <luc@lmichel.fr>
7
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20210128114145.20536-19-peter.maydell@linaro.org
9
Message-id: 20210121190622.22000-19-peter.maydell@linaro.org
10
---
11
hw/timer/cmsdk-apb-timer.c | 18 ++++++++++++++----
12
1 file changed, 14 insertions(+), 4 deletions(-)
6
13
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
diff --git a/hw/timer/cmsdk-apb-timer.c b/hw/timer/cmsdk-apb-timer.c
8
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20181005175350.30752-16-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
target/arm/internals.h | 5 ++
14
target/arm/sve_helper.c | 138 +++++++++++++++++++------------------
15
target/arm/translate-sve.c | 67 +++++++++++-------
16
3 files changed, 121 insertions(+), 89 deletions(-)
17
18
diff --git a/target/arm/internals.h b/target/arm/internals.h
19
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/internals.h
16
--- a/hw/timer/cmsdk-apb-timer.c
21
+++ b/target/arm/internals.h
17
+++ b/hw/timer/cmsdk-apb-timer.c
22
@@ -XXX,XX +XXX,XX @@ static inline uint32_t arm_debug_exception_fsr(CPUARMState *env)
18
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_timer_reset(DeviceState *dev)
23
}
19
ptimer_transaction_commit(s->timer);
24
}
20
}
25
21
26
+/* Note make_memop_idx reserves 4 bits for mmu_idx, and MO_BSWAP is bit 3.
22
+static void cmsdk_apb_timer_clk_update(void *opaque)
27
+ * Thus a TCGMemOpIdx, without any MO_ALIGN bits, fits in 8 bits.
23
+{
28
+ */
24
+ CMSDKAPBTimer *s = CMSDK_APB_TIMER(opaque);
29
+#define MEMOPIDX_SHIFT 8
30
+
25
+
31
#endif
26
+ ptimer_transaction_begin(s->timer);
32
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
27
+ ptimer_set_period_from_clock(s->timer, s->pclk, 1);
33
index XXXXXXX..XXXXXXX 100644
28
+ ptimer_transaction_commit(s->timer);
34
--- a/target/arm/sve_helper.c
35
+++ b/target/arm/sve_helper.c
36
@@ -XXX,XX +XXX,XX @@
37
38
#include "qemu/osdep.h"
39
#include "cpu.h"
40
+#include "internals.h"
41
#include "exec/exec-all.h"
42
#include "exec/cpu_ldst.h"
43
#include "exec/helper-proto.h"
44
@@ -XXX,XX +XXX,XX @@ typedef intptr_t sve_ld1_host_fn(void *vd, void *vg, void *host,
45
* The controlling predicate is known to be true.
46
*/
47
typedef void sve_ld1_tlb_fn(CPUARMState *env, void *vd, intptr_t reg_off,
48
- target_ulong vaddr, int mmu_idx, uintptr_t ra);
49
+ target_ulong vaddr, TCGMemOpIdx oi, uintptr_t ra);
50
typedef sve_ld1_tlb_fn sve_st1_tlb_fn;
51
52
/*
53
@@ -XXX,XX +XXX,XX @@ static intptr_t sve_##NAME##_host(void *vd, void *vg, void *host, \
54
#ifdef CONFIG_SOFTMMU
55
#define DO_LD_TLB(NAME, H, TYPEE, TYPEM, HOST, MOEND, TLB) \
56
static void sve_##NAME##_tlb(CPUARMState *env, void *vd, intptr_t reg_off, \
57
- target_ulong addr, int mmu_idx, uintptr_t ra) \
58
+ target_ulong addr, TCGMemOpIdx oi, uintptr_t ra) \
59
{ \
60
- TCGMemOpIdx oi = make_memop_idx(ctz32(sizeof(TYPEM)) | MOEND, mmu_idx); \
61
TYPEM val = TLB(env, addr, oi, ra); \
62
*(TYPEE *)(vd + H(reg_off)) = val; \
63
}
64
#else
65
#define DO_LD_TLB(NAME, H, TYPEE, TYPEM, HOST, MOEND, TLB) \
66
static void sve_##NAME##_tlb(CPUARMState *env, void *vd, intptr_t reg_off, \
67
- target_ulong addr, int mmu_idx, uintptr_t ra) \
68
+ target_ulong addr, TCGMemOpIdx oi, uintptr_t ra) \
69
{ \
70
TYPEM val = HOST(g2h(addr)); \
71
*(TYPEE *)(vd + H(reg_off)) = val; \
72
@@ -XXX,XX +XXX,XX @@ static void sve_ld1_r(CPUARMState *env, void *vg, const target_ulong addr,
73
sve_ld1_host_fn *host_fn,
74
sve_ld1_tlb_fn *tlb_fn)
75
{
76
- void *vd = &env->vfp.zregs[simd_data(desc)];
77
+ const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT);
78
+ const int mmu_idx = get_mmuidx(oi);
79
+ const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5);
80
+ void *vd = &env->vfp.zregs[rd];
81
const int diffsz = esz - msz;
82
const intptr_t reg_max = simd_oprsz(desc);
83
const intptr_t mem_max = reg_max >> diffsz;
84
- const int mmu_idx = cpu_mmu_index(env, false);
85
ARMVectorReg scratch;
86
void *host;
87
intptr_t split, reg_off, mem_off;
88
@@ -XXX,XX +XXX,XX @@ static void sve_ld1_r(CPUARMState *env, void *vg, const target_ulong addr,
89
* on I/O memory, it may succeed but not bring in the TLB entry.
90
* But even then we have still made forward progress.
91
*/
92
- tlb_fn(env, &scratch, reg_off, addr + mem_off, mmu_idx, retaddr);
93
+ tlb_fn(env, &scratch, reg_off, addr + mem_off, oi, retaddr);
94
reg_off += 1 << esz;
95
}
96
#endif
97
@@ -XXX,XX +XXX,XX @@ static void sve_ld2_r(CPUARMState *env, void *vg, target_ulong addr,
98
uint32_t desc, int size, uintptr_t ra,
99
sve_ld1_tlb_fn *tlb_fn)
100
{
101
- const int mmu_idx = cpu_mmu_index(env, false);
102
+ const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT);
103
+ const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5);
104
intptr_t i, oprsz = simd_oprsz(desc);
105
- unsigned rd = simd_data(desc);
106
ARMVectorReg scratch[2] = { };
107
108
set_helper_retaddr(ra);
109
@@ -XXX,XX +XXX,XX @@ static void sve_ld2_r(CPUARMState *env, void *vg, target_ulong addr,
110
uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));
111
do {
112
if (pg & 1) {
113
- tlb_fn(env, &scratch[0], i, addr, mmu_idx, ra);
114
- tlb_fn(env, &scratch[1], i, addr + size, mmu_idx, ra);
115
+ tlb_fn(env, &scratch[0], i, addr, oi, ra);
116
+ tlb_fn(env, &scratch[1], i, addr + size, oi, ra);
117
}
118
i += size, pg >>= size;
119
addr += 2 * size;
120
@@ -XXX,XX +XXX,XX @@ static void sve_ld3_r(CPUARMState *env, void *vg, target_ulong addr,
121
uint32_t desc, int size, uintptr_t ra,
122
sve_ld1_tlb_fn *tlb_fn)
123
{
124
- const int mmu_idx = cpu_mmu_index(env, false);
125
+ const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT);
126
+ const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5);
127
intptr_t i, oprsz = simd_oprsz(desc);
128
- unsigned rd = simd_data(desc);
129
ARMVectorReg scratch[3] = { };
130
131
set_helper_retaddr(ra);
132
@@ -XXX,XX +XXX,XX @@ static void sve_ld3_r(CPUARMState *env, void *vg, target_ulong addr,
133
uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));
134
do {
135
if (pg & 1) {
136
- tlb_fn(env, &scratch[0], i, addr, mmu_idx, ra);
137
- tlb_fn(env, &scratch[1], i, addr + size, mmu_idx, ra);
138
- tlb_fn(env, &scratch[2], i, addr + 2 * size, mmu_idx, ra);
139
+ tlb_fn(env, &scratch[0], i, addr, oi, ra);
140
+ tlb_fn(env, &scratch[1], i, addr + size, oi, ra);
141
+ tlb_fn(env, &scratch[2], i, addr + 2 * size, oi, ra);
142
}
143
i += size, pg >>= size;
144
addr += 3 * size;
145
@@ -XXX,XX +XXX,XX @@ static void sve_ld4_r(CPUARMState *env, void *vg, target_ulong addr,
146
uint32_t desc, int size, uintptr_t ra,
147
sve_ld1_tlb_fn *tlb_fn)
148
{
149
- const int mmu_idx = cpu_mmu_index(env, false);
150
+ const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT);
151
+ const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5);
152
intptr_t i, oprsz = simd_oprsz(desc);
153
- unsigned rd = simd_data(desc);
154
ARMVectorReg scratch[4] = { };
155
156
set_helper_retaddr(ra);
157
@@ -XXX,XX +XXX,XX @@ static void sve_ld4_r(CPUARMState *env, void *vg, target_ulong addr,
158
uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));
159
do {
160
if (pg & 1) {
161
- tlb_fn(env, &scratch[0], i, addr, mmu_idx, ra);
162
- tlb_fn(env, &scratch[1], i, addr + size, mmu_idx, ra);
163
- tlb_fn(env, &scratch[2], i, addr + 2 * size, mmu_idx, ra);
164
- tlb_fn(env, &scratch[3], i, addr + 3 * size, mmu_idx, ra);
165
+ tlb_fn(env, &scratch[0], i, addr, oi, ra);
166
+ tlb_fn(env, &scratch[1], i, addr + size, oi, ra);
167
+ tlb_fn(env, &scratch[2], i, addr + 2 * size, oi, ra);
168
+ tlb_fn(env, &scratch[3], i, addr + 3 * size, oi, ra);
169
}
170
i += size, pg >>= size;
171
addr += 4 * size;
172
@@ -XXX,XX +XXX,XX @@ static void sve_ldff1_r(CPUARMState *env, void *vg, const target_ulong addr,
173
sve_ld1_host_fn *host_fn,
174
sve_ld1_tlb_fn *tlb_fn)
175
{
176
- void *vd = &env->vfp.zregs[simd_data(desc)];
177
+ const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT);
178
+ const int mmu_idx = get_mmuidx(oi);
179
+ const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5);
180
+ void *vd = &env->vfp.zregs[rd];
181
const int diffsz = esz - msz;
182
const intptr_t reg_max = simd_oprsz(desc);
183
const intptr_t mem_max = reg_max >> diffsz;
184
- const int mmu_idx = cpu_mmu_index(env, false);
185
intptr_t split, reg_off, mem_off;
186
void *host;
187
188
@@ -XXX,XX +XXX,XX @@ static void sve_ldff1_r(CPUARMState *env, void *vg, const target_ulong addr,
189
* Perform one normal read, which will fault or not.
190
* But it is likely to bring the page into the tlb.
191
*/
192
- tlb_fn(env, vd, reg_off, addr + mem_off, mmu_idx, retaddr);
193
+ tlb_fn(env, vd, reg_off, addr + mem_off, oi, retaddr);
194
195
/* After any fault, zero any leading predicated false elts. */
196
swap_memzero(vd, reg_off);
197
@@ -XXX,XX +XXX,XX @@ static void sve_ldnf1_r(CPUARMState *env, void *vg, const target_ulong addr,
198
uint32_t desc, const int esz, const int msz,
199
sve_ld1_host_fn *host_fn)
200
{
201
- void *vd = &env->vfp.zregs[simd_data(desc)];
202
+ const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5);
203
+ void *vd = &env->vfp.zregs[rd];
204
const int diffsz = esz - msz;
205
const intptr_t reg_max = simd_oprsz(desc);
206
const intptr_t mem_max = reg_max >> diffsz;
207
@@ -XXX,XX +XXX,XX @@ DO_LDFF1_LDNF1_2(dd, 3, 3)
208
#ifdef CONFIG_SOFTMMU
209
#define DO_ST_TLB(NAME, H, TYPEM, HOST, MOEND, TLB) \
210
static void sve_##NAME##_tlb(CPUARMState *env, void *vd, intptr_t reg_off, \
211
- target_ulong addr, int mmu_idx, uintptr_t ra) \
212
+ target_ulong addr, TCGMemOpIdx oi, uintptr_t ra) \
213
{ \
214
- TCGMemOpIdx oi = make_memop_idx(ctz32(sizeof(TYPEM)) | MOEND, mmu_idx); \
215
TLB(env, addr, *(TYPEM *)(vd + H(reg_off)), oi, ra); \
216
}
217
#else
218
#define DO_ST_TLB(NAME, H, TYPEM, HOST, MOEND, TLB) \
219
static void sve_##NAME##_tlb(CPUARMState *env, void *vd, intptr_t reg_off, \
220
- target_ulong addr, int mmu_idx, uintptr_t ra) \
221
+ target_ulong addr, TCGMemOpIdx oi, uintptr_t ra) \
222
{ \
223
HOST(g2h(addr), *(TYPEM *)(vd + H(reg_off))); \
224
}
225
@@ -XXX,XX +XXX,XX @@ static void sve_st1_r(CPUARMState *env, void *vg, target_ulong addr,
226
const int esize, const int msize,
227
sve_st1_tlb_fn *tlb_fn)
228
{
229
- const int mmu_idx = cpu_mmu_index(env, false);
230
+ const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT);
231
+ const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5);
232
intptr_t i, oprsz = simd_oprsz(desc);
233
- unsigned rd = simd_data(desc);
234
void *vd = &env->vfp.zregs[rd];
235
236
set_helper_retaddr(ra);
237
@@ -XXX,XX +XXX,XX @@ static void sve_st1_r(CPUARMState *env, void *vg, target_ulong addr,
238
uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));
239
do {
240
if (pg & 1) {
241
- tlb_fn(env, vd, i, addr, mmu_idx, ra);
242
+ tlb_fn(env, vd, i, addr, oi, ra);
243
}
244
i += esize, pg >>= esize;
245
addr += msize;
246
@@ -XXX,XX +XXX,XX @@ static void sve_st2_r(CPUARMState *env, void *vg, target_ulong addr,
247
const int esize, const int msize,
248
sve_st1_tlb_fn *tlb_fn)
249
{
250
- const int mmu_idx = cpu_mmu_index(env, false);
251
+ const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT);
252
+ const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5);
253
intptr_t i, oprsz = simd_oprsz(desc);
254
- unsigned rd = simd_data(desc);
255
void *d1 = &env->vfp.zregs[rd];
256
void *d2 = &env->vfp.zregs[(rd + 1) & 31];
257
258
@@ -XXX,XX +XXX,XX @@ static void sve_st2_r(CPUARMState *env, void *vg, target_ulong addr,
259
uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));
260
do {
261
if (pg & 1) {
262
- tlb_fn(env, d1, i, addr, mmu_idx, ra);
263
- tlb_fn(env, d2, i, addr + msize, mmu_idx, ra);
264
+ tlb_fn(env, d1, i, addr, oi, ra);
265
+ tlb_fn(env, d2, i, addr + msize, oi, ra);
266
}
267
i += esize, pg >>= esize;
268
addr += 2 * msize;
269
@@ -XXX,XX +XXX,XX @@ static void sve_st3_r(CPUARMState *env, void *vg, target_ulong addr,
270
const int esize, const int msize,
271
sve_st1_tlb_fn *tlb_fn)
272
{
273
- const int mmu_idx = cpu_mmu_index(env, false);
274
+ const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT);
275
+ const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5);
276
intptr_t i, oprsz = simd_oprsz(desc);
277
- unsigned rd = simd_data(desc);
278
void *d1 = &env->vfp.zregs[rd];
279
void *d2 = &env->vfp.zregs[(rd + 1) & 31];
280
void *d3 = &env->vfp.zregs[(rd + 2) & 31];
281
@@ -XXX,XX +XXX,XX @@ static void sve_st3_r(CPUARMState *env, void *vg, target_ulong addr,
282
uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));
283
do {
284
if (pg & 1) {
285
- tlb_fn(env, d1, i, addr, mmu_idx, ra);
286
- tlb_fn(env, d2, i, addr + msize, mmu_idx, ra);
287
- tlb_fn(env, d3, i, addr + 2 * msize, mmu_idx, ra);
288
+ tlb_fn(env, d1, i, addr, oi, ra);
289
+ tlb_fn(env, d2, i, addr + msize, oi, ra);
290
+ tlb_fn(env, d3, i, addr + 2 * msize, oi, ra);
291
}
292
i += esize, pg >>= esize;
293
addr += 3 * msize;
294
@@ -XXX,XX +XXX,XX @@ static void sve_st4_r(CPUARMState *env, void *vg, target_ulong addr,
295
const int esize, const int msize,
296
sve_st1_tlb_fn *tlb_fn)
297
{
298
- const int mmu_idx = cpu_mmu_index(env, false);
299
+ const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT);
300
+ const unsigned rd = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 5);
301
intptr_t i, oprsz = simd_oprsz(desc);
302
- unsigned rd = simd_data(desc);
303
void *d1 = &env->vfp.zregs[rd];
304
void *d2 = &env->vfp.zregs[(rd + 1) & 31];
305
void *d3 = &env->vfp.zregs[(rd + 2) & 31];
306
@@ -XXX,XX +XXX,XX @@ static void sve_st4_r(CPUARMState *env, void *vg, target_ulong addr,
307
uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));
308
do {
309
if (pg & 1) {
310
- tlb_fn(env, d1, i, addr, mmu_idx, ra);
311
- tlb_fn(env, d2, i, addr + msize, mmu_idx, ra);
312
- tlb_fn(env, d3, i, addr + 2 * msize, mmu_idx, ra);
313
- tlb_fn(env, d4, i, addr + 3 * msize, mmu_idx, ra);
314
+ tlb_fn(env, d1, i, addr, oi, ra);
315
+ tlb_fn(env, d2, i, addr + msize, oi, ra);
316
+ tlb_fn(env, d3, i, addr + 2 * msize, oi, ra);
317
+ tlb_fn(env, d4, i, addr + 3 * msize, oi, ra);
318
}
319
i += esize, pg >>= esize;
320
addr += 4 * msize;
321
@@ -XXX,XX +XXX,XX @@ static void sve_ld1_zs(CPUARMState *env, void *vd, void *vg, void *vm,
322
target_ulong base, uint32_t desc, uintptr_t ra,
323
zreg_off_fn *off_fn, sve_ld1_tlb_fn *tlb_fn)
324
{
325
- const int mmu_idx = cpu_mmu_index(env, false);
326
+ const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT);
327
+ const int scale = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 2);
328
intptr_t i, oprsz = simd_oprsz(desc);
329
- unsigned scale = simd_data(desc);
330
ARMVectorReg scratch = { };
331
332
set_helper_retaddr(ra);
333
@@ -XXX,XX +XXX,XX @@ static void sve_ld1_zs(CPUARMState *env, void *vd, void *vg, void *vm,
334
do {
335
if (likely(pg & 1)) {
336
target_ulong off = off_fn(vm, i);
337
- tlb_fn(env, &scratch, i, base + (off << scale), mmu_idx, ra);
338
+ tlb_fn(env, &scratch, i, base + (off << scale), oi, ra);
339
}
340
i += 4, pg >>= 4;
341
} while (i & 15);
342
@@ -XXX,XX +XXX,XX @@ static void sve_ld1_zd(CPUARMState *env, void *vd, void *vg, void *vm,
343
target_ulong base, uint32_t desc, uintptr_t ra,
344
zreg_off_fn *off_fn, sve_ld1_tlb_fn *tlb_fn)
345
{
346
- const int mmu_idx = cpu_mmu_index(env, false);
347
+ const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT);
348
+ const int scale = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 2);
349
intptr_t i, oprsz = simd_oprsz(desc) / 8;
350
- unsigned scale = simd_data(desc);
351
ARMVectorReg scratch = { };
352
353
set_helper_retaddr(ra);
354
@@ -XXX,XX +XXX,XX @@ static void sve_ld1_zd(CPUARMState *env, void *vd, void *vg, void *vm,
355
uint8_t pg = *(uint8_t *)(vg + H1(i));
356
if (likely(pg & 1)) {
357
target_ulong off = off_fn(vm, i * 8);
358
- tlb_fn(env, &scratch, i * 8, base + (off << scale), mmu_idx, ra);
359
+ tlb_fn(env, &scratch, i * 8, base + (off << scale), oi, ra);
360
}
361
}
362
set_helper_retaddr(0);
363
@@ -XXX,XX +XXX,XX @@ typedef bool sve_ld1_nf_fn(CPUARMState *env, void *vd, intptr_t reg_off,
364
#ifdef CONFIG_SOFTMMU
365
#define DO_LD_NF(NAME, H, TYPEE, TYPEM, HOST) \
366
static bool sve_ld##NAME##_nf(CPUARMState *env, void *vd, intptr_t reg_off, \
367
- target_ulong addr, int mmu_idx) \
368
+ target_ulong addr, int mmu_idx) \
369
{ \
370
target_ulong next_page = -(addr | TARGET_PAGE_MASK); \
371
if (likely(next_page - addr >= sizeof(TYPEM))) { \
372
@@ -XXX,XX +XXX,XX @@ static inline void sve_ldff1_zs(CPUARMState *env, void *vd, void *vg, void *vm,
373
zreg_off_fn *off_fn, sve_ld1_tlb_fn *tlb_fn,
374
sve_ld1_nf_fn *nonfault_fn)
375
{
376
- const int mmu_idx = cpu_mmu_index(env, false);
377
+ const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT);
378
+ const int mmu_idx = get_mmuidx(oi);
379
+ const int scale = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 2);
380
intptr_t reg_off, reg_max = simd_oprsz(desc);
381
- unsigned scale = simd_data(desc);
382
target_ulong addr;
383
384
/* Skip to the first true predicate. */
385
@@ -XXX,XX +XXX,XX @@ static inline void sve_ldff1_zs(CPUARMState *env, void *vd, void *vg, void *vm,
386
set_helper_retaddr(ra);
387
addr = off_fn(vm, reg_off);
388
addr = base + (addr << scale);
389
- tlb_fn(env, vd, reg_off, addr, mmu_idx, ra);
390
+ tlb_fn(env, vd, reg_off, addr, oi, ra);
391
392
/* The rest of the reads will be non-faulting. */
393
set_helper_retaddr(0);
394
@@ -XXX,XX +XXX,XX @@ static inline void sve_ldff1_zd(CPUARMState *env, void *vd, void *vg, void *vm,
395
zreg_off_fn *off_fn, sve_ld1_tlb_fn *tlb_fn,
396
sve_ld1_nf_fn *nonfault_fn)
397
{
398
- const int mmu_idx = cpu_mmu_index(env, false);
399
+ const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT);
400
+ const int mmu_idx = get_mmuidx(oi);
401
+ const int scale = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 2);
402
intptr_t reg_off, reg_max = simd_oprsz(desc);
403
- unsigned scale = simd_data(desc);
404
target_ulong addr;
405
406
/* Skip to the first true predicate. */
407
@@ -XXX,XX +XXX,XX @@ static inline void sve_ldff1_zd(CPUARMState *env, void *vd, void *vg, void *vm,
408
set_helper_retaddr(ra);
409
addr = off_fn(vm, reg_off);
410
addr = base + (addr << scale);
411
- tlb_fn(env, vd, reg_off, addr, mmu_idx, ra);
412
+ tlb_fn(env, vd, reg_off, addr, oi, ra);
413
414
/* The rest of the reads will be non-faulting. */
415
set_helper_retaddr(0);
416
@@ -XXX,XX +XXX,XX @@ static void sve_st1_zs(CPUARMState *env, void *vd, void *vg, void *vm,
417
target_ulong base, uint32_t desc, uintptr_t ra,
418
zreg_off_fn *off_fn, sve_ld1_tlb_fn *tlb_fn)
419
{
420
- const int mmu_idx = cpu_mmu_index(env, false);
421
+ const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT);
422
+ const int scale = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 2);
423
intptr_t i, oprsz = simd_oprsz(desc);
424
- unsigned scale = simd_data(desc);
425
426
set_helper_retaddr(ra);
427
for (i = 0; i < oprsz; ) {
428
@@ -XXX,XX +XXX,XX @@ static void sve_st1_zs(CPUARMState *env, void *vd, void *vg, void *vm,
429
do {
430
if (likely(pg & 1)) {
431
target_ulong off = off_fn(vm, i);
432
- tlb_fn(env, vd, i, base + (off << scale), mmu_idx, ra);
433
+ tlb_fn(env, vd, i, base + (off << scale), oi, ra);
434
}
435
i += 4, pg >>= 4;
436
} while (i & 15);
437
@@ -XXX,XX +XXX,XX @@ static void sve_st1_zd(CPUARMState *env, void *vd, void *vg, void *vm,
438
target_ulong base, uint32_t desc, uintptr_t ra,
439
zreg_off_fn *off_fn, sve_ld1_tlb_fn *tlb_fn)
440
{
441
- const int mmu_idx = cpu_mmu_index(env, false);
442
+ const TCGMemOpIdx oi = extract32(desc, SIMD_DATA_SHIFT, MEMOPIDX_SHIFT);
443
+ const int scale = extract32(desc, SIMD_DATA_SHIFT + MEMOPIDX_SHIFT, 2);
444
intptr_t i, oprsz = simd_oprsz(desc) / 8;
445
- unsigned scale = simd_data(desc);
446
447
set_helper_retaddr(ra);
448
for (i = 0; i < oprsz; i++) {
449
uint8_t pg = *(uint8_t *)(vg + H1(i));
450
if (likely(pg & 1)) {
451
target_ulong off = off_fn(vm, i * 8);
452
- tlb_fn(env, vd, i * 8, base + (off << scale), mmu_idx, ra);
453
+ tlb_fn(env, vd, i * 8, base + (off << scale), oi, ra);
454
}
455
}
456
set_helper_retaddr(0);
457
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
458
index XXXXXXX..XXXXXXX 100644
459
--- a/target/arm/translate-sve.c
460
+++ b/target/arm/translate-sve.c
461
@@ -XXX,XX +XXX,XX @@ static const uint8_t dtype_esz[16] = {
462
3, 2, 1, 3
463
};
464
465
+static TCGMemOpIdx sve_memopidx(DisasContext *s, int dtype)
466
+{
467
+ return make_memop_idx(s->be_data | dtype_mop[dtype], get_mem_index(s));
468
+}
29
+}
469
+
30
+
470
static void do_mem_zpa(DisasContext *s, int zt, int pg, TCGv_i64 addr,
31
static void cmsdk_apb_timer_init(Object *obj)
471
- gen_helper_gvec_mem *fn)
472
+ int dtype, gen_helper_gvec_mem *fn)
473
{
32
{
474
unsigned vsz = vec_full_reg_size(s);
33
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
475
TCGv_ptr t_pg;
34
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_timer_init(Object *obj)
476
- TCGv_i32 desc;
35
s, "cmsdk-apb-timer", 0x1000);
477
+ TCGv_i32 t_desc;
36
sysbus_init_mmio(sbd, &s->iomem);
478
+ int desc;
37
sysbus_init_irq(sbd, &s->timerint);
479
38
- s->pclk = qdev_init_clock_in(DEVICE(s), "pclk", NULL, NULL);
480
/* For e.g. LD4, there are not enough arguments to pass all 4
39
+ s->pclk = qdev_init_clock_in(DEVICE(s), "pclk",
481
* registers as pointers, so encode the regno into the data field.
40
+ cmsdk_apb_timer_clk_update, s);
482
* For consistency, do this even for LD1.
483
*/
484
- desc = tcg_const_i32(simd_desc(vsz, vsz, zt));
485
+ desc = sve_memopidx(s, dtype);
486
+ desc |= zt << MEMOPIDX_SHIFT;
487
+ desc = simd_desc(vsz, vsz, desc);
488
+ t_desc = tcg_const_i32(desc);
489
t_pg = tcg_temp_new_ptr();
490
491
tcg_gen_addi_ptr(t_pg, cpu_env, pred_full_reg_offset(s, pg));
492
- fn(cpu_env, t_pg, addr, desc);
493
+ fn(cpu_env, t_pg, addr, t_desc);
494
495
tcg_temp_free_ptr(t_pg);
496
- tcg_temp_free_i32(desc);
497
+ tcg_temp_free_i32(t_desc);
498
}
41
}
499
42
500
static void do_ld_zpa(DisasContext *s, int zt, int pg,
43
static void cmsdk_apb_timer_realize(DeviceState *dev, Error **errp)
501
@@ -XXX,XX +XXX,XX @@ static void do_ld_zpa(DisasContext *s, int zt, int pg,
44
{
502
* accessible via the instruction encoding.
45
CMSDKAPBTimer *s = CMSDK_APB_TIMER(dev);
503
*/
46
504
assert(fn != NULL);
47
- if (s->pclk_frq == 0) {
505
- do_mem_zpa(s, zt, pg, addr, fn);
48
- error_setg(errp, "CMSDK APB timer: pclk-frq property must be set");
506
+ do_mem_zpa(s, zt, pg, addr, dtype, fn);
49
+ if (!clock_has_source(s->pclk)) {
50
+ error_setg(errp, "CMSDK APB timer: pclk clock must be connected");
51
return;
52
}
53
54
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_timer_realize(DeviceState *dev, Error **errp)
55
PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
56
57
ptimer_transaction_begin(s->timer);
58
- ptimer_set_freq(s->timer, s->pclk_frq);
59
+ ptimer_set_period_from_clock(s->timer, s->pclk, 1);
60
ptimer_transaction_commit(s->timer);
507
}
61
}
508
62
509
static bool trans_LD_zprr(DisasContext *s, arg_rprr_load *a, uint32_t insn)
510
@@ -XXX,XX +XXX,XX @@ static bool trans_LDFF1_zprr(DisasContext *s, arg_rprr_load *a, uint32_t insn)
511
TCGv_i64 addr = new_tmp_a64(s);
512
tcg_gen_shli_i64(addr, cpu_reg(s, a->rm), dtype_msz(a->dtype));
513
tcg_gen_add_i64(addr, addr, cpu_reg_sp(s, a->rn));
514
- do_mem_zpa(s, a->rd, a->pg, addr, fns[s->be_data == MO_BE][a->dtype]);
515
+ do_mem_zpa(s, a->rd, a->pg, addr, a->dtype,
516
+ fns[s->be_data == MO_BE][a->dtype]);
517
}
518
return true;
519
}
520
@@ -XXX,XX +XXX,XX @@ static bool trans_LDNF1_zpri(DisasContext *s, arg_rpri_load *a, uint32_t insn)
521
TCGv_i64 addr = new_tmp_a64(s);
522
523
tcg_gen_addi_i64(addr, cpu_reg_sp(s, a->rn), off);
524
- do_mem_zpa(s, a->rd, a->pg, addr, fns[s->be_data == MO_BE][a->dtype]);
525
+ do_mem_zpa(s, a->rd, a->pg, addr, a->dtype,
526
+ fns[s->be_data == MO_BE][a->dtype]);
527
}
528
return true;
529
}
530
@@ -XXX,XX +XXX,XX @@ static void do_ldrq(DisasContext *s, int zt, int pg, TCGv_i64 addr, int msz)
531
};
532
unsigned vsz = vec_full_reg_size(s);
533
TCGv_ptr t_pg;
534
- TCGv_i32 desc;
535
- int poff;
536
+ TCGv_i32 t_desc;
537
+ int desc, poff;
538
539
/* Load the first quadword using the normal predicated load helpers. */
540
- desc = tcg_const_i32(simd_desc(16, 16, zt));
541
+ desc = sve_memopidx(s, msz_dtype(msz));
542
+ desc |= zt << MEMOPIDX_SHIFT;
543
+ desc = simd_desc(16, 16, desc);
544
+ t_desc = tcg_const_i32(desc);
545
546
poff = pred_full_reg_offset(s, pg);
547
if (vsz > 16) {
548
@@ -XXX,XX +XXX,XX @@ static void do_ldrq(DisasContext *s, int zt, int pg, TCGv_i64 addr, int msz)
549
t_pg = tcg_temp_new_ptr();
550
tcg_gen_addi_ptr(t_pg, cpu_env, poff);
551
552
- fns[s->be_data == MO_BE][msz](cpu_env, t_pg, addr, desc);
553
+ fns[s->be_data == MO_BE][msz](cpu_env, t_pg, addr, t_desc);
554
555
tcg_temp_free_ptr(t_pg);
556
- tcg_temp_free_i32(desc);
557
+ tcg_temp_free_i32(t_desc);
558
559
/* Replicate that first quadword. */
560
if (vsz > 16) {
561
@@ -XXX,XX +XXX,XX @@ static void do_st_zpa(DisasContext *s, int zt, int pg, TCGv_i64 addr,
562
fn = fn_multiple[be][nreg - 1][msz];
563
}
564
assert(fn != NULL);
565
- do_mem_zpa(s, zt, pg, addr, fn);
566
+ do_mem_zpa(s, zt, pg, addr, msz_dtype(msz), fn);
567
}
568
569
static bool trans_ST_zprr(DisasContext *s, arg_rprr_store *a, uint32_t insn)
570
@@ -XXX,XX +XXX,XX @@ static bool trans_ST_zpri(DisasContext *s, arg_rpri_store *a, uint32_t insn)
571
*** SVE gather loads / scatter stores
572
*/
573
574
-static void do_mem_zpz(DisasContext *s, int zt, int pg, int zm, int scale,
575
- TCGv_i64 scalar, gen_helper_gvec_mem_scatter *fn)
576
+static void do_mem_zpz(DisasContext *s, int zt, int pg, int zm,
577
+ int scale, TCGv_i64 scalar, int msz,
578
+ gen_helper_gvec_mem_scatter *fn)
579
{
580
unsigned vsz = vec_full_reg_size(s);
581
- TCGv_i32 desc = tcg_const_i32(simd_desc(vsz, vsz, scale));
582
TCGv_ptr t_zm = tcg_temp_new_ptr();
583
TCGv_ptr t_pg = tcg_temp_new_ptr();
584
TCGv_ptr t_zt = tcg_temp_new_ptr();
585
+ TCGv_i32 t_desc;
586
+ int desc;
587
+
588
+ desc = sve_memopidx(s, msz_dtype(msz));
589
+ desc |= scale << MEMOPIDX_SHIFT;
590
+ desc = simd_desc(vsz, vsz, desc);
591
+ t_desc = tcg_const_i32(desc);
592
593
tcg_gen_addi_ptr(t_pg, cpu_env, pred_full_reg_offset(s, pg));
594
tcg_gen_addi_ptr(t_zm, cpu_env, vec_full_reg_offset(s, zm));
595
tcg_gen_addi_ptr(t_zt, cpu_env, vec_full_reg_offset(s, zt));
596
- fn(cpu_env, t_zt, t_pg, t_zm, scalar, desc);
597
+ fn(cpu_env, t_zt, t_pg, t_zm, scalar, t_desc);
598
599
tcg_temp_free_ptr(t_zt);
600
tcg_temp_free_ptr(t_zm);
601
tcg_temp_free_ptr(t_pg);
602
- tcg_temp_free_i32(desc);
603
+ tcg_temp_free_i32(t_desc);
604
}
605
606
/* Indexed by [be][ff][xs][u][msz]. */
607
@@ -XXX,XX +XXX,XX @@ static bool trans_LD1_zprz(DisasContext *s, arg_LD1_zprz *a, uint32_t insn)
608
assert(fn != NULL);
609
610
do_mem_zpz(s, a->rd, a->pg, a->rm, a->scale * a->msz,
611
- cpu_reg_sp(s, a->rn), fn);
612
+ cpu_reg_sp(s, a->rn), a->msz, fn);
613
return true;
614
}
615
616
@@ -XXX,XX +XXX,XX @@ static bool trans_LD1_zpiz(DisasContext *s, arg_LD1_zpiz *a, uint32_t insn)
617
* by loading the immediate into the scalar parameter.
618
*/
619
imm = tcg_const_i64(a->imm << a->msz);
620
- do_mem_zpz(s, a->rd, a->pg, a->rn, 0, imm, fn);
621
+ do_mem_zpz(s, a->rd, a->pg, a->rn, 0, imm, a->msz, fn);
622
tcg_temp_free_i64(imm);
623
return true;
624
}
625
@@ -XXX,XX +XXX,XX @@ static bool trans_ST1_zprz(DisasContext *s, arg_ST1_zprz *a, uint32_t insn)
626
g_assert_not_reached();
627
}
628
do_mem_zpz(s, a->rd, a->pg, a->rm, a->scale * a->msz,
629
- cpu_reg_sp(s, a->rn), fn);
630
+ cpu_reg_sp(s, a->rn), a->msz, fn);
631
return true;
632
}
633
634
@@ -XXX,XX +XXX,XX @@ static bool trans_ST1_zpiz(DisasContext *s, arg_ST1_zpiz *a, uint32_t insn)
635
* by loading the immediate into the scalar parameter.
636
*/
637
imm = tcg_const_i64(a->imm << a->msz);
638
- do_mem_zpz(s, a->rd, a->pg, a->rn, 0, imm, fn);
639
+ do_mem_zpz(s, a->rd, a->pg, a->rn, 0, imm, a->msz, fn);
640
tcg_temp_free_i64(imm);
641
return true;
642
}
643
--
63
--
644
2.19.0
64
2.20.1
645
65
646
66
diff view generated by jsdifflib
1
Add code to insert calls to a helper function to do the stack
1
Switch the CMSDK APB dualtimer device over to using its Clock input;
2
limit checking when we handle these forms of instruction
2
the pclk-frq property is now ignored.
3
that write to SP:
4
* ADD (SP plus immediate)
5
* ADD (SP plus register)
6
* SUB (SP minus immediate)
7
* SUB (SP minus register)
8
* MOV (register)
9
3
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Luc Michel <luc@lmichel.fr>
12
Message-id: 20181002163556.10279-5-peter.maydell@linaro.org
6
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20210128114145.20536-20-peter.maydell@linaro.org
9
Message-id: 20210121190622.22000-20-peter.maydell@linaro.org
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
---
11
---
14
target/arm/helper.h | 2 ++
12
hw/timer/cmsdk-apb-dualtimer.c | 42 ++++++++++++++++++++++++++++++----
15
target/arm/internals.h | 14 ++++++++
13
1 file changed, 37 insertions(+), 5 deletions(-)
16
target/arm/op_helper.c | 19 ++++++++++
17
target/arm/translate.c | 80 +++++++++++++++++++++++++++++++++++++-----
18
4 files changed, 106 insertions(+), 9 deletions(-)
19
14
20
diff --git a/target/arm/helper.h b/target/arm/helper.h
15
diff --git a/hw/timer/cmsdk-apb-dualtimer.c b/hw/timer/cmsdk-apb-dualtimer.c
21
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/helper.h
17
--- a/hw/timer/cmsdk-apb-dualtimer.c
23
+++ b/target/arm/helper.h
18
+++ b/hw/timer/cmsdk-apb-dualtimer.c
24
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_2(v7m_blxns, void, env, i32)
19
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_dualtimer_update(CMSDKAPBDualTimer *s)
25
20
qemu_set_irq(s->timerintc, timintc);
26
DEF_HELPER_3(v7m_tt, i32, env, i32, i32)
27
28
+DEF_HELPER_2(v8m_stackcheck, void, env, i32)
29
+
30
DEF_HELPER_4(access_check_cp_reg, void, env, ptr, i32, i32)
31
DEF_HELPER_3(set_cp_reg, void, env, ptr, i32)
32
DEF_HELPER_2(get_cp_reg, i32, env, ptr)
33
diff --git a/target/arm/internals.h b/target/arm/internals.h
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/internals.h
36
+++ b/target/arm/internals.h
37
@@ -XXX,XX +XXX,XX @@ static inline bool v7m_using_psp(CPUARMState *env)
38
env->v7m.control[env->v7m.secure] & R_V7M_CONTROL_SPSEL_MASK;
39
}
21
}
40
22
41
+/**
23
+static int cmsdk_dualtimermod_divisor(CMSDKAPBDualTimerModule *m)
42
+ * v7m_sp_limit: Return SP limit for current CPU state
43
+ * Return the SP limit value for the current CPU security state
44
+ * and stack pointer.
45
+ */
46
+static inline uint32_t v7m_sp_limit(CPUARMState *env)
47
+{
24
+{
48
+ if (v7m_using_psp(env)) {
25
+ /* Return the divisor set by the current CONTROL.PRESCALE value */
49
+ return env->v7m.psplim[env->v7m.secure];
26
+ switch (FIELD_EX32(m->control, CONTROL, PRESCALE)) {
50
+ } else {
27
+ case 0:
51
+ return env->v7m.msplim[env->v7m.secure];
28
+ return 1;
29
+ case 1:
30
+ return 16;
31
+ case 2:
32
+ case 3: /* UNDEFINED, we treat like 2 (and complained when it was set) */
33
+ return 256;
34
+ default:
35
+ g_assert_not_reached();
52
+ }
36
+ }
53
+}
37
+}
54
+
38
+
55
#endif
39
static void cmsdk_dualtimermod_write_control(CMSDKAPBDualTimerModule *m,
56
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
40
uint32_t newctrl)
57
index XXXXXXX..XXXXXXX 100644
41
{
58
--- a/target/arm/op_helper.c
42
@@ -XXX,XX +XXX,XX @@ static void cmsdk_dualtimermod_write_control(CMSDKAPBDualTimerModule *m,
59
+++ b/target/arm/op_helper.c
43
default:
60
@@ -XXX,XX +XXX,XX @@ void arm_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
44
g_assert_not_reached();
61
45
}
62
#endif /* !defined(CONFIG_USER_ONLY) */
46
- ptimer_set_freq(m->timer, m->parent->pclk_frq / divisor);
63
47
+ ptimer_set_period_from_clock(m->timer, m->parent->timclk, divisor);
64
+void HELPER(v8m_stackcheck)(CPUARMState *env, uint32_t newvalue)
48
}
49
50
if (changed & R_CONTROL_MODE_MASK) {
51
@@ -XXX,XX +XXX,XX @@ static void cmsdk_dualtimermod_reset(CMSDKAPBDualTimerModule *m)
52
* limit must both be set to 0xffff, so we wrap at 16 bits.
53
*/
54
ptimer_set_limit(m->timer, 0xffff, 1);
55
- ptimer_set_freq(m->timer, m->parent->pclk_frq);
56
+ ptimer_set_period_from_clock(m->timer, m->parent->timclk,
57
+ cmsdk_dualtimermod_divisor(m));
58
ptimer_transaction_commit(m->timer);
59
}
60
61
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_dualtimer_reset(DeviceState *dev)
62
s->timeritop = 0;
63
}
64
65
+static void cmsdk_apb_dualtimer_clk_update(void *opaque)
65
+{
66
+{
66
+ /*
67
+ CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(opaque);
67
+ * Perform the v8M stack limit check for SP updates from translated code,
68
+ int i;
68
+ * raising an exception if the limit is breached.
69
+ */
70
+ if (newvalue < v7m_sp_limit(env)) {
71
+ CPUState *cs = CPU(arm_env_get_cpu(env));
72
+
69
+
73
+ /*
70
+ for (i = 0; i < ARRAY_SIZE(s->timermod); i++) {
74
+ * Stack limit exceptions are a rare case, so rather than syncing
71
+ CMSDKAPBDualTimerModule *m = &s->timermod[i];
75
+ * PC/condbits before the call, we use cpu_restore_state() to
72
+ ptimer_transaction_begin(m->timer);
76
+ * get them right before raising the exception.
73
+ ptimer_set_period_from_clock(m->timer, m->parent->timclk,
77
+ */
74
+ cmsdk_dualtimermod_divisor(m));
78
+ cpu_restore_state(cs, GETPC(), true);
75
+ ptimer_transaction_commit(m->timer);
79
+ raise_exception(env, EXCP_STKOF, 0, 1);
80
+ }
76
+ }
81
+}
77
+}
82
+
78
+
83
uint32_t HELPER(add_setq)(CPUARMState *env, uint32_t a, uint32_t b)
79
static void cmsdk_apb_dualtimer_init(Object *obj)
84
{
80
{
85
uint32_t res = a + b;
81
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
86
diff --git a/target/arm/translate.c b/target/arm/translate.c
82
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_dualtimer_init(Object *obj)
87
index XXXXXXX..XXXXXXX 100644
83
for (i = 0; i < ARRAY_SIZE(s->timermod); i++) {
88
--- a/target/arm/translate.c
84
sysbus_init_irq(sbd, &s->timermod[i].timerint);
89
+++ b/target/arm/translate.c
85
}
90
@@ -XXX,XX +XXX,XX @@ static void store_reg(DisasContext *s, int reg, TCGv_i32 var)
86
- s->timclk = qdev_init_clock_in(DEVICE(s), "TIMCLK", NULL, NULL);
91
tcg_temp_free_i32(var);
87
+ s->timclk = qdev_init_clock_in(DEVICE(s), "TIMCLK",
88
+ cmsdk_apb_dualtimer_clk_update, s);
92
}
89
}
93
90
94
+/*
91
static void cmsdk_apb_dualtimer_realize(DeviceState *dev, Error **errp)
95
+ * Variant of store_reg which applies v8M stack-limit checks before updating
92
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_dualtimer_realize(DeviceState *dev, Error **errp)
96
+ * SP. If the check fails this will result in an exception being taken.
93
CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(dev);
97
+ * We disable the stack checks for CONFIG_USER_ONLY because we have
94
int i;
98
+ * no idea what the stack limits should be in that case.
95
99
+ * If stack checking is not being done this just acts like store_reg().
96
- if (s->pclk_frq == 0) {
100
+ */
97
- error_setg(errp, "CMSDK APB timer: pclk-frq property must be set");
101
+static void store_sp_checked(DisasContext *s, TCGv_i32 var)
98
+ if (!clock_has_source(s->timclk)) {
102
+{
99
+ error_setg(errp, "CMSDK APB dualtimer: TIMCLK clock must be connected");
103
+#ifndef CONFIG_USER_ONLY
100
return;
104
+ if (s->v8m_stackcheck) {
101
}
105
+ gen_helper_v8m_stackcheck(cpu_env, var);
102
106
+ }
107
+#endif
108
+ store_reg(s, 13, var);
109
+}
110
+
111
/* Value extensions. */
112
#define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
113
#define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
114
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
115
if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
116
goto illegal_op;
117
tcg_temp_free_i32(tmp2);
118
- if (rd != 15) {
119
+ if (rd == 13 &&
120
+ ((op == 2 && rn == 15) ||
121
+ (op == 8 && rn == 13) ||
122
+ (op == 13 && rn == 13))) {
123
+ /* MOV SP, ... or ADD SP, SP, ... or SUB SP, SP, ... */
124
+ store_sp_checked(s, tmp);
125
+ } else if (rd != 15) {
126
store_reg(s, rd, tmp);
127
} else {
128
tcg_temp_free_i32(tmp);
129
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
130
gen_jmp(s, s->pc + offset);
131
}
132
} else {
133
- /* Data processing immediate. */
134
+ /*
135
+ * 0b1111_0xxx_xxxx_0xxx_xxxx_xxxx
136
+ * - Data-processing (modified immediate, plain binary immediate)
137
+ */
138
if (insn & (1 << 25)) {
139
+ /*
140
+ * 0b1111_0x1x_xxxx_0xxx_xxxx_xxxx
141
+ * - Data-processing (plain binary immediate)
142
+ */
143
if (insn & (1 << 24)) {
144
if (insn & (1 << 20))
145
goto illegal_op;
146
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
147
tmp = tcg_temp_new_i32();
148
tcg_gen_movi_i32(tmp, imm);
149
}
150
+ store_reg(s, rd, tmp);
151
} else {
152
/* Add/sub 12-bit immediate. */
153
if (rn == 15) {
154
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
155
offset += imm;
156
tmp = tcg_temp_new_i32();
157
tcg_gen_movi_i32(tmp, offset);
158
+ store_reg(s, rd, tmp);
159
} else {
160
tmp = load_reg(s, rn);
161
if (insn & (1 << 23))
162
tcg_gen_subi_i32(tmp, tmp, imm);
163
else
164
tcg_gen_addi_i32(tmp, tmp, imm);
165
+ if (rn == 13 && rd == 13) {
166
+ /* ADD SP, SP, imm or SUB SP, SP, imm */
167
+ store_sp_checked(s, tmp);
168
+ } else {
169
+ store_reg(s, rd, tmp);
170
+ }
171
}
172
}
173
- store_reg(s, rd, tmp);
174
}
175
} else {
176
+ /*
177
+ * 0b1111_0x0x_xxxx_0xxx_xxxx_xxxx
178
+ * - Data-processing (modified immediate)
179
+ */
180
int shifter_out = 0;
181
/* modified 12-bit immediate. */
182
shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
183
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
184
goto illegal_op;
185
tcg_temp_free_i32(tmp2);
186
rd = (insn >> 8) & 0xf;
187
- if (rd != 15) {
188
+ if (rd == 13 && rn == 13
189
+ && (op == 8 || op == 13)) {
190
+ /* ADD(S) SP, SP, imm or SUB(S) SP, SP, imm */
191
+ store_sp_checked(s, tmp);
192
+ } else if (rd != 15) {
193
store_reg(s, rd, tmp);
194
} else {
195
tcg_temp_free_i32(tmp);
196
@@ -XXX,XX +XXX,XX @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
197
tmp2 = load_reg(s, rm);
198
tcg_gen_add_i32(tmp, tmp, tmp2);
199
tcg_temp_free_i32(tmp2);
200
- store_reg(s, rd, tmp);
201
+ if (rd == 13) {
202
+ /* ADD SP, SP, reg */
203
+ store_sp_checked(s, tmp);
204
+ } else {
205
+ store_reg(s, rd, tmp);
206
+ }
207
break;
208
case 1: /* cmp */
209
tmp = load_reg(s, rd);
210
@@ -XXX,XX +XXX,XX @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
211
break;
212
case 2: /* mov/cpy */
213
tmp = load_reg(s, rm);
214
- store_reg(s, rd, tmp);
215
+ if (rd == 13) {
216
+ /* MOV SP, reg */
217
+ store_sp_checked(s, tmp);
218
+ } else {
219
+ store_reg(s, rd, tmp);
220
+ }
221
break;
222
case 3:
223
{
224
@@ -XXX,XX +XXX,XX @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
225
break;
226
227
case 10:
228
- /* add to high reg */
229
+ /*
230
+ * 0b1010_xxxx_xxxx_xxxx
231
+ * - Add PC/SP (immediate)
232
+ */
233
rd = (insn >> 8) & 7;
234
if (insn & (1 << 11)) {
235
/* SP */
236
@@ -XXX,XX +XXX,XX @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
237
op = (insn >> 8) & 0xf;
238
switch (op) {
239
case 0:
240
- /* adjust stack pointer */
241
+ /*
242
+ * 0b1011_0000_xxxx_xxxx
243
+ * - ADD (SP plus immediate)
244
+ * - SUB (SP minus immediate)
245
+ */
246
tmp = load_reg(s, 13);
247
val = (insn & 0x7f) * 4;
248
if (insn & (1 << 7))
249
val = -(int32_t)val;
250
tcg_gen_addi_i32(tmp, tmp, val);
251
- store_reg(s, 13, tmp);
252
+ store_sp_checked(s, tmp);
253
break;
254
255
case 2: /* sign/zero extend. */
256
--
103
--
257
2.19.0
104
2.20.1
258
105
259
106
diff view generated by jsdifflib
1
Check the v8M stack limits when pushing the frame for a
1
Switch the CMSDK APB watchdog device over to using its Clock input;
2
non-secure function call via BLXNS.
2
the wdogclk_frq property is now ignored.
3
4
In order to be able to generate the exception we need to
5
promote raise_exception() from being local to op_helper.c
6
so we can call it from helper.c.
7
3
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Luc Michel <luc@lmichel.fr>
11
Message-id: 20181002163556.10279-8-peter.maydell@linaro.org
7
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20210128114145.20536-21-peter.maydell@linaro.org
9
Message-id: 20210121190622.22000-21-peter.maydell@linaro.org
12
---
10
---
13
target/arm/internals.h | 9 +++++++++
11
hw/watchdog/cmsdk-apb-watchdog.c | 18 ++++++++++++++----
14
target/arm/helper.c | 4 ++++
12
1 file changed, 14 insertions(+), 4 deletions(-)
15
target/arm/op_helper.c | 4 ++--
16
3 files changed, 15 insertions(+), 2 deletions(-)
17
13
18
diff --git a/target/arm/internals.h b/target/arm/internals.h
14
diff --git a/hw/watchdog/cmsdk-apb-watchdog.c b/hw/watchdog/cmsdk-apb-watchdog.c
19
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/internals.h
16
--- a/hw/watchdog/cmsdk-apb-watchdog.c
21
+++ b/target/arm/internals.h
17
+++ b/hw/watchdog/cmsdk-apb-watchdog.c
22
@@ -XXX,XX +XXX,XX @@ FIELD(V7M_EXCRET, RES1, 7, 25) /* including the must-be-1 prefix */
18
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_watchdog_reset(DeviceState *dev)
23
#define M_FAKE_FSR_NSC_EXEC 0xf /* NS executing in S&NSC memory */
19
ptimer_transaction_commit(s->timer);
24
#define M_FAKE_FSR_SFAULT 0xe /* SecureFault INVTRAN, INVEP or AUVIOL */
20
}
25
21
26
+/**
22
+static void cmsdk_apb_watchdog_clk_update(void *opaque)
27
+ * raise_exception: Raise the specified exception.
23
+{
28
+ * Raise a guest exception with the specified value, syndrome register
24
+ CMSDKAPBWatchdog *s = CMSDK_APB_WATCHDOG(opaque);
29
+ * and target exception level. This should be called from helper functions,
30
+ * and never returns because we will longjump back up to the CPU main loop.
31
+ */
32
+void QEMU_NORETURN raise_exception(CPUARMState *env, uint32_t excp,
33
+ uint32_t syndrome, uint32_t target_el);
34
+
25
+
35
/*
26
+ ptimer_transaction_begin(s->timer);
36
* For AArch64, map a given EL to an index in the banked_spsr array.
27
+ ptimer_set_period_from_clock(s->timer, s->wdogclk, 1);
37
* Note that this mapping and the AArch32 mapping defined in bank_number()
28
+ ptimer_transaction_commit(s->timer);
38
diff --git a/target/arm/helper.c b/target/arm/helper.c
29
+}
39
index XXXXXXX..XXXXXXX 100644
30
+
40
--- a/target/arm/helper.c
31
static void cmsdk_apb_watchdog_init(Object *obj)
41
+++ b/target/arm/helper.c
32
{
42
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_blxns)(CPUARMState *env, uint32_t dest)
33
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
43
"BLXNS with misaligned SP is UNPREDICTABLE\n");
34
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_watchdog_init(Object *obj)
35
s, "cmsdk-apb-watchdog", 0x1000);
36
sysbus_init_mmio(sbd, &s->iomem);
37
sysbus_init_irq(sbd, &s->wdogint);
38
- s->wdogclk = qdev_init_clock_in(DEVICE(s), "WDOGCLK", NULL, NULL);
39
+ s->wdogclk = qdev_init_clock_in(DEVICE(s), "WDOGCLK",
40
+ cmsdk_apb_watchdog_clk_update, s);
41
42
s->is_luminary = false;
43
s->id = cmsdk_apb_watchdog_id;
44
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_watchdog_realize(DeviceState *dev, Error **errp)
45
{
46
CMSDKAPBWatchdog *s = CMSDK_APB_WATCHDOG(dev);
47
48
- if (s->wdogclk_frq == 0) {
49
+ if (!clock_has_source(s->wdogclk)) {
50
error_setg(errp,
51
- "CMSDK APB watchdog: wdogclk-frq property must be set");
52
+ "CMSDK APB watchdog: WDOGCLK clock must be connected");
53
return;
44
}
54
}
45
55
46
+ if (sp < v7m_sp_limit(env)) {
56
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_watchdog_realize(DeviceState *dev, Error **errp)
47
+ raise_exception(env, EXCP_STKOF, 0, 1);
57
PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
48
+ }
58
49
+
59
ptimer_transaction_begin(s->timer);
50
saved_psr = env->v7m.exception;
60
- ptimer_set_freq(s->timer, s->wdogclk_frq);
51
if (env->v7m.control[M_REG_S] & R_V7M_CONTROL_SFPA_MASK) {
61
+ ptimer_set_period_from_clock(s->timer, s->wdogclk, 1);
52
saved_psr |= XPSR_SFPA;
62
ptimer_transaction_commit(s->timer);
53
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
63
}
54
index XXXXXXX..XXXXXXX 100644
55
--- a/target/arm/op_helper.c
56
+++ b/target/arm/op_helper.c
57
@@ -XXX,XX +XXX,XX @@
58
#define SIGNBIT (uint32_t)0x80000000
59
#define SIGNBIT64 ((uint64_t)1 << 63)
60
61
-static void raise_exception(CPUARMState *env, uint32_t excp,
62
- uint32_t syndrome, uint32_t target_el)
63
+void raise_exception(CPUARMState *env, uint32_t excp,
64
+ uint32_t syndrome, uint32_t target_el)
65
{
66
CPUState *cs = CPU(arm_env_get_cpu(env));
67
64
68
--
65
--
69
2.19.0
66
2.20.1
70
67
71
68
diff view generated by jsdifflib
1
The Arm v8M architecture includes hardware stack limit checking.
1
Now that the CMSDK APB watchdog uses its Clock input, it will
2
When certain instructions update the stack pointer, if the new
2
correctly respond when the system clock frequency is changed using
3
value of SP is below the limit set in the associated limit register
3
the RCC register on in the Stellaris board system registers. Test
4
then an exception is taken. Add a TB flag that tracks whether
4
that when the RCC register is written it causes the watchdog timer to
5
the limit-checking code needs to be emitted.
5
change speed.
6
6
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Reviewed-by: Luc Michel <luc@lmichel.fr>
10
Message-id: 20181002163556.10279-2-peter.maydell@linaro.org
10
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Message-id: 20210128114145.20536-22-peter.maydell@linaro.org
12
Message-id: 20210121190622.22000-22-peter.maydell@linaro.org
11
---
13
---
12
target/arm/cpu.h | 7 +++++++
14
tests/qtest/cmsdk-apb-watchdog-test.c | 52 +++++++++++++++++++++++++++
13
target/arm/translate.h | 1 +
15
1 file changed, 52 insertions(+)
14
target/arm/helper.c | 10 ++++++++++
15
target/arm/translate.c | 1 +
16
4 files changed, 19 insertions(+)
17
16
18
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
diff --git a/tests/qtest/cmsdk-apb-watchdog-test.c b/tests/qtest/cmsdk-apb-watchdog-test.c
19
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/cpu.h
19
--- a/tests/qtest/cmsdk-apb-watchdog-test.c
21
+++ b/target/arm/cpu.h
20
+++ b/tests/qtest/cmsdk-apb-watchdog-test.c
22
@@ -XXX,XX +XXX,XX @@ FIELD(V7M_CCR, UNALIGN_TRP, 3, 1)
21
@@ -XXX,XX +XXX,XX @@
23
FIELD(V7M_CCR, DIV_0_TRP, 4, 1)
22
*/
24
FIELD(V7M_CCR, BFHFNMIGN, 8, 1)
23
25
FIELD(V7M_CCR, STKALIGN, 9, 1)
24
#include "qemu/osdep.h"
26
+FIELD(V7M_CCR, STKOFHFNMIGN, 10, 1)
25
+#include "qemu/bitops.h"
27
FIELD(V7M_CCR, DC, 16, 1)
26
#include "libqtest-single.h"
28
FIELD(V7M_CCR, IC, 17, 1)
27
29
+FIELD(V7M_CCR, BP, 18, 1)
28
/*
30
29
@@ -XXX,XX +XXX,XX @@
31
/* V7M SCR bits */
30
#define WDOGMIS 0x14
32
FIELD(V7M_SCR, SLEEPONEXIT, 1, 1)
31
#define WDOGLOCK 0xc00
33
@@ -XXX,XX +XXX,XX @@ static inline bool arm_cpu_data_is_big_endian(CPUARMState *env)
32
34
/* For M profile only, Handler (ie not Thread) mode */
33
+#define SSYS_BASE 0x400fe000
35
#define ARM_TBFLAG_HANDLER_SHIFT 21
34
+#define RCC 0x60
36
#define ARM_TBFLAG_HANDLER_MASK (1 << ARM_TBFLAG_HANDLER_SHIFT)
35
+#define SYSDIV_SHIFT 23
37
+/* For M profile only, whether we should generate stack-limit checks */
36
+#define SYSDIV_LENGTH 4
38
+#define ARM_TBFLAG_STACKCHECK_SHIFT 22
37
+
39
+#define ARM_TBFLAG_STACKCHECK_MASK (1 << ARM_TBFLAG_STACKCHECK_SHIFT)
38
static void test_watchdog(void)
40
39
{
41
/* Bit usage when in AArch64 state */
40
g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 0);
42
#define ARM_TBFLAG_TBI0_SHIFT 0 /* TBI0 for EL0/1 or TBI for EL2/3 */
41
@@ -XXX,XX +XXX,XX @@ static void test_watchdog(void)
43
@@ -XXX,XX +XXX,XX @@ static inline bool arm_cpu_data_is_big_endian(CPUARMState *env)
42
g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 0);
44
(((F) & ARM_TBFLAG_BE_DATA_MASK) >> ARM_TBFLAG_BE_DATA_SHIFT)
43
}
45
#define ARM_TBFLAG_HANDLER(F) \
44
46
(((F) & ARM_TBFLAG_HANDLER_MASK) >> ARM_TBFLAG_HANDLER_SHIFT)
45
+static void test_clock_change(void)
47
+#define ARM_TBFLAG_STACKCHECK(F) \
46
+{
48
+ (((F) & ARM_TBFLAG_STACKCHECK_MASK) >> ARM_TBFLAG_STACKCHECK_SHIFT)
47
+ uint32_t rcc;
49
#define ARM_TBFLAG_TBI0(F) \
48
+
50
(((F) & ARM_TBFLAG_TBI0_MASK) >> ARM_TBFLAG_TBI0_SHIFT)
49
+ /*
51
#define ARM_TBFLAG_TBI1(F) \
50
+ * Test that writing to the stellaris board's RCC register to
52
diff --git a/target/arm/translate.h b/target/arm/translate.h
51
+ * change the system clock frequency causes the watchdog
53
index XXXXXXX..XXXXXXX 100644
52
+ * to change the speed it counts at.
54
--- a/target/arm/translate.h
55
+++ b/target/arm/translate.h
56
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
57
int vec_stride;
58
bool v7m_handler_mode;
59
bool v8m_secure; /* true if v8M and we're in Secure mode */
60
+ bool v8m_stackcheck; /* true if we need to perform v8M stack limit checks */
61
/* Immediate value in AArch32 SVC insn; must be set if is_jmp == DISAS_SWI
62
* so that top level loop can generate correct syndrome information.
63
*/
64
diff --git a/target/arm/helper.c b/target/arm/helper.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/target/arm/helper.c
67
+++ b/target/arm/helper.c
68
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
69
flags |= ARM_TBFLAG_HANDLER_MASK;
70
}
71
72
+ /* v8M always applies stack limit checks unless CCR.STKOFHFNMIGN is
73
+ * suppressing them because the requested execution priority is less than 0.
74
+ */
53
+ */
75
+ if (arm_feature(env, ARM_FEATURE_V8) &&
54
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 0);
76
+ arm_feature(env, ARM_FEATURE_M) &&
77
+ !((mmu_idx & ARM_MMU_IDX_M_NEGPRI) &&
78
+ (env->v7m.ccr[env->v7m.secure] & R_V7M_CCR_STKOFHFNMIGN_MASK))) {
79
+ flags |= ARM_TBFLAG_STACKCHECK_MASK;
80
+ }
81
+
55
+
82
*pflags = flags;
56
+ writel(WDOG_BASE + WDOGCONTROL, 1);
83
*cs_base = 0;
57
+ writel(WDOG_BASE + WDOGLOAD, 1000);
84
}
58
+
85
diff --git a/target/arm/translate.c b/target/arm/translate.c
59
+ /* Step to just past the 500th tick */
86
index XXXXXXX..XXXXXXX 100644
60
+ clock_step(80 * 500 + 1);
87
--- a/target/arm/translate.c
61
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 0);
88
+++ b/target/arm/translate.c
62
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 500);
89
@@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
63
+
90
dc->v7m_handler_mode = ARM_TBFLAG_HANDLER(dc->base.tb->flags);
64
+ /* Rewrite RCC.SYSDIV from 16 to 8, so the clock is now 40ns per tick */
91
dc->v8m_secure = arm_feature(env, ARM_FEATURE_M_SECURITY) &&
65
+ rcc = readl(SSYS_BASE + RCC);
92
regime_is_secure(env, dc->mmu_idx);
66
+ g_assert_cmpuint(extract32(rcc, SYSDIV_SHIFT, SYSDIV_LENGTH), ==, 0xf);
93
+ dc->v8m_stackcheck = ARM_TBFLAG_STACKCHECK(dc->base.tb->flags);
67
+ rcc = deposit32(rcc, SYSDIV_SHIFT, SYSDIV_LENGTH, 7);
94
dc->cp_regs = cpu->cp_regs;
68
+ writel(SSYS_BASE + RCC, rcc);
95
dc->features = env->features;
69
+
70
+ /* Just past the 1000th tick: timer should have fired */
71
+ clock_step(40 * 500);
72
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 1);
73
+
74
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 0);
75
+
76
+ /* VALUE reloads at following tick */
77
+ clock_step(41);
78
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 1000);
79
+
80
+ /* Writing any value to WDOGINTCLR clears the interrupt and reloads */
81
+ clock_step(40 * 500);
82
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 500);
83
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 1);
84
+ writel(WDOG_BASE + WDOGINTCLR, 0);
85
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 1000);
86
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 0);
87
+}
88
+
89
int main(int argc, char **argv)
90
{
91
int r;
92
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
93
qtest_start("-machine lm3s811evb");
94
95
qtest_add_func("/cmsdk-apb-watchdog/watchdog", test_watchdog);
96
+ qtest_add_func("/cmsdk-apb-watchdog/watchdog_clock_change",
97
+ test_clock_change);
98
99
r = g_test_run();
96
100
97
--
101
--
98
2.19.0
102
2.20.1
99
103
100
104
diff view generated by jsdifflib
1
We're going to want v7m_using_psp() in op_helper.c in the
1
Use the MAINCLK Clock input to set the system_clock_scale variable
2
next patch, so move it from helper.c to internals.h.
2
rather than using the mainclk_frq property.
3
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20181002163556.10279-4-peter.maydell@linaro.org
7
Reviewed-by: Luc Michel <luc@lmichel.fr>
8
Message-id: 20210128114145.20536-23-peter.maydell@linaro.org
9
Message-id: 20210121190622.22000-23-peter.maydell@linaro.org
8
---
10
---
9
target/arm/internals.h | 16 ++++++++++++++++
11
hw/arm/armsse.c | 24 +++++++++++++++++++-----
10
target/arm/helper.c | 12 ------------
12
1 file changed, 19 insertions(+), 5 deletions(-)
11
2 files changed, 16 insertions(+), 12 deletions(-)
12
13
13
diff --git a/target/arm/internals.h b/target/arm/internals.h
14
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/internals.h
16
--- a/hw/arm/armsse.c
16
+++ b/target/arm/internals.h
17
+++ b/hw/arm/armsse.c
17
@@ -XXX,XX +XXX,XX @@ static inline uint32_t arm_debug_exception_fsr(CPUARMState *env)
18
@@ -XXX,XX +XXX,XX @@ static void armsse_forward_sec_resp_cfg(ARMSSE *s)
18
*/
19
qdev_connect_gpio_out(dev_splitter, 2, s->sec_resp_cfg_in);
19
#define MEMOPIDX_SHIFT 8
20
}
20
21
21
+/**
22
+static void armsse_mainclk_update(void *opaque)
22
+ * v7m_using_psp: Return true if using process stack pointer
23
+ * Return true if the CPU is currently using the process stack
24
+ * pointer, or false if it is using the main stack pointer.
25
+ */
26
+static inline bool v7m_using_psp(CPUARMState *env)
27
+{
23
+{
28
+ /* Handler mode always uses the main stack; for thread mode
24
+ ARMSSE *s = ARM_SSE(opaque);
29
+ * the CONTROL.SPSEL bit determines the answer.
25
+ /*
30
+ * Note that in v7M it is not possible to be in Handler mode with
26
+ * Set system_clock_scale from our Clock input; this is what
31
+ * CONTROL.SPSEL non-zero, but in v8M it is, so we must check both.
27
+ * controls the tick rate of the CPU SysTick timer.
32
+ */
28
+ */
33
+ return !arm_v7m_is_handler_mode(env) &&
29
+ system_clock_scale = clock_ticks_to_ns(s->mainclk, 1);
34
+ env->v7m.control[env->v7m.secure] & R_V7M_CONTROL_SPSEL_MASK;
35
+}
30
+}
36
+
31
+
37
#endif
32
static void armsse_init(Object *obj)
38
diff --git a/target/arm/helper.c b/target/arm/helper.c
33
{
39
index XXXXXXX..XXXXXXX 100644
34
ARMSSE *s = ARM_SSE(obj);
40
--- a/target/arm/helper.c
35
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
41
+++ b/target/arm/helper.c
36
assert(info->sram_banks <= MAX_SRAM_BANKS);
42
@@ -XXX,XX +XXX,XX @@ pend_fault:
37
assert(info->num_cpus <= SSE_MAX_CPUS);
43
return false;
38
39
- s->mainclk = qdev_init_clock_in(DEVICE(s), "MAINCLK", NULL, NULL);
40
+ s->mainclk = qdev_init_clock_in(DEVICE(s), "MAINCLK",
41
+ armsse_mainclk_update, s);
42
s->s32kclk = qdev_init_clock_in(DEVICE(s), "S32KCLK", NULL, NULL);
43
44
memory_region_init(&s->container, obj, "armsse-container", UINT64_MAX);
45
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
46
return;
47
}
48
49
- if (!s->mainclk_frq) {
50
- error_setg(errp, "MAINCLK_FRQ property was not set");
51
- return;
52
+ if (!clock_has_source(s->mainclk)) {
53
+ error_setg(errp, "MAINCLK clock was not connected");
54
+ }
55
+ if (!clock_has_source(s->s32kclk)) {
56
+ error_setg(errp, "S32KCLK clock was not connected");
57
}
58
59
assert(info->num_cpus <= SSE_MAX_CPUS);
60
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
61
*/
62
sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->container);
63
64
- system_clock_scale = NANOSECONDS_PER_SECOND / s->mainclk_frq;
65
+ /* Set initial system_clock_scale from MAINCLK */
66
+ armsse_mainclk_update(s);
44
}
67
}
45
68
46
-/* Return true if we're using the process stack pointer (not the MSP) */
69
static void armsse_idau_check(IDAUInterface *ii, uint32_t address,
47
-static bool v7m_using_psp(CPUARMState *env)
48
-{
49
- /* Handler mode always uses the main stack; for thread mode
50
- * the CONTROL.SPSEL bit determines the answer.
51
- * Note that in v7M it is not possible to be in Handler mode with
52
- * CONTROL.SPSEL non-zero, but in v8M it is, so we must check both.
53
- */
54
- return !arm_v7m_is_handler_mode(env) &&
55
- env->v7m.control[env->v7m.secure] & R_V7M_CONTROL_SPSEL_MASK;
56
-}
57
-
58
/* Write to v7M CONTROL.SPSEL bit for the specified security bank.
59
* This may change the current stack pointer between Main and Process
60
* stack pointers if it is done for the CONTROL register for the current
61
--
70
--
62
2.19.0
71
2.20.1
63
72
64
73
diff view generated by jsdifflib
1
Add some comments to the Thumb decoder indicating what bits
1
Remove all the code that sets frequency properties on the CMSDK
2
of the instruction have been decoded at various points in
2
timer, dualtimer and watchdog devices and on the ARMSSE SoC device:
3
the code.
3
these properties are unused now that the devices rely on their Clock
4
4
inputs instead.
5
This is not an exhaustive set of comments; we're gradually
6
adding comments as we work with particular bits of the code.
7
5
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Luc Michel <luc@lmichel.fr>
11
Message-id: 20181002163556.10279-6-peter.maydell@linaro.org
9
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Message-id: 20210128114145.20536-24-peter.maydell@linaro.org
11
Message-id: 20210121190622.22000-24-peter.maydell@linaro.org
12
---
12
---
13
target/arm/translate.c | 20 +++++++++++++++++---
13
hw/arm/armsse.c | 7 -------
14
1 file changed, 17 insertions(+), 3 deletions(-)
14
hw/arm/mps2-tz.c | 1 -
15
hw/arm/mps2.c | 3 ---
16
hw/arm/musca.c | 1 -
17
hw/arm/stellaris.c | 3 ---
18
5 files changed, 15 deletions(-)
15
19
16
diff --git a/target/arm/translate.c b/target/arm/translate.c
20
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
17
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/translate.c
22
--- a/hw/arm/armsse.c
19
+++ b/target/arm/translate.c
23
+++ b/hw/arm/armsse.c
20
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
24
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
21
tmp2 = load_reg(s, rm);
25
* it to the appropriate PPC port; then we can realize the PPC and
22
if ((insn & 0x70) != 0)
26
* map its upstream ends to the right place in the container.
23
goto illegal_op;
27
*/
24
+ /*
28
- qdev_prop_set_uint32(DEVICE(&s->timer0), "pclk-frq", s->mainclk_frq);
25
+ * 0b1111_1010_0xxx_xxxx_1111_xxxx_0000_xxxx:
29
qdev_connect_clock_in(DEVICE(&s->timer0), "pclk", s->mainclk);
26
+ * - MOV, MOVS (register-shifted register), flagsetting
30
if (!sysbus_realize(SYS_BUS_DEVICE(&s->timer0), errp)) {
27
+ */
31
return;
28
op = (insn >> 21) & 3;
32
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
29
logic_cc = (insn & (1 << 20)) != 0;
33
object_property_set_link(OBJECT(&s->apb_ppc0), "port[0]", OBJECT(mr),
30
gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
34
&error_abort);
31
@@ -XXX,XX +XXX,XX @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
35
32
rd = insn & 7;
36
- qdev_prop_set_uint32(DEVICE(&s->timer1), "pclk-frq", s->mainclk_frq);
33
op = (insn >> 11) & 3;
37
qdev_connect_clock_in(DEVICE(&s->timer1), "pclk", s->mainclk);
34
if (op == 3) {
38
if (!sysbus_realize(SYS_BUS_DEVICE(&s->timer1), errp)) {
35
- /* add/subtract */
39
return;
36
+ /*
40
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
37
+ * 0b0001_1xxx_xxxx_xxxx
41
object_property_set_link(OBJECT(&s->apb_ppc0), "port[1]", OBJECT(mr),
38
+ * - Add, subtract (three low registers)
42
&error_abort);
39
+ * - Add, subtract (two low registers and immediate)
43
40
+ */
44
- qdev_prop_set_uint32(DEVICE(&s->dualtimer), "pclk-frq", s->mainclk_frq);
41
rn = (insn >> 3) & 7;
45
qdev_connect_clock_in(DEVICE(&s->dualtimer), "TIMCLK", s->mainclk);
42
tmp = load_reg(s, rn);
46
if (!sysbus_realize(SYS_BUS_DEVICE(&s->dualtimer), errp)) {
43
if (insn & (1 << 10)) {
47
return;
44
@@ -XXX,XX +XXX,XX @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
48
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
45
}
49
/* Devices behind APB PPC1:
46
break;
50
* 0x4002f000: S32K timer
47
case 2: case 3:
51
*/
48
- /* arithmetic large immediate */
52
- qdev_prop_set_uint32(DEVICE(&s->s32ktimer), "pclk-frq", S32KCLK);
49
+ /*
53
qdev_connect_clock_in(DEVICE(&s->s32ktimer), "pclk", s->s32kclk);
50
+ * 0b001x_xxxx_xxxx_xxxx
54
if (!sysbus_realize(SYS_BUS_DEVICE(&s->s32ktimer), errp)) {
51
+ * - Add, subtract, compare, move (one low register and immediate)
55
return;
52
+ */
56
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
53
op = (insn >> 11) & 3;
57
qdev_connect_gpio_out(DEVICE(&s->nmi_orgate), 0,
54
rd = (insn >> 8) & 0x7;
58
qdev_get_gpio_in_named(DEVICE(&s->armv7m), "NMI", 0));
55
if (op == 0) { /* mov */
59
56
@@ -XXX,XX +XXX,XX @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
60
- qdev_prop_set_uint32(DEVICE(&s->s32kwatchdog), "wdogclk-frq", S32KCLK);
57
break;
61
qdev_connect_clock_in(DEVICE(&s->s32kwatchdog), "WDOGCLK", s->s32kclk);
58
}
62
if (!sysbus_realize(SYS_BUS_DEVICE(&s->s32kwatchdog), errp)) {
59
63
return;
60
- /* data processing register */
64
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
61
+ /*
65
62
+ * 0b0100_00xx_xxxx_xxxx
66
/* 0x40080000 .. 0x4008ffff : ARMSSE second Base peripheral region */
63
+ * - Data-processing (two low registers)
67
64
+ */
68
- qdev_prop_set_uint32(DEVICE(&s->nswatchdog), "wdogclk-frq", s->mainclk_frq);
65
rd = insn & 7;
69
qdev_connect_clock_in(DEVICE(&s->nswatchdog), "WDOGCLK", s->mainclk);
66
rm = (insn >> 3) & 7;
70
if (!sysbus_realize(SYS_BUS_DEVICE(&s->nswatchdog), errp)) {
67
op = (insn >> 6) & 0xf;
71
return;
72
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
73
armsse_get_common_irq_in(s, 1));
74
sysbus_mmio_map(SYS_BUS_DEVICE(&s->nswatchdog), 0, 0x40081000);
75
76
- qdev_prop_set_uint32(DEVICE(&s->swatchdog), "wdogclk-frq", s->mainclk_frq);
77
qdev_connect_clock_in(DEVICE(&s->swatchdog), "WDOGCLK", s->mainclk);
78
if (!sysbus_realize(SYS_BUS_DEVICE(&s->swatchdog), errp)) {
79
return;
80
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
81
index XXXXXXX..XXXXXXX 100644
82
--- a/hw/arm/mps2-tz.c
83
+++ b/hw/arm/mps2-tz.c
84
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
85
object_property_set_link(OBJECT(&mms->iotkit), "memory",
86
OBJECT(system_memory), &error_abort);
87
qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", MPS2TZ_NUMIRQ);
88
- qdev_prop_set_uint32(iotkitdev, "MAINCLK_FRQ", SYSCLK_FRQ);
89
qdev_connect_clock_in(iotkitdev, "MAINCLK", mms->sysclk);
90
qdev_connect_clock_in(iotkitdev, "S32KCLK", mms->s32kclk);
91
sysbus_realize(SYS_BUS_DEVICE(&mms->iotkit), &error_fatal);
92
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
93
index XXXXXXX..XXXXXXX 100644
94
--- a/hw/arm/mps2.c
95
+++ b/hw/arm/mps2.c
96
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
97
object_initialize_child(OBJECT(mms), name, &mms->timer[i],
98
TYPE_CMSDK_APB_TIMER);
99
sbd = SYS_BUS_DEVICE(&mms->timer[i]);
100
- qdev_prop_set_uint32(DEVICE(&mms->timer[i]), "pclk-frq", SYSCLK_FRQ);
101
qdev_connect_clock_in(DEVICE(&mms->timer[i]), "pclk", mms->sysclk);
102
sysbus_realize_and_unref(sbd, &error_fatal);
103
sysbus_mmio_map(sbd, 0, base);
104
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
105
106
object_initialize_child(OBJECT(mms), "dualtimer", &mms->dualtimer,
107
TYPE_CMSDK_APB_DUALTIMER);
108
- qdev_prop_set_uint32(DEVICE(&mms->dualtimer), "pclk-frq", SYSCLK_FRQ);
109
qdev_connect_clock_in(DEVICE(&mms->dualtimer), "TIMCLK", mms->sysclk);
110
sysbus_realize(SYS_BUS_DEVICE(&mms->dualtimer), &error_fatal);
111
sysbus_connect_irq(SYS_BUS_DEVICE(&mms->dualtimer), 0,
112
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
113
sysbus_mmio_map(SYS_BUS_DEVICE(&mms->dualtimer), 0, 0x40002000);
114
object_initialize_child(OBJECT(mms), "watchdog", &mms->watchdog,
115
TYPE_CMSDK_APB_WATCHDOG);
116
- qdev_prop_set_uint32(DEVICE(&mms->watchdog), "wdogclk-frq", SYSCLK_FRQ);
117
qdev_connect_clock_in(DEVICE(&mms->watchdog), "WDOGCLK", mms->sysclk);
118
sysbus_realize(SYS_BUS_DEVICE(&mms->watchdog), &error_fatal);
119
sysbus_connect_irq(SYS_BUS_DEVICE(&mms->watchdog), 0,
120
diff --git a/hw/arm/musca.c b/hw/arm/musca.c
121
index XXXXXXX..XXXXXXX 100644
122
--- a/hw/arm/musca.c
123
+++ b/hw/arm/musca.c
124
@@ -XXX,XX +XXX,XX @@ static void musca_init(MachineState *machine)
125
qdev_prop_set_uint32(ssedev, "EXP_NUMIRQ", mmc->num_irqs);
126
qdev_prop_set_uint32(ssedev, "init-svtor", mmc->init_svtor);
127
qdev_prop_set_uint32(ssedev, "SRAM_ADDR_WIDTH", mmc->sram_addr_width);
128
- qdev_prop_set_uint32(ssedev, "MAINCLK_FRQ", SYSCLK_FRQ);
129
qdev_connect_clock_in(ssedev, "MAINCLK", mms->sysclk);
130
qdev_connect_clock_in(ssedev, "S32KCLK", mms->s32kclk);
131
/*
132
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
133
index XXXXXXX..XXXXXXX 100644
134
--- a/hw/arm/stellaris.c
135
+++ b/hw/arm/stellaris.c
136
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
137
if (board->dc1 & (1 << 3)) { /* watchdog present */
138
dev = qdev_new(TYPE_LUMINARY_WATCHDOG);
139
140
- /* system_clock_scale is valid now */
141
- uint32_t mainclk = NANOSECONDS_PER_SECOND / system_clock_scale;
142
- qdev_prop_set_uint32(dev, "wdogclk-frq", mainclk);
143
qdev_connect_clock_in(dev, "WDOGCLK",
144
qdev_get_clock_out(ssys_dev, "SYSCLK"));
145
68
--
146
--
69
2.19.0
147
2.20.1
70
148
71
149
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Now no users are setting the frq properties on the CMSDK timer,
2
dualtimer, watchdog or ARMSSE SoC devices, we can remove the
3
properties and the struct fields that back them.
2
4
3
Use the same *_tlb primitives as we use for ld1.
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Luc Michel <luc@lmichel.fr>
8
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20210128114145.20536-25-peter.maydell@linaro.org
10
Message-id: 20210121190622.22000-25-peter.maydell@linaro.org
11
---
12
include/hw/arm/armsse.h | 2 --
13
include/hw/timer/cmsdk-apb-dualtimer.h | 2 --
14
include/hw/timer/cmsdk-apb-timer.h | 2 --
15
include/hw/watchdog/cmsdk-apb-watchdog.h | 2 --
16
hw/arm/armsse.c | 2 --
17
hw/timer/cmsdk-apb-dualtimer.c | 6 ------
18
hw/timer/cmsdk-apb-timer.c | 6 ------
19
hw/watchdog/cmsdk-apb-watchdog.c | 6 ------
20
8 files changed, 28 deletions(-)
4
21
5
For linux-user, this hoists the set of helper_retaddr. For softmmu,
22
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
6
hoists the computation of the current mmu_idx outside the loop,
7
fixes the endianness problem, and moves the main loop out of a
8
macro and into an inlined function.
9
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20181005175350.30752-9-richard.henderson@linaro.org
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
16
target/arm/sve_helper.c | 210 ++++++++++++++++++++++------------------
17
1 file changed, 117 insertions(+), 93 deletions(-)
18
19
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
20
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/sve_helper.c
24
--- a/include/hw/arm/armsse.h
22
+++ b/target/arm/sve_helper.c
25
+++ b/include/hw/arm/armsse.h
23
@@ -XXX,XX +XXX,XX @@ DO_LD1_2(ld1dd, 3, 3)
26
@@ -XXX,XX +XXX,XX @@
24
#undef DO_LD1_1
27
* + Clock input "S32KCLK": slow 32KHz clock used for a few peripherals
25
#undef DO_LD1_2
28
* + QOM property "memory" is a MemoryRegion containing the devices provided
26
29
* by the board model.
27
-#define DO_LD2(NAME, FN, TYPEE, TYPEM, H) \
30
- * + QOM property "MAINCLK_FRQ" is the frequency of the main system clock
28
-void HELPER(NAME)(CPUARMState *env, void *vg, \
31
* + QOM property "EXP_NUMIRQ" sets the number of expansion interrupts.
29
- target_ulong addr, uint32_t desc) \
32
* (In hardware, the SSE-200 permits the number of expansion interrupts
30
-{ \
33
* for the two CPUs to be configured separately, but we restrict it to
31
- intptr_t i, oprsz = simd_oprsz(desc); \
34
@@ -XXX,XX +XXX,XX @@ struct ARMSSE {
32
- intptr_t ra = GETPC(); \
35
/* Properties */
33
- unsigned rd = simd_data(desc); \
36
MemoryRegion *board_memory;
34
- void *d1 = &env->vfp.zregs[rd]; \
37
uint32_t exp_numirq;
35
- void *d2 = &env->vfp.zregs[(rd + 1) & 31]; \
38
- uint32_t mainclk_frq;
36
- for (i = 0; i < oprsz; ) { \
39
uint32_t sram_addr_width;
37
- uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
40
uint32_t init_svtor;
38
- do { \
41
bool cpu_fpu[SSE_MAX_CPUS];
39
- TYPEM m1 = 0, m2 = 0; \
42
diff --git a/include/hw/timer/cmsdk-apb-dualtimer.h b/include/hw/timer/cmsdk-apb-dualtimer.h
40
- if (pg & 1) { \
43
index XXXXXXX..XXXXXXX 100644
41
- m1 = FN(env, addr, ra); \
44
--- a/include/hw/timer/cmsdk-apb-dualtimer.h
42
- m2 = FN(env, addr + sizeof(TYPEM), ra); \
45
+++ b/include/hw/timer/cmsdk-apb-dualtimer.h
43
- } \
46
@@ -XXX,XX +XXX,XX @@
44
- *(TYPEE *)(d1 + H(i)) = m1; \
47
* https://developer.arm.com/products/system-design/system-design-kits/cortex-m-system-design-kit
45
- *(TYPEE *)(d2 + H(i)) = m2; \
48
*
46
- i += sizeof(TYPEE), pg >>= sizeof(TYPEE); \
49
* QEMU interface:
47
- addr += 2 * sizeof(TYPEM); \
50
- * + QOM property "pclk-frq": frequency at which the timer is clocked
48
- } while (i & 15); \
51
* + Clock input "TIMCLK": clock (for both timers)
49
- } \
52
* + sysbus MMIO region 0: the register bank
50
+/*
53
* + sysbus IRQ 0: combined timer interrupt TIMINTC
51
+ * Common helpers for all contiguous 2,3,4-register predicated loads.
54
@@ -XXX,XX +XXX,XX @@ struct CMSDKAPBDualTimer {
52
+ */
55
/*< public >*/
53
+static void sve_ld2_r(CPUARMState *env, void *vg, target_ulong addr,
56
MemoryRegion iomem;
54
+ uint32_t desc, int size, uintptr_t ra,
57
qemu_irq timerintc;
55
+ sve_ld1_tlb_fn *tlb_fn)
58
- uint32_t pclk_frq;
56
+{
59
Clock *timclk;
57
+ const int mmu_idx = cpu_mmu_index(env, false);
60
58
+ intptr_t i, oprsz = simd_oprsz(desc);
61
CMSDKAPBDualTimerModule timermod[CMSDK_APB_DUALTIMER_NUM_MODULES];
59
+ unsigned rd = simd_data(desc);
62
diff --git a/include/hw/timer/cmsdk-apb-timer.h b/include/hw/timer/cmsdk-apb-timer.h
60
+ ARMVectorReg scratch[2] = { };
63
index XXXXXXX..XXXXXXX 100644
61
+
64
--- a/include/hw/timer/cmsdk-apb-timer.h
62
+ set_helper_retaddr(ra);
65
+++ b/include/hw/timer/cmsdk-apb-timer.h
63
+ for (i = 0; i < oprsz; ) {
66
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(CMSDKAPBTimer, CMSDK_APB_TIMER)
64
+ uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));
67
65
+ do {
68
/*
66
+ if (pg & 1) {
69
* QEMU interface:
67
+ tlb_fn(env, &scratch[0], i, addr, mmu_idx, ra);
70
- * + QOM property "pclk-frq": frequency at which the timer is clocked
68
+ tlb_fn(env, &scratch[1], i, addr + size, mmu_idx, ra);
71
* + Clock input "pclk": clock for the timer
69
+ }
72
* + sysbus MMIO region 0: the register bank
70
+ i += size, pg >>= size;
73
* + sysbus IRQ 0: timer interrupt TIMERINT
71
+ addr += 2 * size;
74
@@ -XXX,XX +XXX,XX @@ struct CMSDKAPBTimer {
72
+ } while (i & 15);
75
/*< public >*/
73
+ }
76
MemoryRegion iomem;
74
+ set_helper_retaddr(0);
77
qemu_irq timerint;
75
+
78
- uint32_t pclk_frq;
76
+ /* Wait until all exceptions have been raised to write back. */
79
struct ptimer_state *timer;
77
+ memcpy(&env->vfp.zregs[rd], &scratch[0], oprsz);
80
Clock *pclk;
78
+ memcpy(&env->vfp.zregs[(rd + 1) & 31], &scratch[1], oprsz);
81
82
diff --git a/include/hw/watchdog/cmsdk-apb-watchdog.h b/include/hw/watchdog/cmsdk-apb-watchdog.h
83
index XXXXXXX..XXXXXXX 100644
84
--- a/include/hw/watchdog/cmsdk-apb-watchdog.h
85
+++ b/include/hw/watchdog/cmsdk-apb-watchdog.h
86
@@ -XXX,XX +XXX,XX @@
87
* https://developer.arm.com/products/system-design/system-design-kits/cortex-m-system-design-kit
88
*
89
* QEMU interface:
90
- * + QOM property "wdogclk-frq": frequency at which the watchdog is clocked
91
* + Clock input "WDOGCLK": clock for the watchdog's timer
92
* + sysbus MMIO region 0: the register bank
93
* + sysbus IRQ 0: watchdog interrupt
94
@@ -XXX,XX +XXX,XX @@ struct CMSDKAPBWatchdog {
95
/*< public >*/
96
MemoryRegion iomem;
97
qemu_irq wdogint;
98
- uint32_t wdogclk_frq;
99
bool is_luminary;
100
struct ptimer_state *timer;
101
Clock *wdogclk;
102
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
103
index XXXXXXX..XXXXXXX 100644
104
--- a/hw/arm/armsse.c
105
+++ b/hw/arm/armsse.c
106
@@ -XXX,XX +XXX,XX @@ static Property iotkit_properties[] = {
107
DEFINE_PROP_LINK("memory", ARMSSE, board_memory, TYPE_MEMORY_REGION,
108
MemoryRegion *),
109
DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
110
- DEFINE_PROP_UINT32("MAINCLK_FRQ", ARMSSE, mainclk_frq, 0),
111
DEFINE_PROP_UINT32("SRAM_ADDR_WIDTH", ARMSSE, sram_addr_width, 15),
112
DEFINE_PROP_UINT32("init-svtor", ARMSSE, init_svtor, 0x10000000),
113
DEFINE_PROP_BOOL("CPU0_FPU", ARMSSE, cpu_fpu[0], true),
114
@@ -XXX,XX +XXX,XX @@ static Property armsse_properties[] = {
115
DEFINE_PROP_LINK("memory", ARMSSE, board_memory, TYPE_MEMORY_REGION,
116
MemoryRegion *),
117
DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
118
- DEFINE_PROP_UINT32("MAINCLK_FRQ", ARMSSE, mainclk_frq, 0),
119
DEFINE_PROP_UINT32("SRAM_ADDR_WIDTH", ARMSSE, sram_addr_width, 15),
120
DEFINE_PROP_UINT32("init-svtor", ARMSSE, init_svtor, 0x10000000),
121
DEFINE_PROP_BOOL("CPU0_FPU", ARMSSE, cpu_fpu[0], false),
122
diff --git a/hw/timer/cmsdk-apb-dualtimer.c b/hw/timer/cmsdk-apb-dualtimer.c
123
index XXXXXXX..XXXXXXX 100644
124
--- a/hw/timer/cmsdk-apb-dualtimer.c
125
+++ b/hw/timer/cmsdk-apb-dualtimer.c
126
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription cmsdk_apb_dualtimer_vmstate = {
127
}
128
};
129
130
-static Property cmsdk_apb_dualtimer_properties[] = {
131
- DEFINE_PROP_UINT32("pclk-frq", CMSDKAPBDualTimer, pclk_frq, 0),
132
- DEFINE_PROP_END_OF_LIST(),
133
-};
134
-
135
static void cmsdk_apb_dualtimer_class_init(ObjectClass *klass, void *data)
136
{
137
DeviceClass *dc = DEVICE_CLASS(klass);
138
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_dualtimer_class_init(ObjectClass *klass, void *data)
139
dc->realize = cmsdk_apb_dualtimer_realize;
140
dc->vmsd = &cmsdk_apb_dualtimer_vmstate;
141
dc->reset = cmsdk_apb_dualtimer_reset;
142
- device_class_set_props(dc, cmsdk_apb_dualtimer_properties);
79
}
143
}
80
144
81
-#define DO_LD3(NAME, FN, TYPEE, TYPEM, H) \
145
static const TypeInfo cmsdk_apb_dualtimer_info = {
82
-void HELPER(NAME)(CPUARMState *env, void *vg, \
146
diff --git a/hw/timer/cmsdk-apb-timer.c b/hw/timer/cmsdk-apb-timer.c
83
- target_ulong addr, uint32_t desc) \
147
index XXXXXXX..XXXXXXX 100644
84
-{ \
148
--- a/hw/timer/cmsdk-apb-timer.c
85
- intptr_t i, oprsz = simd_oprsz(desc); \
149
+++ b/hw/timer/cmsdk-apb-timer.c
86
- intptr_t ra = GETPC(); \
150
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription cmsdk_apb_timer_vmstate = {
87
- unsigned rd = simd_data(desc); \
151
}
88
- void *d1 = &env->vfp.zregs[rd]; \
152
};
89
- void *d2 = &env->vfp.zregs[(rd + 1) & 31]; \
153
90
- void *d3 = &env->vfp.zregs[(rd + 2) & 31]; \
154
-static Property cmsdk_apb_timer_properties[] = {
91
- for (i = 0; i < oprsz; ) { \
155
- DEFINE_PROP_UINT32("pclk-frq", CMSDKAPBTimer, pclk_frq, 0),
92
- uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
156
- DEFINE_PROP_END_OF_LIST(),
93
- do { \
157
-};
94
- TYPEM m1 = 0, m2 = 0, m3 = 0; \
158
-
95
- if (pg & 1) { \
159
static void cmsdk_apb_timer_class_init(ObjectClass *klass, void *data)
96
- m1 = FN(env, addr, ra); \
160
{
97
- m2 = FN(env, addr + sizeof(TYPEM), ra); \
161
DeviceClass *dc = DEVICE_CLASS(klass);
98
- m3 = FN(env, addr + 2 * sizeof(TYPEM), ra); \
162
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_timer_class_init(ObjectClass *klass, void *data)
99
- } \
163
dc->realize = cmsdk_apb_timer_realize;
100
- *(TYPEE *)(d1 + H(i)) = m1; \
164
dc->vmsd = &cmsdk_apb_timer_vmstate;
101
- *(TYPEE *)(d2 + H(i)) = m2; \
165
dc->reset = cmsdk_apb_timer_reset;
102
- *(TYPEE *)(d3 + H(i)) = m3; \
166
- device_class_set_props(dc, cmsdk_apb_timer_properties);
103
- i += sizeof(TYPEE), pg >>= sizeof(TYPEE); \
104
- addr += 3 * sizeof(TYPEM); \
105
- } while (i & 15); \
106
- } \
107
+static void sve_ld3_r(CPUARMState *env, void *vg, target_ulong addr,
108
+ uint32_t desc, int size, uintptr_t ra,
109
+ sve_ld1_tlb_fn *tlb_fn)
110
+{
111
+ const int mmu_idx = cpu_mmu_index(env, false);
112
+ intptr_t i, oprsz = simd_oprsz(desc);
113
+ unsigned rd = simd_data(desc);
114
+ ARMVectorReg scratch[3] = { };
115
+
116
+ set_helper_retaddr(ra);
117
+ for (i = 0; i < oprsz; ) {
118
+ uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));
119
+ do {
120
+ if (pg & 1) {
121
+ tlb_fn(env, &scratch[0], i, addr, mmu_idx, ra);
122
+ tlb_fn(env, &scratch[1], i, addr + size, mmu_idx, ra);
123
+ tlb_fn(env, &scratch[2], i, addr + 2 * size, mmu_idx, ra);
124
+ }
125
+ i += size, pg >>= size;
126
+ addr += 3 * size;
127
+ } while (i & 15);
128
+ }
129
+ set_helper_retaddr(0);
130
+
131
+ /* Wait until all exceptions have been raised to write back. */
132
+ memcpy(&env->vfp.zregs[rd], &scratch[0], oprsz);
133
+ memcpy(&env->vfp.zregs[(rd + 1) & 31], &scratch[1], oprsz);
134
+ memcpy(&env->vfp.zregs[(rd + 2) & 31], &scratch[2], oprsz);
135
}
167
}
136
168
137
-#define DO_LD4(NAME, FN, TYPEE, TYPEM, H) \
169
static const TypeInfo cmsdk_apb_timer_info = {
138
-void HELPER(NAME)(CPUARMState *env, void *vg, \
170
diff --git a/hw/watchdog/cmsdk-apb-watchdog.c b/hw/watchdog/cmsdk-apb-watchdog.c
139
- target_ulong addr, uint32_t desc) \
171
index XXXXXXX..XXXXXXX 100644
140
-{ \
172
--- a/hw/watchdog/cmsdk-apb-watchdog.c
141
- intptr_t i, oprsz = simd_oprsz(desc); \
173
+++ b/hw/watchdog/cmsdk-apb-watchdog.c
142
- intptr_t ra = GETPC(); \
174
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription cmsdk_apb_watchdog_vmstate = {
143
- unsigned rd = simd_data(desc); \
175
}
144
- void *d1 = &env->vfp.zregs[rd]; \
176
};
145
- void *d2 = &env->vfp.zregs[(rd + 1) & 31]; \
177
146
- void *d3 = &env->vfp.zregs[(rd + 2) & 31]; \
178
-static Property cmsdk_apb_watchdog_properties[] = {
147
- void *d4 = &env->vfp.zregs[(rd + 3) & 31]; \
179
- DEFINE_PROP_UINT32("wdogclk-frq", CMSDKAPBWatchdog, wdogclk_frq, 0),
148
- for (i = 0; i < oprsz; ) { \
180
- DEFINE_PROP_END_OF_LIST(),
149
- uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
181
-};
150
- do { \
182
-
151
- TYPEM m1 = 0, m2 = 0, m3 = 0, m4 = 0; \
183
static void cmsdk_apb_watchdog_class_init(ObjectClass *klass, void *data)
152
- if (pg & 1) { \
184
{
153
- m1 = FN(env, addr, ra); \
185
DeviceClass *dc = DEVICE_CLASS(klass);
154
- m2 = FN(env, addr + sizeof(TYPEM), ra); \
186
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_watchdog_class_init(ObjectClass *klass, void *data)
155
- m3 = FN(env, addr + 2 * sizeof(TYPEM), ra); \
187
dc->realize = cmsdk_apb_watchdog_realize;
156
- m4 = FN(env, addr + 3 * sizeof(TYPEM), ra); \
188
dc->vmsd = &cmsdk_apb_watchdog_vmstate;
157
- } \
189
dc->reset = cmsdk_apb_watchdog_reset;
158
- *(TYPEE *)(d1 + H(i)) = m1; \
190
- device_class_set_props(dc, cmsdk_apb_watchdog_properties);
159
- *(TYPEE *)(d2 + H(i)) = m2; \
160
- *(TYPEE *)(d3 + H(i)) = m3; \
161
- *(TYPEE *)(d4 + H(i)) = m4; \
162
- i += sizeof(TYPEE), pg >>= sizeof(TYPEE); \
163
- addr += 4 * sizeof(TYPEM); \
164
- } while (i & 15); \
165
- } \
166
+static void sve_ld4_r(CPUARMState *env, void *vg, target_ulong addr,
167
+ uint32_t desc, int size, uintptr_t ra,
168
+ sve_ld1_tlb_fn *tlb_fn)
169
+{
170
+ const int mmu_idx = cpu_mmu_index(env, false);
171
+ intptr_t i, oprsz = simd_oprsz(desc);
172
+ unsigned rd = simd_data(desc);
173
+ ARMVectorReg scratch[4] = { };
174
+
175
+ set_helper_retaddr(ra);
176
+ for (i = 0; i < oprsz; ) {
177
+ uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));
178
+ do {
179
+ if (pg & 1) {
180
+ tlb_fn(env, &scratch[0], i, addr, mmu_idx, ra);
181
+ tlb_fn(env, &scratch[1], i, addr + size, mmu_idx, ra);
182
+ tlb_fn(env, &scratch[2], i, addr + 2 * size, mmu_idx, ra);
183
+ tlb_fn(env, &scratch[3], i, addr + 3 * size, mmu_idx, ra);
184
+ }
185
+ i += size, pg >>= size;
186
+ addr += 4 * size;
187
+ } while (i & 15);
188
+ }
189
+ set_helper_retaddr(0);
190
+
191
+ /* Wait until all exceptions have been raised to write back. */
192
+ memcpy(&env->vfp.zregs[rd], &scratch[0], oprsz);
193
+ memcpy(&env->vfp.zregs[(rd + 1) & 31], &scratch[1], oprsz);
194
+ memcpy(&env->vfp.zregs[(rd + 2) & 31], &scratch[2], oprsz);
195
+ memcpy(&env->vfp.zregs[(rd + 3) & 31], &scratch[3], oprsz);
196
}
191
}
197
192
198
-DO_LD2(sve_ld2bb_r, cpu_ldub_data_ra, uint8_t, uint8_t, H1)
193
static const TypeInfo cmsdk_apb_watchdog_info = {
199
-DO_LD3(sve_ld3bb_r, cpu_ldub_data_ra, uint8_t, uint8_t, H1)
200
-DO_LD4(sve_ld4bb_r, cpu_ldub_data_ra, uint8_t, uint8_t, H1)
201
+#define DO_LDN_1(N) \
202
+void __attribute__((flatten)) HELPER(sve_ld##N##bb_r) \
203
+ (CPUARMState *env, void *vg, target_ulong addr, uint32_t desc) \
204
+{ \
205
+ sve_ld##N##_r(env, vg, addr, desc, 1, GETPC(), sve_ld1bb_tlb); \
206
+}
207
208
-DO_LD2(sve_ld2hh_r, cpu_lduw_data_ra, uint16_t, uint16_t, H1_2)
209
-DO_LD3(sve_ld3hh_r, cpu_lduw_data_ra, uint16_t, uint16_t, H1_2)
210
-DO_LD4(sve_ld4hh_r, cpu_lduw_data_ra, uint16_t, uint16_t, H1_2)
211
+#define DO_LDN_2(N, SUFF, SIZE) \
212
+void __attribute__((flatten)) HELPER(sve_ld##N##SUFF##_r) \
213
+ (CPUARMState *env, void *vg, target_ulong addr, uint32_t desc) \
214
+{ \
215
+ sve_ld##N##_r(env, vg, addr, desc, SIZE, GETPC(), \
216
+ arm_cpu_data_is_big_endian(env) \
217
+ ? sve_ld1##SUFF##_be_tlb : sve_ld1##SUFF##_le_tlb); \
218
+}
219
220
-DO_LD2(sve_ld2ss_r, cpu_ldl_data_ra, uint32_t, uint32_t, H1_4)
221
-DO_LD3(sve_ld3ss_r, cpu_ldl_data_ra, uint32_t, uint32_t, H1_4)
222
-DO_LD4(sve_ld4ss_r, cpu_ldl_data_ra, uint32_t, uint32_t, H1_4)
223
+DO_LDN_1(2)
224
+DO_LDN_1(3)
225
+DO_LDN_1(4)
226
227
-DO_LD2(sve_ld2dd_r, cpu_ldq_data_ra, uint64_t, uint64_t, )
228
-DO_LD3(sve_ld3dd_r, cpu_ldq_data_ra, uint64_t, uint64_t, )
229
-DO_LD4(sve_ld4dd_r, cpu_ldq_data_ra, uint64_t, uint64_t, )
230
+DO_LDN_2(2, hh, 2)
231
+DO_LDN_2(3, hh, 2)
232
+DO_LDN_2(4, hh, 2)
233
234
-#undef DO_LD2
235
-#undef DO_LD3
236
-#undef DO_LD4
237
+DO_LDN_2(2, ss, 4)
238
+DO_LDN_2(3, ss, 4)
239
+DO_LDN_2(4, ss, 4)
240
+
241
+DO_LDN_2(2, dd, 8)
242
+DO_LDN_2(3, dd, 8)
243
+DO_LDN_2(4, dd, 8)
244
+
245
+#undef DO_LDN_1
246
+#undef DO_LDN_2
247
248
/*
249
* Load contiguous data, first-fault and no-fault.
250
--
194
--
251
2.19.0
195
2.20.1
252
196
253
197
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Now that the watchdog device uses its Clock input rather than being
2
passed the value of system_clock_scale at creation time, we can
3
remove the hack where we reset the STELLARIS_SYS at board creation
4
time to force it to set system_clock_scale. Instead it will be reset
5
at the usual point in startup and will inform the watchdog of the
6
clock frequency at that point.
2
7
3
We can choose the endianness at translation time, rather than
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
re-computing it at execution time.
9
Reviewed-by: Luc Michel <luc@lmichel.fr>
10
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Message-id: 20210128114145.20536-26-peter.maydell@linaro.org
13
Message-id: 20210121190622.22000-26-peter.maydell@linaro.org
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
---
16
hw/arm/stellaris.c | 10 ----------
17
1 file changed, 10 deletions(-)
5
18
6
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
19
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20181005175350.30752-12-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/helper-sve.h | 48 +++++++++++++++++--------
13
target/arm/sve_helper.c | 11 ++++--
14
target/arm/translate-sve.c | 72 +++++++++++++++++++++++++++++---------
15
3 files changed, 96 insertions(+), 35 deletions(-)
16
17
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
18
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper-sve.h
21
--- a/hw/arm/stellaris.c
20
+++ b/target/arm/helper-sve.h
22
+++ b/hw/arm/stellaris.c
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(sve_st2bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
23
@@ -XXX,XX +XXX,XX @@ static DeviceState *stellaris_sys_init(uint32_t base, qemu_irq irq,
22
DEF_HELPER_FLAGS_4(sve_st3bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
24
sysbus_mmio_map(sbd, 0, base);
23
DEF_HELPER_FLAGS_4(sve_st4bb_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
25
sysbus_connect_irq(sbd, 0, irq);
24
26
25
-DEF_HELPER_FLAGS_4(sve_st1hh_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
27
- /*
26
-DEF_HELPER_FLAGS_4(sve_st2hh_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
28
- * Normally we should not be resetting devices like this during
27
-DEF_HELPER_FLAGS_4(sve_st3hh_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
29
- * board creation. For the moment we need to do so, because
28
-DEF_HELPER_FLAGS_4(sve_st4hh_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
30
- * system_clock_scale will only get set when the STELLARIS_SYS
29
+DEF_HELPER_FLAGS_4(sve_st1hh_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
31
- * device is reset, and we need its initial value to pass to
30
+DEF_HELPER_FLAGS_4(sve_st2hh_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
32
- * the watchdog device. This hack can be removed once the
31
+DEF_HELPER_FLAGS_4(sve_st3hh_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
33
- * watchdog has been converted to use a Clock input instead.
32
+DEF_HELPER_FLAGS_4(sve_st4hh_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
34
- */
33
35
- device_cold_reset(dev);
34
-DEF_HELPER_FLAGS_4(sve_st1ss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
36
-
35
-DEF_HELPER_FLAGS_4(sve_st2ss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
37
return dev;
36
-DEF_HELPER_FLAGS_4(sve_st3ss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
37
-DEF_HELPER_FLAGS_4(sve_st4ss_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
38
+DEF_HELPER_FLAGS_4(sve_st1hh_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
39
+DEF_HELPER_FLAGS_4(sve_st2hh_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
40
+DEF_HELPER_FLAGS_4(sve_st3hh_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
41
+DEF_HELPER_FLAGS_4(sve_st4hh_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
42
43
-DEF_HELPER_FLAGS_4(sve_st1dd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
44
-DEF_HELPER_FLAGS_4(sve_st2dd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
45
-DEF_HELPER_FLAGS_4(sve_st3dd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
46
-DEF_HELPER_FLAGS_4(sve_st4dd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
47
+DEF_HELPER_FLAGS_4(sve_st1ss_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
48
+DEF_HELPER_FLAGS_4(sve_st2ss_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
49
+DEF_HELPER_FLAGS_4(sve_st3ss_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
50
+DEF_HELPER_FLAGS_4(sve_st4ss_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
51
+
52
+DEF_HELPER_FLAGS_4(sve_st1ss_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
53
+DEF_HELPER_FLAGS_4(sve_st2ss_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
54
+DEF_HELPER_FLAGS_4(sve_st3ss_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
55
+DEF_HELPER_FLAGS_4(sve_st4ss_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
56
+
57
+DEF_HELPER_FLAGS_4(sve_st1dd_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
58
+DEF_HELPER_FLAGS_4(sve_st2dd_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
59
+DEF_HELPER_FLAGS_4(sve_st3dd_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
60
+DEF_HELPER_FLAGS_4(sve_st4dd_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
61
+
62
+DEF_HELPER_FLAGS_4(sve_st1dd_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
63
+DEF_HELPER_FLAGS_4(sve_st2dd_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
64
+DEF_HELPER_FLAGS_4(sve_st3dd_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
65
+DEF_HELPER_FLAGS_4(sve_st4dd_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
66
67
DEF_HELPER_FLAGS_4(sve_st1bh_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
68
DEF_HELPER_FLAGS_4(sve_st1bs_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
69
DEF_HELPER_FLAGS_4(sve_st1bd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
70
71
-DEF_HELPER_FLAGS_4(sve_st1hs_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
72
-DEF_HELPER_FLAGS_4(sve_st1hd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
73
+DEF_HELPER_FLAGS_4(sve_st1hs_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
74
+DEF_HELPER_FLAGS_4(sve_st1hd_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
75
+DEF_HELPER_FLAGS_4(sve_st1hs_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
76
+DEF_HELPER_FLAGS_4(sve_st1hd_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
77
78
-DEF_HELPER_FLAGS_4(sve_st1sd_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
79
+DEF_HELPER_FLAGS_4(sve_st1sd_le_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
80
+DEF_HELPER_FLAGS_4(sve_st1sd_be_r, TCG_CALL_NO_WG, void, env, ptr, tl, i32)
81
82
DEF_HELPER_FLAGS_6(sve_ldbsu_zsu, TCG_CALL_NO_WG,
83
void, env, ptr, ptr, ptr, tl, i32)
84
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
85
index XXXXXXX..XXXXXXX 100644
86
--- a/target/arm/sve_helper.c
87
+++ b/target/arm/sve_helper.c
88
@@ -XXX,XX +XXX,XX @@ void __attribute__((flatten)) HELPER(sve_st##N##NAME##_r) \
89
}
38
}
90
39
91
#define DO_STN_2(N, NAME, ESIZE, MSIZE) \
92
-void __attribute__((flatten)) HELPER(sve_st##N##NAME##_r) \
93
+void __attribute__((flatten)) HELPER(sve_st##N##NAME##_le_r) \
94
(CPUARMState *env, void *vg, target_ulong addr, uint32_t desc) \
95
{ \
96
sve_st##N##_r(env, vg, addr, desc, GETPC(), ESIZE, MSIZE, \
97
- arm_cpu_data_is_big_endian(env) \
98
- ? sve_st1##NAME##_be_tlb : sve_st1##NAME##_le_tlb); \
99
+ sve_st1##NAME##_le_tlb); \
100
+} \
101
+void __attribute__((flatten)) HELPER(sve_st##N##NAME##_be_r) \
102
+ (CPUARMState *env, void *vg, target_ulong addr, uint32_t desc) \
103
+{ \
104
+ sve_st##N##_r(env, vg, addr, desc, GETPC(), ESIZE, MSIZE, \
105
+ sve_st1##NAME##_be_tlb); \
106
}
107
108
DO_STN_1(1, bb, 1)
109
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
110
index XXXXXXX..XXXXXXX 100644
111
--- a/target/arm/translate-sve.c
112
+++ b/target/arm/translate-sve.c
113
@@ -XXX,XX +XXX,XX @@ static bool trans_LD1R_zpri(DisasContext *s, arg_rpri_load *a, uint32_t insn)
114
static void do_st_zpa(DisasContext *s, int zt, int pg, TCGv_i64 addr,
115
int msz, int esz, int nreg)
116
{
117
- static gen_helper_gvec_mem * const fn_single[4][4] = {
118
- { gen_helper_sve_st1bb_r, gen_helper_sve_st1bh_r,
119
- gen_helper_sve_st1bs_r, gen_helper_sve_st1bd_r },
120
- { NULL, gen_helper_sve_st1hh_r,
121
- gen_helper_sve_st1hs_r, gen_helper_sve_st1hd_r },
122
- { NULL, NULL,
123
- gen_helper_sve_st1ss_r, gen_helper_sve_st1sd_r },
124
- { NULL, NULL, NULL, gen_helper_sve_st1dd_r },
125
+ static gen_helper_gvec_mem * const fn_single[2][4][4] = {
126
+ { { gen_helper_sve_st1bb_r,
127
+ gen_helper_sve_st1bh_r,
128
+ gen_helper_sve_st1bs_r,
129
+ gen_helper_sve_st1bd_r },
130
+ { NULL,
131
+ gen_helper_sve_st1hh_le_r,
132
+ gen_helper_sve_st1hs_le_r,
133
+ gen_helper_sve_st1hd_le_r },
134
+ { NULL, NULL,
135
+ gen_helper_sve_st1ss_le_r,
136
+ gen_helper_sve_st1sd_le_r },
137
+ { NULL, NULL, NULL,
138
+ gen_helper_sve_st1dd_le_r } },
139
+ { { gen_helper_sve_st1bb_r,
140
+ gen_helper_sve_st1bh_r,
141
+ gen_helper_sve_st1bs_r,
142
+ gen_helper_sve_st1bd_r },
143
+ { NULL,
144
+ gen_helper_sve_st1hh_be_r,
145
+ gen_helper_sve_st1hs_be_r,
146
+ gen_helper_sve_st1hd_be_r },
147
+ { NULL, NULL,
148
+ gen_helper_sve_st1ss_be_r,
149
+ gen_helper_sve_st1sd_be_r },
150
+ { NULL, NULL, NULL,
151
+ gen_helper_sve_st1dd_be_r } },
152
};
153
- static gen_helper_gvec_mem * const fn_multiple[3][4] = {
154
- { gen_helper_sve_st2bb_r, gen_helper_sve_st2hh_r,
155
- gen_helper_sve_st2ss_r, gen_helper_sve_st2dd_r },
156
- { gen_helper_sve_st3bb_r, gen_helper_sve_st3hh_r,
157
- gen_helper_sve_st3ss_r, gen_helper_sve_st3dd_r },
158
- { gen_helper_sve_st4bb_r, gen_helper_sve_st4hh_r,
159
- gen_helper_sve_st4ss_r, gen_helper_sve_st4dd_r },
160
+ static gen_helper_gvec_mem * const fn_multiple[2][3][4] = {
161
+ { { gen_helper_sve_st2bb_r,
162
+ gen_helper_sve_st2hh_le_r,
163
+ gen_helper_sve_st2ss_le_r,
164
+ gen_helper_sve_st2dd_le_r },
165
+ { gen_helper_sve_st3bb_r,
166
+ gen_helper_sve_st3hh_le_r,
167
+ gen_helper_sve_st3ss_le_r,
168
+ gen_helper_sve_st3dd_le_r },
169
+ { gen_helper_sve_st4bb_r,
170
+ gen_helper_sve_st4hh_le_r,
171
+ gen_helper_sve_st4ss_le_r,
172
+ gen_helper_sve_st4dd_le_r } },
173
+ { { gen_helper_sve_st2bb_r,
174
+ gen_helper_sve_st2hh_be_r,
175
+ gen_helper_sve_st2ss_be_r,
176
+ gen_helper_sve_st2dd_be_r },
177
+ { gen_helper_sve_st3bb_r,
178
+ gen_helper_sve_st3hh_be_r,
179
+ gen_helper_sve_st3ss_be_r,
180
+ gen_helper_sve_st3dd_be_r },
181
+ { gen_helper_sve_st4bb_r,
182
+ gen_helper_sve_st4hh_be_r,
183
+ gen_helper_sve_st4ss_be_r,
184
+ gen_helper_sve_st4dd_be_r } },
185
};
186
gen_helper_gvec_mem *fn;
187
+ int be = s->be_data == MO_BE;
188
189
if (nreg == 0) {
190
/* ST1 */
191
- fn = fn_single[msz][esz];
192
+ fn = fn_single[be][msz][esz];
193
} else {
194
/* ST2, ST3, ST4 -- msz == esz, enforced by encoding */
195
assert(msz == esz);
196
- fn = fn_multiple[nreg - 1][msz];
197
+ fn = fn_multiple[be][nreg - 1][msz];
198
}
199
assert(fn != NULL);
200
do_mem_zpa(s, zt, pg, addr, fn);
201
--
40
--
202
2.19.0
41
2.20.1
203
42
204
43
diff view generated by jsdifflib