1
Second pull request of the week; mostly RTH's support for some
1
The following changes since commit 4c41341af76cfc85b5a6c0f87de4838672ab9f89:
2
new-in-v8.1/v8.3 instructions, and my v8M board model.
3
2
4
thanks
3
Merge remote-tracking branch 'remotes/aperard/tags/pull-xen-20201020' into staging (2020-10-20 11:20:36 +0100)
5
-- PMM
6
7
The following changes since commit 427cbc7e4136a061628cb4315cc8182ea36d772f:
8
9
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging (2018-03-01 18:46:41 +0000)
10
4
11
are available in the Git repository at:
5
are available in the Git repository at:
12
6
13
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20180302
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20201020
14
8
15
for you to fetch changes up to e66a67bf28e1b4fce2e3d72a2610dbd48d9d3078:
9
for you to fetch changes up to 6358890cb939192f6169fdf7664d903bf9b1d338:
16
10
17
target/arm: Enable ARM_FEATURE_V8_FCMA (2018-03-02 11:03:45 +0000)
11
tests/tcg/aarch64: Add bti smoke tests (2020-10-20 16:12:02 +0100)
18
12
19
----------------------------------------------------------------
13
----------------------------------------------------------------
20
target-arm queue:
14
target-arm queue:
21
* implement FCMA and RDM v8.1 and v8.3 instructions
15
* Fix AArch32 SMLAD incorrect setting of Q bit
22
* enable Cortex-M33 v8M core, and provide new mps2-an505 board model
16
* AArch32 VCVT fixed-point to float is always round-to-nearest
23
that uses it
17
* strongarm: Fix 'time to transmit a char' unit comment
24
* decodetree: Propagate return value from translate subroutines
18
* Restrict APEI tables generation to the 'virt' machine
25
* xlnx-zynqmp: Implement the RTC device
19
* bcm2835: minor code cleanups
20
* correctly flush TLBs when TBI is enabled
21
* tests/qtest: Add npcm7xx timer test
22
* loads-stores.rst: add footnote that clarifies GETPC usage
23
* Fix reported EL for mte_check_fail
24
* Ignore HCR_EL2.ATA when {E2H,TGE} != 11
25
* microbit_i2c: Fix coredump when dump-vmstate
26
* nseries: Fix loading kernel image on n8x0 machines
27
* Implement v8.1M low-overhead-loops
28
* linux-user: Support AArch64 BTI
26
29
27
----------------------------------------------------------------
30
----------------------------------------------------------------
28
Alistair Francis (3):
31
Emanuele Giuseppe Esposito (1):
29
xlnx-zynqmp-rtc: Initial commit
32
loads-stores.rst: add footnote that clarifies GETPC usage
30
xlnx-zynqmp-rtc: Add basic time support
31
xlnx-zynqmp: Connect the RTC device
32
33
33
Peter Maydell (19):
34
Havard Skinnemoen (1):
34
loader: Add new load_ramdisk_as()
35
tests/qtest: Add npcm7xx timer test
35
hw/arm/boot: Honour CPU's address space for image loads
36
hw/arm/armv7m: Honour CPU's address space for image loads
37
target/arm: Define an IDAU interface
38
armv7m: Forward idau property to CPU object
39
target/arm: Define init-svtor property for the reset secure VTOR value
40
armv7m: Forward init-svtor property to CPU object
41
target/arm: Add Cortex-M33
42
hw/misc/unimp: Move struct to header file
43
include/hw/or-irq.h: Add missing include guard
44
qdev: Add new qdev_init_gpio_in_named_with_opaque()
45
hw/core/split-irq: Device that splits IRQ lines
46
hw/misc/mps2-fpgaio: FPGA control block for MPS2 AN505
47
hw/misc/tz-ppc: Model TrustZone peripheral protection controller
48
hw/misc/iotkit-secctl: Arm IoT Kit security controller initial skeleton
49
hw/misc/iotkit-secctl: Add handling for PPCs
50
hw/misc/iotkit-secctl: Add remaining simple registers
51
hw/arm/iotkit: Model Arm IOT Kit
52
mps2-an505: New board model: MPS2 with AN505 Cortex-M33 FPGA image
53
36
54
Richard Henderson (17):
37
Peng Liang (1):
55
decodetree: Propagate return value from translate subroutines
38
microbit_i2c: Fix coredump when dump-vmstate
56
target/arm: Add ARM_FEATURE_V8_RDM
57
target/arm: Refactor disas_simd_indexed decode
58
target/arm: Refactor disas_simd_indexed size checks
59
target/arm: Decode aa64 armv8.1 scalar three same extra
60
target/arm: Decode aa64 armv8.1 three same extra
61
target/arm: Decode aa64 armv8.1 scalar/vector x indexed element
62
target/arm: Decode aa32 armv8.1 three same
63
target/arm: Decode aa32 armv8.1 two reg and a scalar
64
target/arm: Enable ARM_FEATURE_V8_RDM
65
target/arm: Add ARM_FEATURE_V8_FCMA
66
target/arm: Decode aa64 armv8.3 fcadd
67
target/arm: Decode aa64 armv8.3 fcmla
68
target/arm: Decode aa32 armv8.3 3-same
69
target/arm: Decode aa32 armv8.3 2-reg-index
70
target/arm: Decode t32 simd 3reg and 2reg_scalar extension
71
target/arm: Enable ARM_FEATURE_V8_FCMA
72
39
73
hw/arm/Makefile.objs | 2 +
40
Peter Maydell (12):
74
hw/core/Makefile.objs | 1 +
41
target/arm: Fix SMLAD incorrect setting of Q bit
75
hw/misc/Makefile.objs | 4 +
42
target/arm: AArch32 VCVT fixed-point to float is always round-to-nearest
76
hw/timer/Makefile.objs | 1 +
43
decodetree: Fix codegen for non-overlapping group inside overlapping group
77
target/arm/Makefile.objs | 2 +-
44
target/arm: Implement v8.1M NOCP handling
78
include/hw/arm/armv7m.h | 5 +
45
target/arm: Implement v8.1M conditional-select insns
79
include/hw/arm/iotkit.h | 109 ++++++
46
target/arm: Make the t32 insn[25:23]=111 group non-overlapping
80
include/hw/arm/xlnx-zynqmp.h | 2 +
47
target/arm: Don't allow BLX imm for M-profile
81
include/hw/core/split-irq.h | 57 +++
48
target/arm: Implement v8.1M branch-future insns (as NOPs)
82
include/hw/irq.h | 4 +-
49
target/arm: Implement v8.1M low-overhead-loop instructions
83
include/hw/loader.h | 12 +-
50
target/arm: Fix has_vfp/has_neon ID reg squashing for M-profile
84
include/hw/misc/iotkit-secctl.h | 103 ++++++
51
target/arm: Allow M-profile CPUs with FP16 to set FPSCR.FP16
85
include/hw/misc/mps2-fpgaio.h | 43 +++
52
target/arm: Implement FPSCR.LTPSIZE for M-profile LOB extension
86
include/hw/misc/tz-ppc.h | 101 ++++++
87
include/hw/misc/unimp.h | 10 +
88
include/hw/or-irq.h | 5 +
89
include/hw/qdev-core.h | 30 +-
90
include/hw/timer/xlnx-zynqmp-rtc.h | 86 +++++
91
target/arm/cpu.h | 8 +
92
target/arm/helper.h | 31 ++
93
target/arm/idau.h | 61 ++++
94
hw/arm/armv7m.c | 35 +-
95
hw/arm/boot.c | 119 ++++---
96
hw/arm/iotkit.c | 598 +++++++++++++++++++++++++++++++
97
hw/arm/mps2-tz.c | 503 ++++++++++++++++++++++++++
98
hw/arm/xlnx-zynqmp.c | 14 +
99
hw/core/loader.c | 8 +-
100
hw/core/qdev.c | 8 +-
101
hw/core/split-irq.c | 89 +++++
102
hw/misc/iotkit-secctl.c | 704 +++++++++++++++++++++++++++++++++++++
103
hw/misc/mps2-fpgaio.c | 176 ++++++++++
104
hw/misc/tz-ppc.c | 302 ++++++++++++++++
105
hw/misc/unimp.c | 10 -
106
hw/timer/xlnx-zynqmp-rtc.c | 272 ++++++++++++++
107
linux-user/elfload.c | 2 +
108
target/arm/cpu.c | 66 +++-
109
target/arm/cpu64.c | 2 +
110
target/arm/helper.c | 28 +-
111
target/arm/translate-a64.c | 514 +++++++++++++++++++++------
112
target/arm/translate.c | 275 +++++++++++++--
113
target/arm/vec_helper.c | 429 ++++++++++++++++++++++
114
default-configs/arm-softmmu.mak | 5 +
115
hw/misc/trace-events | 24 ++
116
hw/timer/trace-events | 3 +
117
scripts/decodetree.py | 5 +-
118
45 files changed, 4668 insertions(+), 200 deletions(-)
119
create mode 100644 include/hw/arm/iotkit.h
120
create mode 100644 include/hw/core/split-irq.h
121
create mode 100644 include/hw/misc/iotkit-secctl.h
122
create mode 100644 include/hw/misc/mps2-fpgaio.h
123
create mode 100644 include/hw/misc/tz-ppc.h
124
create mode 100644 include/hw/timer/xlnx-zynqmp-rtc.h
125
create mode 100644 target/arm/idau.h
126
create mode 100644 hw/arm/iotkit.c
127
create mode 100644 hw/arm/mps2-tz.c
128
create mode 100644 hw/core/split-irq.c
129
create mode 100644 hw/misc/iotkit-secctl.c
130
create mode 100644 hw/misc/mps2-fpgaio.c
131
create mode 100644 hw/misc/tz-ppc.c
132
create mode 100644 hw/timer/xlnx-zynqmp-rtc.c
133
create mode 100644 target/arm/vec_helper.c
134
53
54
Philippe Mathieu-Daudé (10):
55
hw/arm/strongarm: Fix 'time to transmit a char' unit comment
56
hw/arm: Restrict APEI tables generation to the 'virt' machine
57
hw/timer/bcm2835: Introduce BCM2835_SYSTIMER_COUNT definition
58
hw/timer/bcm2835: Rename variable holding CTRL_STATUS register
59
hw/timer/bcm2835: Support the timer COMPARE registers
60
hw/arm/bcm2835_peripherals: Correctly wire the SYS_timer IRQs
61
hw/intc/bcm2835_ic: Trace GPU/CPU IRQ handlers
62
hw/intc/bcm2836_control: Use IRQ definitions instead of magic numbers
63
hw/arm/nseries: Fix loading kernel image on n8x0 machines
64
linux-user/elfload: Avoid leaking interp_name using GLib memory API
65
66
Richard Henderson (16):
67
accel/tcg: Add tlb_flush_page_bits_by_mmuidx*
68
target/arm: Use tlb_flush_page_bits_by_mmuidx*
69
target/arm: Remove redundant mmu_idx lookup
70
target/arm: Fix reported EL for mte_check_fail
71
target/arm: Ignore HCR_EL2.ATA when {E2H,TGE} != 11
72
linux-user/aarch64: Reset btype for signals
73
linux-user: Set PAGE_TARGET_1 for TARGET_PROT_BTI
74
include/elf: Add defines related to GNU property notes for AArch64
75
linux-user/elfload: Fix coding style in load_elf_image
76
linux-user/elfload: Adjust iteration over phdr
77
linux-user/elfload: Move PT_INTERP detection to first loop
78
linux-user/elfload: Use Error for load_elf_image
79
linux-user/elfload: Use Error for load_elf_interp
80
linux-user/elfload: Parse NT_GNU_PROPERTY_TYPE_0 notes
81
linux-user/elfload: Parse GNU_PROPERTY_AARCH64_FEATURE_1_AND
82
tests/tcg/aarch64: Add bti smoke tests
83
84
docs/devel/loads-stores.rst | 8 +-
85
default-configs/devices/arm-softmmu.mak | 1 -
86
include/elf.h | 22 ++
87
include/exec/cpu-all.h | 2 +
88
include/exec/exec-all.h | 36 ++
89
include/hw/timer/bcm2835_systmr.h | 17 +-
90
linux-user/qemu.h | 4 +
91
linux-user/syscall_defs.h | 4 +
92
target/arm/cpu.h | 13 +
93
target/arm/helper.h | 13 +
94
target/arm/internals.h | 9 +-
95
target/arm/m-nocp.decode | 10 +-
96
target/arm/t32.decode | 50 ++-
97
accel/tcg/cputlb.c | 275 +++++++++++++++-
98
hw/arm/bcm2835_peripherals.c | 13 +-
99
hw/arm/nseries.c | 1 +
100
hw/arm/strongarm.c | 2 +-
101
hw/i2c/microbit_i2c.c | 1 +
102
hw/intc/bcm2835_ic.c | 4 +-
103
hw/intc/bcm2836_control.c | 8 +-
104
hw/timer/bcm2835_systmr.c | 57 ++--
105
linux-user/aarch64/signal.c | 10 +-
106
linux-user/elfload.c | 326 ++++++++++++++----
107
linux-user/mmap.c | 16 +
108
target/arm/cpu.c | 38 ++-
109
target/arm/helper.c | 55 +++-
110
target/arm/mte_helper.c | 13 +-
111
target/arm/translate-a64.c | 6 +-
112
target/arm/translate.c | 239 +++++++++++++-
113
target/arm/vfp_helper.c | 76 +++--
114
tests/qtest/npcm7xx_timer-test.c | 562 ++++++++++++++++++++++++++++++++
115
tests/tcg/aarch64/bti-1.c | 62 ++++
116
tests/tcg/aarch64/bti-2.c | 108 ++++++
117
tests/tcg/aarch64/bti-crt.inc.c | 51 +++
118
hw/arm/Kconfig | 1 +
119
hw/intc/trace-events | 4 +
120
hw/timer/trace-events | 6 +-
121
scripts/decodetree.py | 2 +-
122
target/arm/translate-vfp.c.inc | 41 ++-
123
tests/qtest/meson.build | 1 +
124
tests/tcg/aarch64/Makefile.target | 10 +
125
tests/tcg/configure.sh | 4 +
126
42 files changed, 1973 insertions(+), 208 deletions(-)
127
create mode 100644 tests/qtest/npcm7xx_timer-test.c
128
create mode 100644 tests/tcg/aarch64/bti-1.c
129
create mode 100644 tests/tcg/aarch64/bti-2.c
130
create mode 100644 tests/tcg/aarch64/bti-crt.inc.c
131
diff view generated by jsdifflib
1
Define a new board model for the MPS2 with an AN505 FPGA image
1
The SMLAD instruction is supposed to:
2
containing a Cortex-M33. Since the FPGA images for TrustZone
2
* signed multiply Rn[15:0] * Rm[15:0]
3
cores (AN505, and the similar AN519 for Cortex-M23) have a
3
* signed multiply Rn[31:16] * Rm[31:16]
4
significantly different layout of devices to the non-TrustZone
4
* perform a signed addition of the products and Ra
5
images, we use a new source file rather than shoehorning them
5
* set Rd to the low 32 bits of the theoretical
6
into the existing mps2.c.
6
infinite-precision result
7
* set the Q flag if the sign-extension of Rd
8
would differ from the infinite-precision result
9
(ie on overflow)
10
11
Our current implementation doesn't quite do this, though: it performs
12
an addition of the products setting Q on overflow, and then it adds
13
Ra, again possibly setting Q. This sometimes incorrectly sets Q when
14
the architecturally mandated only-check-for-overflow-once algorithm
15
does not. For instance:
16
r1 = 0x80008000; r2 = 0x80008000; r3 = 0xffffffff
17
smlad r0, r1, r2, r3
18
This is (-32768 * -32768) + (-32768 * -32768) - 1
19
20
The products are both 0x4000_0000, so when added together as 32-bit
21
signed numbers they overflow (and QEMU sets Q), but because the
22
addition of Ra == -1 brings the total back down to 0x7fff_ffff
23
there is no overflow for the complete operation and setting Q is
24
incorrect.
25
26
Fix this edge case by resorting to 64-bit arithmetic for the
27
case where we need to add three values together.
7
28
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
29
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
30
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20180220180325.29818-20-peter.maydell@linaro.org
31
Message-id: 20201009144712.11187-1-peter.maydell@linaro.org
11
---
32
---
12
hw/arm/Makefile.objs | 1 +
33
target/arm/translate.c | 58 ++++++++++++++++++++++++++++++++++--------
13
hw/arm/mps2-tz.c | 503 +++++++++++++++++++++++++++++++++++++++++++++++++++
34
1 file changed, 48 insertions(+), 10 deletions(-)
14
2 files changed, 504 insertions(+)
15
create mode 100644 hw/arm/mps2-tz.c
16
35
17
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
36
diff --git a/target/arm/translate.c b/target/arm/translate.c
18
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/Makefile.objs
38
--- a/target/arm/translate.c
20
+++ b/hw/arm/Makefile.objs
39
+++ b/target/arm/translate.c
21
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o
40
@@ -XXX,XX +XXX,XX @@ static bool op_smlad(DisasContext *s, arg_rrrr *a, bool m_swap, bool sub)
22
obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o
41
gen_smul_dual(t1, t2);
23
obj-$(CONFIG_ASPEED_SOC) += aspeed_soc.o aspeed.o
42
24
obj-$(CONFIG_MPS2) += mps2.o
43
if (sub) {
25
+obj-$(CONFIG_MPS2) += mps2-tz.o
44
- /* This subtraction cannot overflow. */
26
obj-$(CONFIG_MSF2) += msf2-soc.o msf2-som.o
45
+ /*
27
obj-$(CONFIG_IOTKIT) += iotkit.o
46
+ * This subtraction cannot overflow, so we can do a simple
28
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
47
+ * 32-bit subtraction and then a possible 32-bit saturating
29
new file mode 100644
48
+ * addition of Ra.
30
index XXXXXXX..XXXXXXX
49
+ */
31
--- /dev/null
50
tcg_gen_sub_i32(t1, t1, t2);
32
+++ b/hw/arm/mps2-tz.c
51
+ tcg_temp_free_i32(t2);
33
@@ -XXX,XX +XXX,XX @@
34
+/*
35
+ * ARM V2M MPS2 board emulation, trustzone aware FPGA images
36
+ *
37
+ * Copyright (c) 2017 Linaro Limited
38
+ * Written by Peter Maydell
39
+ *
40
+ * This program is free software; you can redistribute it and/or modify
41
+ * it under the terms of the GNU General Public License version 2 or
42
+ * (at your option) any later version.
43
+ */
44
+
52
+
45
+/* The MPS2 and MPS2+ dev boards are FPGA based (the 2+ has a bigger
53
+ if (a->ra != 15) {
46
+ * FPGA but is otherwise the same as the 2). Since the CPU itself
54
+ t2 = load_reg(s, a->ra);
47
+ * and most of the devices are in the FPGA, the details of the board
55
+ gen_helper_add_setq(t1, cpu_env, t1, t2);
48
+ * as seen by the guest depend significantly on the FPGA image.
56
+ tcg_temp_free_i32(t2);
49
+ * This source file covers the following FPGA images, for TrustZone cores:
57
+ }
50
+ * "mps2-an505" -- Cortex-M33 as documented in ARM Application Note AN505
58
+ } else if (a->ra == 15) {
51
+ *
59
+ /* Single saturation-checking addition */
52
+ * Links to the TRM for the board itself and to the various Application
60
+ gen_helper_add_setq(t1, cpu_env, t1, t2);
53
+ * Notes which document the FPGA images can be found here:
61
+ tcg_temp_free_i32(t2);
54
+ * https://developer.arm.com/products/system-design/development-boards/fpga-prototyping-boards/mps2
62
} else {
55
+ *
63
/*
56
+ * Board TRM:
64
- * This addition cannot overflow 32 bits; however it may
57
+ * http://infocenter.arm.com/help/topic/com.arm.doc.100112_0200_06_en/versatile_express_cortex_m_prototyping_systems_v2m_mps2_and_v2m_mps2plus_technical_reference_100112_0200_06_en.pdf
65
- * overflow considered as a signed operation, in which case
58
+ * Application Note AN505:
66
- * we must set the Q flag.
59
+ * http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
67
+ * We need to add the products and Ra together and then
60
+ *
68
+ * determine whether the final result overflowed. Doing
61
+ * The AN505 defers to the Cortex-M33 processor ARMv8M IoT Kit FVP User Guide
69
+ * this as two separate add-and-check-overflow steps incorrectly
62
+ * (ARM ECM0601256) for the details of some of the device layout:
70
+ * sets Q for cases like (-32768 * -32768) + (-32768 * -32768) + -1.
63
+ * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
71
+ * Do all the arithmetic at 64-bits and then check for overflow.
64
+ */
72
*/
73
- gen_helper_add_setq(t1, cpu_env, t1, t2);
74
- }
75
- tcg_temp_free_i32(t2);
76
+ TCGv_i64 p64, q64;
77
+ TCGv_i32 t3, qf, one;
78
79
- if (a->ra != 15) {
80
- t2 = load_reg(s, a->ra);
81
- gen_helper_add_setq(t1, cpu_env, t1, t2);
82
+ p64 = tcg_temp_new_i64();
83
+ q64 = tcg_temp_new_i64();
84
+ tcg_gen_ext_i32_i64(p64, t1);
85
+ tcg_gen_ext_i32_i64(q64, t2);
86
+ tcg_gen_add_i64(p64, p64, q64);
87
+ load_reg_var(s, t2, a->ra);
88
+ tcg_gen_ext_i32_i64(q64, t2);
89
+ tcg_gen_add_i64(p64, p64, q64);
90
+ tcg_temp_free_i64(q64);
65
+
91
+
66
+#include "qemu/osdep.h"
92
+ tcg_gen_extr_i64_i32(t1, t2, p64);
67
+#include "qapi/error.h"
93
+ tcg_temp_free_i64(p64);
68
+#include "qemu/error-report.h"
94
+ /*
69
+#include "hw/arm/arm.h"
95
+ * t1 is the low half of the result which goes into Rd.
70
+#include "hw/arm/armv7m.h"
96
+ * We have overflow and must set Q if the high half (t2)
71
+#include "hw/or-irq.h"
97
+ * is different from the sign-extension of t1.
72
+#include "hw/boards.h"
98
+ */
73
+#include "exec/address-spaces.h"
99
+ t3 = tcg_temp_new_i32();
74
+#include "sysemu/sysemu.h"
100
+ tcg_gen_sari_i32(t3, t1, 31);
75
+#include "hw/misc/unimp.h"
101
+ qf = load_cpu_field(QF);
76
+#include "hw/char/cmsdk-apb-uart.h"
102
+ one = tcg_const_i32(1);
77
+#include "hw/timer/cmsdk-apb-timer.h"
103
+ tcg_gen_movcond_i32(TCG_COND_NE, qf, t2, t3, one, qf);
78
+#include "hw/misc/mps2-scc.h"
104
+ store_cpu_field(qf, QF);
79
+#include "hw/misc/mps2-fpgaio.h"
105
+ tcg_temp_free_i32(one);
80
+#include "hw/arm/iotkit.h"
106
+ tcg_temp_free_i32(t3);
81
+#include "hw/devices.h"
107
tcg_temp_free_i32(t2);
82
+#include "net/net.h"
108
}
83
+#include "hw/core/split-irq.h"
109
store_reg(s, a->rd, t1);
84
+
85
+typedef enum MPS2TZFPGAType {
86
+ FPGA_AN505,
87
+} MPS2TZFPGAType;
88
+
89
+typedef struct {
90
+ MachineClass parent;
91
+ MPS2TZFPGAType fpga_type;
92
+ uint32_t scc_id;
93
+} MPS2TZMachineClass;
94
+
95
+typedef struct {
96
+ MachineState parent;
97
+
98
+ IoTKit iotkit;
99
+ MemoryRegion psram;
100
+ MemoryRegion ssram1;
101
+ MemoryRegion ssram1_m;
102
+ MemoryRegion ssram23;
103
+ MPS2SCC scc;
104
+ MPS2FPGAIO fpgaio;
105
+ TZPPC ppc[5];
106
+ UnimplementedDeviceState ssram_mpc[3];
107
+ UnimplementedDeviceState spi[5];
108
+ UnimplementedDeviceState i2c[4];
109
+ UnimplementedDeviceState i2s_audio;
110
+ UnimplementedDeviceState gpio[5];
111
+ UnimplementedDeviceState dma[4];
112
+ UnimplementedDeviceState gfx;
113
+ CMSDKAPBUART uart[5];
114
+ SplitIRQ sec_resp_splitter;
115
+ qemu_or_irq uart_irq_orgate;
116
+} MPS2TZMachineState;
117
+
118
+#define TYPE_MPS2TZ_MACHINE "mps2tz"
119
+#define TYPE_MPS2TZ_AN505_MACHINE MACHINE_TYPE_NAME("mps2-an505")
120
+
121
+#define MPS2TZ_MACHINE(obj) \
122
+ OBJECT_CHECK(MPS2TZMachineState, obj, TYPE_MPS2TZ_MACHINE)
123
+#define MPS2TZ_MACHINE_GET_CLASS(obj) \
124
+ OBJECT_GET_CLASS(MPS2TZMachineClass, obj, TYPE_MPS2TZ_MACHINE)
125
+#define MPS2TZ_MACHINE_CLASS(klass) \
126
+ OBJECT_CLASS_CHECK(MPS2TZMachineClass, klass, TYPE_MPS2TZ_MACHINE)
127
+
128
+/* Main SYSCLK frequency in Hz */
129
+#define SYSCLK_FRQ 20000000
130
+
131
+/* Initialize the auxiliary RAM region @mr and map it into
132
+ * the memory map at @base.
133
+ */
134
+static void make_ram(MemoryRegion *mr, const char *name,
135
+ hwaddr base, hwaddr size)
136
+{
137
+ memory_region_init_ram(mr, NULL, name, size, &error_fatal);
138
+ memory_region_add_subregion(get_system_memory(), base, mr);
139
+}
140
+
141
+/* Create an alias of an entire original MemoryRegion @orig
142
+ * located at @base in the memory map.
143
+ */
144
+static void make_ram_alias(MemoryRegion *mr, const char *name,
145
+ MemoryRegion *orig, hwaddr base)
146
+{
147
+ memory_region_init_alias(mr, NULL, name, orig, 0,
148
+ memory_region_size(orig));
149
+ memory_region_add_subregion(get_system_memory(), base, mr);
150
+}
151
+
152
+static void init_sysbus_child(Object *parent, const char *childname,
153
+ void *child, size_t childsize,
154
+ const char *childtype)
155
+{
156
+ object_initialize(child, childsize, childtype);
157
+ object_property_add_child(parent, childname, OBJECT(child), &error_abort);
158
+ qdev_set_parent_bus(DEVICE(child), sysbus_get_default());
159
+
160
+}
161
+
162
+/* Most of the devices in the AN505 FPGA image sit behind
163
+ * Peripheral Protection Controllers. These data structures
164
+ * define the layout of which devices sit behind which PPCs.
165
+ * The devfn for each port is a function which creates, configures
166
+ * and initializes the device, returning the MemoryRegion which
167
+ * needs to be plugged into the downstream end of the PPC port.
168
+ */
169
+typedef MemoryRegion *MakeDevFn(MPS2TZMachineState *mms, void *opaque,
170
+ const char *name, hwaddr size);
171
+
172
+typedef struct PPCPortInfo {
173
+ const char *name;
174
+ MakeDevFn *devfn;
175
+ void *opaque;
176
+ hwaddr addr;
177
+ hwaddr size;
178
+} PPCPortInfo;
179
+
180
+typedef struct PPCInfo {
181
+ const char *name;
182
+ PPCPortInfo ports[TZ_NUM_PORTS];
183
+} PPCInfo;
184
+
185
+static MemoryRegion *make_unimp_dev(MPS2TZMachineState *mms,
186
+ void *opaque,
187
+ const char *name, hwaddr size)
188
+{
189
+ /* Initialize, configure and realize a TYPE_UNIMPLEMENTED_DEVICE,
190
+ * and return a pointer to its MemoryRegion.
191
+ */
192
+ UnimplementedDeviceState *uds = opaque;
193
+
194
+ init_sysbus_child(OBJECT(mms), name, uds,
195
+ sizeof(UnimplementedDeviceState),
196
+ TYPE_UNIMPLEMENTED_DEVICE);
197
+ qdev_prop_set_string(DEVICE(uds), "name", name);
198
+ qdev_prop_set_uint64(DEVICE(uds), "size", size);
199
+ object_property_set_bool(OBJECT(uds), true, "realized", &error_fatal);
200
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(uds), 0);
201
+}
202
+
203
+static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
204
+ const char *name, hwaddr size)
205
+{
206
+ CMSDKAPBUART *uart = opaque;
207
+ int i = uart - &mms->uart[0];
208
+ Chardev *uartchr = i < MAX_SERIAL_PORTS ? serial_hds[i] : NULL;
209
+ int rxirqno = i * 2;
210
+ int txirqno = i * 2 + 1;
211
+ int combirqno = i + 10;
212
+ SysBusDevice *s;
213
+ DeviceState *iotkitdev = DEVICE(&mms->iotkit);
214
+ DeviceState *orgate_dev = DEVICE(&mms->uart_irq_orgate);
215
+
216
+ init_sysbus_child(OBJECT(mms), name, uart,
217
+ sizeof(mms->uart[0]), TYPE_CMSDK_APB_UART);
218
+ qdev_prop_set_chr(DEVICE(uart), "chardev", uartchr);
219
+ qdev_prop_set_uint32(DEVICE(uart), "pclk-frq", SYSCLK_FRQ);
220
+ object_property_set_bool(OBJECT(uart), true, "realized", &error_fatal);
221
+ s = SYS_BUS_DEVICE(uart);
222
+ sysbus_connect_irq(s, 0, qdev_get_gpio_in_named(iotkitdev,
223
+ "EXP_IRQ", txirqno));
224
+ sysbus_connect_irq(s, 1, qdev_get_gpio_in_named(iotkitdev,
225
+ "EXP_IRQ", rxirqno));
226
+ sysbus_connect_irq(s, 2, qdev_get_gpio_in(orgate_dev, i * 2));
227
+ sysbus_connect_irq(s, 3, qdev_get_gpio_in(orgate_dev, i * 2 + 1));
228
+ sysbus_connect_irq(s, 4, qdev_get_gpio_in_named(iotkitdev,
229
+ "EXP_IRQ", combirqno));
230
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(uart), 0);
231
+}
232
+
233
+static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque,
234
+ const char *name, hwaddr size)
235
+{
236
+ MPS2SCC *scc = opaque;
237
+ DeviceState *sccdev;
238
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
239
+
240
+ object_initialize(scc, sizeof(mms->scc), TYPE_MPS2_SCC);
241
+ sccdev = DEVICE(scc);
242
+ qdev_set_parent_bus(sccdev, sysbus_get_default());
243
+ qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2);
244
+ qdev_prop_set_uint32(sccdev, "scc-aid", 0x02000008);
245
+ qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id);
246
+ object_property_set_bool(OBJECT(scc), true, "realized", &error_fatal);
247
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(sccdev), 0);
248
+}
249
+
250
+static MemoryRegion *make_fpgaio(MPS2TZMachineState *mms, void *opaque,
251
+ const char *name, hwaddr size)
252
+{
253
+ MPS2FPGAIO *fpgaio = opaque;
254
+
255
+ object_initialize(fpgaio, sizeof(mms->fpgaio), TYPE_MPS2_FPGAIO);
256
+ qdev_set_parent_bus(DEVICE(fpgaio), sysbus_get_default());
257
+ object_property_set_bool(OBJECT(fpgaio), true, "realized", &error_fatal);
258
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(fpgaio), 0);
259
+}
260
+
261
+static void mps2tz_common_init(MachineState *machine)
262
+{
263
+ MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine);
264
+ MachineClass *mc = MACHINE_GET_CLASS(machine);
265
+ MemoryRegion *system_memory = get_system_memory();
266
+ DeviceState *iotkitdev;
267
+ DeviceState *dev_splitter;
268
+ int i;
269
+
270
+ if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
271
+ error_report("This board can only be used with CPU %s",
272
+ mc->default_cpu_type);
273
+ exit(1);
274
+ }
275
+
276
+ init_sysbus_child(OBJECT(machine), "iotkit", &mms->iotkit,
277
+ sizeof(mms->iotkit), TYPE_IOTKIT);
278
+ iotkitdev = DEVICE(&mms->iotkit);
279
+ object_property_set_link(OBJECT(&mms->iotkit), OBJECT(system_memory),
280
+ "memory", &error_abort);
281
+ qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", 92);
282
+ qdev_prop_set_uint32(iotkitdev, "MAINCLK", SYSCLK_FRQ);
283
+ object_property_set_bool(OBJECT(&mms->iotkit), true, "realized",
284
+ &error_fatal);
285
+
286
+ /* The sec_resp_cfg output from the IoTKit must be split into multiple
287
+ * lines, one for each of the PPCs we create here.
288
+ */
289
+ object_initialize(&mms->sec_resp_splitter, sizeof(mms->sec_resp_splitter),
290
+ TYPE_SPLIT_IRQ);
291
+ object_property_add_child(OBJECT(machine), "sec-resp-splitter",
292
+ OBJECT(&mms->sec_resp_splitter), &error_abort);
293
+ object_property_set_int(OBJECT(&mms->sec_resp_splitter), 5,
294
+ "num-lines", &error_fatal);
295
+ object_property_set_bool(OBJECT(&mms->sec_resp_splitter), true,
296
+ "realized", &error_fatal);
297
+ dev_splitter = DEVICE(&mms->sec_resp_splitter);
298
+ qdev_connect_gpio_out_named(iotkitdev, "sec_resp_cfg", 0,
299
+ qdev_get_gpio_in(dev_splitter, 0));
300
+
301
+ /* The IoTKit sets up much of the memory layout, including
302
+ * the aliases between secure and non-secure regions in the
303
+ * address space. The FPGA itself contains:
304
+ *
305
+ * 0x00000000..0x003fffff SSRAM1
306
+ * 0x00400000..0x007fffff alias of SSRAM1
307
+ * 0x28000000..0x283fffff 4MB SSRAM2 + SSRAM3
308
+ * 0x40100000..0x4fffffff AHB Master Expansion 1 interface devices
309
+ * 0x80000000..0x80ffffff 16MB PSRAM
310
+ */
311
+
312
+ /* The FPGA images have an odd combination of different RAMs,
313
+ * because in hardware they are different implementations and
314
+ * connected to different buses, giving varying performance/size
315
+ * tradeoffs. For QEMU they're all just RAM, though. We arbitrarily
316
+ * call the 16MB our "system memory", as it's the largest lump.
317
+ */
318
+ memory_region_allocate_system_memory(&mms->psram,
319
+ NULL, "mps.ram", 0x01000000);
320
+ memory_region_add_subregion(system_memory, 0x80000000, &mms->psram);
321
+
322
+ /* The SSRAM memories should all be behind Memory Protection Controllers,
323
+ * but we don't implement that yet.
324
+ */
325
+ make_ram(&mms->ssram1, "mps.ssram1", 0x00000000, 0x00400000);
326
+ make_ram_alias(&mms->ssram1_m, "mps.ssram1_m", &mms->ssram1, 0x00400000);
327
+
328
+ make_ram(&mms->ssram23, "mps.ssram23", 0x28000000, 0x00400000);
329
+
330
+ /* The overflow IRQs for all UARTs are ORed together.
331
+ * Tx, Rx and "combined" IRQs are sent to the NVIC separately.
332
+ * Create the OR gate for this.
333
+ */
334
+ object_initialize(&mms->uart_irq_orgate, sizeof(mms->uart_irq_orgate),
335
+ TYPE_OR_IRQ);
336
+ object_property_add_child(OBJECT(mms), "uart-irq-orgate",
337
+ OBJECT(&mms->uart_irq_orgate), &error_abort);
338
+ object_property_set_int(OBJECT(&mms->uart_irq_orgate), 10, "num-lines",
339
+ &error_fatal);
340
+ object_property_set_bool(OBJECT(&mms->uart_irq_orgate), true,
341
+ "realized", &error_fatal);
342
+ qdev_connect_gpio_out(DEVICE(&mms->uart_irq_orgate), 0,
343
+ qdev_get_gpio_in_named(iotkitdev, "EXP_IRQ", 15));
344
+
345
+ /* Most of the devices in the FPGA are behind Peripheral Protection
346
+ * Controllers. The required order for initializing things is:
347
+ * + initialize the PPC
348
+ * + initialize, configure and realize downstream devices
349
+ * + connect downstream device MemoryRegions to the PPC
350
+ * + realize the PPC
351
+ * + map the PPC's MemoryRegions to the places in the address map
352
+ * where the downstream devices should appear
353
+ * + wire up the PPC's control lines to the IoTKit object
354
+ */
355
+
356
+ const PPCInfo ppcs[] = { {
357
+ .name = "apb_ppcexp0",
358
+ .ports = {
359
+ { "ssram-mpc0", make_unimp_dev, &mms->ssram_mpc[0],
360
+ 0x58007000, 0x1000 },
361
+ { "ssram-mpc1", make_unimp_dev, &mms->ssram_mpc[1],
362
+ 0x58008000, 0x1000 },
363
+ { "ssram-mpc2", make_unimp_dev, &mms->ssram_mpc[2],
364
+ 0x58009000, 0x1000 },
365
+ },
366
+ }, {
367
+ .name = "apb_ppcexp1",
368
+ .ports = {
369
+ { "spi0", make_unimp_dev, &mms->spi[0], 0x40205000, 0x1000 },
370
+ { "spi1", make_unimp_dev, &mms->spi[1], 0x40206000, 0x1000 },
371
+ { "spi2", make_unimp_dev, &mms->spi[2], 0x40209000, 0x1000 },
372
+ { "spi3", make_unimp_dev, &mms->spi[3], 0x4020a000, 0x1000 },
373
+ { "spi4", make_unimp_dev, &mms->spi[4], 0x4020b000, 0x1000 },
374
+ { "uart0", make_uart, &mms->uart[0], 0x40200000, 0x1000 },
375
+ { "uart1", make_uart, &mms->uart[1], 0x40201000, 0x1000 },
376
+ { "uart2", make_uart, &mms->uart[2], 0x40202000, 0x1000 },
377
+ { "uart3", make_uart, &mms->uart[3], 0x40203000, 0x1000 },
378
+ { "uart4", make_uart, &mms->uart[4], 0x40204000, 0x1000 },
379
+ { "i2c0", make_unimp_dev, &mms->i2c[0], 0x40207000, 0x1000 },
380
+ { "i2c1", make_unimp_dev, &mms->i2c[1], 0x40208000, 0x1000 },
381
+ { "i2c2", make_unimp_dev, &mms->i2c[2], 0x4020c000, 0x1000 },
382
+ { "i2c3", make_unimp_dev, &mms->i2c[3], 0x4020d000, 0x1000 },
383
+ },
384
+ }, {
385
+ .name = "apb_ppcexp2",
386
+ .ports = {
387
+ { "scc", make_scc, &mms->scc, 0x40300000, 0x1000 },
388
+ { "i2s-audio", make_unimp_dev, &mms->i2s_audio,
389
+ 0x40301000, 0x1000 },
390
+ { "fpgaio", make_fpgaio, &mms->fpgaio, 0x40302000, 0x1000 },
391
+ },
392
+ }, {
393
+ .name = "ahb_ppcexp0",
394
+ .ports = {
395
+ { "gfx", make_unimp_dev, &mms->gfx, 0x41000000, 0x140000 },
396
+ { "gpio0", make_unimp_dev, &mms->gpio[0], 0x40100000, 0x1000 },
397
+ { "gpio1", make_unimp_dev, &mms->gpio[1], 0x40101000, 0x1000 },
398
+ { "gpio2", make_unimp_dev, &mms->gpio[2], 0x40102000, 0x1000 },
399
+ { "gpio3", make_unimp_dev, &mms->gpio[3], 0x40103000, 0x1000 },
400
+ { "gpio4", make_unimp_dev, &mms->gpio[4], 0x40104000, 0x1000 },
401
+ },
402
+ }, {
403
+ .name = "ahb_ppcexp1",
404
+ .ports = {
405
+ { "dma0", make_unimp_dev, &mms->dma[0], 0x40110000, 0x1000 },
406
+ { "dma1", make_unimp_dev, &mms->dma[1], 0x40111000, 0x1000 },
407
+ { "dma2", make_unimp_dev, &mms->dma[2], 0x40112000, 0x1000 },
408
+ { "dma3", make_unimp_dev, &mms->dma[3], 0x40113000, 0x1000 },
409
+ },
410
+ },
411
+ };
412
+
413
+ for (i = 0; i < ARRAY_SIZE(ppcs); i++) {
414
+ const PPCInfo *ppcinfo = &ppcs[i];
415
+ TZPPC *ppc = &mms->ppc[i];
416
+ DeviceState *ppcdev;
417
+ int port;
418
+ char *gpioname;
419
+
420
+ init_sysbus_child(OBJECT(machine), ppcinfo->name, ppc,
421
+ sizeof(TZPPC), TYPE_TZ_PPC);
422
+ ppcdev = DEVICE(ppc);
423
+
424
+ for (port = 0; port < TZ_NUM_PORTS; port++) {
425
+ const PPCPortInfo *pinfo = &ppcinfo->ports[port];
426
+ MemoryRegion *mr;
427
+ char *portname;
428
+
429
+ if (!pinfo->devfn) {
430
+ continue;
431
+ }
432
+
433
+ mr = pinfo->devfn(mms, pinfo->opaque, pinfo->name, pinfo->size);
434
+ portname = g_strdup_printf("port[%d]", port);
435
+ object_property_set_link(OBJECT(ppc), OBJECT(mr),
436
+ portname, &error_fatal);
437
+ g_free(portname);
438
+ }
439
+
440
+ object_property_set_bool(OBJECT(ppc), true, "realized", &error_fatal);
441
+
442
+ for (port = 0; port < TZ_NUM_PORTS; port++) {
443
+ const PPCPortInfo *pinfo = &ppcinfo->ports[port];
444
+
445
+ if (!pinfo->devfn) {
446
+ continue;
447
+ }
448
+ sysbus_mmio_map(SYS_BUS_DEVICE(ppc), port, pinfo->addr);
449
+
450
+ gpioname = g_strdup_printf("%s_nonsec", ppcinfo->name);
451
+ qdev_connect_gpio_out_named(iotkitdev, gpioname, port,
452
+ qdev_get_gpio_in_named(ppcdev,
453
+ "cfg_nonsec",
454
+ port));
455
+ g_free(gpioname);
456
+ gpioname = g_strdup_printf("%s_ap", ppcinfo->name);
457
+ qdev_connect_gpio_out_named(iotkitdev, gpioname, port,
458
+ qdev_get_gpio_in_named(ppcdev,
459
+ "cfg_ap", port));
460
+ g_free(gpioname);
461
+ }
462
+
463
+ gpioname = g_strdup_printf("%s_irq_enable", ppcinfo->name);
464
+ qdev_connect_gpio_out_named(iotkitdev, gpioname, 0,
465
+ qdev_get_gpio_in_named(ppcdev,
466
+ "irq_enable", 0));
467
+ g_free(gpioname);
468
+ gpioname = g_strdup_printf("%s_irq_clear", ppcinfo->name);
469
+ qdev_connect_gpio_out_named(iotkitdev, gpioname, 0,
470
+ qdev_get_gpio_in_named(ppcdev,
471
+ "irq_clear", 0));
472
+ g_free(gpioname);
473
+ gpioname = g_strdup_printf("%s_irq_status", ppcinfo->name);
474
+ qdev_connect_gpio_out_named(ppcdev, "irq", 0,
475
+ qdev_get_gpio_in_named(iotkitdev,
476
+ gpioname, 0));
477
+ g_free(gpioname);
478
+
479
+ qdev_connect_gpio_out(dev_splitter, i,
480
+ qdev_get_gpio_in_named(ppcdev,
481
+ "cfg_sec_resp", 0));
482
+ }
483
+
484
+ /* In hardware this is a LAN9220; the LAN9118 is software compatible
485
+ * except that it doesn't support the checksum-offload feature.
486
+ * The ethernet controller is not behind a PPC.
487
+ */
488
+ lan9118_init(&nd_table[0], 0x42000000,
489
+ qdev_get_gpio_in_named(iotkitdev, "EXP_IRQ", 16));
490
+
491
+ create_unimplemented_device("FPGA NS PC", 0x48007000, 0x1000);
492
+
493
+ armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x400000);
494
+}
495
+
496
+static void mps2tz_class_init(ObjectClass *oc, void *data)
497
+{
498
+ MachineClass *mc = MACHINE_CLASS(oc);
499
+
500
+ mc->init = mps2tz_common_init;
501
+ mc->max_cpus = 1;
502
+}
503
+
504
+static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
505
+{
506
+ MachineClass *mc = MACHINE_CLASS(oc);
507
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_CLASS(oc);
508
+
509
+ mc->desc = "ARM MPS2 with AN505 FPGA image for Cortex-M33";
510
+ mmc->fpga_type = FPGA_AN505;
511
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
512
+ mmc->scc_id = 0x41040000 | (505 << 4);
513
+}
514
+
515
+static const TypeInfo mps2tz_info = {
516
+ .name = TYPE_MPS2TZ_MACHINE,
517
+ .parent = TYPE_MACHINE,
518
+ .abstract = true,
519
+ .instance_size = sizeof(MPS2TZMachineState),
520
+ .class_size = sizeof(MPS2TZMachineClass),
521
+ .class_init = mps2tz_class_init,
522
+};
523
+
524
+static const TypeInfo mps2tz_an505_info = {
525
+ .name = TYPE_MPS2TZ_AN505_MACHINE,
526
+ .parent = TYPE_MPS2TZ_MACHINE,
527
+ .class_init = mps2tz_an505_class_init,
528
+};
529
+
530
+static void mps2tz_machine_init(void)
531
+{
532
+ type_register_static(&mps2tz_info);
533
+ type_register_static(&mps2tz_an505_info);
534
+}
535
+
536
+type_init(mps2tz_machine_init);
537
--
110
--
538
2.16.2
111
2.20.1
539
112
540
113
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
For AArch32, unlike the VCVT of integer to float, which honours the
2
rounding mode specified by the FPSCR, VCVT of fixed-point to float is
3
always round-to-nearest. (AArch64 fixed-point-to-float conversions
4
always honour the FPCR rounding mode.)
2
5
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Implement this by providing _round_to_nearest versions of the
4
Message-id: 20180228193125.20577-13-richard.henderson@linaro.org
7
relevant helpers which set the rounding mode temporarily when making
8
the call to the underlying softfloat function.
9
10
We only need to change the VFP VCVT instructions, because the
11
standard- FPSCR value used by the Neon VCVT is always set to
12
round-to-nearest, so we don't need to do the extra work of saving
13
and restoring the rounding mode.
14
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
[PMM: renamed e1/e2/e3/e4 to use the same naming as the version
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
of the pseudocode in the Arm ARM]
17
Message-id: 20201013103532.13391-1-peter.maydell@linaro.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
---
18
---
10
target/arm/helper.h | 11 ++++
19
target/arm/helper.h | 13 +++++++++++++
11
target/arm/translate-a64.c | 94 +++++++++++++++++++++++++---
20
target/arm/vfp_helper.c | 23 ++++++++++++++++++++++-
12
target/arm/vec_helper.c | 149 +++++++++++++++++++++++++++++++++++++++++++++
21
target/arm/translate-vfp.c.inc | 24 ++++++++++++------------
13
3 files changed, 246 insertions(+), 8 deletions(-)
22
3 files changed, 47 insertions(+), 13 deletions(-)
14
23
15
diff --git a/target/arm/helper.h b/target/arm/helper.h
24
diff --git a/target/arm/helper.h b/target/arm/helper.h
16
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.h
26
--- a/target/arm/helper.h
18
+++ b/target/arm/helper.h
27
+++ b/target/arm/helper.h
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_fcadds, TCG_CALL_NO_RWG,
28
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(vfp_ultoh, f16, i32, i32, ptr)
20
DEF_HELPER_FLAGS_5(gvec_fcaddd, TCG_CALL_NO_RWG,
29
DEF_HELPER_3(vfp_sqtoh, f16, i64, i32, ptr)
21
void, ptr, ptr, ptr, ptr, i32)
30
DEF_HELPER_3(vfp_uqtoh, f16, i64, i32, ptr)
22
31
23
+DEF_HELPER_FLAGS_5(gvec_fcmlah, TCG_CALL_NO_RWG,
32
+DEF_HELPER_3(vfp_shtos_round_to_nearest, f32, i32, i32, ptr)
24
+ void, ptr, ptr, ptr, ptr, i32)
33
+DEF_HELPER_3(vfp_sltos_round_to_nearest, f32, i32, i32, ptr)
25
+DEF_HELPER_FLAGS_5(gvec_fcmlah_idx, TCG_CALL_NO_RWG,
34
+DEF_HELPER_3(vfp_uhtos_round_to_nearest, f32, i32, i32, ptr)
26
+ void, ptr, ptr, ptr, ptr, i32)
35
+DEF_HELPER_3(vfp_ultos_round_to_nearest, f32, i32, i32, ptr)
27
+DEF_HELPER_FLAGS_5(gvec_fcmlas, TCG_CALL_NO_RWG,
36
+DEF_HELPER_3(vfp_shtod_round_to_nearest, f64, i64, i32, ptr)
28
+ void, ptr, ptr, ptr, ptr, i32)
37
+DEF_HELPER_3(vfp_sltod_round_to_nearest, f64, i64, i32, ptr)
29
+DEF_HELPER_FLAGS_5(gvec_fcmlas_idx, TCG_CALL_NO_RWG,
38
+DEF_HELPER_3(vfp_uhtod_round_to_nearest, f64, i64, i32, ptr)
30
+ void, ptr, ptr, ptr, ptr, i32)
39
+DEF_HELPER_3(vfp_ultod_round_to_nearest, f64, i64, i32, ptr)
31
+DEF_HELPER_FLAGS_5(gvec_fcmlad, TCG_CALL_NO_RWG,
40
+DEF_HELPER_3(vfp_shtoh_round_to_nearest, f16, i32, i32, ptr)
32
+ void, ptr, ptr, ptr, ptr, i32)
41
+DEF_HELPER_3(vfp_uhtoh_round_to_nearest, f16, i32, i32, ptr)
42
+DEF_HELPER_3(vfp_sltoh_round_to_nearest, f16, i32, i32, ptr)
43
+DEF_HELPER_3(vfp_ultoh_round_to_nearest, f16, i32, i32, ptr)
33
+
44
+
34
#ifdef TARGET_AARCH64
45
DEF_HELPER_FLAGS_2(set_rmode, TCG_CALL_NO_RWG, i32, i32, ptr)
35
#include "helper-a64.h"
46
36
#endif
47
DEF_HELPER_FLAGS_3(vfp_fcvt_f16_to_f32, TCG_CALL_NO_RWG, f32, f16, ptr, i32)
37
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
48
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
38
index XXXXXXX..XXXXXXX 100644
49
index XXXXXXX..XXXXXXX 100644
39
--- a/target/arm/translate-a64.c
50
--- a/target/arm/vfp_helper.c
40
+++ b/target/arm/translate-a64.c
51
+++ b/target/arm/vfp_helper.c
41
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
52
@@ -XXX,XX +XXX,XX @@ float32 VFP_HELPER(fcvts, d)(float64 x, CPUARMState *env)
42
}
53
return float64_to_float32(x, &env->vfp.fp_status);
43
feature = ARM_FEATURE_V8_RDM;
54
}
44
break;
55
45
+ case 0x8: /* FCMLA, #0 */
56
-/* VFP3 fixed point conversion. */
46
+ case 0x9: /* FCMLA, #90 */
57
+/*
47
+ case 0xa: /* FCMLA, #180 */
58
+ * VFP3 fixed point conversion. The AArch32 versions of fix-to-float
48
+ case 0xb: /* FCMLA, #270 */
59
+ * must always round-to-nearest; the AArch64 ones honour the FPSCR
49
case 0xc: /* FCADD, #90 */
60
+ * rounding mode. (For AArch32 Neon the standard-FPSCR is set to
50
case 0xe: /* FCADD, #270 */
61
+ * round-to-nearest so either helper will work.) AArch32 float-to-fix
51
if (size == 0
62
+ * must round-to-zero.
52
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
63
+ */
53
}
64
#define VFP_CONV_FIX_FLOAT(name, p, fsz, ftype, isz, itype) \
54
return;
65
ftype HELPER(vfp_##name##to##p)(uint##isz##_t x, uint32_t shift, \
55
66
void *fpstp) \
56
+ case 0x8: /* FCMLA, #0 */
67
{ return itype##_to_##float##fsz##_scalbn(x, -shift, fpstp); }
57
+ case 0x9: /* FCMLA, #90 */
68
58
+ case 0xa: /* FCMLA, #180 */
69
+#define VFP_CONV_FIX_FLOAT_ROUND(name, p, fsz, ftype, isz, itype) \
59
+ case 0xb: /* FCMLA, #270 */
70
+ ftype HELPER(vfp_##name##to##p##_round_to_nearest)(uint##isz##_t x, \
60
+ rot = extract32(opcode, 0, 2);
71
+ uint32_t shift, \
61
+ switch (size) {
72
+ void *fpstp) \
62
+ case 1:
73
+ { \
63
+ gen_gvec_op3_fpst(s, is_q, rd, rn, rm, true, rot,
74
+ ftype ret; \
64
+ gen_helper_gvec_fcmlah);
75
+ float_status *fpst = fpstp; \
65
+ break;
76
+ FloatRoundMode oldmode = fpst->float_rounding_mode; \
66
+ case 2:
77
+ fpst->float_rounding_mode = float_round_nearest_even; \
67
+ gen_gvec_op3_fpst(s, is_q, rd, rn, rm, false, rot,
78
+ ret = itype##_to_##float##fsz##_scalbn(x, -shift, fpstp); \
68
+ gen_helper_gvec_fcmlas);
79
+ fpst->float_rounding_mode = oldmode; \
69
+ break;
80
+ return ret; \
70
+ case 3:
71
+ gen_gvec_op3_fpst(s, is_q, rd, rn, rm, false, rot,
72
+ gen_helper_gvec_fcmlad);
73
+ break;
74
+ default:
75
+ g_assert_not_reached();
76
+ }
77
+ return;
78
+
79
case 0xc: /* FCADD, #90 */
80
case 0xe: /* FCADD, #270 */
81
rot = extract32(opcode, 1, 1);
82
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
83
int rn = extract32(insn, 5, 5);
84
int rd = extract32(insn, 0, 5);
85
bool is_long = false;
86
- bool is_fp = false;
87
+ int is_fp = 0;
88
bool is_fp16 = false;
89
int index;
90
TCGv_ptr fpst;
91
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
92
case 0x05: /* FMLS */
93
case 0x09: /* FMUL */
94
case 0x19: /* FMULX */
95
- is_fp = true;
96
+ is_fp = 1;
97
break;
98
case 0x1d: /* SQRDMLAH */
99
case 0x1f: /* SQRDMLSH */
100
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
101
return;
102
}
103
break;
104
+ case 0x11: /* FCMLA #0 */
105
+ case 0x13: /* FCMLA #90 */
106
+ case 0x15: /* FCMLA #180 */
107
+ case 0x17: /* FCMLA #270 */
108
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_FCMA)) {
109
+ unallocated_encoding(s);
110
+ return;
111
+ }
112
+ is_fp = 2;
113
+ break;
114
default:
115
unallocated_encoding(s);
116
return;
117
}
118
119
- if (is_fp) {
120
+ switch (is_fp) {
121
+ case 1: /* normal fp */
122
/* convert insn encoded size to TCGMemOp size */
123
switch (size) {
124
case 0: /* half-precision */
125
- if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
126
- unallocated_encoding(s);
127
- return;
128
- }
129
size = MO_16;
130
+ is_fp16 = true;
131
break;
132
case MO_32: /* single precision */
133
case MO_64: /* double precision */
134
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
135
unallocated_encoding(s);
136
return;
137
}
138
- } else {
139
+ break;
140
+
141
+ case 2: /* complex fp */
142
+ /* Each indexable element is a complex pair. */
143
+ size <<= 1;
144
+ switch (size) {
145
+ case MO_32:
146
+ if (h && !is_q) {
147
+ unallocated_encoding(s);
148
+ return;
149
+ }
150
+ is_fp16 = true;
151
+ break;
152
+ case MO_64:
153
+ break;
154
+ default:
155
+ unallocated_encoding(s);
156
+ return;
157
+ }
158
+ break;
159
+
160
+ default: /* integer */
161
switch (size) {
162
case MO_8:
163
case MO_64:
164
unallocated_encoding(s);
165
return;
166
}
167
+ break;
168
+ }
169
+ if (is_fp16 && !arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
170
+ unallocated_encoding(s);
171
+ return;
172
}
173
174
/* Given TCGMemOp size, adjust register and indexing. */
175
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
176
fpst = NULL;
177
}
178
179
+ switch (16 * u + opcode) {
180
+ case 0x11: /* FCMLA #0 */
181
+ case 0x13: /* FCMLA #90 */
182
+ case 0x15: /* FCMLA #180 */
183
+ case 0x17: /* FCMLA #270 */
184
+ tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
185
+ vec_full_reg_offset(s, rn),
186
+ vec_reg_offset(s, rm, index, size), fpst,
187
+ is_q ? 16 : 8, vec_full_reg_size(s),
188
+ extract32(insn, 13, 2), /* rot */
189
+ size == MO_64
190
+ ? gen_helper_gvec_fcmlas_idx
191
+ : gen_helper_gvec_fcmlah_idx);
192
+ tcg_temp_free_ptr(fpst);
193
+ return;
194
+ }
81
+ }
195
+
82
+
196
if (size == 3) {
83
#define VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, ROUND, suff) \
197
TCGv_i64 tcg_idx = tcg_temp_new_i64();
84
uint##isz##_t HELPER(vfp_to##name##p##suff)(ftype x, uint32_t shift, \
198
int pass;
85
void *fpst) \
199
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
86
@@ -XXX,XX +XXX,XX @@ uint##isz##_t HELPER(vfp_to##name##p##suff)(ftype x, uint32_t shift, \
87
88
#define VFP_CONV_FIX(name, p, fsz, ftype, isz, itype) \
89
VFP_CONV_FIX_FLOAT(name, p, fsz, ftype, isz, itype) \
90
+VFP_CONV_FIX_FLOAT_ROUND(name, p, fsz, ftype, isz, itype) \
91
VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, \
92
float_round_to_zero, _round_to_zero) \
93
VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, \
94
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
200
index XXXXXXX..XXXXXXX 100644
95
index XXXXXXX..XXXXXXX 100644
201
--- a/target/arm/vec_helper.c
96
--- a/target/arm/translate-vfp.c.inc
202
+++ b/target/arm/vec_helper.c
97
+++ b/target/arm/translate-vfp.c.inc
203
@@ -XXX,XX +XXX,XX @@ void HELPER(gvec_fcaddd)(void *vd, void *vn, void *vm,
98
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_hp(DisasContext *s, arg_VCVT_fix_sp *a)
204
}
99
/* Switch on op:U:sx bits */
205
clear_tail(d, opr_sz, simd_maxsz(desc));
100
switch (a->opc) {
206
}
101
case 0:
207
+
102
- gen_helper_vfp_shtoh(vd, vd, shift, fpst);
208
+void HELPER(gvec_fcmlah)(void *vd, void *vn, void *vm,
103
+ gen_helper_vfp_shtoh_round_to_nearest(vd, vd, shift, fpst);
209
+ void *vfpst, uint32_t desc)
104
break;
210
+{
105
case 1:
211
+ uintptr_t opr_sz = simd_oprsz(desc);
106
- gen_helper_vfp_sltoh(vd, vd, shift, fpst);
212
+ float16 *d = vd;
107
+ gen_helper_vfp_sltoh_round_to_nearest(vd, vd, shift, fpst);
213
+ float16 *n = vn;
108
break;
214
+ float16 *m = vm;
109
case 2:
215
+ float_status *fpst = vfpst;
110
- gen_helper_vfp_uhtoh(vd, vd, shift, fpst);
216
+ intptr_t flip = extract32(desc, SIMD_DATA_SHIFT, 1);
111
+ gen_helper_vfp_uhtoh_round_to_nearest(vd, vd, shift, fpst);
217
+ uint32_t neg_imag = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
112
break;
218
+ uint32_t neg_real = flip ^ neg_imag;
113
case 3:
219
+ uintptr_t i;
114
- gen_helper_vfp_ultoh(vd, vd, shift, fpst);
220
+
115
+ gen_helper_vfp_ultoh_round_to_nearest(vd, vd, shift, fpst);
221
+ /* Shift boolean to the sign bit so we can xor to negate. */
116
break;
222
+ neg_real <<= 15;
117
case 4:
223
+ neg_imag <<= 15;
118
gen_helper_vfp_toshh_round_to_zero(vd, vd, shift, fpst);
224
+
119
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_sp(DisasContext *s, arg_VCVT_fix_sp *a)
225
+ for (i = 0; i < opr_sz / 2; i += 2) {
120
/* Switch on op:U:sx bits */
226
+ float16 e2 = n[H2(i + flip)];
121
switch (a->opc) {
227
+ float16 e1 = m[H2(i + flip)] ^ neg_real;
122
case 0:
228
+ float16 e4 = e2;
123
- gen_helper_vfp_shtos(vd, vd, shift, fpst);
229
+ float16 e3 = m[H2(i + 1 - flip)] ^ neg_imag;
124
+ gen_helper_vfp_shtos_round_to_nearest(vd, vd, shift, fpst);
230
+
125
break;
231
+ d[H2(i)] = float16_muladd(e2, e1, d[H2(i)], 0, fpst);
126
case 1:
232
+ d[H2(i + 1)] = float16_muladd(e4, e3, d[H2(i + 1)], 0, fpst);
127
- gen_helper_vfp_sltos(vd, vd, shift, fpst);
233
+ }
128
+ gen_helper_vfp_sltos_round_to_nearest(vd, vd, shift, fpst);
234
+ clear_tail(d, opr_sz, simd_maxsz(desc));
129
break;
235
+}
130
case 2:
236
+
131
- gen_helper_vfp_uhtos(vd, vd, shift, fpst);
237
+void HELPER(gvec_fcmlah_idx)(void *vd, void *vn, void *vm,
132
+ gen_helper_vfp_uhtos_round_to_nearest(vd, vd, shift, fpst);
238
+ void *vfpst, uint32_t desc)
133
break;
239
+{
134
case 3:
240
+ uintptr_t opr_sz = simd_oprsz(desc);
135
- gen_helper_vfp_ultos(vd, vd, shift, fpst);
241
+ float16 *d = vd;
136
+ gen_helper_vfp_ultos_round_to_nearest(vd, vd, shift, fpst);
242
+ float16 *n = vn;
137
break;
243
+ float16 *m = vm;
138
case 4:
244
+ float_status *fpst = vfpst;
139
gen_helper_vfp_toshs_round_to_zero(vd, vd, shift, fpst);
245
+ intptr_t flip = extract32(desc, SIMD_DATA_SHIFT, 1);
140
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a)
246
+ uint32_t neg_imag = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
141
/* Switch on op:U:sx bits */
247
+ uint32_t neg_real = flip ^ neg_imag;
142
switch (a->opc) {
248
+ uintptr_t i;
143
case 0:
249
+ float16 e1 = m[H2(flip)];
144
- gen_helper_vfp_shtod(vd, vd, shift, fpst);
250
+ float16 e3 = m[H2(1 - flip)];
145
+ gen_helper_vfp_shtod_round_to_nearest(vd, vd, shift, fpst);
251
+
146
break;
252
+ /* Shift boolean to the sign bit so we can xor to negate. */
147
case 1:
253
+ neg_real <<= 15;
148
- gen_helper_vfp_sltod(vd, vd, shift, fpst);
254
+ neg_imag <<= 15;
149
+ gen_helper_vfp_sltod_round_to_nearest(vd, vd, shift, fpst);
255
+ e1 ^= neg_real;
150
break;
256
+ e3 ^= neg_imag;
151
case 2:
257
+
152
- gen_helper_vfp_uhtod(vd, vd, shift, fpst);
258
+ for (i = 0; i < opr_sz / 2; i += 2) {
153
+ gen_helper_vfp_uhtod_round_to_nearest(vd, vd, shift, fpst);
259
+ float16 e2 = n[H2(i + flip)];
154
break;
260
+ float16 e4 = e2;
155
case 3:
261
+
156
- gen_helper_vfp_ultod(vd, vd, shift, fpst);
262
+ d[H2(i)] = float16_muladd(e2, e1, d[H2(i)], 0, fpst);
157
+ gen_helper_vfp_ultod_round_to_nearest(vd, vd, shift, fpst);
263
+ d[H2(i + 1)] = float16_muladd(e4, e3, d[H2(i + 1)], 0, fpst);
158
break;
264
+ }
159
case 4:
265
+ clear_tail(d, opr_sz, simd_maxsz(desc));
160
gen_helper_vfp_toshd_round_to_zero(vd, vd, shift, fpst);
266
+}
267
+
268
+void HELPER(gvec_fcmlas)(void *vd, void *vn, void *vm,
269
+ void *vfpst, uint32_t desc)
270
+{
271
+ uintptr_t opr_sz = simd_oprsz(desc);
272
+ float32 *d = vd;
273
+ float32 *n = vn;
274
+ float32 *m = vm;
275
+ float_status *fpst = vfpst;
276
+ intptr_t flip = extract32(desc, SIMD_DATA_SHIFT, 1);
277
+ uint32_t neg_imag = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
278
+ uint32_t neg_real = flip ^ neg_imag;
279
+ uintptr_t i;
280
+
281
+ /* Shift boolean to the sign bit so we can xor to negate. */
282
+ neg_real <<= 31;
283
+ neg_imag <<= 31;
284
+
285
+ for (i = 0; i < opr_sz / 4; i += 2) {
286
+ float32 e2 = n[H4(i + flip)];
287
+ float32 e1 = m[H4(i + flip)] ^ neg_real;
288
+ float32 e4 = e2;
289
+ float32 e3 = m[H4(i + 1 - flip)] ^ neg_imag;
290
+
291
+ d[H4(i)] = float32_muladd(e2, e1, d[H4(i)], 0, fpst);
292
+ d[H4(i + 1)] = float32_muladd(e4, e3, d[H4(i + 1)], 0, fpst);
293
+ }
294
+ clear_tail(d, opr_sz, simd_maxsz(desc));
295
+}
296
+
297
+void HELPER(gvec_fcmlas_idx)(void *vd, void *vn, void *vm,
298
+ void *vfpst, uint32_t desc)
299
+{
300
+ uintptr_t opr_sz = simd_oprsz(desc);
301
+ float32 *d = vd;
302
+ float32 *n = vn;
303
+ float32 *m = vm;
304
+ float_status *fpst = vfpst;
305
+ intptr_t flip = extract32(desc, SIMD_DATA_SHIFT, 1);
306
+ uint32_t neg_imag = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
307
+ uint32_t neg_real = flip ^ neg_imag;
308
+ uintptr_t i;
309
+ float32 e1 = m[H4(flip)];
310
+ float32 e3 = m[H4(1 - flip)];
311
+
312
+ /* Shift boolean to the sign bit so we can xor to negate. */
313
+ neg_real <<= 31;
314
+ neg_imag <<= 31;
315
+ e1 ^= neg_real;
316
+ e3 ^= neg_imag;
317
+
318
+ for (i = 0; i < opr_sz / 4; i += 2) {
319
+ float32 e2 = n[H4(i + flip)];
320
+ float32 e4 = e2;
321
+
322
+ d[H4(i)] = float32_muladd(e2, e1, d[H4(i)], 0, fpst);
323
+ d[H4(i + 1)] = float32_muladd(e4, e3, d[H4(i + 1)], 0, fpst);
324
+ }
325
+ clear_tail(d, opr_sz, simd_maxsz(desc));
326
+}
327
+
328
+void HELPER(gvec_fcmlad)(void *vd, void *vn, void *vm,
329
+ void *vfpst, uint32_t desc)
330
+{
331
+ uintptr_t opr_sz = simd_oprsz(desc);
332
+ float64 *d = vd;
333
+ float64 *n = vn;
334
+ float64 *m = vm;
335
+ float_status *fpst = vfpst;
336
+ intptr_t flip = extract32(desc, SIMD_DATA_SHIFT, 1);
337
+ uint64_t neg_imag = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
338
+ uint64_t neg_real = flip ^ neg_imag;
339
+ uintptr_t i;
340
+
341
+ /* Shift boolean to the sign bit so we can xor to negate. */
342
+ neg_real <<= 63;
343
+ neg_imag <<= 63;
344
+
345
+ for (i = 0; i < opr_sz / 8; i += 2) {
346
+ float64 e2 = n[i + flip];
347
+ float64 e1 = m[i + flip] ^ neg_real;
348
+ float64 e4 = e2;
349
+ float64 e3 = m[i + 1 - flip] ^ neg_imag;
350
+
351
+ d[i] = float64_muladd(e2, e1, d[i], 0, fpst);
352
+ d[i + 1] = float64_muladd(e4, e3, d[i + 1], 0, fpst);
353
+ }
354
+ clear_tail(d, opr_sz, simd_maxsz(desc));
355
+}
356
--
161
--
357
2.16.2
162
2.20.1
358
163
359
164
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
2
3
The time to transmit a char is expressed in nanoseconds, not in ticks.
4
5
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Message-id: 20201014213601.205222-1-f4bug@amsat.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
hw/arm/strongarm.c | 2 +-
11
1 file changed, 1 insertion(+), 1 deletion(-)
12
13
diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/strongarm.c
16
+++ b/hw/arm/strongarm.c
17
@@ -XXX,XX +XXX,XX @@ struct StrongARMUARTState {
18
uint8_t rx_start;
19
uint8_t rx_len;
20
21
- uint64_t char_transmit_time; /* time to transmit a char in ticks*/
22
+ uint64_t char_transmit_time; /* time to transmit a char in nanoseconds */
23
bool wait_break_end;
24
QEMUTimer *rx_timeout_timer;
25
QEMUTimer *tx_timer;
26
--
27
2.20.1
28
29
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
2
3
While APEI is a generic ACPI feature (usable by X86 and ARM64), only
4
the 'virt' machine uses it, by enabling the RAS Virtualization. See
5
commit 2afa8c8519: "hw/arm/virt: Introduce a RAS machine option").
6
7
Restrict the APEI tables generation code to the single user: the virt
8
machine. If another machine wants to use it, it simply has to 'select
9
ACPI_APEI' in its Kconfig.
10
11
Fixes: aa16508f1d ("ACPI: Build related register address fields via hardware error fw_cfg blob")
12
Acked-by: Michael S. Tsirkin <mst@redhat.com>
13
Reviewed-by: Dongjiu Geng <gengdongjiu@huawei.com>
14
Acked-by: Laszlo Ersek <lersek@redhat.com>
15
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
16
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
17
Message-id: 20201008161414.2672569-1-philmd@redhat.com
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
---
20
default-configs/devices/arm-softmmu.mak | 1 -
21
hw/arm/Kconfig | 1 +
22
2 files changed, 1 insertion(+), 1 deletion(-)
23
24
diff --git a/default-configs/devices/arm-softmmu.mak b/default-configs/devices/arm-softmmu.mak
25
index XXXXXXX..XXXXXXX 100644
26
--- a/default-configs/devices/arm-softmmu.mak
27
+++ b/default-configs/devices/arm-softmmu.mak
28
@@ -XXX,XX +XXX,XX @@ CONFIG_FSL_IMX7=y
29
CONFIG_FSL_IMX6UL=y
30
CONFIG_SEMIHOSTING=y
31
CONFIG_ALLWINNER_H3=y
32
-CONFIG_ACPI_APEI=y
33
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
34
index XXXXXXX..XXXXXXX 100644
35
--- a/hw/arm/Kconfig
36
+++ b/hw/arm/Kconfig
37
@@ -XXX,XX +XXX,XX @@ config ARM_VIRT
38
select ACPI_MEMORY_HOTPLUG
39
select ACPI_HW_REDUCED
40
select ACPI_NVDIMM
41
+ select ACPI_APEI
42
43
config CHEETAH
44
bool
45
--
46
2.20.1
47
48
diff view generated by jsdifflib
1
The IoTKit Security Controller includes various registers
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
that expose to software the controls for the Peripheral
3
Protection Controllers in the system. Implement these.
4
2
3
Use the BCM2835_SYSTIMER_COUNT definition instead of the
4
magic '4' value.
5
6
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20201010203709.3116542-2-f4bug@amsat.org
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180220180325.29818-17-peter.maydell@linaro.org
8
---
11
---
9
include/hw/misc/iotkit-secctl.h | 64 +++++++++-
12
include/hw/timer/bcm2835_systmr.h | 4 +++-
10
hw/misc/iotkit-secctl.c | 270 +++++++++++++++++++++++++++++++++++++---
13
hw/timer/bcm2835_systmr.c | 3 ++-
11
2 files changed, 315 insertions(+), 19 deletions(-)
14
2 files changed, 5 insertions(+), 2 deletions(-)
12
15
13
diff --git a/include/hw/misc/iotkit-secctl.h b/include/hw/misc/iotkit-secctl.h
16
diff --git a/include/hw/timer/bcm2835_systmr.h b/include/hw/timer/bcm2835_systmr.h
14
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/misc/iotkit-secctl.h
18
--- a/include/hw/timer/bcm2835_systmr.h
16
+++ b/include/hw/misc/iotkit-secctl.h
19
+++ b/include/hw/timer/bcm2835_systmr.h
17
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@
18
* QEMU interface:
21
#define TYPE_BCM2835_SYSTIMER "bcm2835-sys-timer"
19
* + sysbus MMIO region 0 is the "secure privilege control block" registers
22
OBJECT_DECLARE_SIMPLE_TYPE(BCM2835SystemTimerState, BCM2835_SYSTIMER)
20
* + sysbus MMIO region 1 is the "non-secure privilege control block" registers
23
21
+ * + named GPIO output "sec_resp_cfg" indicating whether blocked accesses
24
+#define BCM2835_SYSTIMER_COUNT 4
22
+ * should RAZ/WI or bus error
23
+ * Controlling the 2 APB PPCs in the IoTKit:
24
+ * + named GPIO outputs apb_ppc0_nonsec[0..2] and apb_ppc1_nonsec
25
+ * + named GPIO outputs apb_ppc0_ap[0..2] and apb_ppc1_ap
26
+ * + named GPIO outputs apb_ppc{0,1}_irq_enable
27
+ * + named GPIO outputs apb_ppc{0,1}_irq_clear
28
+ * + named GPIO inputs apb_ppc{0,1}_irq_status
29
+ * Controlling each of the 4 expansion APB PPCs which a system using the IoTKit
30
+ * might provide:
31
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_nonsec[0..15]
32
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_ap[0..15]
33
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_irq_enable
34
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_irq_clear
35
+ * + named GPIO inputs apb_ppcexp{0,1,2,3}_irq_status
36
+ * Controlling each of the 4 expansion AHB PPCs which a system using the IoTKit
37
+ * might provide:
38
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_nonsec[0..15]
39
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_ap[0..15]
40
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_enable
41
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_clear
42
+ * + named GPIO inputs ahb_ppcexp{0,1,2,3}_irq_status
43
*/
44
45
#ifndef IOTKIT_SECCTL_H
46
@@ -XXX,XX +XXX,XX @@
47
#define TYPE_IOTKIT_SECCTL "iotkit-secctl"
48
#define IOTKIT_SECCTL(obj) OBJECT_CHECK(IoTKitSecCtl, (obj), TYPE_IOTKIT_SECCTL)
49
50
-typedef struct IoTKitSecCtl {
51
+#define IOTS_APB_PPC0_NUM_PORTS 3
52
+#define IOTS_APB_PPC1_NUM_PORTS 1
53
+#define IOTS_PPC_NUM_PORTS 16
54
+#define IOTS_NUM_APB_PPC 2
55
+#define IOTS_NUM_APB_EXP_PPC 4
56
+#define IOTS_NUM_AHB_EXP_PPC 4
57
+
25
+
58
+typedef struct IoTKitSecCtl IoTKitSecCtl;
26
struct BCM2835SystemTimerState {
59
+
60
+/* State and IRQ lines relating to a PPC. For the
61
+ * PPCs in the IoTKit not all the IRQ lines are used.
62
+ */
63
+typedef struct IoTKitSecCtlPPC {
64
+ qemu_irq nonsec[IOTS_PPC_NUM_PORTS];
65
+ qemu_irq ap[IOTS_PPC_NUM_PORTS];
66
+ qemu_irq irq_enable;
67
+ qemu_irq irq_clear;
68
+
69
+ uint32_t ns;
70
+ uint32_t sp;
71
+ uint32_t nsp;
72
+
73
+ /* Number of ports actually present */
74
+ int numports;
75
+ /* Offset of this PPC's interrupt bits in SECPPCINTSTAT */
76
+ int irq_bit_offset;
77
+ IoTKitSecCtl *parent;
78
+} IoTKitSecCtlPPC;
79
+
80
+struct IoTKitSecCtl {
81
/*< private >*/
27
/*< private >*/
82
SysBusDevice parent_obj;
28
SysBusDevice parent_obj;
83
29
@@ -XXX,XX +XXX,XX @@ struct BCM2835SystemTimerState {
84
/*< public >*/
30
85
+ qemu_irq sec_resp_cfg;
31
struct {
86
32
uint32_t status;
87
MemoryRegion s_regs;
33
- uint32_t compare[4];
88
MemoryRegion ns_regs;
34
+ uint32_t compare[BCM2835_SYSTIMER_COUNT];
89
-} IoTKitSecCtl;
35
} reg;
90
+
36
};
91
+ uint32_t secppcintstat;
37
92
+ uint32_t secppcinten;
38
diff --git a/hw/timer/bcm2835_systmr.c b/hw/timer/bcm2835_systmr.c
93
+ uint32_t secrespcfg;
94
+
95
+ IoTKitSecCtlPPC apb[IOTS_NUM_APB_PPC];
96
+ IoTKitSecCtlPPC apbexp[IOTS_NUM_APB_EXP_PPC];
97
+ IoTKitSecCtlPPC ahbexp[IOTS_NUM_APB_EXP_PPC];
98
+};
99
100
#endif
101
diff --git a/hw/misc/iotkit-secctl.c b/hw/misc/iotkit-secctl.c
102
index XXXXXXX..XXXXXXX 100644
39
index XXXXXXX..XXXXXXX 100644
103
--- a/hw/misc/iotkit-secctl.c
40
--- a/hw/timer/bcm2835_systmr.c
104
+++ b/hw/misc/iotkit-secctl.c
41
+++ b/hw/timer/bcm2835_systmr.c
105
@@ -XXX,XX +XXX,XX @@ static const uint8_t iotkit_secctl_ns_idregs[] = {
42
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription bcm2835_systmr_vmstate = {
106
0x0d, 0xf0, 0x05, 0xb1,
107
};
108
109
+/* The register sets for the various PPCs (AHB internal, APB internal,
110
+ * AHB expansion, APB expansion) are all set up so that they are
111
+ * in 16-aligned blocks so offsets 0xN0, 0xN4, 0xN8, 0xNC are PPCs
112
+ * 0, 1, 2, 3 of that type, so we can convert a register address offset
113
+ * into an an index into a PPC array easily.
114
+ */
115
+static inline int offset_to_ppc_idx(uint32_t offset)
116
+{
117
+ return extract32(offset, 2, 2);
118
+}
119
+
120
+typedef void PerPPCFunction(IoTKitSecCtlPPC *ppc);
121
+
122
+static void foreach_ppc(IoTKitSecCtl *s, PerPPCFunction *fn)
123
+{
124
+ int i;
125
+
126
+ for (i = 0; i < IOTS_NUM_APB_PPC; i++) {
127
+ fn(&s->apb[i]);
128
+ }
129
+ for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) {
130
+ fn(&s->apbexp[i]);
131
+ }
132
+ for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) {
133
+ fn(&s->ahbexp[i]);
134
+ }
135
+}
136
+
137
static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
138
uint64_t *pdata,
139
unsigned size, MemTxAttrs attrs)
140
{
141
uint64_t r;
142
uint32_t offset = addr & ~0x3;
143
+ IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
144
145
switch (offset) {
146
case A_AHBNSPPC0:
147
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
148
r = 0;
149
break;
150
case A_SECRESPCFG:
151
- case A_NSCCFG:
152
- case A_SECMPCINTSTATUS:
153
+ r = s->secrespcfg;
154
+ break;
155
case A_SECPPCINTSTAT:
156
+ r = s->secppcintstat;
157
+ break;
158
case A_SECPPCINTEN:
159
- case A_SECMSCINTSTAT:
160
- case A_SECMSCINTEN:
161
- case A_BRGINTSTAT:
162
- case A_BRGINTEN:
163
+ r = s->secppcinten;
164
+ break;
165
case A_AHBNSPPCEXP0:
166
case A_AHBNSPPCEXP1:
167
case A_AHBNSPPCEXP2:
168
case A_AHBNSPPCEXP3:
169
+ r = s->ahbexp[offset_to_ppc_idx(offset)].ns;
170
+ break;
171
case A_APBNSPPC0:
172
case A_APBNSPPC1:
173
+ r = s->apb[offset_to_ppc_idx(offset)].ns;
174
+ break;
175
case A_APBNSPPCEXP0:
176
case A_APBNSPPCEXP1:
177
case A_APBNSPPCEXP2:
178
case A_APBNSPPCEXP3:
179
+ r = s->apbexp[offset_to_ppc_idx(offset)].ns;
180
+ break;
181
case A_AHBSPPPCEXP0:
182
case A_AHBSPPPCEXP1:
183
case A_AHBSPPPCEXP2:
184
case A_AHBSPPPCEXP3:
185
+ r = s->apbexp[offset_to_ppc_idx(offset)].sp;
186
+ break;
187
case A_APBSPPPC0:
188
case A_APBSPPPC1:
189
+ r = s->apb[offset_to_ppc_idx(offset)].sp;
190
+ break;
191
case A_APBSPPPCEXP0:
192
case A_APBSPPPCEXP1:
193
case A_APBSPPPCEXP2:
194
case A_APBSPPPCEXP3:
195
+ r = s->apbexp[offset_to_ppc_idx(offset)].sp;
196
+ break;
197
+ case A_NSCCFG:
198
+ case A_SECMPCINTSTATUS:
199
+ case A_SECMSCINTSTAT:
200
+ case A_SECMSCINTEN:
201
+ case A_BRGINTSTAT:
202
+ case A_BRGINTEN:
203
case A_NSMSCEXP:
204
qemu_log_mask(LOG_UNIMP,
205
"IoTKit SecCtl S block read: "
206
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
207
return MEMTX_OK;
208
}
209
210
+static void iotkit_secctl_update_ppc_ap(IoTKitSecCtlPPC *ppc)
211
+{
212
+ int i;
213
+
214
+ for (i = 0; i < ppc->numports; i++) {
215
+ bool v;
216
+
217
+ if (extract32(ppc->ns, i, 1)) {
218
+ v = extract32(ppc->nsp, i, 1);
219
+ } else {
220
+ v = extract32(ppc->sp, i, 1);
221
+ }
222
+ qemu_set_irq(ppc->ap[i], v);
223
+ }
224
+}
225
+
226
+static void iotkit_secctl_ppc_ns_write(IoTKitSecCtlPPC *ppc, uint32_t value)
227
+{
228
+ int i;
229
+
230
+ ppc->ns = value & MAKE_64BIT_MASK(0, ppc->numports);
231
+ for (i = 0; i < ppc->numports; i++) {
232
+ qemu_set_irq(ppc->nonsec[i], extract32(ppc->ns, i, 1));
233
+ }
234
+ iotkit_secctl_update_ppc_ap(ppc);
235
+}
236
+
237
+static void iotkit_secctl_ppc_sp_write(IoTKitSecCtlPPC *ppc, uint32_t value)
238
+{
239
+ ppc->sp = value & MAKE_64BIT_MASK(0, ppc->numports);
240
+ iotkit_secctl_update_ppc_ap(ppc);
241
+}
242
+
243
+static void iotkit_secctl_ppc_nsp_write(IoTKitSecCtlPPC *ppc, uint32_t value)
244
+{
245
+ ppc->nsp = value & MAKE_64BIT_MASK(0, ppc->numports);
246
+ iotkit_secctl_update_ppc_ap(ppc);
247
+}
248
+
249
+static void iotkit_secctl_ppc_update_irq_clear(IoTKitSecCtlPPC *ppc)
250
+{
251
+ uint32_t value = ppc->parent->secppcintstat;
252
+
253
+ qemu_set_irq(ppc->irq_clear, extract32(value, ppc->irq_bit_offset, 1));
254
+}
255
+
256
+static void iotkit_secctl_ppc_update_irq_enable(IoTKitSecCtlPPC *ppc)
257
+{
258
+ uint32_t value = ppc->parent->secppcinten;
259
+
260
+ qemu_set_irq(ppc->irq_enable, extract32(value, ppc->irq_bit_offset, 1));
261
+}
262
+
263
static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
264
uint64_t value,
265
unsigned size, MemTxAttrs attrs)
266
{
267
+ IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
268
uint32_t offset = addr;
269
+ IoTKitSecCtlPPC *ppc;
270
271
trace_iotkit_secctl_s_write(offset, value, size);
272
273
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
274
275
switch (offset) {
276
case A_SECRESPCFG:
277
- case A_NSCCFG:
278
+ value &= 1;
279
+ s->secrespcfg = value;
280
+ qemu_set_irq(s->sec_resp_cfg, s->secrespcfg);
281
+ break;
282
case A_SECPPCINTCLR:
283
+ value &= 0x00f000f3;
284
+ foreach_ppc(s, iotkit_secctl_ppc_update_irq_clear);
285
+ break;
286
case A_SECPPCINTEN:
287
- case A_SECMSCINTCLR:
288
- case A_SECMSCINTEN:
289
- case A_BRGINTCLR:
290
- case A_BRGINTEN:
291
+ s->secppcinten = value & 0x00f000f3;
292
+ foreach_ppc(s, iotkit_secctl_ppc_update_irq_enable);
293
+ break;
294
case A_AHBNSPPCEXP0:
295
case A_AHBNSPPCEXP1:
296
case A_AHBNSPPCEXP2:
297
case A_AHBNSPPCEXP3:
298
+ ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
299
+ iotkit_secctl_ppc_ns_write(ppc, value);
300
+ break;
301
case A_APBNSPPC0:
302
case A_APBNSPPC1:
303
+ ppc = &s->apb[offset_to_ppc_idx(offset)];
304
+ iotkit_secctl_ppc_ns_write(ppc, value);
305
+ break;
306
case A_APBNSPPCEXP0:
307
case A_APBNSPPCEXP1:
308
case A_APBNSPPCEXP2:
309
case A_APBNSPPCEXP3:
310
+ ppc = &s->apbexp[offset_to_ppc_idx(offset)];
311
+ iotkit_secctl_ppc_ns_write(ppc, value);
312
+ break;
313
case A_AHBSPPPCEXP0:
314
case A_AHBSPPPCEXP1:
315
case A_AHBSPPPCEXP2:
316
case A_AHBSPPPCEXP3:
317
+ ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
318
+ iotkit_secctl_ppc_sp_write(ppc, value);
319
+ break;
320
case A_APBSPPPC0:
321
case A_APBSPPPC1:
322
+ ppc = &s->apb[offset_to_ppc_idx(offset)];
323
+ iotkit_secctl_ppc_sp_write(ppc, value);
324
+ break;
325
case A_APBSPPPCEXP0:
326
case A_APBSPPPCEXP1:
327
case A_APBSPPPCEXP2:
328
case A_APBSPPPCEXP3:
329
+ ppc = &s->apbexp[offset_to_ppc_idx(offset)];
330
+ iotkit_secctl_ppc_sp_write(ppc, value);
331
+ break;
332
+ case A_NSCCFG:
333
+ case A_SECMSCINTCLR:
334
+ case A_SECMSCINTEN:
335
+ case A_BRGINTCLR:
336
+ case A_BRGINTEN:
337
qemu_log_mask(LOG_UNIMP,
338
"IoTKit SecCtl S block write: "
339
"unimplemented offset 0x%x\n", offset);
340
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_ns_read(void *opaque, hwaddr addr,
341
uint64_t *pdata,
342
unsigned size, MemTxAttrs attrs)
343
{
344
+ IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
345
uint64_t r;
346
uint32_t offset = addr & ~0x3;
347
348
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_ns_read(void *opaque, hwaddr addr,
349
case A_AHBNSPPPCEXP1:
350
case A_AHBNSPPPCEXP2:
351
case A_AHBNSPPPCEXP3:
352
+ r = s->ahbexp[offset_to_ppc_idx(offset)].nsp;
353
+ break;
354
case A_APBNSPPPC0:
355
case A_APBNSPPPC1:
356
+ r = s->apb[offset_to_ppc_idx(offset)].nsp;
357
+ break;
358
case A_APBNSPPPCEXP0:
359
case A_APBNSPPPCEXP1:
360
case A_APBNSPPPCEXP2:
361
case A_APBNSPPPCEXP3:
362
- qemu_log_mask(LOG_UNIMP,
363
- "IoTKit SecCtl NS block read: "
364
- "unimplemented offset 0x%x\n", offset);
365
+ r = s->apbexp[offset_to_ppc_idx(offset)].nsp;
366
break;
367
case A_PID4:
368
case A_PID5:
369
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_ns_write(void *opaque, hwaddr addr,
370
uint64_t value,
371
unsigned size, MemTxAttrs attrs)
372
{
373
+ IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
374
uint32_t offset = addr;
375
+ IoTKitSecCtlPPC *ppc;
376
377
trace_iotkit_secctl_ns_write(offset, value, size);
378
379
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_ns_write(void *opaque, hwaddr addr,
380
case A_AHBNSPPPCEXP1:
381
case A_AHBNSPPPCEXP2:
382
case A_AHBNSPPPCEXP3:
383
+ ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
384
+ iotkit_secctl_ppc_nsp_write(ppc, value);
385
+ break;
386
case A_APBNSPPPC0:
387
case A_APBNSPPPC1:
388
+ ppc = &s->apb[offset_to_ppc_idx(offset)];
389
+ iotkit_secctl_ppc_nsp_write(ppc, value);
390
+ break;
391
case A_APBNSPPPCEXP0:
392
case A_APBNSPPPCEXP1:
393
case A_APBNSPPPCEXP2:
394
case A_APBNSPPPCEXP3:
395
- qemu_log_mask(LOG_UNIMP,
396
- "IoTKit SecCtl NS block write: "
397
- "unimplemented offset 0x%x\n", offset);
398
+ ppc = &s->apbexp[offset_to_ppc_idx(offset)];
399
+ iotkit_secctl_ppc_nsp_write(ppc, value);
400
break;
401
case A_AHBNSPPPC0:
402
case A_PID4:
403
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps iotkit_secctl_ns_ops = {
404
.impl.max_access_size = 4,
405
};
406
407
+static void iotkit_secctl_reset_ppc(IoTKitSecCtlPPC *ppc)
408
+{
409
+ ppc->ns = 0;
410
+ ppc->sp = 0;
411
+ ppc->nsp = 0;
412
+}
413
+
414
static void iotkit_secctl_reset(DeviceState *dev)
415
{
416
+ IoTKitSecCtl *s = IOTKIT_SECCTL(dev);
417
418
+ s->secppcintstat = 0;
419
+ s->secppcinten = 0;
420
+ s->secrespcfg = 0;
421
+
422
+ foreach_ppc(s, iotkit_secctl_reset_ppc);
423
+}
424
+
425
+static void iotkit_secctl_ppc_irqstatus(void *opaque, int n, int level)
426
+{
427
+ IoTKitSecCtlPPC *ppc = opaque;
428
+ IoTKitSecCtl *s = IOTKIT_SECCTL(ppc->parent);
429
+ int irqbit = ppc->irq_bit_offset + n;
430
+
431
+ s->secppcintstat = deposit32(s->secppcintstat, irqbit, 1, level);
432
+}
433
+
434
+static void iotkit_secctl_init_ppc(IoTKitSecCtl *s,
435
+ IoTKitSecCtlPPC *ppc,
436
+ const char *name,
437
+ int numports,
438
+ int irq_bit_offset)
439
+{
440
+ char *gpioname;
441
+ DeviceState *dev = DEVICE(s);
442
+
443
+ ppc->numports = numports;
444
+ ppc->irq_bit_offset = irq_bit_offset;
445
+ ppc->parent = s;
446
+
447
+ gpioname = g_strdup_printf("%s_nonsec", name);
448
+ qdev_init_gpio_out_named(dev, ppc->nonsec, gpioname, numports);
449
+ g_free(gpioname);
450
+ gpioname = g_strdup_printf("%s_ap", name);
451
+ qdev_init_gpio_out_named(dev, ppc->ap, gpioname, numports);
452
+ g_free(gpioname);
453
+ gpioname = g_strdup_printf("%s_irq_enable", name);
454
+ qdev_init_gpio_out_named(dev, &ppc->irq_enable, gpioname, 1);
455
+ g_free(gpioname);
456
+ gpioname = g_strdup_printf("%s_irq_clear", name);
457
+ qdev_init_gpio_out_named(dev, &ppc->irq_clear, gpioname, 1);
458
+ g_free(gpioname);
459
+ gpioname = g_strdup_printf("%s_irq_status", name);
460
+ qdev_init_gpio_in_named_with_opaque(dev, iotkit_secctl_ppc_irqstatus,
461
+ ppc, gpioname, 1);
462
+ g_free(gpioname);
463
}
464
465
static void iotkit_secctl_init(Object *obj)
466
{
467
IoTKitSecCtl *s = IOTKIT_SECCTL(obj);
468
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
469
+ DeviceState *dev = DEVICE(obj);
470
+ int i;
471
+
472
+ iotkit_secctl_init_ppc(s, &s->apb[0], "apb_ppc0",
473
+ IOTS_APB_PPC0_NUM_PORTS, 0);
474
+ iotkit_secctl_init_ppc(s, &s->apb[1], "apb_ppc1",
475
+ IOTS_APB_PPC1_NUM_PORTS, 1);
476
+
477
+ for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) {
478
+ IoTKitSecCtlPPC *ppc = &s->apbexp[i];
479
+ char *ppcname = g_strdup_printf("apb_ppcexp%d", i);
480
+ iotkit_secctl_init_ppc(s, ppc, ppcname, IOTS_PPC_NUM_PORTS, 4 + i);
481
+ g_free(ppcname);
482
+ }
483
+ for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) {
484
+ IoTKitSecCtlPPC *ppc = &s->ahbexp[i];
485
+ char *ppcname = g_strdup_printf("ahb_ppcexp%d", i);
486
+ iotkit_secctl_init_ppc(s, ppc, ppcname, IOTS_PPC_NUM_PORTS, 20 + i);
487
+ g_free(ppcname);
488
+ }
489
+
490
+ qdev_init_gpio_out_named(dev, &s->sec_resp_cfg, "sec_resp_cfg", 1);
491
492
memory_region_init_io(&s->s_regs, obj, &iotkit_secctl_s_ops,
493
s, "iotkit-secctl-s-regs", 0x1000);
494
@@ -XXX,XX +XXX,XX @@ static void iotkit_secctl_init(Object *obj)
495
sysbus_init_mmio(sbd, &s->ns_regs);
496
}
497
498
+static const VMStateDescription iotkit_secctl_ppc_vmstate = {
499
+ .name = "iotkit-secctl-ppc",
500
+ .version_id = 1,
501
+ .minimum_version_id = 1,
502
+ .fields = (VMStateField[]) {
503
+ VMSTATE_UINT32(ns, IoTKitSecCtlPPC),
504
+ VMSTATE_UINT32(sp, IoTKitSecCtlPPC),
505
+ VMSTATE_UINT32(nsp, IoTKitSecCtlPPC),
506
+ VMSTATE_END_OF_LIST()
507
+ }
508
+};
509
+
510
static const VMStateDescription iotkit_secctl_vmstate = {
511
.name = "iotkit-secctl",
512
.version_id = 1,
513
.minimum_version_id = 1,
43
.minimum_version_id = 1,
514
.fields = (VMStateField[]) {
44
.fields = (VMStateField[]) {
515
+ VMSTATE_UINT32(secppcintstat, IoTKitSecCtl),
45
VMSTATE_UINT32(reg.status, BCM2835SystemTimerState),
516
+ VMSTATE_UINT32(secppcinten, IoTKitSecCtl),
46
- VMSTATE_UINT32_ARRAY(reg.compare, BCM2835SystemTimerState, 4),
517
+ VMSTATE_UINT32(secrespcfg, IoTKitSecCtl),
47
+ VMSTATE_UINT32_ARRAY(reg.compare, BCM2835SystemTimerState,
518
+ VMSTATE_STRUCT_ARRAY(apb, IoTKitSecCtl, IOTS_NUM_APB_PPC, 1,
48
+ BCM2835_SYSTIMER_COUNT),
519
+ iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
520
+ VMSTATE_STRUCT_ARRAY(apbexp, IoTKitSecCtl, IOTS_NUM_APB_EXP_PPC, 1,
521
+ iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
522
+ VMSTATE_STRUCT_ARRAY(ahbexp, IoTKitSecCtl, IOTS_NUM_AHB_EXP_PPC, 1,
523
+ iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
524
VMSTATE_END_OF_LIST()
49
VMSTATE_END_OF_LIST()
525
}
50
}
526
};
51
};
527
--
52
--
528
2.16.2
53
2.20.1
529
54
530
55
diff view generated by jsdifflib
1
Model the Arm IoT Kit documented in
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
3
2
4
The Arm IoT Kit is a subsystem which includes a CPU and some devices,
3
The variable holding the CTRL_STATUS register is misnamed
5
and is intended be extended by adding extra devices to form a
4
'status'. Rename it 'ctrl_status' to make it more obvious
6
complete system. It is used in the MPS2 board's AN505 image for the
5
this register is also used to control the peripheral.
7
Cortex-M33.
8
6
7
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Message-id: 20201010203709.3116542-3-f4bug@amsat.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20180220180325.29818-19-peter.maydell@linaro.org
12
---
12
---
13
hw/arm/Makefile.objs | 1 +
13
include/hw/timer/bcm2835_systmr.h | 2 +-
14
include/hw/arm/iotkit.h | 109 ++++++++
14
hw/timer/bcm2835_systmr.c | 8 ++++----
15
hw/arm/iotkit.c | 598 ++++++++++++++++++++++++++++++++++++++++
15
2 files changed, 5 insertions(+), 5 deletions(-)
16
default-configs/arm-softmmu.mak | 1 +
17
4 files changed, 709 insertions(+)
18
create mode 100644 include/hw/arm/iotkit.h
19
create mode 100644 hw/arm/iotkit.c
20
16
21
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
17
diff --git a/include/hw/timer/bcm2835_systmr.h b/include/hw/timer/bcm2835_systmr.h
22
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/arm/Makefile.objs
19
--- a/include/hw/timer/bcm2835_systmr.h
24
+++ b/hw/arm/Makefile.objs
20
+++ b/include/hw/timer/bcm2835_systmr.h
25
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o
21
@@ -XXX,XX +XXX,XX @@ struct BCM2835SystemTimerState {
26
obj-$(CONFIG_ASPEED_SOC) += aspeed_soc.o aspeed.o
22
qemu_irq irq;
27
obj-$(CONFIG_MPS2) += mps2.o
23
28
obj-$(CONFIG_MSF2) += msf2-soc.o msf2-som.o
24
struct {
29
+obj-$(CONFIG_IOTKIT) += iotkit.o
25
- uint32_t status;
30
diff --git a/include/hw/arm/iotkit.h b/include/hw/arm/iotkit.h
26
+ uint32_t ctrl_status;
31
new file mode 100644
27
uint32_t compare[BCM2835_SYSTIMER_COUNT];
32
index XXXXXXX..XXXXXXX
28
} reg;
33
--- /dev/null
29
};
34
+++ b/include/hw/arm/iotkit.h
30
diff --git a/hw/timer/bcm2835_systmr.c b/hw/timer/bcm2835_systmr.c
35
@@ -XXX,XX +XXX,XX @@
36
+/*
37
+ * ARM IoT Kit
38
+ *
39
+ * Copyright (c) 2018 Linaro Limited
40
+ * Written by Peter Maydell
41
+ *
42
+ * This program is free software; you can redistribute it and/or modify
43
+ * it under the terms of the GNU General Public License version 2 or
44
+ * (at your option) any later version.
45
+ */
46
+
47
+/* This is a model of the Arm IoT Kit which is documented in
48
+ * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
49
+ * It contains:
50
+ * a Cortex-M33
51
+ * the IDAU
52
+ * some timers and watchdogs
53
+ * two peripheral protection controllers
54
+ * a memory protection controller
55
+ * a security controller
56
+ * a bus fabric which arranges that some parts of the address
57
+ * space are secure and non-secure aliases of each other
58
+ *
59
+ * QEMU interface:
60
+ * + QOM property "memory" is a MemoryRegion containing the devices provided
61
+ * by the board model.
62
+ * + QOM property "MAINCLK" is the frequency of the main system clock
63
+ * + QOM property "EXP_NUMIRQ" sets the number of expansion interrupts
64
+ * + Named GPIO inputs "EXP_IRQ" 0..n are the expansion interrupts, which
65
+ * are wired to the NVIC lines 32 .. n+32
66
+ * Controlling up to 4 AHB expansion PPBs which a system using the IoTKit
67
+ * might provide:
68
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_nonsec[0..15]
69
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_ap[0..15]
70
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_irq_enable
71
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_irq_clear
72
+ * + named GPIO inputs apb_ppcexp{0,1,2,3}_irq_status
73
+ * Controlling each of the 4 expansion AHB PPCs which a system using the IoTKit
74
+ * might provide:
75
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_nonsec[0..15]
76
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_ap[0..15]
77
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_enable
78
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_clear
79
+ * + named GPIO inputs ahb_ppcexp{0,1,2,3}_irq_status
80
+ */
81
+
82
+#ifndef IOTKIT_H
83
+#define IOTKIT_H
84
+
85
+#include "hw/sysbus.h"
86
+#include "hw/arm/armv7m.h"
87
+#include "hw/misc/iotkit-secctl.h"
88
+#include "hw/misc/tz-ppc.h"
89
+#include "hw/timer/cmsdk-apb-timer.h"
90
+#include "hw/misc/unimp.h"
91
+#include "hw/or-irq.h"
92
+#include "hw/core/split-irq.h"
93
+
94
+#define TYPE_IOTKIT "iotkit"
95
+#define IOTKIT(obj) OBJECT_CHECK(IoTKit, (obj), TYPE_IOTKIT)
96
+
97
+/* We have an IRQ splitter and an OR gate input for each external PPC
98
+ * and the 2 internal PPCs
99
+ */
100
+#define NUM_EXTERNAL_PPCS (IOTS_NUM_AHB_EXP_PPC + IOTS_NUM_APB_EXP_PPC)
101
+#define NUM_PPCS (NUM_EXTERNAL_PPCS + 2)
102
+
103
+typedef struct IoTKit {
104
+ /*< private >*/
105
+ SysBusDevice parent_obj;
106
+
107
+ /*< public >*/
108
+ ARMv7MState armv7m;
109
+ IoTKitSecCtl secctl;
110
+ TZPPC apb_ppc0;
111
+ TZPPC apb_ppc1;
112
+ CMSDKAPBTIMER timer0;
113
+ CMSDKAPBTIMER timer1;
114
+ qemu_or_irq ppc_irq_orgate;
115
+ SplitIRQ sec_resp_splitter;
116
+ SplitIRQ ppc_irq_splitter[NUM_PPCS];
117
+
118
+ UnimplementedDeviceState dualtimer;
119
+ UnimplementedDeviceState s32ktimer;
120
+
121
+ MemoryRegion container;
122
+ MemoryRegion alias1;
123
+ MemoryRegion alias2;
124
+ MemoryRegion alias3;
125
+ MemoryRegion sram0;
126
+
127
+ qemu_irq *exp_irqs;
128
+ qemu_irq ppc0_irq;
129
+ qemu_irq ppc1_irq;
130
+ qemu_irq sec_resp_cfg;
131
+ qemu_irq sec_resp_cfg_in;
132
+ qemu_irq nsc_cfg_in;
133
+
134
+ qemu_irq irq_status_in[NUM_EXTERNAL_PPCS];
135
+
136
+ uint32_t nsccfg;
137
+
138
+ /* Properties */
139
+ MemoryRegion *board_memory;
140
+ uint32_t exp_numirq;
141
+ uint32_t mainclk_frq;
142
+} IoTKit;
143
+
144
+#endif
145
diff --git a/hw/arm/iotkit.c b/hw/arm/iotkit.c
146
new file mode 100644
147
index XXXXXXX..XXXXXXX
148
--- /dev/null
149
+++ b/hw/arm/iotkit.c
150
@@ -XXX,XX +XXX,XX @@
151
+/*
152
+ * Arm IoT Kit
153
+ *
154
+ * Copyright (c) 2018 Linaro Limited
155
+ * Written by Peter Maydell
156
+ *
157
+ * This program is free software; you can redistribute it and/or modify
158
+ * it under the terms of the GNU General Public License version 2 or
159
+ * (at your option) any later version.
160
+ */
161
+
162
+#include "qemu/osdep.h"
163
+#include "qemu/log.h"
164
+#include "qapi/error.h"
165
+#include "trace.h"
166
+#include "hw/sysbus.h"
167
+#include "hw/registerfields.h"
168
+#include "hw/arm/iotkit.h"
169
+#include "hw/misc/unimp.h"
170
+#include "hw/arm/arm.h"
171
+
172
+/* Create an alias region of @size bytes starting at @base
173
+ * which mirrors the memory starting at @orig.
174
+ */
175
+static void make_alias(IoTKit *s, MemoryRegion *mr, const char *name,
176
+ hwaddr base, hwaddr size, hwaddr orig)
177
+{
178
+ memory_region_init_alias(mr, NULL, name, &s->container, orig, size);
179
+ /* The alias is even lower priority than unimplemented_device regions */
180
+ memory_region_add_subregion_overlap(&s->container, base, mr, -1500);
181
+}
182
+
183
+static void init_sysbus_child(Object *parent, const char *childname,
184
+ void *child, size_t childsize,
185
+ const char *childtype)
186
+{
187
+ object_initialize(child, childsize, childtype);
188
+ object_property_add_child(parent, childname, OBJECT(child), &error_abort);
189
+ qdev_set_parent_bus(DEVICE(child), sysbus_get_default());
190
+}
191
+
192
+static void irq_status_forwarder(void *opaque, int n, int level)
193
+{
194
+ qemu_irq destirq = opaque;
195
+
196
+ qemu_set_irq(destirq, level);
197
+}
198
+
199
+static void nsccfg_handler(void *opaque, int n, int level)
200
+{
201
+ IoTKit *s = IOTKIT(opaque);
202
+
203
+ s->nsccfg = level;
204
+}
205
+
206
+static void iotkit_forward_ppc(IoTKit *s, const char *ppcname, int ppcnum)
207
+{
208
+ /* Each of the 4 AHB and 4 APB PPCs that might be present in a
209
+ * system using the IoTKit has a collection of control lines which
210
+ * are provided by the security controller and which we want to
211
+ * expose as control lines on the IoTKit device itself, so the
212
+ * code using the IoTKit can wire them up to the PPCs.
213
+ */
214
+ SplitIRQ *splitter = &s->ppc_irq_splitter[ppcnum];
215
+ DeviceState *iotkitdev = DEVICE(s);
216
+ DeviceState *dev_secctl = DEVICE(&s->secctl);
217
+ DeviceState *dev_splitter = DEVICE(splitter);
218
+ char *name;
219
+
220
+ name = g_strdup_printf("%s_nonsec", ppcname);
221
+ qdev_pass_gpios(dev_secctl, iotkitdev, name);
222
+ g_free(name);
223
+ name = g_strdup_printf("%s_ap", ppcname);
224
+ qdev_pass_gpios(dev_secctl, iotkitdev, name);
225
+ g_free(name);
226
+ name = g_strdup_printf("%s_irq_enable", ppcname);
227
+ qdev_pass_gpios(dev_secctl, iotkitdev, name);
228
+ g_free(name);
229
+ name = g_strdup_printf("%s_irq_clear", ppcname);
230
+ qdev_pass_gpios(dev_secctl, iotkitdev, name);
231
+ g_free(name);
232
+
233
+ /* irq_status is a little more tricky, because we need to
234
+ * split it so we can send it both to the security controller
235
+ * and to our OR gate for the NVIC interrupt line.
236
+ * Connect up the splitter's outputs, and create a GPIO input
237
+ * which will pass the line state to the input splitter.
238
+ */
239
+ name = g_strdup_printf("%s_irq_status", ppcname);
240
+ qdev_connect_gpio_out(dev_splitter, 0,
241
+ qdev_get_gpio_in_named(dev_secctl,
242
+ name, 0));
243
+ qdev_connect_gpio_out(dev_splitter, 1,
244
+ qdev_get_gpio_in(DEVICE(&s->ppc_irq_orgate), ppcnum));
245
+ s->irq_status_in[ppcnum] = qdev_get_gpio_in(dev_splitter, 0);
246
+ qdev_init_gpio_in_named_with_opaque(iotkitdev, irq_status_forwarder,
247
+ s->irq_status_in[ppcnum], name, 1);
248
+ g_free(name);
249
+}
250
+
251
+static void iotkit_forward_sec_resp_cfg(IoTKit *s)
252
+{
253
+ /* Forward the 3rd output from the splitter device as a
254
+ * named GPIO output of the iotkit object.
255
+ */
256
+ DeviceState *dev = DEVICE(s);
257
+ DeviceState *dev_splitter = DEVICE(&s->sec_resp_splitter);
258
+
259
+ qdev_init_gpio_out_named(dev, &s->sec_resp_cfg, "sec_resp_cfg", 1);
260
+ s->sec_resp_cfg_in = qemu_allocate_irq(irq_status_forwarder,
261
+ s->sec_resp_cfg, 1);
262
+ qdev_connect_gpio_out(dev_splitter, 2, s->sec_resp_cfg_in);
263
+}
264
+
265
+static void iotkit_init(Object *obj)
266
+{
267
+ IoTKit *s = IOTKIT(obj);
268
+ int i;
269
+
270
+ memory_region_init(&s->container, obj, "iotkit-container", UINT64_MAX);
271
+
272
+ init_sysbus_child(obj, "armv7m", &s->armv7m, sizeof(s->armv7m),
273
+ TYPE_ARMV7M);
274
+ qdev_prop_set_string(DEVICE(&s->armv7m), "cpu-type",
275
+ ARM_CPU_TYPE_NAME("cortex-m33"));
276
+
277
+ init_sysbus_child(obj, "secctl", &s->secctl, sizeof(s->secctl),
278
+ TYPE_IOTKIT_SECCTL);
279
+ init_sysbus_child(obj, "apb-ppc0", &s->apb_ppc0, sizeof(s->apb_ppc0),
280
+ TYPE_TZ_PPC);
281
+ init_sysbus_child(obj, "apb-ppc1", &s->apb_ppc1, sizeof(s->apb_ppc1),
282
+ TYPE_TZ_PPC);
283
+ init_sysbus_child(obj, "timer0", &s->timer0, sizeof(s->timer0),
284
+ TYPE_CMSDK_APB_TIMER);
285
+ init_sysbus_child(obj, "timer1", &s->timer1, sizeof(s->timer1),
286
+ TYPE_CMSDK_APB_TIMER);
287
+ init_sysbus_child(obj, "dualtimer", &s->dualtimer, sizeof(s->dualtimer),
288
+ TYPE_UNIMPLEMENTED_DEVICE);
289
+ object_initialize(&s->ppc_irq_orgate, sizeof(s->ppc_irq_orgate),
290
+ TYPE_OR_IRQ);
291
+ object_property_add_child(obj, "ppc-irq-orgate",
292
+ OBJECT(&s->ppc_irq_orgate), &error_abort);
293
+ object_initialize(&s->sec_resp_splitter, sizeof(s->sec_resp_splitter),
294
+ TYPE_SPLIT_IRQ);
295
+ object_property_add_child(obj, "sec-resp-splitter",
296
+ OBJECT(&s->sec_resp_splitter), &error_abort);
297
+ for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) {
298
+ char *name = g_strdup_printf("ppc-irq-splitter-%d", i);
299
+ SplitIRQ *splitter = &s->ppc_irq_splitter[i];
300
+
301
+ object_initialize(splitter, sizeof(*splitter), TYPE_SPLIT_IRQ);
302
+ object_property_add_child(obj, name, OBJECT(splitter), &error_abort);
303
+ }
304
+ init_sysbus_child(obj, "s32ktimer", &s->s32ktimer, sizeof(s->s32ktimer),
305
+ TYPE_UNIMPLEMENTED_DEVICE);
306
+}
307
+
308
+static void iotkit_exp_irq(void *opaque, int n, int level)
309
+{
310
+ IoTKit *s = IOTKIT(opaque);
311
+
312
+ qemu_set_irq(s->exp_irqs[n], level);
313
+}
314
+
315
+static void iotkit_realize(DeviceState *dev, Error **errp)
316
+{
317
+ IoTKit *s = IOTKIT(dev);
318
+ int i;
319
+ MemoryRegion *mr;
320
+ Error *err = NULL;
321
+ SysBusDevice *sbd_apb_ppc0;
322
+ SysBusDevice *sbd_secctl;
323
+ DeviceState *dev_apb_ppc0;
324
+ DeviceState *dev_apb_ppc1;
325
+ DeviceState *dev_secctl;
326
+ DeviceState *dev_splitter;
327
+
328
+ if (!s->board_memory) {
329
+ error_setg(errp, "memory property was not set");
330
+ return;
331
+ }
332
+
333
+ if (!s->mainclk_frq) {
334
+ error_setg(errp, "MAINCLK property was not set");
335
+ return;
336
+ }
337
+
338
+ /* Handling of which devices should be available only to secure
339
+ * code is usually done differently for M profile than for A profile.
340
+ * Instead of putting some devices only into the secure address space,
341
+ * devices exist in both address spaces but with hard-wired security
342
+ * permissions that will cause the CPU to fault for non-secure accesses.
343
+ *
344
+ * The IoTKit has an IDAU (Implementation Defined Access Unit),
345
+ * which specifies hard-wired security permissions for different
346
+ * areas of the physical address space. For the IoTKit IDAU, the
347
+ * top 4 bits of the physical address are the IDAU region ID, and
348
+ * if bit 28 (ie the lowest bit of the ID) is 0 then this is an NS
349
+ * region, otherwise it is an S region.
350
+ *
351
+ * The various devices and RAMs are generally all mapped twice,
352
+ * once into a region that the IDAU defines as secure and once
353
+ * into a non-secure region. They sit behind either a Memory
354
+ * Protection Controller (for RAM) or a Peripheral Protection
355
+ * Controller (for devices), which allow a more fine grained
356
+ * configuration of whether non-secure accesses are permitted.
357
+ *
358
+ * (The other place that guest software can configure security
359
+ * permissions is in the architected SAU (Security Attribution
360
+ * Unit), which is entirely inside the CPU. The IDAU can upgrade
361
+ * the security attributes for a region to more restrictive than
362
+ * the SAU specifies, but cannot downgrade them.)
363
+ *
364
+ * 0x10000000..0x1fffffff alias of 0x00000000..0x0fffffff
365
+ * 0x20000000..0x2007ffff 32KB FPGA block RAM
366
+ * 0x30000000..0x3fffffff alias of 0x20000000..0x2fffffff
367
+ * 0x40000000..0x4000ffff base peripheral region 1
368
+ * 0x40010000..0x4001ffff CPU peripherals (none for IoTKit)
369
+ * 0x40020000..0x4002ffff system control element peripherals
370
+ * 0x40080000..0x400fffff base peripheral region 2
371
+ * 0x50000000..0x5fffffff alias of 0x40000000..0x4fffffff
372
+ */
373
+
374
+ memory_region_add_subregion_overlap(&s->container, 0, s->board_memory, -1);
375
+
376
+ qdev_prop_set_uint32(DEVICE(&s->armv7m), "num-irq", s->exp_numirq + 32);
377
+ /* In real hardware the initial Secure VTOR is set from the INITSVTOR0
378
+ * register in the IoT Kit System Control Register block, and the
379
+ * initial value of that is in turn specifiable by the FPGA that
380
+ * instantiates the IoT Kit. In QEMU we don't implement this wrinkle,
381
+ * and simply set the CPU's init-svtor to the IoT Kit default value.
382
+ */
383
+ qdev_prop_set_uint32(DEVICE(&s->armv7m), "init-svtor", 0x10000000);
384
+ object_property_set_link(OBJECT(&s->armv7m), OBJECT(&s->container),
385
+ "memory", &err);
386
+ if (err) {
387
+ error_propagate(errp, err);
388
+ return;
389
+ }
390
+ object_property_set_link(OBJECT(&s->armv7m), OBJECT(s), "idau", &err);
391
+ if (err) {
392
+ error_propagate(errp, err);
393
+ return;
394
+ }
395
+ object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err);
396
+ if (err) {
397
+ error_propagate(errp, err);
398
+ return;
399
+ }
400
+
401
+ /* Connect our EXP_IRQ GPIOs to the NVIC's lines 32 and up. */
402
+ s->exp_irqs = g_new(qemu_irq, s->exp_numirq);
403
+ for (i = 0; i < s->exp_numirq; i++) {
404
+ s->exp_irqs[i] = qdev_get_gpio_in(DEVICE(&s->armv7m), i + 32);
405
+ }
406
+ qdev_init_gpio_in_named(dev, iotkit_exp_irq, "EXP_IRQ", s->exp_numirq);
407
+
408
+ /* Set up the big aliases first */
409
+ make_alias(s, &s->alias1, "alias 1", 0x10000000, 0x10000000, 0x00000000);
410
+ make_alias(s, &s->alias2, "alias 2", 0x30000000, 0x10000000, 0x20000000);
411
+ /* The 0x50000000..0x5fffffff region is not a pure alias: it has
412
+ * a few extra devices that only appear there (generally the
413
+ * control interfaces for the protection controllers).
414
+ * We implement this by mapping those devices over the top of this
415
+ * alias MR at a higher priority.
416
+ */
417
+ make_alias(s, &s->alias3, "alias 3", 0x50000000, 0x10000000, 0x40000000);
418
+
419
+ /* This RAM should be behind a Memory Protection Controller, but we
420
+ * don't implement that yet.
421
+ */
422
+ memory_region_init_ram(&s->sram0, NULL, "iotkit.sram0", 0x00008000, &err);
423
+ if (err) {
424
+ error_propagate(errp, err);
425
+ return;
426
+ }
427
+ memory_region_add_subregion(&s->container, 0x20000000, &s->sram0);
428
+
429
+ /* Security controller */
430
+ object_property_set_bool(OBJECT(&s->secctl), true, "realized", &err);
431
+ if (err) {
432
+ error_propagate(errp, err);
433
+ return;
434
+ }
435
+ sbd_secctl = SYS_BUS_DEVICE(&s->secctl);
436
+ dev_secctl = DEVICE(&s->secctl);
437
+ sysbus_mmio_map(sbd_secctl, 0, 0x50080000);
438
+ sysbus_mmio_map(sbd_secctl, 1, 0x40080000);
439
+
440
+ s->nsc_cfg_in = qemu_allocate_irq(nsccfg_handler, s, 1);
441
+ qdev_connect_gpio_out_named(dev_secctl, "nsc_cfg", 0, s->nsc_cfg_in);
442
+
443
+ /* The sec_resp_cfg output from the security controller must be split into
444
+ * multiple lines, one for each of the PPCs within the IoTKit and one
445
+ * that will be an output from the IoTKit to the system.
446
+ */
447
+ object_property_set_int(OBJECT(&s->sec_resp_splitter), 3,
448
+ "num-lines", &err);
449
+ if (err) {
450
+ error_propagate(errp, err);
451
+ return;
452
+ }
453
+ object_property_set_bool(OBJECT(&s->sec_resp_splitter), true,
454
+ "realized", &err);
455
+ if (err) {
456
+ error_propagate(errp, err);
457
+ return;
458
+ }
459
+ dev_splitter = DEVICE(&s->sec_resp_splitter);
460
+ qdev_connect_gpio_out_named(dev_secctl, "sec_resp_cfg", 0,
461
+ qdev_get_gpio_in(dev_splitter, 0));
462
+
463
+ /* Devices behind APB PPC0:
464
+ * 0x40000000: timer0
465
+ * 0x40001000: timer1
466
+ * 0x40002000: dual timer
467
+ * We must configure and realize each downstream device and connect
468
+ * it to the appropriate PPC port; then we can realize the PPC and
469
+ * map its upstream ends to the right place in the container.
470
+ */
471
+ qdev_prop_set_uint32(DEVICE(&s->timer0), "pclk-frq", s->mainclk_frq);
472
+ object_property_set_bool(OBJECT(&s->timer0), true, "realized", &err);
473
+ if (err) {
474
+ error_propagate(errp, err);
475
+ return;
476
+ }
477
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer0), 0,
478
+ qdev_get_gpio_in(DEVICE(&s->armv7m), 3));
479
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer0), 0);
480
+ object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[0]", &err);
481
+ if (err) {
482
+ error_propagate(errp, err);
483
+ return;
484
+ }
485
+
486
+ qdev_prop_set_uint32(DEVICE(&s->timer1), "pclk-frq", s->mainclk_frq);
487
+ object_property_set_bool(OBJECT(&s->timer1), true, "realized", &err);
488
+ if (err) {
489
+ error_propagate(errp, err);
490
+ return;
491
+ }
492
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer1), 0,
493
+ qdev_get_gpio_in(DEVICE(&s->armv7m), 3));
494
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer1), 0);
495
+ object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[1]", &err);
496
+ if (err) {
497
+ error_propagate(errp, err);
498
+ return;
499
+ }
500
+
501
+ qdev_prop_set_string(DEVICE(&s->dualtimer), "name", "Dual timer");
502
+ qdev_prop_set_uint64(DEVICE(&s->dualtimer), "size", 0x1000);
503
+ object_property_set_bool(OBJECT(&s->dualtimer), true, "realized", &err);
504
+ if (err) {
505
+ error_propagate(errp, err);
506
+ return;
507
+ }
508
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dualtimer), 0);
509
+ object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[2]", &err);
510
+ if (err) {
511
+ error_propagate(errp, err);
512
+ return;
513
+ }
514
+
515
+ object_property_set_bool(OBJECT(&s->apb_ppc0), true, "realized", &err);
516
+ if (err) {
517
+ error_propagate(errp, err);
518
+ return;
519
+ }
520
+
521
+ sbd_apb_ppc0 = SYS_BUS_DEVICE(&s->apb_ppc0);
522
+ dev_apb_ppc0 = DEVICE(&s->apb_ppc0);
523
+
524
+ mr = sysbus_mmio_get_region(sbd_apb_ppc0, 0);
525
+ memory_region_add_subregion(&s->container, 0x40000000, mr);
526
+ mr = sysbus_mmio_get_region(sbd_apb_ppc0, 1);
527
+ memory_region_add_subregion(&s->container, 0x40001000, mr);
528
+ mr = sysbus_mmio_get_region(sbd_apb_ppc0, 2);
529
+ memory_region_add_subregion(&s->container, 0x40002000, mr);
530
+ for (i = 0; i < IOTS_APB_PPC0_NUM_PORTS; i++) {
531
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_nonsec", i,
532
+ qdev_get_gpio_in_named(dev_apb_ppc0,
533
+ "cfg_nonsec", i));
534
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_ap", i,
535
+ qdev_get_gpio_in_named(dev_apb_ppc0,
536
+ "cfg_ap", i));
537
+ }
538
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_irq_enable", 0,
539
+ qdev_get_gpio_in_named(dev_apb_ppc0,
540
+ "irq_enable", 0));
541
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_irq_clear", 0,
542
+ qdev_get_gpio_in_named(dev_apb_ppc0,
543
+ "irq_clear", 0));
544
+ qdev_connect_gpio_out(dev_splitter, 0,
545
+ qdev_get_gpio_in_named(dev_apb_ppc0,
546
+ "cfg_sec_resp", 0));
547
+
548
+ /* All the PPC irq lines (from the 2 internal PPCs and the 8 external
549
+ * ones) are sent individually to the security controller, and also
550
+ * ORed together to give a single combined PPC interrupt to the NVIC.
551
+ */
552
+ object_property_set_int(OBJECT(&s->ppc_irq_orgate),
553
+ NUM_PPCS, "num-lines", &err);
554
+ if (err) {
555
+ error_propagate(errp, err);
556
+ return;
557
+ }
558
+ object_property_set_bool(OBJECT(&s->ppc_irq_orgate), true,
559
+ "realized", &err);
560
+ if (err) {
561
+ error_propagate(errp, err);
562
+ return;
563
+ }
564
+ qdev_connect_gpio_out(DEVICE(&s->ppc_irq_orgate), 0,
565
+ qdev_get_gpio_in(DEVICE(&s->armv7m), 10));
566
+
567
+ /* 0x40010000 .. 0x4001ffff: private CPU region: unused in IoTKit */
568
+
569
+ /* 0x40020000 .. 0x4002ffff : IoTKit system control peripheral region */
570
+ /* Devices behind APB PPC1:
571
+ * 0x4002f000: S32K timer
572
+ */
573
+ qdev_prop_set_string(DEVICE(&s->s32ktimer), "name", "S32KTIMER");
574
+ qdev_prop_set_uint64(DEVICE(&s->s32ktimer), "size", 0x1000);
575
+ object_property_set_bool(OBJECT(&s->s32ktimer), true, "realized", &err);
576
+ if (err) {
577
+ error_propagate(errp, err);
578
+ return;
579
+ }
580
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->s32ktimer), 0);
581
+ object_property_set_link(OBJECT(&s->apb_ppc1), OBJECT(mr), "port[0]", &err);
582
+ if (err) {
583
+ error_propagate(errp, err);
584
+ return;
585
+ }
586
+
587
+ object_property_set_bool(OBJECT(&s->apb_ppc1), true, "realized", &err);
588
+ if (err) {
589
+ error_propagate(errp, err);
590
+ return;
591
+ }
592
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->apb_ppc1), 0);
593
+ memory_region_add_subregion(&s->container, 0x4002f000, mr);
594
+
595
+ dev_apb_ppc1 = DEVICE(&s->apb_ppc1);
596
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_nonsec", 0,
597
+ qdev_get_gpio_in_named(dev_apb_ppc1,
598
+ "cfg_nonsec", 0));
599
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_ap", 0,
600
+ qdev_get_gpio_in_named(dev_apb_ppc1,
601
+ "cfg_ap", 0));
602
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_irq_enable", 0,
603
+ qdev_get_gpio_in_named(dev_apb_ppc1,
604
+ "irq_enable", 0));
605
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_irq_clear", 0,
606
+ qdev_get_gpio_in_named(dev_apb_ppc1,
607
+ "irq_clear", 0));
608
+ qdev_connect_gpio_out(dev_splitter, 1,
609
+ qdev_get_gpio_in_named(dev_apb_ppc1,
610
+ "cfg_sec_resp", 0));
611
+
612
+ /* Using create_unimplemented_device() maps the stub into the
613
+ * system address space rather than into our container, but the
614
+ * overall effect to the guest is the same.
615
+ */
616
+ create_unimplemented_device("SYSINFO", 0x40020000, 0x1000);
617
+
618
+ create_unimplemented_device("SYSCONTROL", 0x50021000, 0x1000);
619
+ create_unimplemented_device("S32KWATCHDOG", 0x5002e000, 0x1000);
620
+
621
+ /* 0x40080000 .. 0x4008ffff : IoTKit second Base peripheral region */
622
+
623
+ create_unimplemented_device("NS watchdog", 0x40081000, 0x1000);
624
+ create_unimplemented_device("S watchdog", 0x50081000, 0x1000);
625
+
626
+ create_unimplemented_device("SRAM0 MPC", 0x50083000, 0x1000);
627
+
628
+ for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) {
629
+ Object *splitter = OBJECT(&s->ppc_irq_splitter[i]);
630
+
631
+ object_property_set_int(splitter, 2, "num-lines", &err);
632
+ if (err) {
633
+ error_propagate(errp, err);
634
+ return;
635
+ }
636
+ object_property_set_bool(splitter, true, "realized", &err);
637
+ if (err) {
638
+ error_propagate(errp, err);
639
+ return;
640
+ }
641
+ }
642
+
643
+ for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) {
644
+ char *ppcname = g_strdup_printf("ahb_ppcexp%d", i);
645
+
646
+ iotkit_forward_ppc(s, ppcname, i);
647
+ g_free(ppcname);
648
+ }
649
+
650
+ for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) {
651
+ char *ppcname = g_strdup_printf("apb_ppcexp%d", i);
652
+
653
+ iotkit_forward_ppc(s, ppcname, i + IOTS_NUM_AHB_EXP_PPC);
654
+ g_free(ppcname);
655
+ }
656
+
657
+ for (i = NUM_EXTERNAL_PPCS; i < NUM_PPCS; i++) {
658
+ /* Wire up IRQ splitter for internal PPCs */
659
+ DeviceState *devs = DEVICE(&s->ppc_irq_splitter[i]);
660
+ char *gpioname = g_strdup_printf("apb_ppc%d_irq_status",
661
+ i - NUM_EXTERNAL_PPCS);
662
+ TZPPC *ppc = (i == NUM_EXTERNAL_PPCS) ? &s->apb_ppc0 : &s->apb_ppc1;
663
+
664
+ qdev_connect_gpio_out(devs, 0,
665
+ qdev_get_gpio_in_named(dev_secctl, gpioname, 0));
666
+ qdev_connect_gpio_out(devs, 1,
667
+ qdev_get_gpio_in(DEVICE(&s->ppc_irq_orgate), i));
668
+ qdev_connect_gpio_out_named(DEVICE(ppc), "irq", 0,
669
+ qdev_get_gpio_in(devs, 0));
670
+ }
671
+
672
+ iotkit_forward_sec_resp_cfg(s);
673
+
674
+ system_clock_scale = NANOSECONDS_PER_SECOND / s->mainclk_frq;
675
+}
676
+
677
+static void iotkit_idau_check(IDAUInterface *ii, uint32_t address,
678
+ int *iregion, bool *exempt, bool *ns, bool *nsc)
679
+{
680
+ /* For IoTKit systems the IDAU responses are simple logical functions
681
+ * of the address bits. The NSC attribute is guest-adjustable via the
682
+ * NSCCFG register in the security controller.
683
+ */
684
+ IoTKit *s = IOTKIT(ii);
685
+ int region = extract32(address, 28, 4);
686
+
687
+ *ns = !(region & 1);
688
+ *nsc = (region == 1 && (s->nsccfg & 1)) || (region == 3 && (s->nsccfg & 2));
689
+ /* 0xe0000000..0xe00fffff and 0xf0000000..0xf00fffff are exempt */
690
+ *exempt = (address & 0xeff00000) == 0xe0000000;
691
+ *iregion = region;
692
+}
693
+
694
+static const VMStateDescription iotkit_vmstate = {
695
+ .name = "iotkit",
696
+ .version_id = 1,
697
+ .minimum_version_id = 1,
698
+ .fields = (VMStateField[]) {
699
+ VMSTATE_UINT32(nsccfg, IoTKit),
700
+ VMSTATE_END_OF_LIST()
701
+ }
702
+};
703
+
704
+static Property iotkit_properties[] = {
705
+ DEFINE_PROP_LINK("memory", IoTKit, board_memory, TYPE_MEMORY_REGION,
706
+ MemoryRegion *),
707
+ DEFINE_PROP_UINT32("EXP_NUMIRQ", IoTKit, exp_numirq, 64),
708
+ DEFINE_PROP_UINT32("MAINCLK", IoTKit, mainclk_frq, 0),
709
+ DEFINE_PROP_END_OF_LIST()
710
+};
711
+
712
+static void iotkit_reset(DeviceState *dev)
713
+{
714
+ IoTKit *s = IOTKIT(dev);
715
+
716
+ s->nsccfg = 0;
717
+}
718
+
719
+static void iotkit_class_init(ObjectClass *klass, void *data)
720
+{
721
+ DeviceClass *dc = DEVICE_CLASS(klass);
722
+ IDAUInterfaceClass *iic = IDAU_INTERFACE_CLASS(klass);
723
+
724
+ dc->realize = iotkit_realize;
725
+ dc->vmsd = &iotkit_vmstate;
726
+ dc->props = iotkit_properties;
727
+ dc->reset = iotkit_reset;
728
+ iic->check = iotkit_idau_check;
729
+}
730
+
731
+static const TypeInfo iotkit_info = {
732
+ .name = TYPE_IOTKIT,
733
+ .parent = TYPE_SYS_BUS_DEVICE,
734
+ .instance_size = sizeof(IoTKit),
735
+ .instance_init = iotkit_init,
736
+ .class_init = iotkit_class_init,
737
+ .interfaces = (InterfaceInfo[]) {
738
+ { TYPE_IDAU_INTERFACE },
739
+ { }
740
+ }
741
+};
742
+
743
+static void iotkit_register_types(void)
744
+{
745
+ type_register_static(&iotkit_info);
746
+}
747
+
748
+type_init(iotkit_register_types);
749
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
750
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
751
--- a/default-configs/arm-softmmu.mak
32
--- a/hw/timer/bcm2835_systmr.c
752
+++ b/default-configs/arm-softmmu.mak
33
+++ b/hw/timer/bcm2835_systmr.c
753
@@ -XXX,XX +XXX,XX @@ CONFIG_MPS2_FPGAIO=y
34
@@ -XXX,XX +XXX,XX @@ REG32(COMPARE3, 0x18)
754
CONFIG_MPS2_SCC=y
35
755
36
static void bcm2835_systmr_update_irq(BCM2835SystemTimerState *s)
756
CONFIG_TZ_PPC=y
37
{
757
+CONFIG_IOTKIT=y
38
- bool enable = !!s->reg.status;
758
CONFIG_IOTKIT_SECCTL=y
39
+ bool enable = !!s->reg.ctrl_status;
759
40
760
CONFIG_VERSATILE_PCI=y
41
trace_bcm2835_systmr_irq(enable);
42
qemu_set_irq(s->irq, enable);
43
@@ -XXX,XX +XXX,XX @@ static uint64_t bcm2835_systmr_read(void *opaque, hwaddr offset,
44
45
switch (offset) {
46
case A_CTRL_STATUS:
47
- r = s->reg.status;
48
+ r = s->reg.ctrl_status;
49
break;
50
case A_COMPARE0 ... A_COMPARE3:
51
r = s->reg.compare[(offset - A_COMPARE0) >> 2];
52
@@ -XXX,XX +XXX,XX @@ static void bcm2835_systmr_write(void *opaque, hwaddr offset,
53
trace_bcm2835_systmr_write(offset, value);
54
switch (offset) {
55
case A_CTRL_STATUS:
56
- s->reg.status &= ~value; /* Ack */
57
+ s->reg.ctrl_status &= ~value; /* Ack */
58
bcm2835_systmr_update_irq(s);
59
break;
60
case A_COMPARE0 ... A_COMPARE3:
61
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription bcm2835_systmr_vmstate = {
62
.version_id = 1,
63
.minimum_version_id = 1,
64
.fields = (VMStateField[]) {
65
- VMSTATE_UINT32(reg.status, BCM2835SystemTimerState),
66
+ VMSTATE_UINT32(reg.ctrl_status, BCM2835SystemTimerState),
67
VMSTATE_UINT32_ARRAY(reg.compare, BCM2835SystemTimerState,
68
BCM2835_SYSTIMER_COUNT),
69
VMSTATE_END_OF_LIST()
761
--
70
--
762
2.16.2
71
2.20.1
763
72
764
73
diff view generated by jsdifflib
1
From: Alistair Francis <alistair.francis@xilinx.com>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
Allow the guest to determine the time set from the QEMU command line.
3
This peripheral has 1 free-running timer and 4 compare registers.
4
4
5
This includes adding a trace event to debug the new time.
5
Only the free-running timer is implemented. Add support the
6
COMPARE registers (each register is wired to an IRQ).
6
7
7
Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
8
Reference: "BCM2835 ARM Peripherals" datasheet [*]
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
chapter 12 "System Timer":
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
11
The System Timer peripheral provides four 32-bit timer channels
12
and a single 64-bit free running counter. Each channel has an
13
output compare register, which is compared against the 32 least
14
significant bits of the free running counter values. When the
15
two values match, the system timer peripheral generates a signal
16
to indicate a match for the appropriate channel. The match signal
17
is then fed into the interrupt controller.
18
19
This peripheral is used since Linux 3.7, commit ee4af5696720
20
("ARM: bcm2835: add system timer").
21
22
[*] https://www.raspberrypi.org/app/uploads/2012/02/BCM2835-ARM-Peripherals.pdf
23
24
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
25
Reviewed-by: Luc Michel <luc@lmichel.fr>
26
Message-id: 20201010203709.3116542-4-f4bug@amsat.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
28
---
12
include/hw/timer/xlnx-zynqmp-rtc.h | 2 ++
29
include/hw/timer/bcm2835_systmr.h | 11 +++++--
13
hw/timer/xlnx-zynqmp-rtc.c | 58 ++++++++++++++++++++++++++++++++++++++
30
hw/timer/bcm2835_systmr.c | 48 ++++++++++++++++++++-----------
14
hw/timer/trace-events | 3 ++
31
hw/timer/trace-events | 6 ++--
15
3 files changed, 63 insertions(+)
32
3 files changed, 44 insertions(+), 21 deletions(-)
16
33
17
diff --git a/include/hw/timer/xlnx-zynqmp-rtc.h b/include/hw/timer/xlnx-zynqmp-rtc.h
34
diff --git a/include/hw/timer/bcm2835_systmr.h b/include/hw/timer/bcm2835_systmr.h
18
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/timer/xlnx-zynqmp-rtc.h
36
--- a/include/hw/timer/bcm2835_systmr.h
20
+++ b/include/hw/timer/xlnx-zynqmp-rtc.h
37
+++ b/include/hw/timer/bcm2835_systmr.h
21
@@ -XXX,XX +XXX,XX @@ typedef struct XlnxZynqMPRTC {
38
@@ -XXX,XX +XXX,XX @@
22
qemu_irq irq_rtc_int;
39
23
qemu_irq irq_addr_error_int;
40
#include "hw/sysbus.h"
24
41
#include "hw/irq.h"
25
+ uint32_t tick_offset;
42
+#include "qemu/timer.h"
43
#include "qom/object.h"
44
45
#define TYPE_BCM2835_SYSTIMER "bcm2835-sys-timer"
46
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(BCM2835SystemTimerState, BCM2835_SYSTIMER)
47
48
#define BCM2835_SYSTIMER_COUNT 4
49
50
+typedef struct {
51
+ unsigned id;
52
+ QEMUTimer timer;
53
+ qemu_irq irq;
54
+ BCM2835SystemTimerState *state;
55
+} BCM2835SystemTimerCompare;
26
+
56
+
27
uint32_t regs[XLNX_ZYNQMP_RTC_R_MAX];
57
struct BCM2835SystemTimerState {
28
RegisterInfo regs_info[XLNX_ZYNQMP_RTC_R_MAX];
58
/*< private >*/
29
} XlnxZynqMPRTC;
59
SysBusDevice parent_obj;
30
diff --git a/hw/timer/xlnx-zynqmp-rtc.c b/hw/timer/xlnx-zynqmp-rtc.c
60
61
/*< public >*/
62
MemoryRegion iomem;
63
- qemu_irq irq;
64
-
65
struct {
66
uint32_t ctrl_status;
67
uint32_t compare[BCM2835_SYSTIMER_COUNT];
68
} reg;
69
+ BCM2835SystemTimerCompare tmr[BCM2835_SYSTIMER_COUNT];
70
};
71
72
#endif
73
diff --git a/hw/timer/bcm2835_systmr.c b/hw/timer/bcm2835_systmr.c
31
index XXXXXXX..XXXXXXX 100644
74
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/timer/xlnx-zynqmp-rtc.c
75
--- a/hw/timer/bcm2835_systmr.c
33
+++ b/hw/timer/xlnx-zynqmp-rtc.c
76
+++ b/hw/timer/bcm2835_systmr.c
34
@@ -XXX,XX +XXX,XX @@
77
@@ -XXX,XX +XXX,XX @@ REG32(COMPARE1, 0x10)
35
#include "hw/register.h"
78
REG32(COMPARE2, 0x14)
36
#include "qemu/bitops.h"
79
REG32(COMPARE3, 0x18)
37
#include "qemu/log.h"
80
38
+#include "hw/ptimer.h"
81
-static void bcm2835_systmr_update_irq(BCM2835SystemTimerState *s)
39
+#include "qemu/cutils.h"
82
+static void bcm2835_systmr_timer_expire(void *opaque)
40
+#include "sysemu/sysemu.h"
83
{
41
+#include "trace.h"
84
- bool enable = !!s->reg.ctrl_status;
42
#include "hw/timer/xlnx-zynqmp-rtc.h"
85
+ BCM2835SystemTimerCompare *tmr = opaque;
43
86
44
#ifndef XLNX_ZYNQMP_RTC_ERR_DEBUG
87
- trace_bcm2835_systmr_irq(enable);
45
@@ -XXX,XX +XXX,XX @@ static void addr_error_int_update_irq(XlnxZynqMPRTC *s)
88
- qemu_set_irq(s->irq, enable);
46
qemu_set_irq(s->irq_addr_error_int, pending);
89
-}
90
-
91
-static void bcm2835_systmr_update_compare(BCM2835SystemTimerState *s,
92
- unsigned timer_index)
93
-{
94
- /* TODO fow now, since neither Linux nor U-boot use these timers. */
95
- qemu_log_mask(LOG_UNIMP, "COMPARE register %u not implemented\n",
96
- timer_index);
97
+ trace_bcm2835_systmr_timer_expired(tmr->id);
98
+ tmr->state->reg.ctrl_status |= 1 << tmr->id;
99
+ qemu_set_irq(tmr->irq, 1);
47
}
100
}
48
101
49
+static uint32_t rtc_get_count(XlnxZynqMPRTC *s)
102
static uint64_t bcm2835_systmr_read(void *opaque, hwaddr offset,
50
+{
103
@@ -XXX,XX +XXX,XX @@ static uint64_t bcm2835_systmr_read(void *opaque, hwaddr offset,
51
+ int64_t now = qemu_clock_get_ns(rtc_clock);
104
}
52
+ return s->tick_offset + now / NANOSECONDS_PER_SECOND;
105
53
+}
106
static void bcm2835_systmr_write(void *opaque, hwaddr offset,
107
- uint64_t value, unsigned size)
108
+ uint64_t value64, unsigned size)
109
{
110
BCM2835SystemTimerState *s = BCM2835_SYSTIMER(opaque);
111
+ int index;
112
+ uint32_t value = value64;
113
+ uint32_t triggers_delay_us;
114
+ uint64_t now;
115
116
trace_bcm2835_systmr_write(offset, value);
117
switch (offset) {
118
case A_CTRL_STATUS:
119
s->reg.ctrl_status &= ~value; /* Ack */
120
- bcm2835_systmr_update_irq(s);
121
+ for (index = 0; index < ARRAY_SIZE(s->tmr); index++) {
122
+ if (extract32(value, index, 1)) {
123
+ trace_bcm2835_systmr_irq_ack(index);
124
+ qemu_set_irq(s->tmr[index].irq, 0);
125
+ }
126
+ }
127
break;
128
case A_COMPARE0 ... A_COMPARE3:
129
- s->reg.compare[(offset - A_COMPARE0) >> 2] = value;
130
- bcm2835_systmr_update_compare(s, (offset - A_COMPARE0) >> 2);
131
+ index = (offset - A_COMPARE0) >> 2;
132
+ s->reg.compare[index] = value;
133
+ now = qemu_clock_get_us(QEMU_CLOCK_VIRTUAL);
134
+ /* Compare lower 32-bits of the free-running counter. */
135
+ triggers_delay_us = value - now;
136
+ trace_bcm2835_systmr_run(index, triggers_delay_us);
137
+ timer_mod(&s->tmr[index].timer, now + triggers_delay_us);
138
break;
139
case A_COUNTER_LOW:
140
case A_COUNTER_HIGH:
141
@@ -XXX,XX +XXX,XX @@ static void bcm2835_systmr_realize(DeviceState *dev, Error **errp)
142
memory_region_init_io(&s->iomem, OBJECT(dev), &bcm2835_systmr_ops,
143
s, "bcm2835-sys-timer", 0x20);
144
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
145
- sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq);
54
+
146
+
55
+static uint64_t current_time_postr(RegisterInfo *reg, uint64_t val64)
147
+ for (size_t i = 0; i < ARRAY_SIZE(s->tmr); i++) {
56
+{
148
+ s->tmr[i].id = i;
57
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
149
+ s->tmr[i].state = s;
58
+
150
+ sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->tmr[i].irq);
59
+ return rtc_get_count(s);
151
+ timer_init_us(&s->tmr[i].timer, QEMU_CLOCK_VIRTUAL,
60
+}
152
+ bcm2835_systmr_timer_expire, &s->tmr[i]);
61
+
153
+ }
62
static void rtc_int_status_postw(RegisterInfo *reg, uint64_t val64)
63
{
64
XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
65
@@ -XXX,XX +XXX,XX @@ static uint64_t addr_error_int_dis_prew(RegisterInfo *reg, uint64_t val64)
66
67
static const RegisterAccessInfo rtc_regs_info[] = {
68
{ .name = "SET_TIME_WRITE", .addr = A_SET_TIME_WRITE,
69
+ .unimp = MAKE_64BIT_MASK(0, 32),
70
},{ .name = "SET_TIME_READ", .addr = A_SET_TIME_READ,
71
.ro = 0xffffffff,
72
+ .post_read = current_time_postr,
73
},{ .name = "CALIB_WRITE", .addr = A_CALIB_WRITE,
74
+ .unimp = MAKE_64BIT_MASK(0, 32),
75
},{ .name = "CALIB_READ", .addr = A_CALIB_READ,
76
.ro = 0x1fffff,
77
},{ .name = "CURRENT_TIME", .addr = A_CURRENT_TIME,
78
.ro = 0xffffffff,
79
+ .post_read = current_time_postr,
80
},{ .name = "CURRENT_TICK", .addr = A_CURRENT_TICK,
81
.ro = 0xffff,
82
},{ .name = "ALARM", .addr = A_ALARM,
83
@@ -XXX,XX +XXX,XX @@ static void rtc_init(Object *obj)
84
XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(obj);
85
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
86
RegisterInfoArray *reg_array;
87
+ struct tm current_tm;
88
89
memory_region_init(&s->iomem, obj, TYPE_XLNX_ZYNQMP_RTC,
90
XLNX_ZYNQMP_RTC_R_MAX * 4);
91
@@ -XXX,XX +XXX,XX @@ static void rtc_init(Object *obj)
92
sysbus_init_mmio(sbd, &s->iomem);
93
sysbus_init_irq(sbd, &s->irq_rtc_int);
94
sysbus_init_irq(sbd, &s->irq_addr_error_int);
95
+
96
+ qemu_get_timedate(&current_tm, 0);
97
+ s->tick_offset = mktimegm(&current_tm) -
98
+ qemu_clock_get_ns(rtc_clock) / NANOSECONDS_PER_SECOND;
99
+
100
+ trace_xlnx_zynqmp_rtc_gettime(current_tm.tm_year, current_tm.tm_mon,
101
+ current_tm.tm_mday, current_tm.tm_hour,
102
+ current_tm.tm_min, current_tm.tm_sec);
103
+}
104
+
105
+static int rtc_pre_save(void *opaque)
106
+{
107
+ XlnxZynqMPRTC *s = opaque;
108
+ int64_t now = qemu_clock_get_ns(rtc_clock) / NANOSECONDS_PER_SECOND;
109
+
110
+ /* Add the time at migration */
111
+ s->tick_offset = s->tick_offset + now;
112
+
113
+ return 0;
114
+}
115
+
116
+static int rtc_post_load(void *opaque, int version_id)
117
+{
118
+ XlnxZynqMPRTC *s = opaque;
119
+ int64_t now = qemu_clock_get_ns(rtc_clock) / NANOSECONDS_PER_SECOND;
120
+
121
+ /* Subtract the time after migration. This combined with the pre_save
122
+ * action results in us having subtracted the time that the guest was
123
+ * stopped to the offset.
124
+ */
125
+ s->tick_offset = s->tick_offset - now;
126
+
127
+ return 0;
128
}
154
}
129
155
130
static const VMStateDescription vmstate_rtc = {
156
static const VMStateDescription bcm2835_systmr_vmstate = {
131
.name = TYPE_XLNX_ZYNQMP_RTC,
132
.version_id = 1,
133
.minimum_version_id = 1,
134
+ .pre_save = rtc_pre_save,
135
+ .post_load = rtc_post_load,
136
.fields = (VMStateField[]) {
137
VMSTATE_UINT32_ARRAY(regs, XlnxZynqMPRTC, XLNX_ZYNQMP_RTC_R_MAX),
138
+ VMSTATE_UINT32(tick_offset, XlnxZynqMPRTC),
139
VMSTATE_END_OF_LIST(),
140
}
141
};
142
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
157
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
143
index XXXXXXX..XXXXXXX 100644
158
index XXXXXXX..XXXXXXX 100644
144
--- a/hw/timer/trace-events
159
--- a/hw/timer/trace-events
145
+++ b/hw/timer/trace-events
160
+++ b/hw/timer/trace-events
146
@@ -XXX,XX +XXX,XX @@ systick_write(uint64_t addr, uint32_t value, unsigned size) "systick write addr
161
@@ -XXX,XX +XXX,XX @@ nrf51_timer_write(uint8_t timer_id, uint64_t addr, uint32_t value, unsigned size
147
cmsdk_apb_timer_read(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB timer read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
162
nrf51_timer_set_count(uint8_t timer_id, uint8_t counter_id, uint32_t value) "timer %u counter %u count 0x%" PRIx32
148
cmsdk_apb_timer_write(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB timer write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
163
149
cmsdk_apb_timer_reset(void) "CMSDK APB timer: reset"
164
# bcm2835_systmr.c
150
+
165
-bcm2835_systmr_irq(bool enable) "timer irq state %u"
151
+# hw/timer/xlnx-zynqmp-rtc.c
166
+bcm2835_systmr_timer_expired(unsigned id) "timer #%u expired"
152
+xlnx_zynqmp_rtc_gettime(int year, int month, int day, int hour, int min, int sec) "Get time from host: %d-%d-%d %2d:%02d:%02d"
167
+bcm2835_systmr_irq_ack(unsigned id) "timer #%u acked"
168
bcm2835_systmr_read(uint64_t offset, uint64_t data) "timer read: offset 0x%" PRIx64 " data 0x%" PRIx64
169
-bcm2835_systmr_write(uint64_t offset, uint64_t data) "timer write: offset 0x%" PRIx64 " data 0x%" PRIx64
170
+bcm2835_systmr_write(uint64_t offset, uint32_t data) "timer write: offset 0x%" PRIx64 " data 0x%" PRIx32
171
+bcm2835_systmr_run(unsigned id, uint64_t delay_us) "timer #%u expiring in %"PRIu64" us"
172
173
# avr_timer16.c
174
avr_timer16_read(uint8_t addr, uint8_t value) "timer16 read addr:%u value:%u"
153
--
175
--
154
2.16.2
176
2.20.1
155
177
156
178
diff view generated by jsdifflib
1
Add remaining easy registers to iotkit-secctl:
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
* NSCCFG just routes its two bits out to external GPIO lines
3
* BRGINSTAT/BRGINTCLR/BRGINTEN can be dummies, because QEMU's
4
bus fabric can never report errors
5
2
3
The SYS_timer is not directly wired to the ARM core, but to the
4
SoC (peripheral) interrupt controller.
5
6
Fixes: 0e5bbd74064 ("hw/arm/bcm2835_peripherals: Use the SYS_timer")
7
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Message-id: 20201010203709.3116542-5-f4bug@amsat.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20180220180325.29818-18-peter.maydell@linaro.org
8
---
12
---
9
include/hw/misc/iotkit-secctl.h | 4 ++++
13
hw/arm/bcm2835_peripherals.c | 13 +++++++++++--
10
hw/misc/iotkit-secctl.c | 32 ++++++++++++++++++++++++++------
14
1 file changed, 11 insertions(+), 2 deletions(-)
11
2 files changed, 30 insertions(+), 6 deletions(-)
12
15
13
diff --git a/include/hw/misc/iotkit-secctl.h b/include/hw/misc/iotkit-secctl.h
16
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
14
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/misc/iotkit-secctl.h
18
--- a/hw/arm/bcm2835_peripherals.c
16
+++ b/include/hw/misc/iotkit-secctl.h
19
+++ b/hw/arm/bcm2835_peripherals.c
17
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
18
* + sysbus MMIO region 1 is the "non-secure privilege control block" registers
21
memory_region_add_subregion(&s->peri_mr, ST_OFFSET,
19
* + named GPIO output "sec_resp_cfg" indicating whether blocked accesses
22
sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->systmr), 0));
20
* should RAZ/WI or bus error
23
sysbus_connect_irq(SYS_BUS_DEVICE(&s->systmr), 0,
21
+ * + named GPIO output "nsc_cfg" whose value tracks the NSCCFG register value
24
- qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_ARM_IRQ,
22
* Controlling the 2 APB PPCs in the IoTKit:
25
- INTERRUPT_ARM_TIMER));
23
* + named GPIO outputs apb_ppc0_nonsec[0..2] and apb_ppc1_nonsec
26
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
24
* + named GPIO outputs apb_ppc0_ap[0..2] and apb_ppc1_ap
27
+ INTERRUPT_TIMER0));
25
@@ -XXX,XX +XXX,XX @@ struct IoTKitSecCtl {
28
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->systmr), 1,
26
29
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
27
/*< public >*/
30
+ INTERRUPT_TIMER1));
28
qemu_irq sec_resp_cfg;
31
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->systmr), 2,
29
+ qemu_irq nsc_cfg_irq;
32
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
30
33
+ INTERRUPT_TIMER2));
31
MemoryRegion s_regs;
34
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->systmr), 3,
32
MemoryRegion ns_regs;
35
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
33
@@ -XXX,XX +XXX,XX @@ struct IoTKitSecCtl {
36
+ INTERRUPT_TIMER3));
34
uint32_t secppcintstat;
37
35
uint32_t secppcinten;
38
/* UART0 */
36
uint32_t secrespcfg;
39
qdev_prop_set_chr(DEVICE(&s->uart0), "chardev", serial_hd(0));
37
+ uint32_t nsccfg;
38
+ uint32_t brginten;
39
40
IoTKitSecCtlPPC apb[IOTS_NUM_APB_PPC];
41
IoTKitSecCtlPPC apbexp[IOTS_NUM_APB_EXP_PPC];
42
diff --git a/hw/misc/iotkit-secctl.c b/hw/misc/iotkit-secctl.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/hw/misc/iotkit-secctl.c
45
+++ b/hw/misc/iotkit-secctl.c
46
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
47
case A_SECRESPCFG:
48
r = s->secrespcfg;
49
break;
50
+ case A_NSCCFG:
51
+ r = s->nsccfg;
52
+ break;
53
case A_SECPPCINTSTAT:
54
r = s->secppcintstat;
55
break;
56
case A_SECPPCINTEN:
57
r = s->secppcinten;
58
break;
59
+ case A_BRGINTSTAT:
60
+ /* QEMU's bus fabric can never report errors as it doesn't buffer
61
+ * writes, so we never report bridge interrupts.
62
+ */
63
+ r = 0;
64
+ break;
65
+ case A_BRGINTEN:
66
+ r = s->brginten;
67
+ break;
68
case A_AHBNSPPCEXP0:
69
case A_AHBNSPPCEXP1:
70
case A_AHBNSPPCEXP2:
71
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
72
case A_APBSPPPCEXP3:
73
r = s->apbexp[offset_to_ppc_idx(offset)].sp;
74
break;
75
- case A_NSCCFG:
76
case A_SECMPCINTSTATUS:
77
case A_SECMSCINTSTAT:
78
case A_SECMSCINTEN:
79
- case A_BRGINTSTAT:
80
- case A_BRGINTEN:
81
case A_NSMSCEXP:
82
qemu_log_mask(LOG_UNIMP,
83
"IoTKit SecCtl S block read: "
84
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
85
}
86
87
switch (offset) {
88
+ case A_NSCCFG:
89
+ s->nsccfg = value & 3;
90
+ qemu_set_irq(s->nsc_cfg_irq, s->nsccfg);
91
+ break;
92
case A_SECRESPCFG:
93
value &= 1;
94
s->secrespcfg = value;
95
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
96
s->secppcinten = value & 0x00f000f3;
97
foreach_ppc(s, iotkit_secctl_ppc_update_irq_enable);
98
break;
99
+ case A_BRGINTCLR:
100
+ break;
101
+ case A_BRGINTEN:
102
+ s->brginten = value & 0xffff0000;
103
+ break;
104
case A_AHBNSPPCEXP0:
105
case A_AHBNSPPCEXP1:
106
case A_AHBNSPPCEXP2:
107
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
108
ppc = &s->apbexp[offset_to_ppc_idx(offset)];
109
iotkit_secctl_ppc_sp_write(ppc, value);
110
break;
111
- case A_NSCCFG:
112
case A_SECMSCINTCLR:
113
case A_SECMSCINTEN:
114
- case A_BRGINTCLR:
115
- case A_BRGINTEN:
116
qemu_log_mask(LOG_UNIMP,
117
"IoTKit SecCtl S block write: "
118
"unimplemented offset 0x%x\n", offset);
119
@@ -XXX,XX +XXX,XX @@ static void iotkit_secctl_reset(DeviceState *dev)
120
s->secppcintstat = 0;
121
s->secppcinten = 0;
122
s->secrespcfg = 0;
123
+ s->nsccfg = 0;
124
+ s->brginten = 0;
125
126
foreach_ppc(s, iotkit_secctl_reset_ppc);
127
}
128
@@ -XXX,XX +XXX,XX @@ static void iotkit_secctl_init(Object *obj)
129
}
130
131
qdev_init_gpio_out_named(dev, &s->sec_resp_cfg, "sec_resp_cfg", 1);
132
+ qdev_init_gpio_out_named(dev, &s->nsc_cfg_irq, "nsc_cfg", 1);
133
134
memory_region_init_io(&s->s_regs, obj, &iotkit_secctl_s_ops,
135
s, "iotkit-secctl-s-regs", 0x1000);
136
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription iotkit_secctl_vmstate = {
137
VMSTATE_UINT32(secppcintstat, IoTKitSecCtl),
138
VMSTATE_UINT32(secppcinten, IoTKitSecCtl),
139
VMSTATE_UINT32(secrespcfg, IoTKitSecCtl),
140
+ VMSTATE_UINT32(nsccfg, IoTKitSecCtl),
141
+ VMSTATE_UINT32(brginten, IoTKitSecCtl),
142
VMSTATE_STRUCT_ARRAY(apb, IoTKitSecCtl, IOTS_NUM_APB_PPC, 1,
143
iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
144
VMSTATE_STRUCT_ARRAY(apbexp, IoTKitSecCtl, IOTS_NUM_APB_EXP_PPC, 1,
145
--
40
--
146
2.16.2
41
2.20.1
147
42
148
43
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The integer size check was already outside of the opcode switch;
3
On ARM, the Top Byte Ignore feature means that only 56 bits of
4
move the floating-point size check outside as well. Unify the
4
the address are significant in the virtual address. We are
5
size vs index adjustment between fp and integer paths.
5
required to give the entire 64-bit address to FAR_ELx on fault,
6
which means that we do not "clean" the top byte early in TCG.
7
8
This new interface allows us to flush all 256 possible aliases
9
for a given page, currently missed by tlb_flush_page*.
6
10
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20180228193125.20577-4-richard.henderson@linaro.org
14
Message-id: 20201016210754.818257-2-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
16
---
12
target/arm/translate-a64.c | 65 +++++++++++++++++++++++-----------------------
17
include/exec/exec-all.h | 36 ++++++
13
1 file changed, 32 insertions(+), 33 deletions(-)
18
accel/tcg/cputlb.c | 275 ++++++++++++++++++++++++++++++++++++++--
14
19
2 files changed, 302 insertions(+), 9 deletions(-)
15
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
20
21
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
16
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate-a64.c
23
--- a/include/exec/exec-all.h
18
+++ b/target/arm/translate-a64.c
24
+++ b/include/exec/exec-all.h
19
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
25
@@ -XXX,XX +XXX,XX @@ void tlb_flush_by_mmuidx_all_cpus(CPUState *cpu, uint16_t idxmap);
20
case 0x05: /* FMLS */
26
* depend on when the guests translation ends the TB.
21
case 0x09: /* FMUL */
27
*/
22
case 0x19: /* FMULX */
28
void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *cpu, uint16_t idxmap);
23
- if (size == 1) {
29
+
24
- unallocated_encoding(s);
30
+/**
25
- return;
31
+ * tlb_flush_page_bits_by_mmuidx
26
- }
32
+ * @cpu: CPU whose TLB should be flushed
27
is_fp = true;
33
+ * @addr: virtual address of page to be flushed
28
break;
34
+ * @idxmap: bitmap of mmu indexes to flush
29
default:
35
+ * @bits: number of significant bits in address
30
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
36
+ *
31
if (is_fp) {
37
+ * Similar to tlb_flush_page_mask, but with a bitmap of indexes.
32
/* convert insn encoded size to TCGMemOp size */
38
+ */
33
switch (size) {
39
+void tlb_flush_page_bits_by_mmuidx(CPUState *cpu, target_ulong addr,
34
- case 2: /* single precision */
40
+ uint16_t idxmap, unsigned bits);
35
- size = MO_32;
41
+
36
- index = h << 1 | l;
42
+/* Similarly, with broadcast and syncing. */
37
- rm |= (m << 4);
43
+void tlb_flush_page_bits_by_mmuidx_all_cpus(CPUState *cpu, target_ulong addr,
38
- break;
44
+ uint16_t idxmap, unsigned bits);
39
- case 3: /* double precision */
45
+void tlb_flush_page_bits_by_mmuidx_all_cpus_synced
40
- size = MO_64;
46
+ (CPUState *cpu, target_ulong addr, uint16_t idxmap, unsigned bits);
41
- if (l || !is_q) {
47
+
42
+ case 0: /* half-precision */
48
/**
43
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
49
* tlb_set_page_with_attrs:
44
unallocated_encoding(s);
50
* @cpu: CPU to add this TLB entry for
45
return;
51
@@ -XXX,XX +XXX,XX @@ static inline void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *cpu,
46
}
52
uint16_t idxmap)
47
- index = h;
53
{
48
- rm |= (m << 4);
54
}
49
- break;
55
+static inline void tlb_flush_page_bits_by_mmuidx(CPUState *cpu,
50
- case 0: /* half precision */
56
+ target_ulong addr,
51
size = MO_16;
57
+ uint16_t idxmap,
52
- index = h << 2 | l << 1 | m;
58
+ unsigned bits)
53
- is_fp16 = true;
59
+{
54
- if (arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
60
+}
55
- break;
61
+static inline void tlb_flush_page_bits_by_mmuidx_all_cpus(CPUState *cpu,
56
- }
62
+ target_ulong addr,
57
- /* fallthru */
63
+ uint16_t idxmap,
58
- default: /* unallocated */
64
+ unsigned bits)
59
- unallocated_encoding(s);
65
+{
60
- return;
66
+}
61
- }
67
+static inline void
62
- } else {
68
+tlb_flush_page_bits_by_mmuidx_all_cpus_synced(CPUState *cpu, target_ulong addr,
63
- switch (size) {
69
+ uint16_t idxmap, unsigned bits)
64
- case 1:
70
+{
65
- index = h << 2 | l << 1 | m;
71
+}
66
break;
72
#endif
67
- case 2:
73
/**
68
- index = h << 1 | l;
74
* probe_access:
69
- rm |= (m << 4);
75
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
70
+ case MO_32: /* single precision */
76
index XXXXXXX..XXXXXXX 100644
71
+ case MO_64: /* double precision */
77
--- a/accel/tcg/cputlb.c
72
break;
78
+++ b/accel/tcg/cputlb.c
73
default:
79
@@ -XXX,XX +XXX,XX @@ void tlb_flush_all_cpus_synced(CPUState *src_cpu)
74
unallocated_encoding(s);
80
tlb_flush_by_mmuidx_all_cpus_synced(src_cpu, ALL_MMUIDX_BITS);
75
return;
81
}
82
83
+static bool tlb_hit_page_mask_anyprot(CPUTLBEntry *tlb_entry,
84
+ target_ulong page, target_ulong mask)
85
+{
86
+ page &= mask;
87
+ mask &= TARGET_PAGE_MASK | TLB_INVALID_MASK;
88
+
89
+ return (page == (tlb_entry->addr_read & mask) ||
90
+ page == (tlb_addr_write(tlb_entry) & mask) ||
91
+ page == (tlb_entry->addr_code & mask));
92
+}
93
+
94
static inline bool tlb_hit_page_anyprot(CPUTLBEntry *tlb_entry,
95
target_ulong page)
96
{
97
- return tlb_hit_page(tlb_entry->addr_read, page) ||
98
- tlb_hit_page(tlb_addr_write(tlb_entry), page) ||
99
- tlb_hit_page(tlb_entry->addr_code, page);
100
+ return tlb_hit_page_mask_anyprot(tlb_entry, page, -1);
101
}
102
103
/**
104
@@ -XXX,XX +XXX,XX @@ static inline bool tlb_entry_is_empty(const CPUTLBEntry *te)
105
}
106
107
/* Called with tlb_c.lock held */
108
-static inline bool tlb_flush_entry_locked(CPUTLBEntry *tlb_entry,
109
- target_ulong page)
110
+static bool tlb_flush_entry_mask_locked(CPUTLBEntry *tlb_entry,
111
+ target_ulong page,
112
+ target_ulong mask)
113
{
114
- if (tlb_hit_page_anyprot(tlb_entry, page)) {
115
+ if (tlb_hit_page_mask_anyprot(tlb_entry, page, mask)) {
116
memset(tlb_entry, -1, sizeof(*tlb_entry));
117
return true;
118
}
119
return false;
120
}
121
122
+static inline bool tlb_flush_entry_locked(CPUTLBEntry *tlb_entry,
123
+ target_ulong page)
124
+{
125
+ return tlb_flush_entry_mask_locked(tlb_entry, page, -1);
126
+}
127
+
128
/* Called with tlb_c.lock held */
129
-static inline void tlb_flush_vtlb_page_locked(CPUArchState *env, int mmu_idx,
130
- target_ulong page)
131
+static void tlb_flush_vtlb_page_mask_locked(CPUArchState *env, int mmu_idx,
132
+ target_ulong page,
133
+ target_ulong mask)
134
{
135
CPUTLBDesc *d = &env_tlb(env)->d[mmu_idx];
136
int k;
137
138
assert_cpu_is_self(env_cpu(env));
139
for (k = 0; k < CPU_VTLB_SIZE; k++) {
140
- if (tlb_flush_entry_locked(&d->vtable[k], page)) {
141
+ if (tlb_flush_entry_mask_locked(&d->vtable[k], page, mask)) {
142
tlb_n_used_entries_dec(env, mmu_idx);
76
}
143
}
144
}
145
}
146
147
+static inline void tlb_flush_vtlb_page_locked(CPUArchState *env, int mmu_idx,
148
+ target_ulong page)
149
+{
150
+ tlb_flush_vtlb_page_mask_locked(env, mmu_idx, page, -1);
151
+}
152
+
153
static void tlb_flush_page_locked(CPUArchState *env, int midx,
154
target_ulong page)
155
{
156
@@ -XXX,XX +XXX,XX @@ void tlb_flush_page_all_cpus_synced(CPUState *src, target_ulong addr)
157
tlb_flush_page_by_mmuidx_all_cpus_synced(src, addr, ALL_MMUIDX_BITS);
158
}
159
160
+static void tlb_flush_page_bits_locked(CPUArchState *env, int midx,
161
+ target_ulong page, unsigned bits)
162
+{
163
+ CPUTLBDesc *d = &env_tlb(env)->d[midx];
164
+ CPUTLBDescFast *f = &env_tlb(env)->f[midx];
165
+ target_ulong mask = MAKE_64BIT_MASK(0, bits);
166
+
167
+ /*
168
+ * If @bits is smaller than the tlb size, there may be multiple entries
169
+ * within the TLB; otherwise all addresses that match under @mask hit
170
+ * the same TLB entry.
171
+ *
172
+ * TODO: Perhaps allow bits to be a few bits less than the size.
173
+ * For now, just flush the entire TLB.
174
+ */
175
+ if (mask < f->mask) {
176
+ tlb_debug("forcing full flush midx %d ("
177
+ TARGET_FMT_lx "/" TARGET_FMT_lx ")\n",
178
+ midx, page, mask);
179
+ tlb_flush_one_mmuidx_locked(env, midx, get_clock_realtime());
180
+ return;
181
+ }
182
+
183
+ /* Check if we need to flush due to large pages. */
184
+ if ((page & d->large_page_mask) == d->large_page_addr) {
185
+ tlb_debug("forcing full flush midx %d ("
186
+ TARGET_FMT_lx "/" TARGET_FMT_lx ")\n",
187
+ midx, d->large_page_addr, d->large_page_mask);
188
+ tlb_flush_one_mmuidx_locked(env, midx, get_clock_realtime());
189
+ return;
190
+ }
191
+
192
+ if (tlb_flush_entry_mask_locked(tlb_entry(env, midx, page), page, mask)) {
193
+ tlb_n_used_entries_dec(env, midx);
194
+ }
195
+ tlb_flush_vtlb_page_mask_locked(env, midx, page, mask);
196
+}
197
+
198
+typedef struct {
199
+ target_ulong addr;
200
+ uint16_t idxmap;
201
+ uint16_t bits;
202
+} TLBFlushPageBitsByMMUIdxData;
203
+
204
+static void
205
+tlb_flush_page_bits_by_mmuidx_async_0(CPUState *cpu,
206
+ TLBFlushPageBitsByMMUIdxData d)
207
+{
208
+ CPUArchState *env = cpu->env_ptr;
209
+ int mmu_idx;
210
+
211
+ assert_cpu_is_self(cpu);
212
+
213
+ tlb_debug("page addr:" TARGET_FMT_lx "/%u mmu_map:0x%x\n",
214
+ d.addr, d.bits, d.idxmap);
215
+
216
+ qemu_spin_lock(&env_tlb(env)->c.lock);
217
+ for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
218
+ if ((d.idxmap >> mmu_idx) & 1) {
219
+ tlb_flush_page_bits_locked(env, mmu_idx, d.addr, d.bits);
220
+ }
221
+ }
222
+ qemu_spin_unlock(&env_tlb(env)->c.lock);
223
+
224
+ tb_flush_jmp_cache(cpu, d.addr);
225
+}
226
+
227
+static bool encode_pbm_to_runon(run_on_cpu_data *out,
228
+ TLBFlushPageBitsByMMUIdxData d)
229
+{
230
+ /* We need 6 bits to hold to hold @bits up to 63. */
231
+ if (d.idxmap <= MAKE_64BIT_MASK(0, TARGET_PAGE_BITS - 6)) {
232
+ *out = RUN_ON_CPU_TARGET_PTR(d.addr | (d.idxmap << 6) | d.bits);
233
+ return true;
234
+ }
235
+ return false;
236
+}
237
+
238
+static TLBFlushPageBitsByMMUIdxData
239
+decode_runon_to_pbm(run_on_cpu_data data)
240
+{
241
+ target_ulong addr_map_bits = (target_ulong) data.target_ptr;
242
+ return (TLBFlushPageBitsByMMUIdxData){
243
+ .addr = addr_map_bits & TARGET_PAGE_MASK,
244
+ .idxmap = (addr_map_bits & ~TARGET_PAGE_MASK) >> 6,
245
+ .bits = addr_map_bits & 0x3f
246
+ };
247
+}
248
+
249
+static void tlb_flush_page_bits_by_mmuidx_async_1(CPUState *cpu,
250
+ run_on_cpu_data runon)
251
+{
252
+ tlb_flush_page_bits_by_mmuidx_async_0(cpu, decode_runon_to_pbm(runon));
253
+}
254
+
255
+static void tlb_flush_page_bits_by_mmuidx_async_2(CPUState *cpu,
256
+ run_on_cpu_data data)
257
+{
258
+ TLBFlushPageBitsByMMUIdxData *d = data.host_ptr;
259
+ tlb_flush_page_bits_by_mmuidx_async_0(cpu, *d);
260
+ g_free(d);
261
+}
262
+
263
+void tlb_flush_page_bits_by_mmuidx(CPUState *cpu, target_ulong addr,
264
+ uint16_t idxmap, unsigned bits)
265
+{
266
+ TLBFlushPageBitsByMMUIdxData d;
267
+ run_on_cpu_data runon;
268
+
269
+ /* If all bits are significant, this devolves to tlb_flush_page. */
270
+ if (bits >= TARGET_LONG_BITS) {
271
+ tlb_flush_page_by_mmuidx(cpu, addr, idxmap);
272
+ return;
273
+ }
274
+ /* If no page bits are significant, this devolves to tlb_flush. */
275
+ if (bits < TARGET_PAGE_BITS) {
276
+ tlb_flush_by_mmuidx(cpu, idxmap);
277
+ return;
278
+ }
279
+
280
+ /* This should already be page aligned */
281
+ d.addr = addr & TARGET_PAGE_MASK;
282
+ d.idxmap = idxmap;
283
+ d.bits = bits;
284
+
285
+ if (qemu_cpu_is_self(cpu)) {
286
+ tlb_flush_page_bits_by_mmuidx_async_0(cpu, d);
287
+ } else if (encode_pbm_to_runon(&runon, d)) {
288
+ async_run_on_cpu(cpu, tlb_flush_page_bits_by_mmuidx_async_1, runon);
77
+ } else {
289
+ } else {
78
+ switch (size) {
290
+ TLBFlushPageBitsByMMUIdxData *p
79
+ case MO_8:
291
+ = g_new(TLBFlushPageBitsByMMUIdxData, 1);
80
+ case MO_64:
292
+
81
+ unallocated_encoding(s);
293
+ /* Otherwise allocate a structure, freed by the worker. */
82
+ return;
294
+ *p = d;
295
+ async_run_on_cpu(cpu, tlb_flush_page_bits_by_mmuidx_async_2,
296
+ RUN_ON_CPU_HOST_PTR(p));
297
+ }
298
+}
299
+
300
+void tlb_flush_page_bits_by_mmuidx_all_cpus(CPUState *src_cpu,
301
+ target_ulong addr,
302
+ uint16_t idxmap,
303
+ unsigned bits)
304
+{
305
+ TLBFlushPageBitsByMMUIdxData d;
306
+ run_on_cpu_data runon;
307
+
308
+ /* If all bits are significant, this devolves to tlb_flush_page. */
309
+ if (bits >= TARGET_LONG_BITS) {
310
+ tlb_flush_page_by_mmuidx_all_cpus(src_cpu, addr, idxmap);
311
+ return;
312
+ }
313
+ /* If no page bits are significant, this devolves to tlb_flush. */
314
+ if (bits < TARGET_PAGE_BITS) {
315
+ tlb_flush_by_mmuidx_all_cpus(src_cpu, idxmap);
316
+ return;
317
+ }
318
+
319
+ /* This should already be page aligned */
320
+ d.addr = addr & TARGET_PAGE_MASK;
321
+ d.idxmap = idxmap;
322
+ d.bits = bits;
323
+
324
+ if (encode_pbm_to_runon(&runon, d)) {
325
+ flush_all_helper(src_cpu, tlb_flush_page_bits_by_mmuidx_async_1, runon);
326
+ } else {
327
+ CPUState *dst_cpu;
328
+ TLBFlushPageBitsByMMUIdxData *p;
329
+
330
+ /* Allocate a separate data block for each destination cpu. */
331
+ CPU_FOREACH(dst_cpu) {
332
+ if (dst_cpu != src_cpu) {
333
+ p = g_new(TLBFlushPageBitsByMMUIdxData, 1);
334
+ *p = d;
335
+ async_run_on_cpu(dst_cpu,
336
+ tlb_flush_page_bits_by_mmuidx_async_2,
337
+ RUN_ON_CPU_HOST_PTR(p));
338
+ }
83
+ }
339
+ }
84
+ }
340
+ }
85
+
341
+
86
+ /* Given TCGMemOp size, adjust register and indexing. */
342
+ tlb_flush_page_bits_by_mmuidx_async_0(src_cpu, d);
87
+ switch (size) {
343
+}
88
+ case MO_16:
344
+
89
+ index = h << 2 | l << 1 | m;
345
+void tlb_flush_page_bits_by_mmuidx_all_cpus_synced(CPUState *src_cpu,
90
+ break;
346
+ target_ulong addr,
91
+ case MO_32:
347
+ uint16_t idxmap,
92
+ index = h << 1 | l;
348
+ unsigned bits)
93
+ rm |= m << 4;
349
+{
94
+ break;
350
+ TLBFlushPageBitsByMMUIdxData d;
95
+ case MO_64:
351
+ run_on_cpu_data runon;
96
+ if (l || !is_q) {
352
+
97
+ unallocated_encoding(s);
353
+ /* If all bits are significant, this devolves to tlb_flush_page. */
98
+ return;
354
+ if (bits >= TARGET_LONG_BITS) {
355
+ tlb_flush_page_by_mmuidx_all_cpus_synced(src_cpu, addr, idxmap);
356
+ return;
357
+ }
358
+ /* If no page bits are significant, this devolves to tlb_flush. */
359
+ if (bits < TARGET_PAGE_BITS) {
360
+ tlb_flush_by_mmuidx_all_cpus_synced(src_cpu, idxmap);
361
+ return;
362
+ }
363
+
364
+ /* This should already be page aligned */
365
+ d.addr = addr & TARGET_PAGE_MASK;
366
+ d.idxmap = idxmap;
367
+ d.bits = bits;
368
+
369
+ if (encode_pbm_to_runon(&runon, d)) {
370
+ flush_all_helper(src_cpu, tlb_flush_page_bits_by_mmuidx_async_1, runon);
371
+ async_safe_run_on_cpu(src_cpu, tlb_flush_page_bits_by_mmuidx_async_1,
372
+ runon);
373
+ } else {
374
+ CPUState *dst_cpu;
375
+ TLBFlushPageBitsByMMUIdxData *p;
376
+
377
+ /* Allocate a separate data block for each destination cpu. */
378
+ CPU_FOREACH(dst_cpu) {
379
+ if (dst_cpu != src_cpu) {
380
+ p = g_new(TLBFlushPageBitsByMMUIdxData, 1);
381
+ *p = d;
382
+ async_run_on_cpu(dst_cpu, tlb_flush_page_bits_by_mmuidx_async_2,
383
+ RUN_ON_CPU_HOST_PTR(p));
384
+ }
99
+ }
385
+ }
100
+ index = h;
386
+
101
+ rm |= m << 4;
387
+ p = g_new(TLBFlushPageBitsByMMUIdxData, 1);
102
+ break;
388
+ *p = d;
103
+ default:
389
+ async_safe_run_on_cpu(src_cpu, tlb_flush_page_bits_by_mmuidx_async_2,
104
+ g_assert_not_reached();
390
+ RUN_ON_CPU_HOST_PTR(p));
105
}
391
+ }
106
392
+}
107
if (!fp_access_check(s)) {
393
+
394
/* update the TLBs so that writes to code in the virtual page 'addr'
395
can be detected */
396
void tlb_protect_code(ram_addr_t ram_addr)
108
--
397
--
109
2.16.2
398
2.20.1
110
399
111
400
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
When TBI is enabled in a given regime, 56 bits of the address
4
are significant and we need to clear out any other matching
5
virtual addresses with differing tags.
6
7
The other uses of tlb_flush_page (without mmuidx) in this file
8
are only used by aarch32 mode.
9
10
Fixes: 38d931687fa1
11
Reported-by: Jordan Frank <jordanfrank@fb.com>
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180228193125.20577-6-richard.henderson@linaro.org
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Message-id: 20201016210754.818257-3-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
17
---
8
target/arm/helper.h | 9 +++++
18
target/arm/helper.c | 46 ++++++++++++++++++++++++++++++++++++++-------
9
target/arm/translate-a64.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++
19
1 file changed, 39 insertions(+), 7 deletions(-)
10
target/arm/vec_helper.c | 74 +++++++++++++++++++++++++++++++++++++++++
11
3 files changed, 166 insertions(+)
12
20
13
diff --git a/target/arm/helper.h b/target/arm/helper.h
21
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.h
23
--- a/target/arm/helper.c
16
+++ b/target/arm/helper.h
24
+++ b/target/arm/helper.c
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_2(dc_zva, void, env, i64)
25
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
18
DEF_HELPER_FLAGS_2(neon_pmull_64_lo, TCG_CALL_NO_RWG_SE, i64, i64, i64)
26
#endif
19
DEF_HELPER_FLAGS_2(neon_pmull_64_hi, TCG_CALL_NO_RWG_SE, i64, i64, i64)
27
20
28
static void switch_mode(CPUARMState *env, int mode);
21
+DEF_HELPER_FLAGS_5(gvec_qrdmlah_s16, TCG_CALL_NO_RWG,
29
+static int aa64_va_parameter_tbi(uint64_t tcr, ARMMMUIdx mmu_idx);
22
+ void, ptr, ptr, ptr, ptr, i32)
30
23
+DEF_HELPER_FLAGS_5(gvec_qrdmlsh_s16, TCG_CALL_NO_RWG,
31
static int vfp_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg)
24
+ void, ptr, ptr, ptr, ptr, i32)
32
{
25
+DEF_HELPER_FLAGS_5(gvec_qrdmlah_s32, TCG_CALL_NO_RWG,
33
@@ -XXX,XX +XXX,XX @@ static int vae1_tlbmask(CPUARMState *env)
26
+ void, ptr, ptr, ptr, ptr, i32)
34
}
27
+DEF_HELPER_FLAGS_5(gvec_qrdmlsh_s32, TCG_CALL_NO_RWG,
35
}
28
+ void, ptr, ptr, ptr, ptr, i32)
36
37
+/* Return 56 if TBI is enabled, 64 otherwise. */
38
+static int tlbbits_for_regime(CPUARMState *env, ARMMMUIdx mmu_idx,
39
+ uint64_t addr)
40
+{
41
+ uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr;
42
+ int tbi = aa64_va_parameter_tbi(tcr, mmu_idx);
43
+ int select = extract64(addr, 55, 1);
29
+
44
+
30
#ifdef TARGET_AARCH64
45
+ return (tbi >> select) & 1 ? 56 : 64;
31
#include "helper-a64.h"
32
#endif
33
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/translate-a64.c
36
+++ b/target/arm/translate-a64.c
37
@@ -XXX,XX +XXX,XX @@ static void gen_gvec_op3(DisasContext *s, bool is_q, int rd,
38
vec_full_reg_size(s), gvec_op);
39
}
40
41
+/* Expand a 3-operand + env pointer operation using
42
+ * an out-of-line helper.
43
+ */
44
+static void gen_gvec_op3_env(DisasContext *s, bool is_q, int rd,
45
+ int rn, int rm, gen_helper_gvec_3_ptr *fn)
46
+{
47
+ tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
48
+ vec_full_reg_offset(s, rn),
49
+ vec_full_reg_offset(s, rm), cpu_env,
50
+ is_q ? 16 : 8, vec_full_reg_size(s), 0, fn);
51
+}
46
+}
52
+
47
+
53
/* Set ZF and NF based on a 64 bit result. This is alas fiddlier
48
+static int vae1_tlbbits(CPUARMState *env, uint64_t addr)
54
* than the 32 bit equivalent.
55
*/
56
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_fp16(DisasContext *s, uint32_t insn)
57
clear_vec_high(s, is_q, rd);
58
}
59
60
+/* AdvSIMD three same extra
61
+ * 31 30 29 28 24 23 22 21 20 16 15 14 11 10 9 5 4 0
62
+ * +---+---+---+-----------+------+---+------+---+--------+---+----+----+
63
+ * | 0 | Q | U | 0 1 1 1 0 | size | 0 | Rm | 1 | opcode | 1 | Rn | Rd |
64
+ * +---+---+---+-----------+------+---+------+---+--------+---+----+----+
65
+ */
66
+static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
67
+{
49
+{
68
+ int rd = extract32(insn, 0, 5);
50
+ ARMMMUIdx mmu_idx;
69
+ int rn = extract32(insn, 5, 5);
70
+ int opcode = extract32(insn, 11, 4);
71
+ int rm = extract32(insn, 16, 5);
72
+ int size = extract32(insn, 22, 2);
73
+ bool u = extract32(insn, 29, 1);
74
+ bool is_q = extract32(insn, 30, 1);
75
+ int feature;
76
+
51
+
77
+ switch (u * 16 + opcode) {
52
+ /* Only the regime of the mmu_idx below is significant. */
78
+ case 0x10: /* SQRDMLAH (vector) */
53
+ if (arm_is_secure_below_el3(env)) {
79
+ case 0x11: /* SQRDMLSH (vector) */
54
+ mmu_idx = ARMMMUIdx_SE10_0;
80
+ if (size != 1 && size != 2) {
55
+ } else if ((env->cp15.hcr_el2 & (HCR_E2H | HCR_TGE))
81
+ unallocated_encoding(s);
56
+ == (HCR_E2H | HCR_TGE)) {
82
+ return;
57
+ mmu_idx = ARMMMUIdx_E20_0;
83
+ }
58
+ } else {
84
+ feature = ARM_FEATURE_V8_RDM;
59
+ mmu_idx = ARMMMUIdx_E10_0;
85
+ break;
86
+ default:
87
+ unallocated_encoding(s);
88
+ return;
89
+ }
60
+ }
90
+ if (!arm_dc_feature(s, feature)) {
61
+ return tlbbits_for_regime(env, mmu_idx, addr);
91
+ unallocated_encoding(s);
92
+ return;
93
+ }
94
+ if (!fp_access_check(s)) {
95
+ return;
96
+ }
97
+
98
+ switch (opcode) {
99
+ case 0x0: /* SQRDMLAH (vector) */
100
+ switch (size) {
101
+ case 1:
102
+ gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlah_s16);
103
+ break;
104
+ case 2:
105
+ gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlah_s32);
106
+ break;
107
+ default:
108
+ g_assert_not_reached();
109
+ }
110
+ return;
111
+
112
+ case 0x1: /* SQRDMLSH (vector) */
113
+ switch (size) {
114
+ case 1:
115
+ gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlsh_s16);
116
+ break;
117
+ case 2:
118
+ gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlsh_s32);
119
+ break;
120
+ default:
121
+ g_assert_not_reached();
122
+ }
123
+ return;
124
+
125
+ default:
126
+ g_assert_not_reached();
127
+ }
128
+}
62
+}
129
+
63
+
130
static void handle_2misc_widening(DisasContext *s, int opcode, bool is_q,
64
static void tlbi_aa64_vmalle1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
131
int size, int rn, int rd)
65
uint64_t value)
132
{
66
{
133
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_imm2(DisasContext *s, uint32_t insn)
67
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
134
static const AArch64DecodeTable data_proc_simd[] = {
68
CPUState *cs = env_cpu(env);
135
/* pattern , mask , fn */
69
int mask = vae1_tlbmask(env);
136
{ 0x0e200400, 0x9f200400, disas_simd_three_reg_same },
70
uint64_t pageaddr = sextract64(value << 12, 0, 56);
137
+ { 0x0e008400, 0x9f208400, disas_simd_three_reg_same_extra },
71
+ int bits = vae1_tlbbits(env, pageaddr);
138
{ 0x0e200000, 0x9f200c00, disas_simd_three_reg_diff },
72
139
{ 0x0e200800, 0x9f3e0c00, disas_simd_two_reg_misc },
73
- tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, mask);
140
{ 0x0e300800, 0x9f3e0c00, disas_simd_across_lanes },
74
+ tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, mask, bits);
141
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
142
index XXXXXXX..XXXXXXX 100644
143
--- a/target/arm/vec_helper.c
144
+++ b/target/arm/vec_helper.c
145
@@ -XXX,XX +XXX,XX @@
146
147
#define SET_QC() env->vfp.xregs[ARM_VFP_FPSCR] |= CPSR_Q
148
149
+static void clear_tail(void *vd, uintptr_t opr_sz, uintptr_t max_sz)
150
+{
151
+ uint64_t *d = vd + opr_sz;
152
+ uintptr_t i;
153
+
154
+ for (i = opr_sz; i < max_sz; i += 8) {
155
+ *d++ = 0;
156
+ }
157
+}
158
+
159
/* Signed saturating rounding doubling multiply-accumulate high half, 16-bit */
160
static uint16_t inl_qrdmlah_s16(CPUARMState *env, int16_t src1,
161
int16_t src2, int16_t src3)
162
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(neon_qrdmlah_s16)(CPUARMState *env, uint32_t src1,
163
return deposit32(e1, 16, 16, e2);
164
}
75
}
165
76
166
+void HELPER(gvec_qrdmlah_s16)(void *vd, void *vn, void *vm,
77
static void tlbi_aa64_vae1_write(CPUARMState *env, const ARMCPRegInfo *ri,
167
+ void *ve, uint32_t desc)
78
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae1_write(CPUARMState *env, const ARMCPRegInfo *ri,
168
+{
79
CPUState *cs = env_cpu(env);
169
+ uintptr_t opr_sz = simd_oprsz(desc);
80
int mask = vae1_tlbmask(env);
170
+ int16_t *d = vd;
81
uint64_t pageaddr = sextract64(value << 12, 0, 56);
171
+ int16_t *n = vn;
82
+ int bits = vae1_tlbbits(env, pageaddr);
172
+ int16_t *m = vm;
83
173
+ CPUARMState *env = ve;
84
if (tlb_force_broadcast(env)) {
174
+ uintptr_t i;
85
- tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, mask);
175
+
86
+ tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, mask, bits);
176
+ for (i = 0; i < opr_sz / 2; ++i) {
87
} else {
177
+ d[i] = inl_qrdmlah_s16(env, n[i], m[i], d[i]);
88
- tlb_flush_page_by_mmuidx(cs, pageaddr, mask);
178
+ }
89
+ tlb_flush_page_bits_by_mmuidx(cs, pageaddr, mask, bits);
179
+ clear_tail(d, opr_sz, simd_maxsz(desc));
90
}
180
+}
181
+
182
/* Signed saturating rounding doubling multiply-subtract high half, 16-bit */
183
static uint16_t inl_qrdmlsh_s16(CPUARMState *env, int16_t src1,
184
int16_t src2, int16_t src3)
185
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(neon_qrdmlsh_s16)(CPUARMState *env, uint32_t src1,
186
return deposit32(e1, 16, 16, e2);
187
}
91
}
188
92
189
+void HELPER(gvec_qrdmlsh_s16)(void *vd, void *vn, void *vm,
93
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae2is_write(CPUARMState *env, const ARMCPRegInfo *ri,
190
+ void *ve, uint32_t desc)
94
{
191
+{
95
CPUState *cs = env_cpu(env);
192
+ uintptr_t opr_sz = simd_oprsz(desc);
96
uint64_t pageaddr = sextract64(value << 12, 0, 56);
193
+ int16_t *d = vd;
97
+ int bits = tlbbits_for_regime(env, ARMMMUIdx_E2, pageaddr);
194
+ int16_t *n = vn;
98
195
+ int16_t *m = vm;
99
- tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
196
+ CPUARMState *env = ve;
100
- ARMMMUIdxBit_E2);
197
+ uintptr_t i;
101
+ tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr,
198
+
102
+ ARMMMUIdxBit_E2, bits);
199
+ for (i = 0; i < opr_sz / 2; ++i) {
200
+ d[i] = inl_qrdmlsh_s16(env, n[i], m[i], d[i]);
201
+ }
202
+ clear_tail(d, opr_sz, simd_maxsz(desc));
203
+}
204
+
205
/* Signed saturating rounding doubling multiply-accumulate high half, 32-bit */
206
uint32_t HELPER(neon_qrdmlah_s32)(CPUARMState *env, int32_t src1,
207
int32_t src2, int32_t src3)
208
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(neon_qrdmlah_s32)(CPUARMState *env, int32_t src1,
209
return ret;
210
}
103
}
211
104
212
+void HELPER(gvec_qrdmlah_s32)(void *vd, void *vn, void *vm,
105
static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
213
+ void *ve, uint32_t desc)
106
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
214
+{
107
{
215
+ uintptr_t opr_sz = simd_oprsz(desc);
108
CPUState *cs = env_cpu(env);
216
+ int32_t *d = vd;
109
uint64_t pageaddr = sextract64(value << 12, 0, 56);
217
+ int32_t *n = vn;
110
+ int bits = tlbbits_for_regime(env, ARMMMUIdx_SE3, pageaddr);
218
+ int32_t *m = vm;
111
219
+ CPUARMState *env = ve;
112
- tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
220
+ uintptr_t i;
113
- ARMMMUIdxBit_SE3);
221
+
114
+ tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr,
222
+ for (i = 0; i < opr_sz / 4; ++i) {
115
+ ARMMMUIdxBit_SE3, bits);
223
+ d[i] = helper_neon_qrdmlah_s32(env, n[i], m[i], d[i]);
224
+ }
225
+ clear_tail(d, opr_sz, simd_maxsz(desc));
226
+}
227
+
228
/* Signed saturating rounding doubling multiply-subtract high half, 32-bit */
229
uint32_t HELPER(neon_qrdmlsh_s32)(CPUARMState *env, int32_t src1,
230
int32_t src2, int32_t src3)
231
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(neon_qrdmlsh_s32)(CPUARMState *env, int32_t src1,
232
}
233
return ret;
234
}
116
}
235
+
117
236
+void HELPER(gvec_qrdmlsh_s32)(void *vd, void *vn, void *vm,
118
static CPAccessResult aa64_zva_access(CPUARMState *env, const ARMCPRegInfo *ri,
237
+ void *ve, uint32_t desc)
238
+{
239
+ uintptr_t opr_sz = simd_oprsz(desc);
240
+ int32_t *d = vd;
241
+ int32_t *n = vn;
242
+ int32_t *m = vm;
243
+ CPUARMState *env = ve;
244
+ uintptr_t i;
245
+
246
+ for (i = 0; i < opr_sz / 4; ++i) {
247
+ d[i] = helper_neon_qrdmlsh_s32(env, n[i], m[i], d[i]);
248
+ }
249
+ clear_tail(d, opr_sz, simd_maxsz(desc));
250
+}
251
--
119
--
252
2.16.2
120
2.20.1
253
121
254
122
diff view generated by jsdifflib
1
From: Alistair Francis <alistair.francis@xilinx.com>
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
2
3
Initial commit of the ZynqMP RTC device.
3
This test exercises the various modes of the npcm7xx timer. In
4
4
particular, it triggers the bug found by the fuzzer, as reported here:
5
Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
5
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
https://lists.gnu.org/archive/html/qemu-devel/2020-09/msg02992.html
7
8
It also found several other bugs, especially related to interrupt
9
handling.
10
11
The test exercises all the timers in all the timer modules, which
12
expands to 180 test cases in total.
13
14
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
15
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
16
Message-id: 20201008232154.94221-2-hskinnemoen@google.com
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
18
---
9
hw/timer/Makefile.objs | 1 +
19
tests/qtest/npcm7xx_timer-test.c | 562 +++++++++++++++++++++++++++++++
10
include/hw/timer/xlnx-zynqmp-rtc.h | 84 +++++++++++++++
20
tests/qtest/meson.build | 1 +
11
hw/timer/xlnx-zynqmp-rtc.c | 214 +++++++++++++++++++++++++++++++++++++
21
2 files changed, 563 insertions(+)
12
3 files changed, 299 insertions(+)
22
create mode 100644 tests/qtest/npcm7xx_timer-test.c
13
create mode 100644 include/hw/timer/xlnx-zynqmp-rtc.h
23
14
create mode 100644 hw/timer/xlnx-zynqmp-rtc.c
24
diff --git a/tests/qtest/npcm7xx_timer-test.c b/tests/qtest/npcm7xx_timer-test.c
15
16
diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/timer/Makefile.objs
19
+++ b/hw/timer/Makefile.objs
20
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_IMX) += imx_epit.o
21
common-obj-$(CONFIG_IMX) += imx_gpt.o
22
common-obj-$(CONFIG_LM32) += lm32_timer.o
23
common-obj-$(CONFIG_MILKYMIST) += milkymist-sysctl.o
24
+common-obj-$(CONFIG_XLNX_ZYNQMP) += xlnx-zynqmp-rtc.o
25
26
obj-$(CONFIG_ALTERA_TIMER) += altera_timer.o
27
obj-$(CONFIG_EXYNOS4) += exynos4210_mct.o
28
diff --git a/include/hw/timer/xlnx-zynqmp-rtc.h b/include/hw/timer/xlnx-zynqmp-rtc.h
29
new file mode 100644
25
new file mode 100644
30
index XXXXXXX..XXXXXXX
26
index XXXXXXX..XXXXXXX
31
--- /dev/null
27
--- /dev/null
32
+++ b/include/hw/timer/xlnx-zynqmp-rtc.h
28
+++ b/tests/qtest/npcm7xx_timer-test.c
33
@@ -XXX,XX +XXX,XX @@
29
@@ -XXX,XX +XXX,XX @@
34
+/*
30
+/*
35
+ * QEMU model of the Xilinx ZynqMP Real Time Clock (RTC).
31
+ * QTest testcase for the Nuvoton NPCM7xx Timer
36
+ *
32
+ *
37
+ * Copyright (c) 2017 Xilinx Inc.
33
+ * Copyright 2020 Google LLC
38
+ *
34
+ *
39
+ * Written-by: Alistair Francis <alistair.francis@xilinx.com>
35
+ * This program is free software; you can redistribute it and/or modify it
36
+ * under the terms of the GNU General Public License as published by the
37
+ * Free Software Foundation; either version 2 of the License, or
38
+ * (at your option) any later version.
40
+ *
39
+ *
41
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
40
+ * This program is distributed in the hope that it will be useful, but WITHOUT
42
+ * of this software and associated documentation files (the "Software"), to deal
41
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
43
+ * in the Software without restriction, including without limitation the rights
42
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
44
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
43
+ * for more details.
45
+ * copies of the Software, and to permit persons to whom the Software is
46
+ * furnished to do so, subject to the following conditions:
47
+ *
48
+ * The above copyright notice and this permission notice shall be included in
49
+ * all copies or substantial portions of the Software.
50
+ *
51
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
52
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
53
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
54
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
55
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
56
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
57
+ * THE SOFTWARE.
58
+ */
44
+ */
59
+
45
+
60
+#include "hw/register.h"
61
+
62
+#define TYPE_XLNX_ZYNQMP_RTC "xlnx-zynmp.rtc"
63
+
64
+#define XLNX_ZYNQMP_RTC(obj) \
65
+ OBJECT_CHECK(XlnxZynqMPRTC, (obj), TYPE_XLNX_ZYNQMP_RTC)
66
+
67
+REG32(SET_TIME_WRITE, 0x0)
68
+REG32(SET_TIME_READ, 0x4)
69
+REG32(CALIB_WRITE, 0x8)
70
+ FIELD(CALIB_WRITE, FRACTION_EN, 20, 1)
71
+ FIELD(CALIB_WRITE, FRACTION_DATA, 16, 4)
72
+ FIELD(CALIB_WRITE, MAX_TICK, 0, 16)
73
+REG32(CALIB_READ, 0xc)
74
+ FIELD(CALIB_READ, FRACTION_EN, 20, 1)
75
+ FIELD(CALIB_READ, FRACTION_DATA, 16, 4)
76
+ FIELD(CALIB_READ, MAX_TICK, 0, 16)
77
+REG32(CURRENT_TIME, 0x10)
78
+REG32(CURRENT_TICK, 0x14)
79
+ FIELD(CURRENT_TICK, VALUE, 0, 16)
80
+REG32(ALARM, 0x18)
81
+REG32(RTC_INT_STATUS, 0x20)
82
+ FIELD(RTC_INT_STATUS, ALARM, 1, 1)
83
+ FIELD(RTC_INT_STATUS, SECONDS, 0, 1)
84
+REG32(RTC_INT_MASK, 0x24)
85
+ FIELD(RTC_INT_MASK, ALARM, 1, 1)
86
+ FIELD(RTC_INT_MASK, SECONDS, 0, 1)
87
+REG32(RTC_INT_EN, 0x28)
88
+ FIELD(RTC_INT_EN, ALARM, 1, 1)
89
+ FIELD(RTC_INT_EN, SECONDS, 0, 1)
90
+REG32(RTC_INT_DIS, 0x2c)
91
+ FIELD(RTC_INT_DIS, ALARM, 1, 1)
92
+ FIELD(RTC_INT_DIS, SECONDS, 0, 1)
93
+REG32(ADDR_ERROR, 0x30)
94
+ FIELD(ADDR_ERROR, STATUS, 0, 1)
95
+REG32(ADDR_ERROR_INT_MASK, 0x34)
96
+ FIELD(ADDR_ERROR_INT_MASK, MASK, 0, 1)
97
+REG32(ADDR_ERROR_INT_EN, 0x38)
98
+ FIELD(ADDR_ERROR_INT_EN, MASK, 0, 1)
99
+REG32(ADDR_ERROR_INT_DIS, 0x3c)
100
+ FIELD(ADDR_ERROR_INT_DIS, MASK, 0, 1)
101
+REG32(CONTROL, 0x40)
102
+ FIELD(CONTROL, BATTERY_DISABLE, 31, 1)
103
+ FIELD(CONTROL, OSC_CNTRL, 24, 4)
104
+ FIELD(CONTROL, SLVERR_ENABLE, 0, 1)
105
+REG32(SAFETY_CHK, 0x50)
106
+
107
+#define XLNX_ZYNQMP_RTC_R_MAX (R_SAFETY_CHK + 1)
108
+
109
+typedef struct XlnxZynqMPRTC {
110
+ SysBusDevice parent_obj;
111
+ MemoryRegion iomem;
112
+ qemu_irq irq_rtc_int;
113
+ qemu_irq irq_addr_error_int;
114
+
115
+ uint32_t regs[XLNX_ZYNQMP_RTC_R_MAX];
116
+ RegisterInfo regs_info[XLNX_ZYNQMP_RTC_R_MAX];
117
+} XlnxZynqMPRTC;
118
diff --git a/hw/timer/xlnx-zynqmp-rtc.c b/hw/timer/xlnx-zynqmp-rtc.c
119
new file mode 100644
120
index XXXXXXX..XXXXXXX
121
--- /dev/null
122
+++ b/hw/timer/xlnx-zynqmp-rtc.c
123
@@ -XXX,XX +XXX,XX @@
124
+/*
125
+ * QEMU model of the Xilinx ZynqMP Real Time Clock (RTC).
126
+ *
127
+ * Copyright (c) 2017 Xilinx Inc.
128
+ *
129
+ * Written-by: Alistair Francis <alistair.francis@xilinx.com>
130
+ *
131
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
132
+ * of this software and associated documentation files (the "Software"), to deal
133
+ * in the Software without restriction, including without limitation the rights
134
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
135
+ * copies of the Software, and to permit persons to whom the Software is
136
+ * furnished to do so, subject to the following conditions:
137
+ *
138
+ * The above copyright notice and this permission notice shall be included in
139
+ * all copies or substantial portions of the Software.
140
+ *
141
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
142
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
143
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
144
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
145
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
146
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
147
+ * THE SOFTWARE.
148
+ */
149
+
150
+#include "qemu/osdep.h"
46
+#include "qemu/osdep.h"
151
+#include "hw/sysbus.h"
47
+#include "qemu/timer.h"
152
+#include "hw/register.h"
48
+#include "libqtest-single.h"
153
+#include "qemu/bitops.h"
49
+
154
+#include "qemu/log.h"
50
+#define TIM_REF_HZ (25000000)
155
+#include "hw/timer/xlnx-zynqmp-rtc.h"
51
+
156
+
52
+/* Bits in TCSRx */
157
+#ifndef XLNX_ZYNQMP_RTC_ERR_DEBUG
53
+#define CEN BIT(30)
158
+#define XLNX_ZYNQMP_RTC_ERR_DEBUG 0
54
+#define IE BIT(29)
159
+#endif
55
+#define MODE_ONESHOT (0 << 27)
160
+
56
+#define MODE_PERIODIC (1 << 27)
161
+static void rtc_int_update_irq(XlnxZynqMPRTC *s)
57
+#define CRST BIT(26)
162
+{
58
+#define CACT BIT(25)
163
+ bool pending = s->regs[R_RTC_INT_STATUS] & ~s->regs[R_RTC_INT_MASK];
59
+#define PRESCALE(x) (x)
164
+ qemu_set_irq(s->irq_rtc_int, pending);
60
+
165
+}
61
+/* Registers shared between all timers in a module. */
166
+
62
+#define TISR 0x18
167
+static void addr_error_int_update_irq(XlnxZynqMPRTC *s)
63
+#define WTCR 0x1c
168
+{
64
+# define WTCLK(x) ((x) << 10)
169
+ bool pending = s->regs[R_ADDR_ERROR] & ~s->regs[R_ADDR_ERROR_INT_MASK];
65
+
170
+ qemu_set_irq(s->irq_addr_error_int, pending);
66
+/* Power-on default; used to re-initialize timers before each test. */
171
+}
67
+#define TCSR_DEFAULT PRESCALE(5)
172
+
68
+
173
+static void rtc_int_status_postw(RegisterInfo *reg, uint64_t val64)
69
+/* Register offsets for a timer within a timer block. */
174
+{
70
+typedef struct Timer {
175
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
71
+ unsigned int tcsr_offset;
176
+ rtc_int_update_irq(s);
72
+ unsigned int ticr_offset;
177
+}
73
+ unsigned int tdr_offset;
178
+
74
+} Timer;
179
+static uint64_t rtc_int_en_prew(RegisterInfo *reg, uint64_t val64)
75
+
180
+{
76
+/* A timer block containing 5 timers. */
181
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
77
+typedef struct TimerBlock {
182
+
78
+ int irq_base;
183
+ s->regs[R_RTC_INT_MASK] &= (uint32_t) ~val64;
79
+ uint64_t base_addr;
184
+ rtc_int_update_irq(s);
80
+} TimerBlock;
185
+ return 0;
81
+
186
+}
82
+/* Testdata for testing a particular timer within a timer block. */
187
+
83
+typedef struct TestData {
188
+static uint64_t rtc_int_dis_prew(RegisterInfo *reg, uint64_t val64)
84
+ const TimerBlock *tim;
189
+{
85
+ const Timer *timer;
190
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
86
+} TestData;
191
+
87
+
192
+ s->regs[R_RTC_INT_MASK] |= (uint32_t) val64;
88
+const TimerBlock timer_block[] = {
193
+ rtc_int_update_irq(s);
89
+ {
194
+ return 0;
90
+ .irq_base = 32,
195
+}
91
+ .base_addr = 0xf0008000,
196
+
92
+ },
197
+static void addr_error_postw(RegisterInfo *reg, uint64_t val64)
93
+ {
198
+{
94
+ .irq_base = 37,
199
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
95
+ .base_addr = 0xf0009000,
200
+ addr_error_int_update_irq(s);
96
+ },
201
+}
97
+ {
202
+
98
+ .irq_base = 42,
203
+static uint64_t addr_error_int_en_prew(RegisterInfo *reg, uint64_t val64)
99
+ .base_addr = 0xf000a000,
204
+{
205
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
206
+
207
+ s->regs[R_ADDR_ERROR_INT_MASK] &= (uint32_t) ~val64;
208
+ addr_error_int_update_irq(s);
209
+ return 0;
210
+}
211
+
212
+static uint64_t addr_error_int_dis_prew(RegisterInfo *reg, uint64_t val64)
213
+{
214
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
215
+
216
+ s->regs[R_ADDR_ERROR_INT_MASK] |= (uint32_t) val64;
217
+ addr_error_int_update_irq(s);
218
+ return 0;
219
+}
220
+
221
+static const RegisterAccessInfo rtc_regs_info[] = {
222
+ { .name = "SET_TIME_WRITE", .addr = A_SET_TIME_WRITE,
223
+ },{ .name = "SET_TIME_READ", .addr = A_SET_TIME_READ,
224
+ .ro = 0xffffffff,
225
+ },{ .name = "CALIB_WRITE", .addr = A_CALIB_WRITE,
226
+ },{ .name = "CALIB_READ", .addr = A_CALIB_READ,
227
+ .ro = 0x1fffff,
228
+ },{ .name = "CURRENT_TIME", .addr = A_CURRENT_TIME,
229
+ .ro = 0xffffffff,
230
+ },{ .name = "CURRENT_TICK", .addr = A_CURRENT_TICK,
231
+ .ro = 0xffff,
232
+ },{ .name = "ALARM", .addr = A_ALARM,
233
+ },{ .name = "RTC_INT_STATUS", .addr = A_RTC_INT_STATUS,
234
+ .w1c = 0x3,
235
+ .post_write = rtc_int_status_postw,
236
+ },{ .name = "RTC_INT_MASK", .addr = A_RTC_INT_MASK,
237
+ .reset = 0x3,
238
+ .ro = 0x3,
239
+ },{ .name = "RTC_INT_EN", .addr = A_RTC_INT_EN,
240
+ .pre_write = rtc_int_en_prew,
241
+ },{ .name = "RTC_INT_DIS", .addr = A_RTC_INT_DIS,
242
+ .pre_write = rtc_int_dis_prew,
243
+ },{ .name = "ADDR_ERROR", .addr = A_ADDR_ERROR,
244
+ .w1c = 0x1,
245
+ .post_write = addr_error_postw,
246
+ },{ .name = "ADDR_ERROR_INT_MASK", .addr = A_ADDR_ERROR_INT_MASK,
247
+ .reset = 0x1,
248
+ .ro = 0x1,
249
+ },{ .name = "ADDR_ERROR_INT_EN", .addr = A_ADDR_ERROR_INT_EN,
250
+ .pre_write = addr_error_int_en_prew,
251
+ },{ .name = "ADDR_ERROR_INT_DIS", .addr = A_ADDR_ERROR_INT_DIS,
252
+ .pre_write = addr_error_int_dis_prew,
253
+ },{ .name = "CONTROL", .addr = A_CONTROL,
254
+ .reset = 0x1000000,
255
+ .rsvd = 0x70fffffe,
256
+ },{ .name = "SAFETY_CHK", .addr = A_SAFETY_CHK,
257
+ }
258
+};
259
+
260
+static void rtc_reset(DeviceState *dev)
261
+{
262
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(dev);
263
+ unsigned int i;
264
+
265
+ for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
266
+ register_reset(&s->regs_info[i]);
267
+ }
268
+
269
+ rtc_int_update_irq(s);
270
+ addr_error_int_update_irq(s);
271
+}
272
+
273
+static const MemoryRegionOps rtc_ops = {
274
+ .read = register_read_memory,
275
+ .write = register_write_memory,
276
+ .endianness = DEVICE_LITTLE_ENDIAN,
277
+ .valid = {
278
+ .min_access_size = 4,
279
+ .max_access_size = 4,
280
+ },
100
+ },
281
+};
101
+};
282
+
102
+
283
+static void rtc_init(Object *obj)
103
+const Timer timer[] = {
284
+{
104
+ {
285
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(obj);
105
+ .tcsr_offset = 0x00,
286
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
106
+ .ticr_offset = 0x08,
287
+ RegisterInfoArray *reg_array;
107
+ .tdr_offset = 0x10,
288
+
108
+ }, {
289
+ memory_region_init(&s->iomem, obj, TYPE_XLNX_ZYNQMP_RTC,
109
+ .tcsr_offset = 0x04,
290
+ XLNX_ZYNQMP_RTC_R_MAX * 4);
110
+ .ticr_offset = 0x0c,
291
+ reg_array =
111
+ .tdr_offset = 0x14,
292
+ register_init_block32(DEVICE(obj), rtc_regs_info,
112
+ }, {
293
+ ARRAY_SIZE(rtc_regs_info),
113
+ .tcsr_offset = 0x20,
294
+ s->regs_info, s->regs,
114
+ .ticr_offset = 0x28,
295
+ &rtc_ops,
115
+ .tdr_offset = 0x30,
296
+ XLNX_ZYNQMP_RTC_ERR_DEBUG,
116
+ }, {
297
+ XLNX_ZYNQMP_RTC_R_MAX * 4);
117
+ .tcsr_offset = 0x24,
298
+ memory_region_add_subregion(&s->iomem,
118
+ .ticr_offset = 0x2c,
299
+ 0x0,
119
+ .tdr_offset = 0x34,
300
+ &reg_array->mem);
120
+ }, {
301
+ sysbus_init_mmio(sbd, &s->iomem);
121
+ .tcsr_offset = 0x40,
302
+ sysbus_init_irq(sbd, &s->irq_rtc_int);
122
+ .ticr_offset = 0x48,
303
+ sysbus_init_irq(sbd, &s->irq_addr_error_int);
123
+ .tdr_offset = 0x50,
304
+}
124
+ },
305
+
125
+};
306
+static const VMStateDescription vmstate_rtc = {
126
+
307
+ .name = TYPE_XLNX_ZYNQMP_RTC,
127
+/* Returns the index of the timer block. */
308
+ .version_id = 1,
128
+static int tim_index(const TimerBlock *tim)
309
+ .minimum_version_id = 1,
129
+{
310
+ .fields = (VMStateField[]) {
130
+ ptrdiff_t diff = tim - timer_block;
311
+ VMSTATE_UINT32_ARRAY(regs, XlnxZynqMPRTC, XLNX_ZYNQMP_RTC_R_MAX),
131
+
312
+ VMSTATE_END_OF_LIST(),
132
+ g_assert(diff >= 0 && diff < ARRAY_SIZE(timer_block));
133
+
134
+ return diff;
135
+}
136
+
137
+/* Returns the index of a timer within a timer block. */
138
+static int timer_index(const Timer *t)
139
+{
140
+ ptrdiff_t diff = t - timer;
141
+
142
+ g_assert(diff >= 0 && diff < ARRAY_SIZE(timer));
143
+
144
+ return diff;
145
+}
146
+
147
+/* Returns the irq line for a given timer. */
148
+static int tim_timer_irq(const TestData *td)
149
+{
150
+ return td->tim->irq_base + timer_index(td->timer);
151
+}
152
+
153
+/* Register read/write accessors. */
154
+
155
+static void tim_write(const TestData *td,
156
+ unsigned int offset, uint32_t value)
157
+{
158
+ writel(td->tim->base_addr + offset, value);
159
+}
160
+
161
+static uint32_t tim_read(const TestData *td, unsigned int offset)
162
+{
163
+ return readl(td->tim->base_addr + offset);
164
+}
165
+
166
+static void tim_write_tcsr(const TestData *td, uint32_t value)
167
+{
168
+ tim_write(td, td->timer->tcsr_offset, value);
169
+}
170
+
171
+static uint32_t tim_read_tcsr(const TestData *td)
172
+{
173
+ return tim_read(td, td->timer->tcsr_offset);
174
+}
175
+
176
+static void tim_write_ticr(const TestData *td, uint32_t value)
177
+{
178
+ tim_write(td, td->timer->ticr_offset, value);
179
+}
180
+
181
+static uint32_t tim_read_ticr(const TestData *td)
182
+{
183
+ return tim_read(td, td->timer->ticr_offset);
184
+}
185
+
186
+static uint32_t tim_read_tdr(const TestData *td)
187
+{
188
+ return tim_read(td, td->timer->tdr_offset);
189
+}
190
+
191
+/* Returns the number of nanoseconds to count the given number of cycles. */
192
+static int64_t tim_calculate_step(uint32_t count, uint32_t prescale)
193
+{
194
+ return (1000000000LL / TIM_REF_HZ) * count * (prescale + 1);
195
+}
196
+
197
+/* Returns a bitmask corresponding to the timer under test. */
198
+static uint32_t tim_timer_bit(const TestData *td)
199
+{
200
+ return BIT(timer_index(td->timer));
201
+}
202
+
203
+/* Resets all timers to power-on defaults. */
204
+static void tim_reset(const TestData *td)
205
+{
206
+ int i, j;
207
+
208
+ /* Reset all the timers, in case a previous test left a timer running. */
209
+ for (i = 0; i < ARRAY_SIZE(timer_block); i++) {
210
+ for (j = 0; j < ARRAY_SIZE(timer); j++) {
211
+ writel(timer_block[i].base_addr + timer[j].tcsr_offset,
212
+ CRST | TCSR_DEFAULT);
213
+ }
214
+ writel(timer_block[i].base_addr + TISR, -1);
313
+ }
215
+ }
314
+};
216
+}
315
+
217
+
316
+static void rtc_class_init(ObjectClass *klass, void *data)
218
+/* Verifies the reset state of a timer. */
317
+{
219
+static void test_reset(gconstpointer test_data)
318
+ DeviceClass *dc = DEVICE_CLASS(klass);
220
+{
319
+
221
+ const TestData *td = test_data;
320
+ dc->reset = rtc_reset;
222
+
321
+ dc->vmsd = &vmstate_rtc;
223
+ tim_reset(td);
322
+}
224
+
323
+
225
+ g_assert_cmphex(tim_read_tcsr(td), ==, TCSR_DEFAULT);
324
+static const TypeInfo rtc_info = {
226
+ g_assert_cmphex(tim_read_ticr(td), ==, 0);
325
+ .name = TYPE_XLNX_ZYNQMP_RTC,
227
+ g_assert_cmphex(tim_read_tdr(td), ==, 0);
326
+ .parent = TYPE_SYS_BUS_DEVICE,
228
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
327
+ .instance_size = sizeof(XlnxZynqMPRTC),
229
+ g_assert_cmphex(tim_read(td, WTCR), ==, WTCLK(1));
328
+ .class_init = rtc_class_init,
230
+}
329
+ .instance_init = rtc_init,
231
+
330
+};
232
+/* Verifies that CRST wins if both CEN and CRST are set. */
331
+
233
+static void test_reset_overrides_enable(gconstpointer test_data)
332
+static void rtc_register_types(void)
234
+{
333
+{
235
+ const TestData *td = test_data;
334
+ type_register_static(&rtc_info);
236
+
335
+}
237
+ tim_reset(td);
336
+
238
+
337
+type_init(rtc_register_types)
239
+ /* CRST should force CEN to 0 */
240
+ tim_write_tcsr(td, CEN | CRST | TCSR_DEFAULT);
241
+
242
+ g_assert_cmphex(tim_read_tcsr(td), ==, TCSR_DEFAULT);
243
+ g_assert_cmphex(tim_read_tdr(td), ==, 0);
244
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
245
+}
246
+
247
+/* Verifies the behavior when CEN is set and then cleared. */
248
+static void test_oneshot_enable_then_disable(gconstpointer test_data)
249
+{
250
+ const TestData *td = test_data;
251
+
252
+ tim_reset(td);
253
+
254
+ /* Enable the timer with zero initial count, then disable it again. */
255
+ tim_write_tcsr(td, CEN | TCSR_DEFAULT);
256
+ tim_write_tcsr(td, TCSR_DEFAULT);
257
+
258
+ g_assert_cmphex(tim_read_tcsr(td), ==, TCSR_DEFAULT);
259
+ g_assert_cmphex(tim_read_tdr(td), ==, 0);
260
+ /* Timer interrupt flag should be set, but interrupts are not enabled. */
261
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
262
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
263
+}
264
+
265
+/* Verifies that a one-shot timer fires when expected with prescaler 5. */
266
+static void test_oneshot_ps5(gconstpointer test_data)
267
+{
268
+ const TestData *td = test_data;
269
+ unsigned int count = 256;
270
+ unsigned int ps = 5;
271
+
272
+ tim_reset(td);
273
+
274
+ tim_write_ticr(td, count);
275
+ tim_write_tcsr(td, CEN | PRESCALE(ps));
276
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
277
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
278
+
279
+ clock_step(tim_calculate_step(count, ps) - 1);
280
+
281
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
282
+ g_assert_cmpuint(tim_read_tdr(td), <, count);
283
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
284
+
285
+ clock_step(1);
286
+
287
+ g_assert_cmphex(tim_read_tcsr(td), ==, PRESCALE(ps));
288
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
289
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
290
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
291
+
292
+ /* Clear the interrupt flag. */
293
+ tim_write(td, TISR, tim_timer_bit(td));
294
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
295
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
296
+
297
+ /* Verify that this isn't a periodic timer. */
298
+ clock_step(2 * tim_calculate_step(count, ps));
299
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
300
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
301
+}
302
+
303
+/* Verifies that a one-shot timer fires when expected with prescaler 0. */
304
+static void test_oneshot_ps0(gconstpointer test_data)
305
+{
306
+ const TestData *td = test_data;
307
+ unsigned int count = 1;
308
+ unsigned int ps = 0;
309
+
310
+ tim_reset(td);
311
+
312
+ tim_write_ticr(td, count);
313
+ tim_write_tcsr(td, CEN | PRESCALE(ps));
314
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
315
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
316
+
317
+ clock_step(tim_calculate_step(count, ps) - 1);
318
+
319
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
320
+ g_assert_cmpuint(tim_read_tdr(td), <, count);
321
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
322
+
323
+ clock_step(1);
324
+
325
+ g_assert_cmphex(tim_read_tcsr(td), ==, PRESCALE(ps));
326
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
327
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
328
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
329
+}
330
+
331
+/* Verifies that a one-shot timer fires when expected with highest prescaler. */
332
+static void test_oneshot_ps255(gconstpointer test_data)
333
+{
334
+ const TestData *td = test_data;
335
+ unsigned int count = (1U << 24) - 1;
336
+ unsigned int ps = 255;
337
+
338
+ tim_reset(td);
339
+
340
+ tim_write_ticr(td, count);
341
+ tim_write_tcsr(td, CEN | PRESCALE(ps));
342
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
343
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
344
+
345
+ clock_step(tim_calculate_step(count, ps) - 1);
346
+
347
+ g_assert_cmphex(tim_read_tcsr(td), ==, CEN | CACT | PRESCALE(ps));
348
+ g_assert_cmpuint(tim_read_tdr(td), <, count);
349
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
350
+
351
+ clock_step(1);
352
+
353
+ g_assert_cmphex(tim_read_tcsr(td), ==, PRESCALE(ps));
354
+ g_assert_cmpuint(tim_read_tdr(td), ==, count);
355
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
356
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
357
+}
358
+
359
+/* Verifies that a oneshot timer fires an interrupt when expected. */
360
+static void test_oneshot_interrupt(gconstpointer test_data)
361
+{
362
+ const TestData *td = test_data;
363
+ unsigned int count = 256;
364
+ unsigned int ps = 7;
365
+
366
+ tim_reset(td);
367
+
368
+ tim_write_ticr(td, count);
369
+ tim_write_tcsr(td, IE | CEN | MODE_ONESHOT | PRESCALE(ps));
370
+
371
+ clock_step_next();
372
+
373
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
374
+ g_assert_true(qtest_get_irq(global_qtest, tim_timer_irq(td)));
375
+}
376
+
377
+/*
378
+ * Verifies that the timer can be paused and later resumed, and it still fires
379
+ * at the right moment.
380
+ */
381
+static void test_pause_resume(gconstpointer test_data)
382
+{
383
+ const TestData *td = test_data;
384
+ unsigned int count = 256;
385
+ unsigned int ps = 1;
386
+
387
+ tim_reset(td);
388
+
389
+ tim_write_ticr(td, count);
390
+ tim_write_tcsr(td, IE | CEN | MODE_ONESHOT | PRESCALE(ps));
391
+
392
+ /* Pause the timer halfway to expiration. */
393
+ clock_step(tim_calculate_step(count / 2, ps));
394
+ tim_write_tcsr(td, IE | MODE_ONESHOT | PRESCALE(ps));
395
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 2);
396
+
397
+ /* Counter should not advance during the following step. */
398
+ clock_step(2 * tim_calculate_step(count, ps));
399
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 2);
400
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
401
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
402
+
403
+ /* Resume the timer and run _almost_ to expiration. */
404
+ tim_write_tcsr(td, IE | CEN | MODE_ONESHOT | PRESCALE(ps));
405
+ clock_step(tim_calculate_step(count / 2, ps) - 1);
406
+ g_assert_cmpuint(tim_read_tdr(td), <, count);
407
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
408
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
409
+
410
+ /* Now, run the rest of the way and verify that the interrupt fires. */
411
+ clock_step(1);
412
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
413
+ g_assert_true(qtest_get_irq(global_qtest, tim_timer_irq(td)));
414
+}
415
+
416
+/* Verifies that the prescaler can be changed while the timer is runnin. */
417
+static void test_prescaler_change(gconstpointer test_data)
418
+{
419
+ const TestData *td = test_data;
420
+ unsigned int count = 256;
421
+ unsigned int ps = 5;
422
+
423
+ tim_reset(td);
424
+
425
+ tim_write_ticr(td, count);
426
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
427
+
428
+ /* Run a quarter of the way, and change the prescaler. */
429
+ clock_step(tim_calculate_step(count / 4, ps));
430
+ g_assert_cmpuint(tim_read_tdr(td), ==, 3 * count / 4);
431
+ ps = 2;
432
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
433
+ /* The counter must not change. */
434
+ g_assert_cmpuint(tim_read_tdr(td), ==, 3 * count / 4);
435
+
436
+ /* Run another quarter of the way, and change the prescaler again. */
437
+ clock_step(tim_calculate_step(count / 4, ps));
438
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 2);
439
+ ps = 8;
440
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
441
+ /* The counter must not change. */
442
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 2);
443
+
444
+ /* Run another quarter of the way, and change the prescaler again. */
445
+ clock_step(tim_calculate_step(count / 4, ps));
446
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 4);
447
+ ps = 0;
448
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
449
+ /* The counter must not change. */
450
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 4);
451
+
452
+ /* Run almost to expiration, and verify the timer didn't fire yet. */
453
+ clock_step(tim_calculate_step(count / 4, ps) - 1);
454
+ g_assert_cmpuint(tim_read_tdr(td), <, count);
455
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
456
+
457
+ /* Now, run the rest of the way and verify that the timer fires. */
458
+ clock_step(1);
459
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
460
+}
461
+
462
+/* Verifies that a periodic timer automatically restarts after expiration. */
463
+static void test_periodic_no_interrupt(gconstpointer test_data)
464
+{
465
+ const TestData *td = test_data;
466
+ unsigned int count = 2;
467
+ unsigned int ps = 3;
468
+ int i;
469
+
470
+ tim_reset(td);
471
+
472
+ tim_write_ticr(td, count);
473
+ tim_write_tcsr(td, CEN | MODE_PERIODIC | PRESCALE(ps));
474
+
475
+ for (i = 0; i < 4; i++) {
476
+ clock_step_next();
477
+
478
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
479
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
480
+
481
+ tim_write(td, TISR, tim_timer_bit(td));
482
+
483
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
484
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
485
+ }
486
+}
487
+
488
+/* Verifies that a periodict timer fires an interrupt every time it expires. */
489
+static void test_periodic_interrupt(gconstpointer test_data)
490
+{
491
+ const TestData *td = test_data;
492
+ unsigned int count = 65535;
493
+ unsigned int ps = 2;
494
+ int i;
495
+
496
+ tim_reset(td);
497
+
498
+ tim_write_ticr(td, count);
499
+ tim_write_tcsr(td, CEN | IE | MODE_PERIODIC | PRESCALE(ps));
500
+
501
+ for (i = 0; i < 4; i++) {
502
+ clock_step_next();
503
+
504
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
505
+ g_assert_true(qtest_get_irq(global_qtest, tim_timer_irq(td)));
506
+
507
+ tim_write(td, TISR, tim_timer_bit(td));
508
+
509
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
510
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
511
+ }
512
+}
513
+
514
+/*
515
+ * Verifies that the timer behaves correctly when disabled right before and
516
+ * exactly when it's supposed to expire.
517
+ */
518
+static void test_disable_on_expiration(gconstpointer test_data)
519
+{
520
+ const TestData *td = test_data;
521
+ unsigned int count = 8;
522
+ unsigned int ps = 255;
523
+
524
+ tim_reset(td);
525
+
526
+ tim_write_ticr(td, count);
527
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
528
+
529
+ clock_step(tim_calculate_step(count, ps) - 1);
530
+
531
+ tim_write_tcsr(td, MODE_ONESHOT | PRESCALE(ps));
532
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
533
+ clock_step(1);
534
+ tim_write_tcsr(td, MODE_ONESHOT | PRESCALE(ps));
535
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
536
+}
537
+
538
+/*
539
+ * Constructs a name that includes the timer block, timer and testcase name,
540
+ * and adds the test to the test suite.
541
+ */
542
+static void tim_add_test(const char *name, const TestData *td, GTestDataFunc fn)
543
+{
544
+ g_autofree char *full_name;
545
+
546
+ full_name = g_strdup_printf("npcm7xx_timer/tim[%d]/timer[%d]/%s",
547
+ tim_index(td->tim), timer_index(td->timer),
548
+ name);
549
+ qtest_add_data_func(full_name, td, fn);
550
+}
551
+
552
+/* Convenience macro for adding a test with a predictable function name. */
553
+#define add_test(name, td) tim_add_test(#name, td, test_##name)
554
+
555
+int main(int argc, char **argv)
556
+{
557
+ TestData testdata[ARRAY_SIZE(timer_block) * ARRAY_SIZE(timer)];
558
+ int ret;
559
+ int i, j;
560
+
561
+ g_test_init(&argc, &argv, NULL);
562
+ g_test_set_nonfatal_assertions();
563
+
564
+ for (i = 0; i < ARRAY_SIZE(timer_block); i++) {
565
+ for (j = 0; j < ARRAY_SIZE(timer); j++) {
566
+ TestData *td = &testdata[i * ARRAY_SIZE(timer) + j];
567
+ td->tim = &timer_block[i];
568
+ td->timer = &timer[j];
569
+
570
+ add_test(reset, td);
571
+ add_test(reset_overrides_enable, td);
572
+ add_test(oneshot_enable_then_disable, td);
573
+ add_test(oneshot_ps5, td);
574
+ add_test(oneshot_ps0, td);
575
+ add_test(oneshot_ps255, td);
576
+ add_test(oneshot_interrupt, td);
577
+ add_test(pause_resume, td);
578
+ add_test(prescaler_change, td);
579
+ add_test(periodic_no_interrupt, td);
580
+ add_test(periodic_interrupt, td);
581
+ add_test(disable_on_expiration, td);
582
+ }
583
+ }
584
+
585
+ qtest_start("-machine npcm750-evb");
586
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/a9mpcore/gic");
587
+ ret = g_test_run();
588
+ qtest_end();
589
+
590
+ return ret;
591
+}
592
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
593
index XXXXXXX..XXXXXXX 100644
594
--- a/tests/qtest/meson.build
595
+++ b/tests/qtest/meson.build
596
@@ -XXX,XX +XXX,XX @@ qtests_arm = \
597
['arm-cpu-features',
598
'microbit-test',
599
'm25p80-test',
600
+ 'npcm7xx_timer-test',
601
'test-arm-mptimer',
602
'boot-serial-test',
603
'hexloader-test']
338
--
604
--
339
2.16.2
605
2.20.1
340
606
341
607
diff view generated by jsdifflib
1
The Arm IoT Kit includes a "security controller" which is largely a
1
From: Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com>
2
collection of registers for controlling the PPCs and other bits of
3
glue in the system. This commit provides the initial skeleton of the
4
device, implementing just the ID registers, and a couple of read-only
5
read-as-zero registers.
6
2
3
Current documentation is not too clear on the GETPC usage.
4
In particular, when used outside the top level helper function
5
it causes unexpected behavior.
6
7
Signed-off-by: Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com>
8
Message-id: 20201015095147.1691-1-e.emanuelegiuseppe@gmail.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20180220180325.29818-16-peter.maydell@linaro.org
10
---
11
---
11
hw/misc/Makefile.objs | 1 +
12
docs/devel/loads-stores.rst | 8 +++++++-
12
include/hw/misc/iotkit-secctl.h | 39 ++++
13
1 file changed, 7 insertions(+), 1 deletion(-)
13
hw/misc/iotkit-secctl.c | 448 ++++++++++++++++++++++++++++++++++++++++
14
default-configs/arm-softmmu.mak | 1 +
15
hw/misc/trace-events | 7 +
16
5 files changed, 496 insertions(+)
17
create mode 100644 include/hw/misc/iotkit-secctl.h
18
create mode 100644 hw/misc/iotkit-secctl.c
19
14
20
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
15
diff --git a/docs/devel/loads-stores.rst b/docs/devel/loads-stores.rst
21
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/misc/Makefile.objs
17
--- a/docs/devel/loads-stores.rst
23
+++ b/hw/misc/Makefile.objs
18
+++ b/docs/devel/loads-stores.rst
24
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_MPS2_FPGAIO) += mps2-fpgaio.o
19
@@ -XXX,XX +XXX,XX @@ guest CPU state in case of a guest CPU exception. This is passed
25
obj-$(CONFIG_MPS2_SCC) += mps2-scc.o
20
to ``cpu_restore_state()``. Therefore the value should either be 0,
26
21
to indicate that the guest CPU state is already synchronized, or
27
obj-$(CONFIG_TZ_PPC) += tz-ppc.o
22
the result of ``GETPC()`` from the top level ``HELPER(foo)``
28
+obj-$(CONFIG_IOTKIT_SECCTL) += iotkit-secctl.o
23
-function, which is a return address into the generated code.
29
24
+function, which is a return address into the generated code [#gpc]_.
30
obj-$(CONFIG_PVPANIC) += pvpanic.o
31
obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
32
diff --git a/include/hw/misc/iotkit-secctl.h b/include/hw/misc/iotkit-secctl.h
33
new file mode 100644
34
index XXXXXXX..XXXXXXX
35
--- /dev/null
36
+++ b/include/hw/misc/iotkit-secctl.h
37
@@ -XXX,XX +XXX,XX @@
38
+/*
39
+ * ARM IoT Kit security controller
40
+ *
41
+ * Copyright (c) 2018 Linaro Limited
42
+ * Written by Peter Maydell
43
+ *
44
+ * This program is free software; you can redistribute it and/or modify
45
+ * it under the terms of the GNU General Public License version 2 or
46
+ * (at your option) any later version.
47
+ */
48
+
25
+
49
+/* This is a model of the security controller which is part of the
26
+.. [#gpc] Note that ``GETPC()`` should be used with great care: calling
50
+ * Arm IoT Kit and documented in
27
+ it in other functions that are *not* the top level
51
+ * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
28
+ ``HELPER(foo)`` will cause unexpected behavior. Instead, the
52
+ *
29
+ value of ``GETPC()`` should be read from the helper and passed
53
+ * QEMU interface:
30
+ if needed to the functions that the helper calls.
54
+ * + sysbus MMIO region 0 is the "secure privilege control block" registers
31
55
+ * + sysbus MMIO region 1 is the "non-secure privilege control block" registers
32
Function names follow the pattern:
56
+ */
33
57
+
58
+#ifndef IOTKIT_SECCTL_H
59
+#define IOTKIT_SECCTL_H
60
+
61
+#include "hw/sysbus.h"
62
+
63
+#define TYPE_IOTKIT_SECCTL "iotkit-secctl"
64
+#define IOTKIT_SECCTL(obj) OBJECT_CHECK(IoTKitSecCtl, (obj), TYPE_IOTKIT_SECCTL)
65
+
66
+typedef struct IoTKitSecCtl {
67
+ /*< private >*/
68
+ SysBusDevice parent_obj;
69
+
70
+ /*< public >*/
71
+
72
+ MemoryRegion s_regs;
73
+ MemoryRegion ns_regs;
74
+} IoTKitSecCtl;
75
+
76
+#endif
77
diff --git a/hw/misc/iotkit-secctl.c b/hw/misc/iotkit-secctl.c
78
new file mode 100644
79
index XXXXXXX..XXXXXXX
80
--- /dev/null
81
+++ b/hw/misc/iotkit-secctl.c
82
@@ -XXX,XX +XXX,XX @@
83
+/*
84
+ * Arm IoT Kit security controller
85
+ *
86
+ * Copyright (c) 2018 Linaro Limited
87
+ * Written by Peter Maydell
88
+ *
89
+ * This program is free software; you can redistribute it and/or modify
90
+ * it under the terms of the GNU General Public License version 2 or
91
+ * (at your option) any later version.
92
+ */
93
+
94
+#include "qemu/osdep.h"
95
+#include "qemu/log.h"
96
+#include "qapi/error.h"
97
+#include "trace.h"
98
+#include "hw/sysbus.h"
99
+#include "hw/registerfields.h"
100
+#include "hw/misc/iotkit-secctl.h"
101
+
102
+/* Registers in the secure privilege control block */
103
+REG32(SECRESPCFG, 0x10)
104
+REG32(NSCCFG, 0x14)
105
+REG32(SECMPCINTSTATUS, 0x1c)
106
+REG32(SECPPCINTSTAT, 0x20)
107
+REG32(SECPPCINTCLR, 0x24)
108
+REG32(SECPPCINTEN, 0x28)
109
+REG32(SECMSCINTSTAT, 0x30)
110
+REG32(SECMSCINTCLR, 0x34)
111
+REG32(SECMSCINTEN, 0x38)
112
+REG32(BRGINTSTAT, 0x40)
113
+REG32(BRGINTCLR, 0x44)
114
+REG32(BRGINTEN, 0x48)
115
+REG32(AHBNSPPC0, 0x50)
116
+REG32(AHBNSPPCEXP0, 0x60)
117
+REG32(AHBNSPPCEXP1, 0x64)
118
+REG32(AHBNSPPCEXP2, 0x68)
119
+REG32(AHBNSPPCEXP3, 0x6c)
120
+REG32(APBNSPPC0, 0x70)
121
+REG32(APBNSPPC1, 0x74)
122
+REG32(APBNSPPCEXP0, 0x80)
123
+REG32(APBNSPPCEXP1, 0x84)
124
+REG32(APBNSPPCEXP2, 0x88)
125
+REG32(APBNSPPCEXP3, 0x8c)
126
+REG32(AHBSPPPC0, 0x90)
127
+REG32(AHBSPPPCEXP0, 0xa0)
128
+REG32(AHBSPPPCEXP1, 0xa4)
129
+REG32(AHBSPPPCEXP2, 0xa8)
130
+REG32(AHBSPPPCEXP3, 0xac)
131
+REG32(APBSPPPC0, 0xb0)
132
+REG32(APBSPPPC1, 0xb4)
133
+REG32(APBSPPPCEXP0, 0xc0)
134
+REG32(APBSPPPCEXP1, 0xc4)
135
+REG32(APBSPPPCEXP2, 0xc8)
136
+REG32(APBSPPPCEXP3, 0xcc)
137
+REG32(NSMSCEXP, 0xd0)
138
+REG32(PID4, 0xfd0)
139
+REG32(PID5, 0xfd4)
140
+REG32(PID6, 0xfd8)
141
+REG32(PID7, 0xfdc)
142
+REG32(PID0, 0xfe0)
143
+REG32(PID1, 0xfe4)
144
+REG32(PID2, 0xfe8)
145
+REG32(PID3, 0xfec)
146
+REG32(CID0, 0xff0)
147
+REG32(CID1, 0xff4)
148
+REG32(CID2, 0xff8)
149
+REG32(CID3, 0xffc)
150
+
151
+/* Registers in the non-secure privilege control block */
152
+REG32(AHBNSPPPC0, 0x90)
153
+REG32(AHBNSPPPCEXP0, 0xa0)
154
+REG32(AHBNSPPPCEXP1, 0xa4)
155
+REG32(AHBNSPPPCEXP2, 0xa8)
156
+REG32(AHBNSPPPCEXP3, 0xac)
157
+REG32(APBNSPPPC0, 0xb0)
158
+REG32(APBNSPPPC1, 0xb4)
159
+REG32(APBNSPPPCEXP0, 0xc0)
160
+REG32(APBNSPPPCEXP1, 0xc4)
161
+REG32(APBNSPPPCEXP2, 0xc8)
162
+REG32(APBNSPPPCEXP3, 0xcc)
163
+/* PID and CID registers are also present in the NS block */
164
+
165
+static const uint8_t iotkit_secctl_s_idregs[] = {
166
+ 0x04, 0x00, 0x00, 0x00,
167
+ 0x52, 0xb8, 0x0b, 0x00,
168
+ 0x0d, 0xf0, 0x05, 0xb1,
169
+};
170
+
171
+static const uint8_t iotkit_secctl_ns_idregs[] = {
172
+ 0x04, 0x00, 0x00, 0x00,
173
+ 0x53, 0xb8, 0x0b, 0x00,
174
+ 0x0d, 0xf0, 0x05, 0xb1,
175
+};
176
+
177
+static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
178
+ uint64_t *pdata,
179
+ unsigned size, MemTxAttrs attrs)
180
+{
181
+ uint64_t r;
182
+ uint32_t offset = addr & ~0x3;
183
+
184
+ switch (offset) {
185
+ case A_AHBNSPPC0:
186
+ case A_AHBSPPPC0:
187
+ r = 0;
188
+ break;
189
+ case A_SECRESPCFG:
190
+ case A_NSCCFG:
191
+ case A_SECMPCINTSTATUS:
192
+ case A_SECPPCINTSTAT:
193
+ case A_SECPPCINTEN:
194
+ case A_SECMSCINTSTAT:
195
+ case A_SECMSCINTEN:
196
+ case A_BRGINTSTAT:
197
+ case A_BRGINTEN:
198
+ case A_AHBNSPPCEXP0:
199
+ case A_AHBNSPPCEXP1:
200
+ case A_AHBNSPPCEXP2:
201
+ case A_AHBNSPPCEXP3:
202
+ case A_APBNSPPC0:
203
+ case A_APBNSPPC1:
204
+ case A_APBNSPPCEXP0:
205
+ case A_APBNSPPCEXP1:
206
+ case A_APBNSPPCEXP2:
207
+ case A_APBNSPPCEXP3:
208
+ case A_AHBSPPPCEXP0:
209
+ case A_AHBSPPPCEXP1:
210
+ case A_AHBSPPPCEXP2:
211
+ case A_AHBSPPPCEXP3:
212
+ case A_APBSPPPC0:
213
+ case A_APBSPPPC1:
214
+ case A_APBSPPPCEXP0:
215
+ case A_APBSPPPCEXP1:
216
+ case A_APBSPPPCEXP2:
217
+ case A_APBSPPPCEXP3:
218
+ case A_NSMSCEXP:
219
+ qemu_log_mask(LOG_UNIMP,
220
+ "IoTKit SecCtl S block read: "
221
+ "unimplemented offset 0x%x\n", offset);
222
+ r = 0;
223
+ break;
224
+ case A_PID4:
225
+ case A_PID5:
226
+ case A_PID6:
227
+ case A_PID7:
228
+ case A_PID0:
229
+ case A_PID1:
230
+ case A_PID2:
231
+ case A_PID3:
232
+ case A_CID0:
233
+ case A_CID1:
234
+ case A_CID2:
235
+ case A_CID3:
236
+ r = iotkit_secctl_s_idregs[(offset - A_PID4) / 4];
237
+ break;
238
+ case A_SECPPCINTCLR:
239
+ case A_SECMSCINTCLR:
240
+ case A_BRGINTCLR:
241
+ qemu_log_mask(LOG_GUEST_ERROR,
242
+ "IotKit SecCtl S block read: write-only offset 0x%x\n",
243
+ offset);
244
+ r = 0;
245
+ break;
246
+ default:
247
+ qemu_log_mask(LOG_GUEST_ERROR,
248
+ "IotKit SecCtl S block read: bad offset 0x%x\n", offset);
249
+ r = 0;
250
+ break;
251
+ }
252
+
253
+ if (size != 4) {
254
+ /* None of our registers are access-sensitive, so just pull the right
255
+ * byte out of the word read result.
256
+ */
257
+ r = extract32(r, (addr & 3) * 8, size * 8);
258
+ }
259
+
260
+ trace_iotkit_secctl_s_read(offset, r, size);
261
+ *pdata = r;
262
+ return MEMTX_OK;
263
+}
264
+
265
+static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
266
+ uint64_t value,
267
+ unsigned size, MemTxAttrs attrs)
268
+{
269
+ uint32_t offset = addr;
270
+
271
+ trace_iotkit_secctl_s_write(offset, value, size);
272
+
273
+ if (size != 4) {
274
+ /* Byte and halfword writes are ignored */
275
+ qemu_log_mask(LOG_GUEST_ERROR,
276
+ "IotKit SecCtl S block write: bad size, ignored\n");
277
+ return MEMTX_OK;
278
+ }
279
+
280
+ switch (offset) {
281
+ case A_SECRESPCFG:
282
+ case A_NSCCFG:
283
+ case A_SECPPCINTCLR:
284
+ case A_SECPPCINTEN:
285
+ case A_SECMSCINTCLR:
286
+ case A_SECMSCINTEN:
287
+ case A_BRGINTCLR:
288
+ case A_BRGINTEN:
289
+ case A_AHBNSPPCEXP0:
290
+ case A_AHBNSPPCEXP1:
291
+ case A_AHBNSPPCEXP2:
292
+ case A_AHBNSPPCEXP3:
293
+ case A_APBNSPPC0:
294
+ case A_APBNSPPC1:
295
+ case A_APBNSPPCEXP0:
296
+ case A_APBNSPPCEXP1:
297
+ case A_APBNSPPCEXP2:
298
+ case A_APBNSPPCEXP3:
299
+ case A_AHBSPPPCEXP0:
300
+ case A_AHBSPPPCEXP1:
301
+ case A_AHBSPPPCEXP2:
302
+ case A_AHBSPPPCEXP3:
303
+ case A_APBSPPPC0:
304
+ case A_APBSPPPC1:
305
+ case A_APBSPPPCEXP0:
306
+ case A_APBSPPPCEXP1:
307
+ case A_APBSPPPCEXP2:
308
+ case A_APBSPPPCEXP3:
309
+ qemu_log_mask(LOG_UNIMP,
310
+ "IoTKit SecCtl S block write: "
311
+ "unimplemented offset 0x%x\n", offset);
312
+ break;
313
+ case A_SECMPCINTSTATUS:
314
+ case A_SECPPCINTSTAT:
315
+ case A_SECMSCINTSTAT:
316
+ case A_BRGINTSTAT:
317
+ case A_AHBNSPPC0:
318
+ case A_AHBSPPPC0:
319
+ case A_NSMSCEXP:
320
+ case A_PID4:
321
+ case A_PID5:
322
+ case A_PID6:
323
+ case A_PID7:
324
+ case A_PID0:
325
+ case A_PID1:
326
+ case A_PID2:
327
+ case A_PID3:
328
+ case A_CID0:
329
+ case A_CID1:
330
+ case A_CID2:
331
+ case A_CID3:
332
+ qemu_log_mask(LOG_GUEST_ERROR,
333
+ "IoTKit SecCtl S block write: "
334
+ "read-only offset 0x%x\n", offset);
335
+ break;
336
+ default:
337
+ qemu_log_mask(LOG_GUEST_ERROR,
338
+ "IotKit SecCtl S block write: bad offset 0x%x\n",
339
+ offset);
340
+ break;
341
+ }
342
+
343
+ return MEMTX_OK;
344
+}
345
+
346
+static MemTxResult iotkit_secctl_ns_read(void *opaque, hwaddr addr,
347
+ uint64_t *pdata,
348
+ unsigned size, MemTxAttrs attrs)
349
+{
350
+ uint64_t r;
351
+ uint32_t offset = addr & ~0x3;
352
+
353
+ switch (offset) {
354
+ case A_AHBNSPPPC0:
355
+ r = 0;
356
+ break;
357
+ case A_AHBNSPPPCEXP0:
358
+ case A_AHBNSPPPCEXP1:
359
+ case A_AHBNSPPPCEXP2:
360
+ case A_AHBNSPPPCEXP3:
361
+ case A_APBNSPPPC0:
362
+ case A_APBNSPPPC1:
363
+ case A_APBNSPPPCEXP0:
364
+ case A_APBNSPPPCEXP1:
365
+ case A_APBNSPPPCEXP2:
366
+ case A_APBNSPPPCEXP3:
367
+ qemu_log_mask(LOG_UNIMP,
368
+ "IoTKit SecCtl NS block read: "
369
+ "unimplemented offset 0x%x\n", offset);
370
+ break;
371
+ case A_PID4:
372
+ case A_PID5:
373
+ case A_PID6:
374
+ case A_PID7:
375
+ case A_PID0:
376
+ case A_PID1:
377
+ case A_PID2:
378
+ case A_PID3:
379
+ case A_CID0:
380
+ case A_CID1:
381
+ case A_CID2:
382
+ case A_CID3:
383
+ r = iotkit_secctl_ns_idregs[(offset - A_PID4) / 4];
384
+ break;
385
+ default:
386
+ qemu_log_mask(LOG_GUEST_ERROR,
387
+ "IotKit SecCtl NS block write: bad offset 0x%x\n",
388
+ offset);
389
+ r = 0;
390
+ break;
391
+ }
392
+
393
+ if (size != 4) {
394
+ /* None of our registers are access-sensitive, so just pull the right
395
+ * byte out of the word read result.
396
+ */
397
+ r = extract32(r, (addr & 3) * 8, size * 8);
398
+ }
399
+
400
+ trace_iotkit_secctl_ns_read(offset, r, size);
401
+ *pdata = r;
402
+ return MEMTX_OK;
403
+}
404
+
405
+static MemTxResult iotkit_secctl_ns_write(void *opaque, hwaddr addr,
406
+ uint64_t value,
407
+ unsigned size, MemTxAttrs attrs)
408
+{
409
+ uint32_t offset = addr;
410
+
411
+ trace_iotkit_secctl_ns_write(offset, value, size);
412
+
413
+ if (size != 4) {
414
+ /* Byte and halfword writes are ignored */
415
+ qemu_log_mask(LOG_GUEST_ERROR,
416
+ "IotKit SecCtl NS block write: bad size, ignored\n");
417
+ return MEMTX_OK;
418
+ }
419
+
420
+ switch (offset) {
421
+ case A_AHBNSPPPCEXP0:
422
+ case A_AHBNSPPPCEXP1:
423
+ case A_AHBNSPPPCEXP2:
424
+ case A_AHBNSPPPCEXP3:
425
+ case A_APBNSPPPC0:
426
+ case A_APBNSPPPC1:
427
+ case A_APBNSPPPCEXP0:
428
+ case A_APBNSPPPCEXP1:
429
+ case A_APBNSPPPCEXP2:
430
+ case A_APBNSPPPCEXP3:
431
+ qemu_log_mask(LOG_UNIMP,
432
+ "IoTKit SecCtl NS block write: "
433
+ "unimplemented offset 0x%x\n", offset);
434
+ break;
435
+ case A_AHBNSPPPC0:
436
+ case A_PID4:
437
+ case A_PID5:
438
+ case A_PID6:
439
+ case A_PID7:
440
+ case A_PID0:
441
+ case A_PID1:
442
+ case A_PID2:
443
+ case A_PID3:
444
+ case A_CID0:
445
+ case A_CID1:
446
+ case A_CID2:
447
+ case A_CID3:
448
+ qemu_log_mask(LOG_GUEST_ERROR,
449
+ "IoTKit SecCtl NS block write: "
450
+ "read-only offset 0x%x\n", offset);
451
+ break;
452
+ default:
453
+ qemu_log_mask(LOG_GUEST_ERROR,
454
+ "IotKit SecCtl NS block write: bad offset 0x%x\n",
455
+ offset);
456
+ break;
457
+ }
458
+
459
+ return MEMTX_OK;
460
+}
461
+
462
+static const MemoryRegionOps iotkit_secctl_s_ops = {
463
+ .read_with_attrs = iotkit_secctl_s_read,
464
+ .write_with_attrs = iotkit_secctl_s_write,
465
+ .endianness = DEVICE_LITTLE_ENDIAN,
466
+ .valid.min_access_size = 1,
467
+ .valid.max_access_size = 4,
468
+ .impl.min_access_size = 1,
469
+ .impl.max_access_size = 4,
470
+};
471
+
472
+static const MemoryRegionOps iotkit_secctl_ns_ops = {
473
+ .read_with_attrs = iotkit_secctl_ns_read,
474
+ .write_with_attrs = iotkit_secctl_ns_write,
475
+ .endianness = DEVICE_LITTLE_ENDIAN,
476
+ .valid.min_access_size = 1,
477
+ .valid.max_access_size = 4,
478
+ .impl.min_access_size = 1,
479
+ .impl.max_access_size = 4,
480
+};
481
+
482
+static void iotkit_secctl_reset(DeviceState *dev)
483
+{
484
+
485
+}
486
+
487
+static void iotkit_secctl_init(Object *obj)
488
+{
489
+ IoTKitSecCtl *s = IOTKIT_SECCTL(obj);
490
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
491
+
492
+ memory_region_init_io(&s->s_regs, obj, &iotkit_secctl_s_ops,
493
+ s, "iotkit-secctl-s-regs", 0x1000);
494
+ memory_region_init_io(&s->ns_regs, obj, &iotkit_secctl_ns_ops,
495
+ s, "iotkit-secctl-ns-regs", 0x1000);
496
+ sysbus_init_mmio(sbd, &s->s_regs);
497
+ sysbus_init_mmio(sbd, &s->ns_regs);
498
+}
499
+
500
+static const VMStateDescription iotkit_secctl_vmstate = {
501
+ .name = "iotkit-secctl",
502
+ .version_id = 1,
503
+ .minimum_version_id = 1,
504
+ .fields = (VMStateField[]) {
505
+ VMSTATE_END_OF_LIST()
506
+ }
507
+};
508
+
509
+static void iotkit_secctl_class_init(ObjectClass *klass, void *data)
510
+{
511
+ DeviceClass *dc = DEVICE_CLASS(klass);
512
+
513
+ dc->vmsd = &iotkit_secctl_vmstate;
514
+ dc->reset = iotkit_secctl_reset;
515
+}
516
+
517
+static const TypeInfo iotkit_secctl_info = {
518
+ .name = TYPE_IOTKIT_SECCTL,
519
+ .parent = TYPE_SYS_BUS_DEVICE,
520
+ .instance_size = sizeof(IoTKitSecCtl),
521
+ .instance_init = iotkit_secctl_init,
522
+ .class_init = iotkit_secctl_class_init,
523
+};
524
+
525
+static void iotkit_secctl_register_types(void)
526
+{
527
+ type_register_static(&iotkit_secctl_info);
528
+}
529
+
530
+type_init(iotkit_secctl_register_types);
531
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
532
index XXXXXXX..XXXXXXX 100644
533
--- a/default-configs/arm-softmmu.mak
534
+++ b/default-configs/arm-softmmu.mak
535
@@ -XXX,XX +XXX,XX @@ CONFIG_MPS2_FPGAIO=y
536
CONFIG_MPS2_SCC=y
537
538
CONFIG_TZ_PPC=y
539
+CONFIG_IOTKIT_SECCTL=y
540
541
CONFIG_VERSATILE_PCI=y
542
CONFIG_VERSATILE_I2C=y
543
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
544
index XXXXXXX..XXXXXXX 100644
545
--- a/hw/misc/trace-events
546
+++ b/hw/misc/trace-events
547
@@ -XXX,XX +XXX,XX @@ tz_ppc_irq_clear(int level) "TZ PPC: int_clear = %d"
548
tz_ppc_update_irq(int level) "TZ PPC: setting irq line to %d"
549
tz_ppc_read_blocked(int n, hwaddr offset, bool secure, bool user) "TZ PPC: port %d offset 0x%" HWADDR_PRIx " read (secure %d user %d) blocked"
550
tz_ppc_write_blocked(int n, hwaddr offset, bool secure, bool user) "TZ PPC: port %d offset 0x%" HWADDR_PRIx " write (secure %d user %d) blocked"
551
+
552
+# hw/misc/iotkit-secctl.c
553
+iotkit_secctl_s_read(uint32_t offset, uint64_t data, unsigned size) "IoTKit SecCtl S regs read: offset 0x%x data 0x%" PRIx64 " size %u"
554
+iotkit_secctl_s_write(uint32_t offset, uint64_t data, unsigned size) "IoTKit SecCtl S regs write: offset 0x%x data 0x%" PRIx64 " size %u"
555
+iotkit_secctl_ns_read(uint32_t offset, uint64_t data, unsigned size) "IoTKit SecCtl NS regs read: offset 0x%x data 0x%" PRIx64 " size %u"
556
+iotkit_secctl_ns_write(uint32_t offset, uint64_t data, unsigned size) "IoTKit SecCtl NS regs write: offset 0x%x data 0x%" PRIx64 " size %u"
557
+iotkit_secctl_reset(void) "IoTKit SecCtl: reset"
558
--
34
--
559
2.16.2
35
2.20.1
560
36
561
37
diff view generated by jsdifflib
1
The or-irq.h header file is missing the customary guard against
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
multiple inclusion, which means compilation fails if it gets
3
included twice. Fix the omission.
4
2
3
Add trace events for GPU and CPU IRQs.
4
5
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
6
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20201017180731.1165871-2-f4bug@amsat.org
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180220180325.29818-11-peter.maydell@linaro.org
9
---
9
---
10
include/hw/or-irq.h | 5 +++++
10
hw/intc/bcm2835_ic.c | 4 +++-
11
1 file changed, 5 insertions(+)
11
hw/intc/trace-events | 4 ++++
12
2 files changed, 7 insertions(+), 1 deletion(-)
12
13
13
diff --git a/include/hw/or-irq.h b/include/hw/or-irq.h
14
diff --git a/hw/intc/bcm2835_ic.c b/hw/intc/bcm2835_ic.c
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/or-irq.h
16
--- a/hw/intc/bcm2835_ic.c
16
+++ b/include/hw/or-irq.h
17
+++ b/hw/intc/bcm2835_ic.c
17
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@
18
* THE SOFTWARE.
19
#include "migration/vmstate.h"
19
*/
20
#include "qemu/log.h"
20
21
#include "qemu/module.h"
21
+#ifndef HW_OR_IRQ_H
22
+#include "trace.h"
22
+#define HW_OR_IRQ_H
23
24
#define GPU_IRQS 64
25
#define ARM_IRQS 8
26
@@ -XXX,XX +XXX,XX @@ static void bcm2835_ic_update(BCM2835ICState *s)
27
set = (s->gpu_irq_level & s->gpu_irq_enable)
28
|| (s->arm_irq_level & s->arm_irq_enable);
29
qemu_set_irq(s->irq, set);
30
-
31
}
32
33
static void bcm2835_ic_set_gpu_irq(void *opaque, int irq, int level)
34
@@ -XXX,XX +XXX,XX @@ static void bcm2835_ic_set_gpu_irq(void *opaque, int irq, int level)
35
BCM2835ICState *s = opaque;
36
37
assert(irq >= 0 && irq < 64);
38
+ trace_bcm2835_ic_set_gpu_irq(irq, level);
39
s->gpu_irq_level = deposit64(s->gpu_irq_level, irq, 1, level != 0);
40
bcm2835_ic_update(s);
41
}
42
@@ -XXX,XX +XXX,XX @@ static void bcm2835_ic_set_arm_irq(void *opaque, int irq, int level)
43
BCM2835ICState *s = opaque;
44
45
assert(irq >= 0 && irq < 8);
46
+ trace_bcm2835_ic_set_cpu_irq(irq, level);
47
s->arm_irq_level = deposit32(s->arm_irq_level, irq, 1, level != 0);
48
bcm2835_ic_update(s);
49
}
50
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
51
index XXXXXXX..XXXXXXX 100644
52
--- a/hw/intc/trace-events
53
+++ b/hw/intc/trace-events
54
@@ -XXX,XX +XXX,XX @@ nvic_sysreg_write(uint64_t addr, uint32_t value, unsigned size) "NVIC sysreg wri
55
heathrow_write(uint64_t addr, unsigned int n, uint64_t value) "0x%"PRIx64" %u: 0x%"PRIx64
56
heathrow_read(uint64_t addr, unsigned int n, uint64_t value) "0x%"PRIx64" %u: 0x%"PRIx64
57
heathrow_set_irq(int num, int level) "set_irq: num=0x%02x level=%d"
23
+
58
+
24
#include "hw/irq.h"
59
+# bcm2835_ic.c
25
#include "hw/sysbus.h"
60
+bcm2835_ic_set_gpu_irq(int irq, int level) "GPU irq #%d level %d"
26
#include "qom/object.h"
61
+bcm2835_ic_set_cpu_irq(int irq, int level) "CPU irq #%d level %d"
27
@@ -XXX,XX +XXX,XX @@ struct OrIRQState {
28
bool levels[MAX_OR_LINES];
29
uint16_t num_lines;
30
};
31
+
32
+#endif
33
--
62
--
34
2.16.2
63
2.20.1
35
64
36
65
diff view generated by jsdifflib
1
From: Alistair Francis <alistair.francis@xilinx.com>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
3
The IRQ values are defined few lines earlier, use them instead of
4
the magic numbers.
5
6
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20201017180731.1165871-3-f4bug@amsat.org
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
10
---
8
include/hw/arm/xlnx-zynqmp.h | 2 ++
11
hw/intc/bcm2836_control.c | 8 ++++----
9
hw/arm/xlnx-zynqmp.c | 14 ++++++++++++++
12
1 file changed, 4 insertions(+), 4 deletions(-)
10
2 files changed, 16 insertions(+)
11
13
12
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
14
diff --git a/hw/intc/bcm2836_control.c b/hw/intc/bcm2836_control.c
13
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
14
--- a/include/hw/arm/xlnx-zynqmp.h
16
--- a/hw/intc/bcm2836_control.c
15
+++ b/include/hw/arm/xlnx-zynqmp.h
17
+++ b/hw/intc/bcm2836_control.c
16
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ static void bcm2836_control_set_local_irq(void *opaque, int core, int local_irq,
17
#include "hw/dma/xlnx_dpdma.h"
19
18
#include "hw/display/xlnx_dp.h"
20
static void bcm2836_control_set_local_irq0(void *opaque, int core, int level)
19
#include "hw/intc/xlnx-zynqmp-ipi.h"
21
{
20
+#include "hw/timer/xlnx-zynqmp-rtc.h"
22
- bcm2836_control_set_local_irq(opaque, core, 0, level);
21
23
+ bcm2836_control_set_local_irq(opaque, core, IRQ_CNTPSIRQ, level);
22
#define TYPE_XLNX_ZYNQMP "xlnx,zynqmp"
23
#define XLNX_ZYNQMP(obj) OBJECT_CHECK(XlnxZynqMPState, (obj), \
24
@@ -XXX,XX +XXX,XX @@ typedef struct XlnxZynqMPState {
25
XlnxDPState dp;
26
XlnxDPDMAState dpdma;
27
XlnxZynqMPIPI ipi;
28
+ XlnxZynqMPRTC rtc;
29
30
char *boot_cpu;
31
ARMCPU *boot_cpu_ptr;
32
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/hw/arm/xlnx-zynqmp.c
35
+++ b/hw/arm/xlnx-zynqmp.c
36
@@ -XXX,XX +XXX,XX @@
37
#define IPI_ADDR 0xFF300000
38
#define IPI_IRQ 64
39
40
+#define RTC_ADDR 0xffa60000
41
+#define RTC_IRQ 26
42
+
43
#define SDHCI_CAPABILITIES 0x280737ec6481 /* Datasheet: UG1085 (v1.7) */
44
45
static const uint64_t gem_addr[XLNX_ZYNQMP_NUM_GEMS] = {
46
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_init(Object *obj)
47
48
object_initialize(&s->ipi, sizeof(s->ipi), TYPE_XLNX_ZYNQMP_IPI);
49
qdev_set_parent_bus(DEVICE(&s->ipi), sysbus_get_default());
50
+
51
+ object_initialize(&s->rtc, sizeof(s->rtc), TYPE_XLNX_ZYNQMP_RTC);
52
+ qdev_set_parent_bus(DEVICE(&s->rtc), sysbus_get_default());
53
}
24
}
54
25
55
static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
26
static void bcm2836_control_set_local_irq1(void *opaque, int core, int level)
56
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
27
{
57
}
28
- bcm2836_control_set_local_irq(opaque, core, 1, level);
58
sysbus_mmio_map(SYS_BUS_DEVICE(&s->ipi), 0, IPI_ADDR);
29
+ bcm2836_control_set_local_irq(opaque, core, IRQ_CNTPNSIRQ, level);
59
sysbus_connect_irq(SYS_BUS_DEVICE(&s->ipi), 0, gic_spi[IPI_IRQ]);
60
+
61
+ object_property_set_bool(OBJECT(&s->rtc), true, "realized", &err);
62
+ if (err) {
63
+ error_propagate(errp, err);
64
+ return;
65
+ }
66
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->rtc), 0, RTC_ADDR);
67
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->rtc), 0, gic_spi[RTC_IRQ]);
68
}
30
}
69
31
70
static Property xlnx_zynqmp_props[] = {
32
static void bcm2836_control_set_local_irq2(void *opaque, int core, int level)
33
{
34
- bcm2836_control_set_local_irq(opaque, core, 2, level);
35
+ bcm2836_control_set_local_irq(opaque, core, IRQ_CNTHPIRQ, level);
36
}
37
38
static void bcm2836_control_set_local_irq3(void *opaque, int core, int level)
39
{
40
- bcm2836_control_set_local_irq(opaque, core, 3, level);
41
+ bcm2836_control_set_local_irq(opaque, core, IRQ_CNTVIRQ, level);
42
}
43
44
static void bcm2836_control_set_gpu_irq(void *opaque, int irq, int level)
71
--
45
--
72
2.16.2
46
2.20.1
73
47
74
48
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Enable it for the "any" CPU used by *-linux-user.
3
We already have the full ARMMMUIdx as computed from the
4
function parameter.
5
6
For the purpose of regime_has_2_ranges, we can ignore any
7
difference between AccType_Normal and AccType_Unpriv, which
8
would be the only difference between the passed mmu_idx
9
and arm_mmu_idx_el.
4
10
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20180228193125.20577-17-richard.henderson@linaro.org
13
Reviewed-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
14
Tested-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
15
Message-id: 20201008162155.161886-2-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
17
---
10
target/arm/cpu.c | 1 +
18
target/arm/mte_helper.c | 3 +--
11
target/arm/cpu64.c | 1 +
19
1 file changed, 1 insertion(+), 2 deletions(-)
12
2 files changed, 2 insertions(+)
13
20
14
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
21
diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c
15
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.c
23
--- a/target/arm/mte_helper.c
17
+++ b/target/arm/cpu.c
24
+++ b/target/arm/mte_helper.c
18
@@ -XXX,XX +XXX,XX @@ static void arm_any_initfn(Object *obj)
25
@@ -XXX,XX +XXX,XX @@ static void mte_check_fail(CPUARMState *env, uint32_t desc,
19
set_feature(&cpu->env, ARM_FEATURE_V8_PMULL);
26
20
set_feature(&cpu->env, ARM_FEATURE_CRC);
27
case 2:
21
set_feature(&cpu->env, ARM_FEATURE_V8_RDM);
28
/* Tag check fail causes asynchronous flag set. */
22
+ set_feature(&cpu->env, ARM_FEATURE_V8_FCMA);
29
- mmu_idx = arm_mmu_idx_el(env, el);
23
cpu->midr = 0xffffffff;
30
- if (regime_has_2_ranges(mmu_idx)) {
24
}
31
+ if (regime_has_2_ranges(arm_mmu_idx)) {
25
#endif
32
select = extract64(dirty_ptr, 55, 1);
26
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
33
} else {
27
index XXXXXXX..XXXXXXX 100644
34
select = 0;
28
--- a/target/arm/cpu64.c
29
+++ b/target/arm/cpu64.c
30
@@ -XXX,XX +XXX,XX @@ static void aarch64_any_initfn(Object *obj)
31
set_feature(&cpu->env, ARM_FEATURE_CRC);
32
set_feature(&cpu->env, ARM_FEATURE_V8_RDM);
33
set_feature(&cpu->env, ARM_FEATURE_V8_FP16);
34
+ set_feature(&cpu->env, ARM_FEATURE_V8_FCMA);
35
cpu->ctr = 0x80038003; /* 32 byte I and D cacheline size, VIPT icache */
36
cpu->dcz_blocksize = 7; /* 512 bytes */
37
}
38
--
35
--
39
2.16.2
36
2.20.1
40
37
41
38
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
3
The reporting in AArch64.TagCheckFail only depends on PSTATE.EL,
4
and not the AccType of the operation. There are two guest
5
visible problems that affect LDTR and STTR because of this:
6
7
(1) Selecting TCF0 vs TCF1 to decide on reporting,
8
(2) Report "data abort same el" not "data abort lower el".
9
10
Reported-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180228193125.20577-9-richard.henderson@linaro.org
12
Reviewed-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
13
Tested-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
14
Message-id: 20201008162155.161886-3-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
16
---
8
target/arm/translate.c | 46 ++++++++++++++++++++++++++++++++++++++++++----
17
target/arm/mte_helper.c | 10 +++-------
9
1 file changed, 42 insertions(+), 4 deletions(-)
18
1 file changed, 3 insertions(+), 7 deletions(-)
10
19
11
diff --git a/target/arm/translate.c b/target/arm/translate.c
20
diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c
12
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate.c
22
--- a/target/arm/mte_helper.c
14
+++ b/target/arm/translate.c
23
+++ b/target/arm/mte_helper.c
15
@@ -XXX,XX +XXX,XX @@ static const char *regnames[] =
24
@@ -XXX,XX +XXX,XX @@ static void mte_check_fail(CPUARMState *env, uint32_t desc,
16
{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
25
reg_el = regime_el(env, arm_mmu_idx);
17
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
26
sctlr = env->cp15.sctlr_el[reg_el];
18
27
19
+/* Function prototypes for gen_ functions calling Neon helpers. */
28
- switch (arm_mmu_idx) {
20
+typedef void NeonGenThreeOpEnvFn(TCGv_i32, TCGv_env, TCGv_i32,
29
- case ARMMMUIdx_E10_0:
21
+ TCGv_i32, TCGv_i32);
30
- case ARMMMUIdx_E20_0:
22
+
31
- el = 0;
23
/* initialize TCG globals. */
32
+ el = arm_current_el(env);
24
void arm_translate_init(void)
33
+ if (el == 0) {
25
{
34
tcf = extract64(sctlr, 38, 2);
26
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
35
- break;
27
}
36
- default:
28
neon_store_reg64(cpu_V0, rd + pass);
37
- el = reg_el;
29
}
38
+ } else {
30
-
39
tcf = extract64(sctlr, 40, 2);
31
-
40
}
32
break;
41
33
- default: /* 14 and 15 are RESERVED */
34
- return 1;
35
+ case 14: /* VQRDMLAH scalar */
36
+ case 15: /* VQRDMLSH scalar */
37
+ {
38
+ NeonGenThreeOpEnvFn *fn;
39
+
40
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_RDM)) {
41
+ return 1;
42
+ }
43
+ if (u && ((rd | rn) & 1)) {
44
+ return 1;
45
+ }
46
+ if (op == 14) {
47
+ if (size == 1) {
48
+ fn = gen_helper_neon_qrdmlah_s16;
49
+ } else {
50
+ fn = gen_helper_neon_qrdmlah_s32;
51
+ }
52
+ } else {
53
+ if (size == 1) {
54
+ fn = gen_helper_neon_qrdmlsh_s16;
55
+ } else {
56
+ fn = gen_helper_neon_qrdmlsh_s32;
57
+ }
58
+ }
59
+
60
+ tmp2 = neon_get_scalar(size, rm);
61
+ for (pass = 0; pass < (u ? 4 : 2); pass++) {
62
+ tmp = neon_load_reg(rn, pass);
63
+ tmp3 = neon_load_reg(rd, pass);
64
+ fn(tmp, cpu_env, tmp, tmp2, tmp3);
65
+ tcg_temp_free_i32(tmp3);
66
+ neon_store_reg(rd, pass, tmp);
67
+ }
68
+ tcg_temp_free_i32(tmp2);
69
+ }
70
+ break;
71
+ default:
72
+ g_assert_not_reached();
73
}
74
}
75
} else { /* size == 3 */
76
--
42
--
77
2.16.2
43
2.20.1
78
44
79
45
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Enable it for the "any" CPU used by *-linux-user.
3
Unlike many other bits in HCR_EL2, the description for this
4
bit does not contain the phrase "if ... this field behaves
5
as 0 for all purposes other than", so do not squash the bit
6
in arm_hcr_el2_eff.
4
7
8
Instead, replicate the E2H+TGE test in the two places that
9
require it.
10
11
Reported-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
7
Message-id: 20180228193125.20577-10-richard.henderson@linaro.org
14
Tested-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
15
Message-id: 20201008162155.161886-4-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
17
---
10
target/arm/cpu.c | 1 +
18
target/arm/internals.h | 9 +++++----
11
target/arm/cpu64.c | 1 +
19
target/arm/helper.c | 9 +++++----
12
2 files changed, 2 insertions(+)
20
2 files changed, 10 insertions(+), 8 deletions(-)
13
21
14
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
22
diff --git a/target/arm/internals.h b/target/arm/internals.h
15
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.c
24
--- a/target/arm/internals.h
17
+++ b/target/arm/cpu.c
25
+++ b/target/arm/internals.h
18
@@ -XXX,XX +XXX,XX @@ static void arm_any_initfn(Object *obj)
26
@@ -XXX,XX +XXX,XX @@ static inline bool allocation_tag_access_enabled(CPUARMState *env, int el,
19
set_feature(&cpu->env, ARM_FEATURE_V8_SHA256);
27
&& !(env->cp15.scr_el3 & SCR_ATA)) {
20
set_feature(&cpu->env, ARM_FEATURE_V8_PMULL);
28
return false;
21
set_feature(&cpu->env, ARM_FEATURE_CRC);
29
}
22
+ set_feature(&cpu->env, ARM_FEATURE_V8_RDM);
30
- if (el < 2
23
cpu->midr = 0xffffffff;
31
- && arm_feature(env, ARM_FEATURE_EL2)
24
}
32
- && !(arm_hcr_el2_eff(env) & HCR_ATA)) {
25
#endif
33
- return false;
26
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
34
+ if (el < 2 && arm_feature(env, ARM_FEATURE_EL2)) {
35
+ uint64_t hcr = arm_hcr_el2_eff(env);
36
+ if (!(hcr & HCR_ATA) && (!(hcr & HCR_E2H) || !(hcr & HCR_TGE))) {
37
+ return false;
38
+ }
39
}
40
sctlr &= (el == 0 ? SCTLR_ATA0 : SCTLR_ATA);
41
return sctlr != 0;
42
diff --git a/target/arm/helper.c b/target/arm/helper.c
27
index XXXXXXX..XXXXXXX 100644
43
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/cpu64.c
44
--- a/target/arm/helper.c
29
+++ b/target/arm/cpu64.c
45
+++ b/target/arm/helper.c
30
@@ -XXX,XX +XXX,XX @@ static void aarch64_any_initfn(Object *obj)
46
@@ -XXX,XX +XXX,XX @@ static CPAccessResult access_mte(CPUARMState *env, const ARMCPRegInfo *ri,
31
set_feature(&cpu->env, ARM_FEATURE_V8_SM4);
47
{
32
set_feature(&cpu->env, ARM_FEATURE_V8_PMULL);
48
int el = arm_current_el(env);
33
set_feature(&cpu->env, ARM_FEATURE_CRC);
49
34
+ set_feature(&cpu->env, ARM_FEATURE_V8_RDM);
50
- if (el < 2 &&
35
set_feature(&cpu->env, ARM_FEATURE_V8_FP16);
51
- arm_feature(env, ARM_FEATURE_EL2) &&
36
cpu->ctr = 0x80038003; /* 32 byte I and D cacheline size, VIPT icache */
52
- !(arm_hcr_el2_eff(env) & HCR_ATA)) {
37
cpu->dcz_blocksize = 7; /* 512 bytes */
53
- return CP_ACCESS_TRAP_EL2;
54
+ if (el < 2 && arm_feature(env, ARM_FEATURE_EL2)) {
55
+ uint64_t hcr = arm_hcr_el2_eff(env);
56
+ if (!(hcr & HCR_ATA) && (!(hcr & HCR_E2H) || !(hcr & HCR_TGE))) {
57
+ return CP_ACCESS_TRAP_EL2;
58
+ }
59
}
60
if (el < 3 &&
61
arm_feature(env, ARM_FEATURE_EL3) &&
38
--
62
--
39
2.16.2
63
2.20.1
40
64
41
65
diff view generated by jsdifflib
1
Create an "init-svtor" property on the armv7m container
1
From: Peng Liang <liangpeng10@huawei.com>
2
object which we can forward to the CPU object.
3
2
3
VMStateDescription.fields should be end with VMSTATE_END_OF_LIST().
4
However, microbit_i2c_vmstate doesn't follow it. Let's change it.
5
6
Fixes: 9d68bf564e ("arm: Stub out NRF51 TWI magnetometer/accelerometer detection")
7
Reported-by: Euler Robot <euler.robot@huawei.com>
8
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Message-id: 20201019093401.2993833-1-liangpeng10@huawei.com
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20180220180325.29818-8-peter.maydell@linaro.org
7
---
12
---
8
include/hw/arm/armv7m.h | 2 ++
13
hw/i2c/microbit_i2c.c | 1 +
9
hw/arm/armv7m.c | 9 +++++++++
14
1 file changed, 1 insertion(+)
10
2 files changed, 11 insertions(+)
11
15
12
diff --git a/include/hw/arm/armv7m.h b/include/hw/arm/armv7m.h
16
diff --git a/hw/i2c/microbit_i2c.c b/hw/i2c/microbit_i2c.c
13
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
14
--- a/include/hw/arm/armv7m.h
18
--- a/hw/i2c/microbit_i2c.c
15
+++ b/include/hw/arm/armv7m.h
19
+++ b/hw/i2c/microbit_i2c.c
16
@@ -XXX,XX +XXX,XX @@ typedef struct {
20
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription microbit_i2c_vmstate = {
17
* that CPU accesses see. (The NVIC, bitbanding and other CPU-internal
21
.fields = (VMStateField[]) {
18
* devices will be automatically layered on top of this view.)
22
VMSTATE_UINT32_ARRAY(regs, MicrobitI2CState, MICROBIT_I2C_NREGS),
19
* + Property "idau": IDAU interface (forwarded to CPU object)
23
VMSTATE_UINT32(read_idx, MicrobitI2CState),
20
+ * + Property "init-svtor": secure VTOR reset value (forwarded to CPU object)
24
+ VMSTATE_END_OF_LIST()
21
*/
25
},
22
typedef struct ARMv7MState {
23
/*< private >*/
24
@@ -XXX,XX +XXX,XX @@ typedef struct ARMv7MState {
25
/* MemoryRegion the board provides to us (with its devices, RAM, etc) */
26
MemoryRegion *board_memory;
27
Object *idau;
28
+ uint32_t init_svtor;
29
} ARMv7MState;
30
31
#endif
32
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/hw/arm/armv7m.c
35
+++ b/hw/arm/armv7m.c
36
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
37
return;
38
}
39
}
40
+ if (object_property_find(OBJECT(s->cpu), "init-svtor", NULL)) {
41
+ object_property_set_uint(OBJECT(s->cpu), s->init_svtor,
42
+ "init-svtor", &err);
43
+ if (err != NULL) {
44
+ error_propagate(errp, err);
45
+ return;
46
+ }
47
+ }
48
object_property_set_bool(OBJECT(s->cpu), true, "realized", &err);
49
if (err != NULL) {
50
error_propagate(errp, err);
51
@@ -XXX,XX +XXX,XX @@ static Property armv7m_properties[] = {
52
DEFINE_PROP_LINK("memory", ARMv7MState, board_memory, TYPE_MEMORY_REGION,
53
MemoryRegion *),
54
DEFINE_PROP_LINK("idau", ARMv7MState, idau, TYPE_IDAU_INTERFACE, Object *),
55
+ DEFINE_PROP_UINT32("init-svtor", ARMv7MState, init_svtor, 0),
56
DEFINE_PROP_END_OF_LIST(),
57
};
26
};
58
27
59
--
28
--
60
2.16.2
29
2.20.1
61
30
62
31
diff view generated by jsdifflib
1
Move the definition of the struct for the unimplemented-device
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
from unimp.c to unimp.h, so that users can embed the struct
3
in their own device structs if they prefer.
4
2
3
Commit 7998beb9c2e removed the ram_size initialization in the
4
arm_boot_info structure, however it is used by arm_load_kernel().
5
6
Initialize the field to fix:
7
8
$ qemu-system-arm -M n800 -append 'console=ttyS1' \
9
-kernel meego-arm-n8x0-1.0.80.20100712.1431-vmlinuz-2.6.35~rc4-129.1-n8x0
10
qemu-system-arm: kernel 'meego-arm-n8x0-1.0.80.20100712.1431-vmlinuz-2.6.35~rc4-129.1-n8x0' is too large to fit in RAM (kernel size 1964608, RAM size 0)
11
12
Noticed while running the test introduced in commit 050a82f0c5b
13
("tests/acceptance: Add a test for the N800 and N810 arm machines").
14
15
Fixes: 7998beb9c2e ("arm/nseries: use memdev for RAM")
16
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Tested-by: Thomas Huth <thuth@redhat.com>
19
Message-id: 20201019095148.1602119-1-f4bug@amsat.org
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180220180325.29818-10-peter.maydell@linaro.org
9
---
21
---
10
include/hw/misc/unimp.h | 10 ++++++++++
22
hw/arm/nseries.c | 1 +
11
hw/misc/unimp.c | 10 ----------
23
1 file changed, 1 insertion(+)
12
2 files changed, 10 insertions(+), 10 deletions(-)
13
24
14
diff --git a/include/hw/misc/unimp.h b/include/hw/misc/unimp.h
25
diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
15
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
16
--- a/include/hw/misc/unimp.h
27
--- a/hw/arm/nseries.c
17
+++ b/include/hw/misc/unimp.h
28
+++ b/hw/arm/nseries.c
18
@@ -XXX,XX +XXX,XX @@
29
@@ -XXX,XX +XXX,XX @@ static void n8x0_init(MachineState *machine,
19
30
g_free(sz);
20
#define TYPE_UNIMPLEMENTED_DEVICE "unimplemented-device"
31
exit(EXIT_FAILURE);
21
32
}
22
+#define UNIMPLEMENTED_DEVICE(obj) \
33
+ binfo->ram_size = machine->ram_size;
23
+ OBJECT_CHECK(UnimplementedDeviceState, (obj), TYPE_UNIMPLEMENTED_DEVICE)
34
24
+
35
memory_region_add_subregion(get_system_memory(), OMAP2_Q2_BASE,
25
+typedef struct {
36
machine->ram);
26
+ SysBusDevice parent_obj;
27
+ MemoryRegion iomem;
28
+ char *name;
29
+ uint64_t size;
30
+} UnimplementedDeviceState;
31
+
32
/**
33
* create_unimplemented_device: create and map a dummy device
34
* @name: name of the device for debug logging
35
diff --git a/hw/misc/unimp.c b/hw/misc/unimp.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/hw/misc/unimp.c
38
+++ b/hw/misc/unimp.c
39
@@ -XXX,XX +XXX,XX @@
40
#include "qemu/log.h"
41
#include "qapi/error.h"
42
43
-#define UNIMPLEMENTED_DEVICE(obj) \
44
- OBJECT_CHECK(UnimplementedDeviceState, (obj), TYPE_UNIMPLEMENTED_DEVICE)
45
-
46
-typedef struct {
47
- SysBusDevice parent_obj;
48
- MemoryRegion iomem;
49
- char *name;
50
- uint64_t size;
51
-} UnimplementedDeviceState;
52
-
53
static uint64_t unimp_read(void *opaque, hwaddr offset, unsigned size)
54
{
55
UnimplementedDeviceState *s = UNIMPLEMENTED_DEVICE(opaque);
56
--
37
--
57
2.16.2
38
2.20.1
58
39
59
40
diff view generated by jsdifflib
1
Create an "idau" property on the armv7m container object which
1
For nested groups like:
2
we can forward to the CPU object. Annoyingly, we can't use
3
object_property_add_alias() because the CPU object we want to
4
forward to doesn't exist until the armv7m container is realized.
5
2
3
{
4
[
5
pattern 1
6
pattern 2
7
]
8
pattern 3
9
}
10
11
the intended behaviour is that patterns 1 and 2 must not
12
overlap with each other; if the insn matches neither then
13
we fall through to pattern 3 as the next thing in the
14
outer overlapping group.
15
16
Currently we generate incorrect code for this situation,
17
because in the code path for a failed match inside the
18
inner non-overlapping group we generate a "return" statement,
19
which causes decode to stop entirely rather than continuing
20
to the next thing in the outer group.
21
22
Generate a "break" instead, so that decode flow behaves
23
as required for this nested group case.
24
25
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
26
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
28
Message-id: 20201019151301.2046-2-peter.maydell@linaro.org
8
Message-id: 20180220180325.29818-6-peter.maydell@linaro.org
9
---
29
---
10
include/hw/arm/armv7m.h | 3 +++
30
scripts/decodetree.py | 2 +-
11
hw/arm/armv7m.c | 9 +++++++++
31
1 file changed, 1 insertion(+), 1 deletion(-)
12
2 files changed, 12 insertions(+)
13
32
14
diff --git a/include/hw/arm/armv7m.h b/include/hw/arm/armv7m.h
33
diff --git a/scripts/decodetree.py b/scripts/decodetree.py
15
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
16
--- a/include/hw/arm/armv7m.h
35
--- a/scripts/decodetree.py
17
+++ b/include/hw/arm/armv7m.h
36
+++ b/scripts/decodetree.py
18
@@ -XXX,XX +XXX,XX @@
37
@@ -XXX,XX +XXX,XX @@ class Tree:
19
38
output(ind, ' /* ',
20
#include "hw/sysbus.h"
39
str_match_bits(innerbits, innermask), ' */\n')
21
#include "hw/intc/armv7m_nvic.h"
40
s.output_code(i + 4, extracted, innerbits, innermask)
22
+#include "target/arm/idau.h"
41
- output(ind, ' return false;\n')
23
42
+ output(ind, ' break;\n')
24
#define TYPE_BITBAND "ARM,bitband-memory"
43
output(ind, '}\n')
25
#define BITBAND(obj) OBJECT_CHECK(BitBandState, (obj), TYPE_BITBAND)
44
# end Tree
26
@@ -XXX,XX +XXX,XX @@ typedef struct {
27
* + Property "memory": MemoryRegion defining the physical address space
28
* that CPU accesses see. (The NVIC, bitbanding and other CPU-internal
29
* devices will be automatically layered on top of this view.)
30
+ * + Property "idau": IDAU interface (forwarded to CPU object)
31
*/
32
typedef struct ARMv7MState {
33
/*< private >*/
34
@@ -XXX,XX +XXX,XX @@ typedef struct ARMv7MState {
35
char *cpu_type;
36
/* MemoryRegion the board provides to us (with its devices, RAM, etc) */
37
MemoryRegion *board_memory;
38
+ Object *idau;
39
} ARMv7MState;
40
41
#endif
42
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/hw/arm/armv7m.c
45
+++ b/hw/arm/armv7m.c
46
@@ -XXX,XX +XXX,XX @@
47
#include "sysemu/qtest.h"
48
#include "qemu/error-report.h"
49
#include "exec/address-spaces.h"
50
+#include "target/arm/idau.h"
51
52
/* Bitbanded IO. Each word corresponds to a single bit. */
53
54
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
55
56
object_property_set_link(OBJECT(s->cpu), OBJECT(&s->container), "memory",
57
&error_abort);
58
+ if (object_property_find(OBJECT(s->cpu), "idau", NULL)) {
59
+ object_property_set_link(OBJECT(s->cpu), s->idau, "idau", &err);
60
+ if (err != NULL) {
61
+ error_propagate(errp, err);
62
+ return;
63
+ }
64
+ }
65
object_property_set_bool(OBJECT(s->cpu), true, "realized", &err);
66
if (err != NULL) {
67
error_propagate(errp, err);
68
@@ -XXX,XX +XXX,XX @@ static Property armv7m_properties[] = {
69
DEFINE_PROP_STRING("cpu-type", ARMv7MState, cpu_type),
70
DEFINE_PROP_LINK("memory", ARMv7MState, board_memory, TYPE_MEMORY_REGION,
71
MemoryRegion *),
72
+ DEFINE_PROP_LINK("idau", ARMv7MState, idau, TYPE_IDAU_INTERFACE, Object *),
73
DEFINE_PROP_END_OF_LIST(),
74
};
75
45
76
--
46
--
77
2.16.2
47
2.20.1
78
48
79
49
diff view generated by jsdifflib
1
In v8M, the Implementation Defined Attribution Unit (IDAU) is
1
From v8.1M, disabled-coprocessor handling changes slightly:
2
a small piece of hardware typically implemented in the SoC
2
* coprocessors 8, 9, 14 and 15 are also governed by the
3
which provides board or SoC specific security attribution
3
cp10 enable bit, like cp11
4
information for each address that the CPU performs MPU/SAU
4
* an extra range of instruction patterns is considered
5
checks on. For QEMU, we model this with a QOM interface which
5
to be inside the coprocessor space
6
is implemented by the board or SoC object and connected to
7
the CPU using a link property.
8
6
9
This commit defines the new interface class, adds the link
7
We previously marked these up with TODO comments; implement the
10
property to the CPU object, and makes the SAU checking
8
correct behaviour.
11
code call the IDAU interface if one is present.
9
10
Unfortunately there is no ID register field which indicates this
11
behaviour. We could in theory test an unrelated ID register which
12
indicates guaranteed-to-be-in-v8.1M behaviour like ID_ISAR0.CmpBranch
13
>= 3 (low-overhead-loops), but it seems better to simply define a new
14
ARM_FEATURE_V8_1M feature flag and use it for this and other
15
new-in-v8.1M behaviour that isn't identifiable from the ID registers.
12
16
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20180220180325.29818-5-peter.maydell@linaro.org
19
Message-id: 20201019151301.2046-3-peter.maydell@linaro.org
16
---
20
---
17
target/arm/cpu.h | 3 +++
21
target/arm/cpu.h | 1 +
18
target/arm/idau.h | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++
22
target/arm/m-nocp.decode | 10 ++++++----
19
target/arm/cpu.c | 15 +++++++++++++
23
target/arm/translate-vfp.c.inc | 17 +++++++++++++++--
20
target/arm/helper.c | 28 +++++++++++++++++++++---
24
3 files changed, 22 insertions(+), 6 deletions(-)
21
4 files changed, 104 insertions(+), 3 deletions(-)
22
create mode 100644 target/arm/idau.h
23
25
24
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
26
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
25
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/cpu.h
28
--- a/target/arm/cpu.h
27
+++ b/target/arm/cpu.h
29
+++ b/target/arm/cpu.h
28
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
30
@@ -XXX,XX +XXX,XX @@ enum arm_features {
29
/* MemoryRegion to use for secure physical accesses */
31
ARM_FEATURE_VBAR, /* has cp15 VBAR */
30
MemoryRegion *secure_memory;
32
ARM_FEATURE_M_SECURITY, /* M profile Security Extension */
31
33
ARM_FEATURE_M_MAIN, /* M profile Main Extension */
32
+ /* For v8M, pointer to the IDAU interface provided by board/SoC */
34
+ ARM_FEATURE_V8_1M, /* M profile extras only in v8.1M and later */
33
+ Object *idau;
35
};
36
37
static inline int arm_feature(CPUARMState *env, int feature)
38
diff --git a/target/arm/m-nocp.decode b/target/arm/m-nocp.decode
39
index XXXXXXX..XXXXXXX 100644
40
--- a/target/arm/m-nocp.decode
41
+++ b/target/arm/m-nocp.decode
42
@@ -XXX,XX +XXX,XX @@
43
# If the coprocessor is not present or disabled then we will generate
44
# the NOCP exception; otherwise we let the insn through to the main decode.
45
46
+&nocp cp
34
+
47
+
35
/* 'compatible' string for this CPU for Linux device trees */
48
{
36
const char *dtb_compatible;
49
# Special cases which do not take an early NOCP: VLLDM and VLSTM
37
50
VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 0000 0000
38
diff --git a/target/arm/idau.h b/target/arm/idau.h
51
# TODO: VSCCLRM (new in v8.1M) is similar:
39
new file mode 100644
52
#VSCCLRM 1110 1100 1-01 1111 ---- 1011 ---- ---0
40
index XXXXXXX..XXXXXXX
53
41
--- /dev/null
54
- NOCP 111- 1110 ---- ---- ---- cp:4 ---- ----
42
+++ b/target/arm/idau.h
55
- NOCP 111- 110- ---- ---- ---- cp:4 ---- ----
43
@@ -XXX,XX +XXX,XX @@
56
- # TODO: From v8.1M onwards we will also want this range to NOCP
44
+/*
57
- #NOCP_8_1 111- 1111 ---- ---- ---- ---- ---- ---- cp=10
45
+ * QEMU ARM CPU -- interface for the Arm v8M IDAU
58
+ NOCP 111- 1110 ---- ---- ---- cp:4 ---- ---- &nocp
46
+ *
59
+ NOCP 111- 110- ---- ---- ---- cp:4 ---- ---- &nocp
47
+ * Copyright (c) 2018 Linaro Ltd
60
+ # From v8.1M onwards this range will also NOCP:
48
+ *
61
+ NOCP_8_1 111- 1111 ---- ---- ---- ---- ---- ---- &nocp cp=10
49
+ * This program is free software; you can redistribute it and/or
62
}
50
+ * modify it under the terms of the GNU General Public License
63
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
51
+ * as published by the Free Software Foundation; either version 2
64
index XXXXXXX..XXXXXXX 100644
52
+ * of the License, or (at your option) any later version.
65
--- a/target/arm/translate-vfp.c.inc
53
+ *
66
+++ b/target/arm/translate-vfp.c.inc
54
+ * This program is distributed in the hope that it will be useful,
67
@@ -XXX,XX +XXX,XX @@ static bool trans_VLLDM_VLSTM(DisasContext *s, arg_VLLDM_VLSTM *a)
55
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
68
return true;
56
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
69
}
57
+ * GNU General Public License for more details.
70
58
+ *
71
-static bool trans_NOCP(DisasContext *s, arg_NOCP *a)
59
+ * You should have received a copy of the GNU General Public License
72
+static bool trans_NOCP(DisasContext *s, arg_nocp *a)
60
+ * along with this program; if not, see
73
{
61
+ * <http://www.gnu.org/licenses/gpl-2.0.html>
74
/*
62
+ *
75
* Handle M-profile early check for disabled coprocessor:
63
+ * In the v8M architecture, the IDAU is a small piece of hardware
76
@@ -XXX,XX +XXX,XX @@ static bool trans_NOCP(DisasContext *s, arg_NOCP *a)
64
+ * typically implemented in the SoC which provides board or SoC
77
if (a->cp == 11) {
65
+ * specific security attribution information for each address that
78
a->cp = 10;
66
+ * the CPU performs MPU/SAU checks on. For QEMU, we model this with a
79
}
67
+ * QOM interface which is implemented by the board or SoC object and
80
- /* TODO: in v8.1M cp 8, 9, 14, 15 also are governed by the cp10 enable */
68
+ * connected to the CPU using a link property.
81
+ if (arm_dc_feature(s, ARM_FEATURE_V8_1M) &&
69
+ */
82
+ (a->cp == 8 || a->cp == 9 || a->cp == 14 || a->cp == 15)) {
83
+ /* in v8.1M cp 8, 9, 14, 15 also are governed by the cp10 enable */
84
+ a->cp = 10;
85
+ }
86
87
if (a->cp != 10) {
88
gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
89
@@ -XXX,XX +XXX,XX @@ static bool trans_NOCP(DisasContext *s, arg_NOCP *a)
90
return false;
91
}
92
93
+static bool trans_NOCP_8_1(DisasContext *s, arg_nocp *a)
94
+{
95
+ /* This range needs a coprocessor check for v8.1M and later only */
96
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
97
+ return false;
98
+ }
99
+ return trans_NOCP(s, a);
100
+}
70
+
101
+
71
+#ifndef TARGET_ARM_IDAU_H
102
static bool trans_VINS(DisasContext *s, arg_VINS *a)
72
+#define TARGET_ARM_IDAU_H
73
+
74
+#include "qom/object.h"
75
+
76
+#define TYPE_IDAU_INTERFACE "idau-interface"
77
+#define IDAU_INTERFACE(obj) \
78
+ INTERFACE_CHECK(IDAUInterface, (obj), TYPE_IDAU_INTERFACE)
79
+#define IDAU_INTERFACE_CLASS(class) \
80
+ OBJECT_CLASS_CHECK(IDAUInterfaceClass, (class), TYPE_IDAU_INTERFACE)
81
+#define IDAU_INTERFACE_GET_CLASS(obj) \
82
+ OBJECT_GET_CLASS(IDAUInterfaceClass, (obj), TYPE_IDAU_INTERFACE)
83
+
84
+typedef struct IDAUInterface {
85
+ Object parent;
86
+} IDAUInterface;
87
+
88
+#define IREGION_NOTVALID -1
89
+
90
+typedef struct IDAUInterfaceClass {
91
+ InterfaceClass parent;
92
+
93
+ /* Check the specified address and return the IDAU security information
94
+ * for it by filling in iregion, exempt, ns and nsc:
95
+ * iregion: IDAU region number, or IREGION_NOTVALID if not valid
96
+ * exempt: true if address is exempt from security attribution
97
+ * ns: true if the address is NonSecure
98
+ * nsc: true if the address is NonSecure-callable
99
+ */
100
+ void (*check)(IDAUInterface *ii, uint32_t address, int *iregion,
101
+ bool *exempt, bool *ns, bool *nsc);
102
+} IDAUInterfaceClass;
103
+
104
+#endif
105
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
106
index XXXXXXX..XXXXXXX 100644
107
--- a/target/arm/cpu.c
108
+++ b/target/arm/cpu.c
109
@@ -XXX,XX +XXX,XX @@
110
*/
111
112
#include "qemu/osdep.h"
113
+#include "target/arm/idau.h"
114
#include "qemu/error-report.h"
115
#include "qapi/error.h"
116
#include "cpu.h"
117
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_post_init(Object *obj)
118
}
119
}
120
121
+ if (arm_feature(&cpu->env, ARM_FEATURE_M_SECURITY)) {
122
+ object_property_add_link(obj, "idau", TYPE_IDAU_INTERFACE, &cpu->idau,
123
+ qdev_prop_allow_set_link_before_realize,
124
+ OBJ_PROP_LINK_UNREF_ON_RELEASE,
125
+ &error_abort);
126
+ }
127
+
128
qdev_property_add_static(DEVICE(obj), &arm_cpu_cfgend_property,
129
&error_abort);
130
}
131
@@ -XXX,XX +XXX,XX @@ static const TypeInfo arm_cpu_type_info = {
132
.class_init = arm_cpu_class_init,
133
};
134
135
+static const TypeInfo idau_interface_type_info = {
136
+ .name = TYPE_IDAU_INTERFACE,
137
+ .parent = TYPE_INTERFACE,
138
+ .class_size = sizeof(IDAUInterfaceClass),
139
+};
140
+
141
static void arm_cpu_register_types(void)
142
{
103
{
143
const ARMCPUInfo *info = arm_cpus;
104
TCGv_i32 rd, rm;
144
145
type_register_static(&arm_cpu_type_info);
146
+ type_register_static(&idau_interface_type_info);
147
148
while (info->name) {
149
cpu_register(info);
150
diff --git a/target/arm/helper.c b/target/arm/helper.c
151
index XXXXXXX..XXXXXXX 100644
152
--- a/target/arm/helper.c
153
+++ b/target/arm/helper.c
154
@@ -XXX,XX +XXX,XX @@
155
#include "qemu/osdep.h"
156
+#include "target/arm/idau.h"
157
#include "trace.h"
158
#include "cpu.h"
159
#include "internals.h"
160
@@ -XXX,XX +XXX,XX @@ static void v8m_security_lookup(CPUARMState *env, uint32_t address,
161
*/
162
ARMCPU *cpu = arm_env_get_cpu(env);
163
int r;
164
+ bool idau_exempt = false, idau_ns = true, idau_nsc = true;
165
+ int idau_region = IREGION_NOTVALID;
166
167
- /* TODO: implement IDAU */
168
+ if (cpu->idau) {
169
+ IDAUInterfaceClass *iic = IDAU_INTERFACE_GET_CLASS(cpu->idau);
170
+ IDAUInterface *ii = IDAU_INTERFACE(cpu->idau);
171
+
172
+ iic->check(ii, address, &idau_region, &idau_exempt, &idau_ns,
173
+ &idau_nsc);
174
+ }
175
176
if (access_type == MMU_INST_FETCH && extract32(address, 28, 4) == 0xf) {
177
/* 0xf0000000..0xffffffff is always S for insn fetches */
178
return;
179
}
180
181
- if (v8m_is_sau_exempt(env, address, access_type)) {
182
+ if (idau_exempt || v8m_is_sau_exempt(env, address, access_type)) {
183
sattrs->ns = !regime_is_secure(env, mmu_idx);
184
return;
185
}
186
187
+ if (idau_region != IREGION_NOTVALID) {
188
+ sattrs->irvalid = true;
189
+ sattrs->iregion = idau_region;
190
+ }
191
+
192
switch (env->sau.ctrl & 3) {
193
case 0: /* SAU.ENABLE == 0, SAU.ALLNS == 0 */
194
break;
195
@@ -XXX,XX +XXX,XX @@ static void v8m_security_lookup(CPUARMState *env, uint32_t address,
196
}
197
}
198
199
- /* TODO when we support the IDAU then it may override the result here */
200
+ /* The IDAU will override the SAU lookup results if it specifies
201
+ * higher security than the SAU does.
202
+ */
203
+ if (!idau_ns) {
204
+ if (sattrs->ns || (!idau_nsc && sattrs->nsc)) {
205
+ sattrs->ns = false;
206
+ sattrs->nsc = idau_nsc;
207
+ }
208
+ }
209
break;
210
}
211
}
212
--
105
--
213
2.16.2
106
2.20.1
214
107
215
108
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
v8.1M brings four new insns to M-profile:
2
* CSEL : Rd = cond ? Rn : Rm
3
* CSINC : Rd = cond ? Rn : Rm+1
4
* CSINV : Rd = cond ? Rn : ~Rm
5
* CSNEG : Rd = cond ? Rn : -Rm
2
6
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Implement these.
4
Message-id: 20180228193125.20577-15-richard.henderson@linaro.org
8
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20201019151301.2046-4-peter.maydell@linaro.org
7
---
12
---
8
target/arm/translate.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++
13
target/arm/t32.decode | 3 +++
9
1 file changed, 61 insertions(+)
14
target/arm/translate.c | 60 ++++++++++++++++++++++++++++++++++++++++++
15
2 files changed, 63 insertions(+)
10
16
17
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/t32.decode
20
+++ b/target/arm/t32.decode
21
@@ -XXX,XX +XXX,XX @@ SBC_rrri 1110101 1011 . .... 0 ... .... .... .... @s_rrr_shi
22
}
23
RSB_rrri 1110101 1110 . .... 0 ... .... .... .... @s_rrr_shi
24
25
+# v8.1M CSEL and friends
26
+CSEL 1110101 0010 1 rn:4 10 op:2 rd:4 fcond:4 rm:4
27
+
28
# Data-processing (register-shifted register)
29
30
MOV_rxrr 1111 1010 0 shty:2 s:1 rm:4 1111 rd:4 0000 rs:4 \
11
diff --git a/target/arm/translate.c b/target/arm/translate.c
31
diff --git a/target/arm/translate.c b/target/arm/translate.c
12
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate.c
33
--- a/target/arm/translate.c
14
+++ b/target/arm/translate.c
34
+++ b/target/arm/translate.c
15
@@ -XXX,XX +XXX,XX @@ static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
35
@@ -XXX,XX +XXX,XX @@ static bool trans_IT(DisasContext *s, arg_IT *a)
16
return 0;
36
return true;
17
}
37
}
18
38
19
+/* Advanced SIMD two registers and a scalar extension.
39
+/* v8.1M CSEL/CSINC/CSNEG/CSINV */
20
+ * 31 24 23 22 20 16 12 11 10 9 8 3 0
40
+static bool trans_CSEL(DisasContext *s, arg_CSEL *a)
21
+ * +-----------------+----+---+----+----+----+---+----+---+----+---------+----+
41
+{
22
+ * | 1 1 1 1 1 1 1 0 | o1 | D | o2 | Vn | Vd | 1 | o3 | 0 | o4 | N Q M U | Vm |
42
+ TCGv_i32 rn, rm, zero;
23
+ * +-----------------+----+---+----+----+----+---+----+---+----+---------+----+
43
+ DisasCompare c;
24
+ *
25
+ */
26
+
44
+
27
+static int disas_neon_insn_2reg_scalar_ext(DisasContext *s, uint32_t insn)
45
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
28
+{
46
+ return false;
29
+ int rd, rn, rm, rot, size, opr_sz;
30
+ TCGv_ptr fpst;
31
+ bool q;
32
+
33
+ q = extract32(insn, 6, 1);
34
+ VFP_DREG_D(rd, insn);
35
+ VFP_DREG_N(rn, insn);
36
+ VFP_DREG_M(rm, insn);
37
+ if ((rd | rn) & q) {
38
+ return 1;
39
+ }
47
+ }
40
+
48
+
41
+ if ((insn & 0xff000f10) == 0xfe000800) {
49
+ if (a->rm == 13) {
42
+ /* VCMLA (indexed) -- 1111 1110 S.RR .... .... 1000 ...0 .... */
50
+ /* SEE "Related encodings" (MVE shifts) */
43
+ rot = extract32(insn, 20, 2);
51
+ return false;
44
+ size = extract32(insn, 23, 1);
45
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_FCMA)
46
+ || (!size && !arm_dc_feature(s, ARM_FEATURE_V8_FP16))) {
47
+ return 1;
48
+ }
49
+ } else {
50
+ return 1;
51
+ }
52
+ }
52
+
53
+
53
+ if (s->fp_excp_el) {
54
+ if (a->rd == 13 || a->rd == 15 || a->rn == 13 || a->fcond >= 14) {
54
+ gen_exception_insn(s, 4, EXCP_UDEF,
55
+ /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */
55
+ syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
56
+ return false;
56
+ return 0;
57
+ }
58
+ if (!s->vfp_enabled) {
59
+ return 1;
60
+ }
57
+ }
61
+
58
+
62
+ opr_sz = (1 + q) * 8;
59
+ /* In this insn input reg fields of 0b1111 mean "zero", not "PC" */
63
+ fpst = get_fpstatus_ptr(1);
60
+ if (a->rn == 15) {
64
+ tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
61
+ rn = tcg_const_i32(0);
65
+ vfp_reg_offset(1, rn),
62
+ } else {
66
+ vfp_reg_offset(1, rm), fpst,
63
+ rn = load_reg(s, a->rn);
67
+ opr_sz, opr_sz, rot,
64
+ }
68
+ size ? gen_helper_gvec_fcmlas_idx
65
+ if (a->rm == 15) {
69
+ : gen_helper_gvec_fcmlah_idx);
66
+ rm = tcg_const_i32(0);
70
+ tcg_temp_free_ptr(fpst);
67
+ } else {
71
+ return 0;
68
+ rm = load_reg(s, a->rm);
69
+ }
70
+
71
+ switch (a->op) {
72
+ case 0: /* CSEL */
73
+ break;
74
+ case 1: /* CSINC */
75
+ tcg_gen_addi_i32(rm, rm, 1);
76
+ break;
77
+ case 2: /* CSINV */
78
+ tcg_gen_not_i32(rm, rm);
79
+ break;
80
+ case 3: /* CSNEG */
81
+ tcg_gen_neg_i32(rm, rm);
82
+ break;
83
+ default:
84
+ g_assert_not_reached();
85
+ }
86
+
87
+ arm_test_cc(&c, a->fcond);
88
+ zero = tcg_const_i32(0);
89
+ tcg_gen_movcond_i32(c.cond, rn, c.value, zero, rn, rm);
90
+ arm_free_cc(&c);
91
+ tcg_temp_free_i32(zero);
92
+
93
+ store_reg(s, a->rd, rn);
94
+ tcg_temp_free_i32(rm);
95
+
96
+ return true;
72
+}
97
+}
73
+
98
+
74
static int disas_coproc_insn(DisasContext *s, uint32_t insn)
99
/*
75
{
100
* Legacy decoder.
76
int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
101
*/
77
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
78
goto illegal_op;
79
}
80
return;
81
+ } else if ((insn & 0x0f000a00) == 0x0e000800
82
+ && arm_dc_feature(s, ARM_FEATURE_V8)) {
83
+ if (disas_neon_insn_2reg_scalar_ext(s, insn)) {
84
+ goto illegal_op;
85
+ }
86
+ return;
87
} else if ((insn & 0x0fe00000) == 0x0c400000) {
88
/* Coprocessor double register transfer. */
89
ARCH(5TE);
90
--
102
--
91
2.16.2
103
2.20.1
92
104
93
105
diff view generated by jsdifflib
1
The function qdev_init_gpio_in_named() passes the DeviceState pointer
1
The t32 decode has a group which represents a set of insns
2
as the opaque data pointor for the irq handler function. Usually
2
which overlap with B_cond_thumb because they have [25:23]=111
3
this is what you want, but in some cases it would be helpful to use
3
(which is an invalid condition code field for the branch insn).
4
some other data pointer.
4
This group is currently defined using the {} overlap-OK syntax,
5
but it is almost entirely non-overlapping patterns. Switch
6
it over to use a non-overlapping group.
5
7
6
Add a new function qdev_init_gpio_in_named_with_opaque() which allows
8
For this to be valid syntactically, CPS must move into the same
7
the caller to specify the data pointer they want.
9
overlapping-group as the hint insns (CPS vs hints was the
10
only actual use of the overlap facility for the group).
8
11
12
The non-overlapping subgroup for CLREX/DSB/DMB/ISB/SB is no longer
13
necessary and so we can remove it (promoting those insns to
14
be members of the parent group).
15
16
Reviewed-by: Richard Henderson <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
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
18
Message-id: 20201019151301.2046-5-peter.maydell@linaro.org
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20180220180325.29818-12-peter.maydell@linaro.org
13
---
19
---
14
include/hw/qdev-core.h | 30 ++++++++++++++++++++++++++++--
20
target/arm/t32.decode | 26 ++++++++++++--------------
15
hw/core/qdev.c | 8 +++++---
21
1 file changed, 12 insertions(+), 14 deletions(-)
16
2 files changed, 33 insertions(+), 5 deletions(-)
17
22
18
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
23
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
19
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/qdev-core.h
25
--- a/target/arm/t32.decode
21
+++ b/include/hw/qdev-core.h
26
+++ b/target/arm/t32.decode
22
@@ -XXX,XX +XXX,XX @@ BusState *qdev_get_child_bus(DeviceState *dev, const char *name);
27
@@ -XXX,XX +XXX,XX @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm
23
/* GPIO inputs also double as IRQ sinks. */
28
{
24
void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n);
29
# Group insn[25:23] = 111, which is cond=111x for the branch below,
25
void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n);
30
# or unconditional, which would be illegal for the branch.
26
-void qdev_init_gpio_in_named(DeviceState *dev, qemu_irq_handler handler,
31
- {
27
- const char *name, int n);
32
- # Hints
28
void qdev_init_gpio_out_named(DeviceState *dev, qemu_irq *pins,
33
+ [
29
const char *name, int n);
34
+ # Hints, and CPS
30
+/**
35
{
31
+ * qdev_init_gpio_in_named_with_opaque: create an array of input GPIO lines
36
YIELD 1111 0011 1010 1111 1000 0000 0000 0001
32
+ * for the specified device
37
WFE 1111 0011 1010 1111 1000 0000 0000 0010
33
+ *
38
@@ -XXX,XX +XXX,XX @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm
34
+ * @dev: Device to create input GPIOs for
39
# The canonical nop ends in 0000 0000, but the whole rest
35
+ * @handler: Function to call when GPIO line value is set
40
# of the space is "reserved hint, behaves as nop".
36
+ * @opaque: Opaque data pointer to pass to @handler
41
NOP 1111 0011 1010 1111 1000 0000 ---- ----
37
+ * @name: Name of the GPIO input (must be unique for this device)
38
+ * @n: Number of GPIO lines in this input set
39
+ */
40
+void qdev_init_gpio_in_named_with_opaque(DeviceState *dev,
41
+ qemu_irq_handler handler,
42
+ void *opaque,
43
+ const char *name, int n);
44
+
42
+
45
+/**
43
+ # If imod == '00' && M == '0' then SEE "Hint instructions", above.
46
+ * qdev_init_gpio_in_named: create an array of input GPIO lines
44
+ CPS 1111 0011 1010 1111 1000 0 imod:2 M:1 A:1 I:1 F:1 mode:5 \
47
+ * for the specified device
45
+ &cps
48
+ *
46
}
49
+ * Like qdev_init_gpio_in_named_with_opaque(), but the opaque pointer
47
50
+ * passed to the handler is @dev (which is the most commonly desired behaviour).
48
- # If imod == '00' && M == '0' then SEE "Hint instructions", above.
51
+ */
49
- CPS 1111 0011 1010 1111 1000 0 imod:2 M:1 A:1 I:1 F:1 mode:5 \
52
+static inline void qdev_init_gpio_in_named(DeviceState *dev,
50
- &cps
53
+ qemu_irq_handler handler,
51
-
54
+ const char *name, int n)
52
# Miscellaneous control
55
+{
53
- [
56
+ qdev_init_gpio_in_named_with_opaque(dev, handler, dev, name, n);
54
- CLREX 1111 0011 1011 1111 1000 1111 0010 1111
57
+}
55
- DSB 1111 0011 1011 1111 1000 1111 0100 ----
58
56
- DMB 1111 0011 1011 1111 1000 1111 0101 ----
59
void qdev_pass_gpios(DeviceState *dev, DeviceState *container,
57
- ISB 1111 0011 1011 1111 1000 1111 0110 ----
60
const char *name);
58
- SB 1111 0011 1011 1111 1000 1111 0111 0000
61
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
59
- ]
62
index XXXXXXX..XXXXXXX 100644
60
+ CLREX 1111 0011 1011 1111 1000 1111 0010 1111
63
--- a/hw/core/qdev.c
61
+ DSB 1111 0011 1011 1111 1000 1111 0100 ----
64
+++ b/hw/core/qdev.c
62
+ DMB 1111 0011 1011 1111 1000 1111 0101 ----
65
@@ -XXX,XX +XXX,XX @@ static NamedGPIOList *qdev_get_named_gpio_list(DeviceState *dev,
63
+ ISB 1111 0011 1011 1111 1000 1111 0110 ----
66
return ngl;
64
+ SB 1111 0011 1011 1111 1000 1111 0111 0000
65
66
# Note that the v7m insn overlaps both the normal and banked insn.
67
{
68
@@ -XXX,XX +XXX,XX @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm
69
HVC 1111 0111 1110 .... 1000 .... .... .... \
70
&i imm=%imm16_16_0
71
UDF 1111 0111 1111 ---- 1010 ---- ---- ----
72
- }
73
+ ]
74
B_cond_thumb 1111 0. cond:4 ...... 10.0 ............ &ci imm=%imm21
67
}
75
}
68
76
69
-void qdev_init_gpio_in_named(DeviceState *dev, qemu_irq_handler handler,
70
- const char *name, int n)
71
+void qdev_init_gpio_in_named_with_opaque(DeviceState *dev,
72
+ qemu_irq_handler handler,
73
+ void *opaque,
74
+ const char *name, int n)
75
{
76
int i;
77
NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name);
78
79
assert(gpio_list->num_out == 0 || !name);
80
gpio_list->in = qemu_extend_irqs(gpio_list->in, gpio_list->num_in, handler,
81
- dev, n);
82
+ opaque, n);
83
84
if (!name) {
85
name = "unnamed-gpio-in";
86
--
77
--
87
2.16.2
78
2.20.1
88
79
89
80
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The BLX immediate insn in the Thumb encoding always performs
2
a switch from Thumb to Arm state. This would be totally useless
3
in M-profile which has no Arm decoder, and so the instruction
4
does not exist at all there. Make the encoding UNDEF for M-profile.
2
5
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
(This part of the encoding space is used for the branch-future
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
and low-overhead-loop insns in v8.1M.)
5
Message-id: 20180228193125.20577-14-richard.henderson@linaro.org
8
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20201019151301.2046-6-peter.maydell@linaro.org
7
---
12
---
8
target/arm/translate.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++
13
target/arm/translate.c | 8 ++++++++
9
1 file changed, 68 insertions(+)
14
1 file changed, 8 insertions(+)
10
15
11
diff --git a/target/arm/translate.c b/target/arm/translate.c
16
diff --git a/target/arm/translate.c b/target/arm/translate.c
12
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate.c
18
--- a/target/arm/translate.c
14
+++ b/target/arm/translate.c
19
+++ b/target/arm/translate.c
15
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
20
@@ -XXX,XX +XXX,XX @@ static bool trans_BLX_i(DisasContext *s, arg_BLX_i *a)
16
return 0;
21
{
17
}
22
TCGv_i32 tmp;
18
23
19
+/* Advanced SIMD three registers of the same length extension.
24
+ /*
20
+ * 31 25 23 22 20 16 12 11 10 9 8 3 0
25
+ * BLX <imm> would be useless on M-profile; the encoding space
21
+ * +---------------+-----+---+-----+----+----+---+----+---+----+---------+----+
26
+ * is used for other insns from v8.1M onward, and UNDEFs before that.
22
+ * | 1 1 1 1 1 1 0 | op1 | D | op2 | Vn | Vd | 1 | o3 | 0 | o4 | N Q M U | Vm |
27
+ */
23
+ * +---------------+-----+---+-----+----+----+---+----+---+----+---------+----+
28
+ if (arm_dc_feature(s, ARM_FEATURE_M)) {
24
+ */
29
+ return false;
25
+static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
26
+{
27
+ gen_helper_gvec_3_ptr *fn_gvec_ptr;
28
+ int rd, rn, rm, rot, size, opr_sz;
29
+ TCGv_ptr fpst;
30
+ bool q;
31
+
32
+ q = extract32(insn, 6, 1);
33
+ VFP_DREG_D(rd, insn);
34
+ VFP_DREG_N(rn, insn);
35
+ VFP_DREG_M(rm, insn);
36
+ if ((rd | rn | rm) & q) {
37
+ return 1;
38
+ }
30
+ }
39
+
31
+
40
+ if ((insn & 0xfe200f10) == 0xfc200800) {
32
/* For A32, ARM_FEATURE_V5 is checked near the start of the uncond block. */
41
+ /* VCMLA -- 1111 110R R.1S .... .... 1000 ...0 .... */
33
if (s->thumb && (a->imm & 2)) {
42
+ size = extract32(insn, 20, 1);
34
return false;
43
+ rot = extract32(insn, 23, 2);
44
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_FCMA)
45
+ || (!size && !arm_dc_feature(s, ARM_FEATURE_V8_FP16))) {
46
+ return 1;
47
+ }
48
+ fn_gvec_ptr = size ? gen_helper_gvec_fcmlas : gen_helper_gvec_fcmlah;
49
+ } else if ((insn & 0xfea00f10) == 0xfc800800) {
50
+ /* VCADD -- 1111 110R 1.0S .... .... 1000 ...0 .... */
51
+ size = extract32(insn, 20, 1);
52
+ rot = extract32(insn, 24, 1);
53
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_FCMA)
54
+ || (!size && !arm_dc_feature(s, ARM_FEATURE_V8_FP16))) {
55
+ return 1;
56
+ }
57
+ fn_gvec_ptr = size ? gen_helper_gvec_fcadds : gen_helper_gvec_fcaddh;
58
+ } else {
59
+ return 1;
60
+ }
61
+
62
+ if (s->fp_excp_el) {
63
+ gen_exception_insn(s, 4, EXCP_UDEF,
64
+ syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
65
+ return 0;
66
+ }
67
+ if (!s->vfp_enabled) {
68
+ return 1;
69
+ }
70
+
71
+ opr_sz = (1 + q) * 8;
72
+ fpst = get_fpstatus_ptr(1);
73
+ tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
74
+ vfp_reg_offset(1, rn),
75
+ vfp_reg_offset(1, rm), fpst,
76
+ opr_sz, opr_sz, rot, fn_gvec_ptr);
77
+ tcg_temp_free_ptr(fpst);
78
+ return 0;
79
+}
80
+
81
static int disas_coproc_insn(DisasContext *s, uint32_t insn)
82
{
83
int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
84
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
85
}
86
}
87
}
88
+ } else if ((insn & 0x0e000a00) == 0x0c000800
89
+ && arm_dc_feature(s, ARM_FEATURE_V8)) {
90
+ if (disas_neon_insn_3same_ext(s, insn)) {
91
+ goto illegal_op;
92
+ }
93
+ return;
94
} else if ((insn & 0x0fe00000) == 0x0c400000) {
95
/* Coprocessor double register transfer. */
96
ARCH(5TE);
97
--
35
--
98
2.16.2
36
2.20.1
99
37
100
38
diff view generated by jsdifflib
1
The MPS2 AN505 FPGA image includes a "FPGA control block"
1
v8.1M implements a new 'branch future' feature, which is a
2
which is a small set of registers handling LEDs, buttons
2
set of instructions that request the CPU to perform a branch
3
and some counters.
3
"in the future", when it reaches a particular execution address.
4
In hardware, the expected implementation is that the information
5
about the branch location and destination is cached and then
6
acted upon when execution reaches the specified address.
7
However the architecture permits an implementation to discard
8
this cached information at any point, and so guest code must
9
always include a normal branch insn at the branch point as
10
a fallback. In particular, an implementation is specifically
11
permitted to treat all BF insns as NOPs (which is equivalent
12
to discarding the cached information immediately).
4
13
14
For QEMU, implementing this caching of branch information
15
would be complicated and would not improve the speed of
16
execution at all, so we make the IMPDEF choice to implement
17
all BF insns as NOPs.
18
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Message-id: 20201019151301.2046-7-peter.maydell@linaro.org
7
Message-id: 20180220180325.29818-14-peter.maydell@linaro.org
8
---
22
---
9
hw/misc/Makefile.objs | 1 +
23
target/arm/cpu.h | 6 ++++++
10
include/hw/misc/mps2-fpgaio.h | 43 ++++++++++
24
target/arm/t32.decode | 13 ++++++++++++-
11
hw/misc/mps2-fpgaio.c | 176 ++++++++++++++++++++++++++++++++++++++++
25
target/arm/translate.c | 20 ++++++++++++++++++++
12
default-configs/arm-softmmu.mak | 1 +
26
3 files changed, 38 insertions(+), 1 deletion(-)
13
hw/misc/trace-events | 6 ++
14
5 files changed, 227 insertions(+)
15
create mode 100644 include/hw/misc/mps2-fpgaio.h
16
create mode 100644 hw/misc/mps2-fpgaio.c
17
27
18
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
28
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
19
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/misc/Makefile.objs
30
--- a/target/arm/cpu.h
21
+++ b/hw/misc/Makefile.objs
31
+++ b/target/arm/cpu.h
22
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_STM32F2XX_SYSCFG) += stm32f2xx_syscfg.o
32
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_arm_div(const ARMISARegisters *id)
23
obj-$(CONFIG_MIPS_CPS) += mips_cmgcr.o
33
return FIELD_EX32(id->id_isar0, ID_ISAR0, DIVIDE) > 1;
24
obj-$(CONFIG_MIPS_CPS) += mips_cpc.o
34
}
25
obj-$(CONFIG_MIPS_ITU) += mips_itu.o
35
26
+obj-$(CONFIG_MPS2_FPGAIO) += mps2-fpgaio.o
36
+static inline bool isar_feature_aa32_lob(const ARMISARegisters *id)
27
obj-$(CONFIG_MPS2_SCC) += mps2-scc.o
28
29
obj-$(CONFIG_PVPANIC) += pvpanic.o
30
diff --git a/include/hw/misc/mps2-fpgaio.h b/include/hw/misc/mps2-fpgaio.h
31
new file mode 100644
32
index XXXXXXX..XXXXXXX
33
--- /dev/null
34
+++ b/include/hw/misc/mps2-fpgaio.h
35
@@ -XXX,XX +XXX,XX @@
36
+/*
37
+ * ARM MPS2 FPGAIO emulation
38
+ *
39
+ * Copyright (c) 2018 Linaro Limited
40
+ * Written by Peter Maydell
41
+ *
42
+ * This program is free software; you can redistribute it and/or modify
43
+ * it under the terms of the GNU General Public License version 2 or
44
+ * (at your option) any later version.
45
+ */
46
+
47
+/* This is a model of the FPGAIO register block in the AN505
48
+ * FPGA image for the MPS2 dev board; it is documented in the
49
+ * application note:
50
+ * http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
51
+ *
52
+ * QEMU interface:
53
+ * + sysbus MMIO region 0: the register bank
54
+ */
55
+
56
+#ifndef MPS2_FPGAIO_H
57
+#define MPS2_FPGAIO_H
58
+
59
+#include "hw/sysbus.h"
60
+
61
+#define TYPE_MPS2_FPGAIO "mps2-fpgaio"
62
+#define MPS2_FPGAIO(obj) OBJECT_CHECK(MPS2FPGAIO, (obj), TYPE_MPS2_FPGAIO)
63
+
64
+typedef struct {
65
+ /*< private >*/
66
+ SysBusDevice parent_obj;
67
+
68
+ /*< public >*/
69
+ MemoryRegion iomem;
70
+
71
+ uint32_t led0;
72
+ uint32_t prescale;
73
+ uint32_t misc;
74
+
75
+ uint32_t prescale_clk;
76
+} MPS2FPGAIO;
77
+
78
+#endif
79
diff --git a/hw/misc/mps2-fpgaio.c b/hw/misc/mps2-fpgaio.c
80
new file mode 100644
81
index XXXXXXX..XXXXXXX
82
--- /dev/null
83
+++ b/hw/misc/mps2-fpgaio.c
84
@@ -XXX,XX +XXX,XX @@
85
+/*
86
+ * ARM MPS2 AN505 FPGAIO emulation
87
+ *
88
+ * Copyright (c) 2018 Linaro Limited
89
+ * Written by Peter Maydell
90
+ *
91
+ * This program is free software; you can redistribute it and/or modify
92
+ * it under the terms of the GNU General Public License version 2 or
93
+ * (at your option) any later version.
94
+ */
95
+
96
+/* This is a model of the "FPGA system control and I/O" block found
97
+ * in the AN505 FPGA image for the MPS2 devboard.
98
+ * It is documented in AN505:
99
+ * http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
100
+ */
101
+
102
+#include "qemu/osdep.h"
103
+#include "qemu/log.h"
104
+#include "qapi/error.h"
105
+#include "trace.h"
106
+#include "hw/sysbus.h"
107
+#include "hw/registerfields.h"
108
+#include "hw/misc/mps2-fpgaio.h"
109
+
110
+REG32(LED0, 0)
111
+REG32(BUTTON, 8)
112
+REG32(CLK1HZ, 0x10)
113
+REG32(CLK100HZ, 0x14)
114
+REG32(COUNTER, 0x18)
115
+REG32(PRESCALE, 0x1c)
116
+REG32(PSCNTR, 0x20)
117
+REG32(MISC, 0x4c)
118
+
119
+static uint64_t mps2_fpgaio_read(void *opaque, hwaddr offset, unsigned size)
120
+{
37
+{
121
+ MPS2FPGAIO *s = MPS2_FPGAIO(opaque);
38
+ /* (M-profile) low-overhead loops and branch future */
122
+ uint64_t r;
39
+ return FIELD_EX32(id->id_isar0, ID_ISAR0, CMPBRANCH) >= 3;
123
+
124
+ switch (offset) {
125
+ case A_LED0:
126
+ r = s->led0;
127
+ break;
128
+ case A_BUTTON:
129
+ /* User-pressable board buttons. We don't model that, so just return
130
+ * zeroes.
131
+ */
132
+ r = 0;
133
+ break;
134
+ case A_PRESCALE:
135
+ r = s->prescale;
136
+ break;
137
+ case A_MISC:
138
+ r = s->misc;
139
+ break;
140
+ case A_CLK1HZ:
141
+ case A_CLK100HZ:
142
+ case A_COUNTER:
143
+ case A_PSCNTR:
144
+ /* These are all upcounters of various frequencies. */
145
+ qemu_log_mask(LOG_UNIMP, "MPS2 FPGAIO: counters unimplemented\n");
146
+ r = 0;
147
+ break;
148
+ default:
149
+ qemu_log_mask(LOG_GUEST_ERROR,
150
+ "MPS2 FPGAIO read: bad offset %x\n", (int) offset);
151
+ r = 0;
152
+ break;
153
+ }
154
+
155
+ trace_mps2_fpgaio_read(offset, r, size);
156
+ return r;
157
+}
40
+}
158
+
41
+
159
+static void mps2_fpgaio_write(void *opaque, hwaddr offset, uint64_t value,
42
static inline bool isar_feature_aa32_jazelle(const ARMISARegisters *id)
160
+ unsigned size)
43
{
44
return FIELD_EX32(id->id_isar1, ID_ISAR1, JAZELLE) != 0;
45
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
46
index XXXXXXX..XXXXXXX 100644
47
--- a/target/arm/t32.decode
48
+++ b/target/arm/t32.decode
49
@@ -XXX,XX +XXX,XX @@ MRC 1110 1110 ... 1 .... .... .... ... 1 .... @mcr
50
51
B 1111 0. .......... 10.1 ............ @branch24
52
BL 1111 0. .......... 11.1 ............ @branch24
53
-BLX_i 1111 0. .......... 11.0 ............ @branch24
161
+{
54
+{
162
+ MPS2FPGAIO *s = MPS2_FPGAIO(opaque);
55
+ # BLX_i is non-M-profile only
163
+
56
+ BLX_i 1111 0. .......... 11.0 ............ @branch24
164
+ trace_mps2_fpgaio_write(offset, value, size);
57
+ # M-profile only: loop and branch insns
165
+
58
+ [
166
+ switch (offset) {
59
+ # All these BF insns have boff != 0b0000; we NOP them all
167
+ case A_LED0:
60
+ BF 1111 0 boff:4 ------- 1100 - ---------- 1 # BFL
168
+ /* LED bits [1:0] control board LEDs. We don't currently have
61
+ BF 1111 0 boff:4 0 ------ 1110 - ---------- 1 # BFCSEL
169
+ * a mechanism for displaying this graphically, so use a trace event.
62
+ BF 1111 0 boff:4 10 ----- 1110 - ---------- 1 # BF
170
+ */
63
+ BF 1111 0 boff:4 11 ----- 1110 0 0000000000 1 # BFX, BFLX
171
+ trace_mps2_fpgaio_leds(value & 0x02 ? '*' : '.',
64
+ ]
172
+ value & 0x01 ? '*' : '.');
65
+}
173
+ s->led0 = value & 0x3;
66
diff --git a/target/arm/translate.c b/target/arm/translate.c
174
+ break;
67
index XXXXXXX..XXXXXXX 100644
175
+ case A_PRESCALE:
68
--- a/target/arm/translate.c
176
+ s->prescale = value;
69
+++ b/target/arm/translate.c
177
+ break;
70
@@ -XXX,XX +XXX,XX @@ static bool trans_BLX_suffix(DisasContext *s, arg_BLX_suffix *a)
178
+ case A_MISC:
71
return true;
179
+ /* These are control bits for some of the other devices on the
72
}
180
+ * board (SPI, CLCD, etc). We don't implement that yet, so just
73
181
+ * make the bits read as written.
74
+static bool trans_BF(DisasContext *s, arg_BF *a)
182
+ */
75
+{
183
+ qemu_log_mask(LOG_UNIMP,
76
+ /*
184
+ "MPS2 FPGAIO: MISC control bits unimplemented\n");
77
+ * M-profile branch future insns. The architecture permits an
185
+ s->misc = value;
78
+ * implementation to implement these as NOPs (equivalent to
186
+ break;
79
+ * discarding the LO_BRANCH_INFO cache immediately), and we
187
+ default:
80
+ * take that IMPDEF option because for QEMU a "real" implementation
188
+ qemu_log_mask(LOG_GUEST_ERROR,
81
+ * would be complicated and wouldn't execute any faster.
189
+ "MPS2 FPGAIO write: bad offset 0x%x\n", (int) offset);
82
+ */
190
+ break;
83
+ if (!dc_isar_feature(aa32_lob, s)) {
84
+ return false;
191
+ }
85
+ }
86
+ if (a->boff == 0) {
87
+ /* SEE "Related encodings" (loop insns) */
88
+ return false;
89
+ }
90
+ /* Handle as NOP */
91
+ return true;
192
+}
92
+}
193
+
93
+
194
+static const MemoryRegionOps mps2_fpgaio_ops = {
94
static bool op_tbranch(DisasContext *s, arg_tbranch *a, bool half)
195
+ .read = mps2_fpgaio_read,
95
{
196
+ .write = mps2_fpgaio_write,
96
TCGv_i32 addr, tmp;
197
+ .endianness = DEVICE_LITTLE_ENDIAN,
198
+};
199
+
200
+static void mps2_fpgaio_reset(DeviceState *dev)
201
+{
202
+ MPS2FPGAIO *s = MPS2_FPGAIO(dev);
203
+
204
+ trace_mps2_fpgaio_reset();
205
+ s->led0 = 0;
206
+ s->prescale = 0;
207
+ s->misc = 0;
208
+}
209
+
210
+static void mps2_fpgaio_init(Object *obj)
211
+{
212
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
213
+ MPS2FPGAIO *s = MPS2_FPGAIO(obj);
214
+
215
+ memory_region_init_io(&s->iomem, obj, &mps2_fpgaio_ops, s,
216
+ "mps2-fpgaio", 0x1000);
217
+ sysbus_init_mmio(sbd, &s->iomem);
218
+}
219
+
220
+static const VMStateDescription mps2_fpgaio_vmstate = {
221
+ .name = "mps2-fpgaio",
222
+ .version_id = 1,
223
+ .minimum_version_id = 1,
224
+ .fields = (VMStateField[]) {
225
+ VMSTATE_UINT32(led0, MPS2FPGAIO),
226
+ VMSTATE_UINT32(prescale, MPS2FPGAIO),
227
+ VMSTATE_UINT32(misc, MPS2FPGAIO),
228
+ VMSTATE_END_OF_LIST()
229
+ }
230
+};
231
+
232
+static Property mps2_fpgaio_properties[] = {
233
+ /* Frequency of the prescale counter */
234
+ DEFINE_PROP_UINT32("prescale-clk", MPS2FPGAIO, prescale_clk, 20000000),
235
+ DEFINE_PROP_END_OF_LIST(),
236
+};
237
+
238
+static void mps2_fpgaio_class_init(ObjectClass *klass, void *data)
239
+{
240
+ DeviceClass *dc = DEVICE_CLASS(klass);
241
+
242
+ dc->vmsd = &mps2_fpgaio_vmstate;
243
+ dc->reset = mps2_fpgaio_reset;
244
+ dc->props = mps2_fpgaio_properties;
245
+}
246
+
247
+static const TypeInfo mps2_fpgaio_info = {
248
+ .name = TYPE_MPS2_FPGAIO,
249
+ .parent = TYPE_SYS_BUS_DEVICE,
250
+ .instance_size = sizeof(MPS2FPGAIO),
251
+ .instance_init = mps2_fpgaio_init,
252
+ .class_init = mps2_fpgaio_class_init,
253
+};
254
+
255
+static void mps2_fpgaio_register_types(void)
256
+{
257
+ type_register_static(&mps2_fpgaio_info);
258
+}
259
+
260
+type_init(mps2_fpgaio_register_types);
261
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
262
index XXXXXXX..XXXXXXX 100644
263
--- a/default-configs/arm-softmmu.mak
264
+++ b/default-configs/arm-softmmu.mak
265
@@ -XXX,XX +XXX,XX @@ CONFIG_STM32F205_SOC=y
266
CONFIG_CMSDK_APB_TIMER=y
267
CONFIG_CMSDK_APB_UART=y
268
269
+CONFIG_MPS2_FPGAIO=y
270
CONFIG_MPS2_SCC=y
271
272
CONFIG_VERSATILE_PCI=y
273
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
274
index XXXXXXX..XXXXXXX 100644
275
--- a/hw/misc/trace-events
276
+++ b/hw/misc/trace-events
277
@@ -XXX,XX +XXX,XX @@ mps2_scc_leds(char led7, char led6, char led5, char led4, char led3, char led2,
278
mps2_scc_cfg_write(unsigned function, unsigned device, uint32_t value) "MPS2 SCC config write: function %d device %d data 0x%" PRIx32
279
mps2_scc_cfg_read(unsigned function, unsigned device, uint32_t value) "MPS2 SCC config read: function %d device %d data 0x%" PRIx32
280
281
+# hw/misc/mps2_fpgaio.c
282
+mps2_fpgaio_read(uint64_t offset, uint64_t data, unsigned size) "MPS2 FPGAIO read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
283
+mps2_fpgaio_write(uint64_t offset, uint64_t data, unsigned size) "MPS2 FPGAIO write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
284
+mps2_fpgaio_reset(void) "MPS2 FPGAIO: reset"
285
+mps2_fpgaio_leds(char led1, char led0) "MPS2 FPGAIO LEDs: %c%c"
286
+
287
# hw/misc/msf2-sysreg.c
288
msf2_sysreg_write(uint64_t offset, uint32_t val, uint32_t prev) "msf2-sysreg write: addr 0x%08" HWADDR_PRIx " data 0x%" PRIx32 " prev 0x%" PRIx32
289
msf2_sysreg_read(uint64_t offset, uint32_t val) "msf2-sysreg read: addr 0x%08" HWADDR_PRIx " data 0x%08" PRIx32
290
--
97
--
291
2.16.2
98
2.20.1
292
99
293
100
diff view generated by jsdifflib
1
Add a model of the TrustZone peripheral protection controller (PPC),
1
v8.1M's "low-overhead-loop" extension has three instructions
2
which is used to gate transactions to non-TZ-aware peripherals so
2
for looping:
3
that secure software can configure them to not be accessible to
3
* DLS (start of a do-loop)
4
non-secure software.
4
* WLS (start of a while-loop)
5
* LE (end of a loop)
6
7
The loop-start instructions are both simple operations to start a
8
loop whose iteration count (if any) is in LR. The loop-end
9
instruction handles "decrement iteration count and jump back to loop
10
start"; it also caches the information about the branch back to the
11
start of the loop to improve performance of the branch on subsequent
12
iterations.
13
14
As with the branch-future instructions, the architecture permits an
15
implementation to discard the LO_BRANCH_INFO cache at any time, and
16
QEMU takes the IMPDEF option to never set it in the first place
17
(equivalent to discarding it immediately), because for us a "real"
18
implementation would be unnecessary complexity.
19
20
(This implementation only provides the simple looping constructs; the
21
vector extension MVE (Helium) adds some extra variants to handle
22
looping across vectors. We'll add those later when we implement
23
MVE.)
5
24
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
26
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180220180325.29818-15-peter.maydell@linaro.org
27
Message-id: 20201019151301.2046-8-peter.maydell@linaro.org
9
---
28
---
10
hw/misc/Makefile.objs | 2 +
29
target/arm/t32.decode | 8 ++++
11
include/hw/misc/tz-ppc.h | 101 ++++++++++++++
30
target/arm/translate.c | 93 +++++++++++++++++++++++++++++++++++++++++-
12
hw/misc/tz-ppc.c | 302 ++++++++++++++++++++++++++++++++++++++++
31
2 files changed, 99 insertions(+), 2 deletions(-)
13
default-configs/arm-softmmu.mak | 2 +
14
hw/misc/trace-events | 11 ++
15
5 files changed, 418 insertions(+)
16
create mode 100644 include/hw/misc/tz-ppc.h
17
create mode 100644 hw/misc/tz-ppc.c
18
32
19
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
33
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
20
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/misc/Makefile.objs
35
--- a/target/arm/t32.decode
22
+++ b/hw/misc/Makefile.objs
36
+++ b/target/arm/t32.decode
23
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_MIPS_ITU) += mips_itu.o
37
@@ -XXX,XX +XXX,XX @@ BL 1111 0. .......... 11.1 ............ @branch24
24
obj-$(CONFIG_MPS2_FPGAIO) += mps2-fpgaio.o
38
BF 1111 0 boff:4 10 ----- 1110 - ---------- 1 # BF
25
obj-$(CONFIG_MPS2_SCC) += mps2-scc.o
39
BF 1111 0 boff:4 11 ----- 1110 0 0000000000 1 # BFX, BFLX
26
40
]
27
+obj-$(CONFIG_TZ_PPC) += tz-ppc.o
41
+ [
42
+ # LE and WLS immediate
43
+ %lob_imm 1:10 11:1 !function=times_2
28
+
44
+
29
obj-$(CONFIG_PVPANIC) += pvpanic.o
45
+ DLS 1111 0 0000 100 rn:4 1110 0000 0000 0001
30
obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
46
+ WLS 1111 0 0000 100 rn:4 1100 . .......... 1 imm=%lob_imm
31
obj-$(CONFIG_AUX) += auxbus.o
47
+ LE 1111 0 0000 0 f:1 0 1111 1100 . .......... 1 imm=%lob_imm
32
diff --git a/include/hw/misc/tz-ppc.h b/include/hw/misc/tz-ppc.h
48
+ ]
33
new file mode 100644
49
}
34
index XXXXXXX..XXXXXXX
50
diff --git a/target/arm/translate.c b/target/arm/translate.c
35
--- /dev/null
51
index XXXXXXX..XXXXXXX 100644
36
+++ b/include/hw/misc/tz-ppc.h
52
--- a/target/arm/translate.c
37
@@ -XXX,XX +XXX,XX @@
53
+++ b/target/arm/translate.c
38
+/*
54
@@ -XXX,XX +XXX,XX @@ static void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
39
+ * ARM TrustZone peripheral protection controller emulation
55
s->base.is_jmp = DISAS_NORETURN;
40
+ *
56
}
41
+ * Copyright (c) 2018 Linaro Limited
57
42
+ * Written by Peter Maydell
58
-static inline void gen_jmp (DisasContext *s, uint32_t dest)
43
+ *
59
+/* Jump, specifying which TB number to use if we gen_goto_tb() */
44
+ * This program is free software; you can redistribute it and/or modify
60
+static inline void gen_jmp_tb(DisasContext *s, uint32_t dest, int tbno)
45
+ * it under the terms of the GNU General Public License version 2 or
61
{
46
+ * (at your option) any later version.
62
if (unlikely(is_singlestepping(s))) {
47
+ */
63
/* An indirect jump so that we still trigger the debug exception. */
48
+
64
gen_set_pc_im(s, dest);
49
+/* This is a model of the TrustZone peripheral protection controller (PPC).
65
s->base.is_jmp = DISAS_JUMP;
50
+ * It is documented in the ARM CoreLink SIE-200 System IP for Embedded TRM
66
} else {
51
+ * (DDI 0571G):
67
- gen_goto_tb(s, 0, dest);
52
+ * https://developer.arm.com/products/architecture/m-profile/docs/ddi0571/g
68
+ gen_goto_tb(s, tbno, dest);
53
+ *
69
}
54
+ * The PPC sits in front of peripherals and allows secure software to
70
}
55
+ * configure it to either pass through or reject transactions.
71
56
+ * Rejected transactions may be configured to either be aborted, or to
72
+static inline void gen_jmp(DisasContext *s, uint32_t dest)
57
+ * behave as RAZ/WI. An interrupt can be signalled for a rejected transaction.
58
+ *
59
+ * The PPC has no register interface -- it is configured purely by a
60
+ * collection of input signals from other hardware in the system. Typically
61
+ * they are either hardwired or exposed in an ad-hoc register interface by
62
+ * the SoC that uses the PPC.
63
+ *
64
+ * This QEMU model can be used to model either the AHB5 or APB4 TZ PPC,
65
+ * since the only difference between them is that the AHB version has a
66
+ * "default" port which has no security checks applied. In QEMU the default
67
+ * port can be emulated simply by wiring its downstream devices directly
68
+ * into the parent address space, since the PPC does not need to intercept
69
+ * transactions there.
70
+ *
71
+ * In the hardware, selection of which downstream port to use is done by
72
+ * the user's decode logic asserting one of the hsel[] signals. In QEMU,
73
+ * we provide 16 MMIO regions, one per port, and the user maps these into
74
+ * the desired addresses to implement the address decode.
75
+ *
76
+ * QEMU interface:
77
+ * + sysbus MMIO regions 0..15: MemoryRegions defining the upstream end
78
+ * of each of the 16 ports of the PPC
79
+ * + Property "port[0..15]": MemoryRegion defining the downstream device(s)
80
+ * for each of the 16 ports of the PPC
81
+ * + Named GPIO inputs "cfg_nonsec[0..15]": set to 1 if the port should be
82
+ * accessible to NonSecure transactions
83
+ * + Named GPIO inputs "cfg_ap[0..15]": set to 1 if the port should be
84
+ * accessible to non-privileged transactions
85
+ * + Named GPIO input "cfg_sec_resp": set to 1 if a rejected transaction should
86
+ * result in a transaction error, or 0 for the transaction to RAZ/WI
87
+ * + Named GPIO input "irq_enable": set to 1 to enable interrupts
88
+ * + Named GPIO input "irq_clear": set to 1 to clear a pending interrupt
89
+ * + Named GPIO output "irq": set for a transaction-failed interrupt
90
+ * + Property "NONSEC_MASK": if a bit is set in this mask then accesses to
91
+ * the associated port do not have the TZ security check performed. (This
92
+ * corresponds to the hardware allowing this to be set as a Verilog
93
+ * parameter.)
94
+ */
95
+
96
+#ifndef TZ_PPC_H
97
+#define TZ_PPC_H
98
+
99
+#include "hw/sysbus.h"
100
+
101
+#define TYPE_TZ_PPC "tz-ppc"
102
+#define TZ_PPC(obj) OBJECT_CHECK(TZPPC, (obj), TYPE_TZ_PPC)
103
+
104
+#define TZ_NUM_PORTS 16
105
+
106
+typedef struct TZPPC TZPPC;
107
+
108
+typedef struct TZPPCPort {
109
+ TZPPC *ppc;
110
+ MemoryRegion upstream;
111
+ AddressSpace downstream_as;
112
+ MemoryRegion *downstream;
113
+} TZPPCPort;
114
+
115
+struct TZPPC {
116
+ /*< private >*/
117
+ SysBusDevice parent_obj;
118
+
119
+ /*< public >*/
120
+
121
+ /* State: these just track the values of our input signals */
122
+ bool cfg_nonsec[TZ_NUM_PORTS];
123
+ bool cfg_ap[TZ_NUM_PORTS];
124
+ bool cfg_sec_resp;
125
+ bool irq_enable;
126
+ bool irq_clear;
127
+ /* State: are we asserting irq ? */
128
+ bool irq_status;
129
+
130
+ qemu_irq irq;
131
+
132
+ /* Properties */
133
+ uint32_t nonsec_mask;
134
+
135
+ TZPPCPort port[TZ_NUM_PORTS];
136
+};
137
+
138
+#endif
139
diff --git a/hw/misc/tz-ppc.c b/hw/misc/tz-ppc.c
140
new file mode 100644
141
index XXXXXXX..XXXXXXX
142
--- /dev/null
143
+++ b/hw/misc/tz-ppc.c
144
@@ -XXX,XX +XXX,XX @@
145
+/*
146
+ * ARM TrustZone peripheral protection controller emulation
147
+ *
148
+ * Copyright (c) 2018 Linaro Limited
149
+ * Written by Peter Maydell
150
+ *
151
+ * This program is free software; you can redistribute it and/or modify
152
+ * it under the terms of the GNU General Public License version 2 or
153
+ * (at your option) any later version.
154
+ */
155
+
156
+#include "qemu/osdep.h"
157
+#include "qemu/log.h"
158
+#include "qapi/error.h"
159
+#include "trace.h"
160
+#include "hw/sysbus.h"
161
+#include "hw/registerfields.h"
162
+#include "hw/misc/tz-ppc.h"
163
+
164
+static void tz_ppc_update_irq(TZPPC *s)
165
+{
73
+{
166
+ bool level = s->irq_status && s->irq_enable;
74
+ gen_jmp_tb(s, dest, 0);
167
+
168
+ trace_tz_ppc_update_irq(level);
169
+ qemu_set_irq(s->irq, level);
170
+}
75
+}
171
+
76
+
172
+static void tz_ppc_cfg_nonsec(void *opaque, int n, int level)
77
static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y)
78
{
79
if (x)
80
@@ -XXX,XX +XXX,XX @@ static bool trans_BF(DisasContext *s, arg_BF *a)
81
return true;
82
}
83
84
+static bool trans_DLS(DisasContext *s, arg_DLS *a)
173
+{
85
+{
174
+ TZPPC *s = TZ_PPC(opaque);
86
+ /* M-profile low-overhead loop start */
87
+ TCGv_i32 tmp;
175
+
88
+
176
+ assert(n < TZ_NUM_PORTS);
89
+ if (!dc_isar_feature(aa32_lob, s)) {
177
+ trace_tz_ppc_cfg_nonsec(n, level);
178
+ s->cfg_nonsec[n] = level;
179
+}
180
+
181
+static void tz_ppc_cfg_ap(void *opaque, int n, int level)
182
+{
183
+ TZPPC *s = TZ_PPC(opaque);
184
+
185
+ assert(n < TZ_NUM_PORTS);
186
+ trace_tz_ppc_cfg_ap(n, level);
187
+ s->cfg_ap[n] = level;
188
+}
189
+
190
+static void tz_ppc_cfg_sec_resp(void *opaque, int n, int level)
191
+{
192
+ TZPPC *s = TZ_PPC(opaque);
193
+
194
+ trace_tz_ppc_cfg_sec_resp(level);
195
+ s->cfg_sec_resp = level;
196
+}
197
+
198
+static void tz_ppc_irq_enable(void *opaque, int n, int level)
199
+{
200
+ TZPPC *s = TZ_PPC(opaque);
201
+
202
+ trace_tz_ppc_irq_enable(level);
203
+ s->irq_enable = level;
204
+ tz_ppc_update_irq(s);
205
+}
206
+
207
+static void tz_ppc_irq_clear(void *opaque, int n, int level)
208
+{
209
+ TZPPC *s = TZ_PPC(opaque);
210
+
211
+ trace_tz_ppc_irq_clear(level);
212
+
213
+ s->irq_clear = level;
214
+ if (level) {
215
+ s->irq_status = false;
216
+ tz_ppc_update_irq(s);
217
+ }
218
+}
219
+
220
+static bool tz_ppc_check(TZPPC *s, int n, MemTxAttrs attrs)
221
+{
222
+ /* Check whether to allow an access to port n; return true if
223
+ * the check passes, and false if the transaction must be blocked.
224
+ * If the latter, the caller must check cfg_sec_resp to determine
225
+ * whether to abort or RAZ/WI the transaction.
226
+ * The checks are:
227
+ * + nonsec_mask suppresses any check of the secure attribute
228
+ * + otherwise, block if cfg_nonsec is 1 and transaction is secure,
229
+ * or if cfg_nonsec is 0 and transaction is non-secure
230
+ * + block if transaction is usermode and cfg_ap is 0
231
+ */
232
+ if ((attrs.secure == s->cfg_nonsec[n] && !(s->nonsec_mask & (1 << n))) ||
233
+ (attrs.user && !s->cfg_ap[n])) {
234
+ /* Block the transaction. */
235
+ if (!s->irq_clear) {
236
+ /* Note that holding irq_clear high suppresses interrupts */
237
+ s->irq_status = true;
238
+ tz_ppc_update_irq(s);
239
+ }
240
+ return false;
90
+ return false;
241
+ }
91
+ }
92
+ if (a->rn == 13 || a->rn == 15) {
93
+ /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */
94
+ return false;
95
+ }
96
+
97
+ /* Not a while loop, no tail predication: just set LR to the count */
98
+ tmp = load_reg(s, a->rn);
99
+ store_reg(s, 14, tmp);
242
+ return true;
100
+ return true;
243
+}
101
+}
244
+
102
+
245
+static MemTxResult tz_ppc_read(void *opaque, hwaddr addr, uint64_t *pdata,
103
+static bool trans_WLS(DisasContext *s, arg_WLS *a)
246
+ unsigned size, MemTxAttrs attrs)
247
+{
104
+{
248
+ TZPPCPort *p = opaque;
105
+ /* M-profile low-overhead while-loop start */
249
+ TZPPC *s = p->ppc;
106
+ TCGv_i32 tmp;
250
+ int n = p - s->port;
107
+ TCGLabel *nextlabel;
251
+ AddressSpace *as = &p->downstream_as;
252
+ uint64_t data;
253
+ MemTxResult res;
254
+
108
+
255
+ if (!tz_ppc_check(s, n, attrs)) {
109
+ if (!dc_isar_feature(aa32_lob, s)) {
256
+ trace_tz_ppc_read_blocked(n, addr, attrs.secure, attrs.user);
110
+ return false;
257
+ if (s->cfg_sec_resp) {
111
+ }
258
+ return MEMTX_ERROR;
112
+ if (a->rn == 13 || a->rn == 15) {
259
+ } else {
113
+ /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */
260
+ *pdata = 0;
114
+ return false;
261
+ return MEMTX_OK;
115
+ }
262
+ }
116
+ if (s->condexec_mask) {
117
+ /*
118
+ * WLS in an IT block is CONSTRAINED UNPREDICTABLE;
119
+ * we choose to UNDEF, because otherwise our use of
120
+ * gen_goto_tb(1) would clash with the use of TB exit 1
121
+ * in the dc->condjmp condition-failed codepath in
122
+ * arm_tr_tb_stop() and we'd get an assertion.
123
+ */
124
+ return false;
125
+ }
126
+ nextlabel = gen_new_label();
127
+ tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_R[a->rn], 0, nextlabel);
128
+ tmp = load_reg(s, a->rn);
129
+ store_reg(s, 14, tmp);
130
+ gen_jmp_tb(s, s->base.pc_next, 1);
131
+
132
+ gen_set_label(nextlabel);
133
+ gen_jmp(s, read_pc(s) + a->imm);
134
+ return true;
135
+}
136
+
137
+static bool trans_LE(DisasContext *s, arg_LE *a)
138
+{
139
+ /*
140
+ * M-profile low-overhead loop end. The architecture permits an
141
+ * implementation to discard the LO_BRANCH_INFO cache at any time,
142
+ * and we take the IMPDEF option to never set it in the first place
143
+ * (equivalent to always discarding it immediately), because for QEMU
144
+ * a "real" implementation would be complicated and wouldn't execute
145
+ * any faster.
146
+ */
147
+ TCGv_i32 tmp;
148
+
149
+ if (!dc_isar_feature(aa32_lob, s)) {
150
+ return false;
263
+ }
151
+ }
264
+
152
+
265
+ switch (size) {
153
+ if (!a->f) {
266
+ case 1:
154
+ /* Not loop-forever. If LR <= 1 this is the last loop: do nothing. */
267
+ data = address_space_ldub(as, addr, attrs, &res);
155
+ arm_gen_condlabel(s);
268
+ break;
156
+ tcg_gen_brcondi_i32(TCG_COND_LEU, cpu_R[14], 1, s->condlabel);
269
+ case 2:
157
+ /* Decrement LR */
270
+ data = address_space_lduw_le(as, addr, attrs, &res);
158
+ tmp = load_reg(s, 14);
271
+ break;
159
+ tcg_gen_addi_i32(tmp, tmp, -1);
272
+ case 4:
160
+ store_reg(s, 14, tmp);
273
+ data = address_space_ldl_le(as, addr, attrs, &res);
274
+ break;
275
+ case 8:
276
+ data = address_space_ldq_le(as, addr, attrs, &res);
277
+ break;
278
+ default:
279
+ g_assert_not_reached();
280
+ }
161
+ }
281
+ *pdata = data;
162
+ /* Jump back to the loop start */
282
+ return res;
163
+ gen_jmp(s, read_pc(s) - a->imm);
164
+ return true;
283
+}
165
+}
284
+
166
+
285
+static MemTxResult tz_ppc_write(void *opaque, hwaddr addr, uint64_t val,
167
static bool op_tbranch(DisasContext *s, arg_tbranch *a, bool half)
286
+ unsigned size, MemTxAttrs attrs)
168
{
287
+{
169
TCGv_i32 addr, tmp;
288
+ TZPPCPort *p = opaque;
289
+ TZPPC *s = p->ppc;
290
+ AddressSpace *as = &p->downstream_as;
291
+ int n = p - s->port;
292
+ MemTxResult res;
293
+
294
+ if (!tz_ppc_check(s, n, attrs)) {
295
+ trace_tz_ppc_write_blocked(n, addr, attrs.secure, attrs.user);
296
+ if (s->cfg_sec_resp) {
297
+ return MEMTX_ERROR;
298
+ } else {
299
+ return MEMTX_OK;
300
+ }
301
+ }
302
+
303
+ switch (size) {
304
+ case 1:
305
+ address_space_stb(as, addr, val, attrs, &res);
306
+ break;
307
+ case 2:
308
+ address_space_stw_le(as, addr, val, attrs, &res);
309
+ break;
310
+ case 4:
311
+ address_space_stl_le(as, addr, val, attrs, &res);
312
+ break;
313
+ case 8:
314
+ address_space_stq_le(as, addr, val, attrs, &res);
315
+ break;
316
+ default:
317
+ g_assert_not_reached();
318
+ }
319
+ return res;
320
+}
321
+
322
+static const MemoryRegionOps tz_ppc_ops = {
323
+ .read_with_attrs = tz_ppc_read,
324
+ .write_with_attrs = tz_ppc_write,
325
+ .endianness = DEVICE_LITTLE_ENDIAN,
326
+};
327
+
328
+static void tz_ppc_reset(DeviceState *dev)
329
+{
330
+ TZPPC *s = TZ_PPC(dev);
331
+
332
+ trace_tz_ppc_reset();
333
+ s->cfg_sec_resp = false;
334
+ memset(s->cfg_nonsec, 0, sizeof(s->cfg_nonsec));
335
+ memset(s->cfg_ap, 0, sizeof(s->cfg_ap));
336
+}
337
+
338
+static void tz_ppc_init(Object *obj)
339
+{
340
+ DeviceState *dev = DEVICE(obj);
341
+ TZPPC *s = TZ_PPC(obj);
342
+
343
+ qdev_init_gpio_in_named(dev, tz_ppc_cfg_nonsec, "cfg_nonsec", TZ_NUM_PORTS);
344
+ qdev_init_gpio_in_named(dev, tz_ppc_cfg_ap, "cfg_ap", TZ_NUM_PORTS);
345
+ qdev_init_gpio_in_named(dev, tz_ppc_cfg_sec_resp, "cfg_sec_resp", 1);
346
+ qdev_init_gpio_in_named(dev, tz_ppc_irq_enable, "irq_enable", 1);
347
+ qdev_init_gpio_in_named(dev, tz_ppc_irq_clear, "irq_clear", 1);
348
+ qdev_init_gpio_out_named(dev, &s->irq, "irq", 1);
349
+}
350
+
351
+static void tz_ppc_realize(DeviceState *dev, Error **errp)
352
+{
353
+ Object *obj = OBJECT(dev);
354
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
355
+ TZPPC *s = TZ_PPC(dev);
356
+ int i;
357
+
358
+ /* We can't create the upstream end of the port until realize,
359
+ * as we don't know the size of the MR used as the downstream until then.
360
+ */
361
+ for (i = 0; i < TZ_NUM_PORTS; i++) {
362
+ TZPPCPort *port = &s->port[i];
363
+ char *name;
364
+ uint64_t size;
365
+
366
+ if (!port->downstream) {
367
+ continue;
368
+ }
369
+
370
+ name = g_strdup_printf("tz-ppc-port[%d]", i);
371
+
372
+ port->ppc = s;
373
+ address_space_init(&port->downstream_as, port->downstream, name);
374
+
375
+ size = memory_region_size(port->downstream);
376
+ memory_region_init_io(&port->upstream, obj, &tz_ppc_ops,
377
+ port, name, size);
378
+ sysbus_init_mmio(sbd, &port->upstream);
379
+ g_free(name);
380
+ }
381
+}
382
+
383
+static const VMStateDescription tz_ppc_vmstate = {
384
+ .name = "tz-ppc",
385
+ .version_id = 1,
386
+ .minimum_version_id = 1,
387
+ .fields = (VMStateField[]) {
388
+ VMSTATE_BOOL_ARRAY(cfg_nonsec, TZPPC, 16),
389
+ VMSTATE_BOOL_ARRAY(cfg_ap, TZPPC, 16),
390
+ VMSTATE_BOOL(cfg_sec_resp, TZPPC),
391
+ VMSTATE_BOOL(irq_enable, TZPPC),
392
+ VMSTATE_BOOL(irq_clear, TZPPC),
393
+ VMSTATE_BOOL(irq_status, TZPPC),
394
+ VMSTATE_END_OF_LIST()
395
+ }
396
+};
397
+
398
+#define DEFINE_PORT(N) \
399
+ DEFINE_PROP_LINK("port[" #N "]", TZPPC, port[N].downstream, \
400
+ TYPE_MEMORY_REGION, MemoryRegion *)
401
+
402
+static Property tz_ppc_properties[] = {
403
+ DEFINE_PROP_UINT32("NONSEC_MASK", TZPPC, nonsec_mask, 0),
404
+ DEFINE_PORT(0),
405
+ DEFINE_PORT(1),
406
+ DEFINE_PORT(2),
407
+ DEFINE_PORT(3),
408
+ DEFINE_PORT(4),
409
+ DEFINE_PORT(5),
410
+ DEFINE_PORT(6),
411
+ DEFINE_PORT(7),
412
+ DEFINE_PORT(8),
413
+ DEFINE_PORT(9),
414
+ DEFINE_PORT(10),
415
+ DEFINE_PORT(11),
416
+ DEFINE_PORT(12),
417
+ DEFINE_PORT(13),
418
+ DEFINE_PORT(14),
419
+ DEFINE_PORT(15),
420
+ DEFINE_PROP_END_OF_LIST(),
421
+};
422
+
423
+static void tz_ppc_class_init(ObjectClass *klass, void *data)
424
+{
425
+ DeviceClass *dc = DEVICE_CLASS(klass);
426
+
427
+ dc->realize = tz_ppc_realize;
428
+ dc->vmsd = &tz_ppc_vmstate;
429
+ dc->reset = tz_ppc_reset;
430
+ dc->props = tz_ppc_properties;
431
+}
432
+
433
+static const TypeInfo tz_ppc_info = {
434
+ .name = TYPE_TZ_PPC,
435
+ .parent = TYPE_SYS_BUS_DEVICE,
436
+ .instance_size = sizeof(TZPPC),
437
+ .instance_init = tz_ppc_init,
438
+ .class_init = tz_ppc_class_init,
439
+};
440
+
441
+static void tz_ppc_register_types(void)
442
+{
443
+ type_register_static(&tz_ppc_info);
444
+}
445
+
446
+type_init(tz_ppc_register_types);
447
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
448
index XXXXXXX..XXXXXXX 100644
449
--- a/default-configs/arm-softmmu.mak
450
+++ b/default-configs/arm-softmmu.mak
451
@@ -XXX,XX +XXX,XX @@ CONFIG_CMSDK_APB_UART=y
452
CONFIG_MPS2_FPGAIO=y
453
CONFIG_MPS2_SCC=y
454
455
+CONFIG_TZ_PPC=y
456
+
457
CONFIG_VERSATILE_PCI=y
458
CONFIG_VERSATILE_I2C=y
459
460
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
461
index XXXXXXX..XXXXXXX 100644
462
--- a/hw/misc/trace-events
463
+++ b/hw/misc/trace-events
464
@@ -XXX,XX +XXX,XX @@ mos6522_get_next_irq_time(uint16_t latch, int64_t d, int64_t delta) "latch=%d co
465
mos6522_set_sr_int(void) "set sr_int"
466
mos6522_write(uint64_t addr, uint64_t val) "reg=0x%"PRIx64 " val=0x%"PRIx64
467
mos6522_read(uint64_t addr, unsigned val) "reg=0x%"PRIx64 " val=0x%x"
468
+
469
+# hw/misc/tz-ppc.c
470
+tz_ppc_reset(void) "TZ PPC: reset"
471
+tz_ppc_cfg_nonsec(int n, int level) "TZ PPC: cfg_nonsec[%d] = %d"
472
+tz_ppc_cfg_ap(int n, int level) "TZ PPC: cfg_ap[%d] = %d"
473
+tz_ppc_cfg_sec_resp(int level) "TZ PPC: cfg_sec_resp = %d"
474
+tz_ppc_irq_enable(int level) "TZ PPC: int_enable = %d"
475
+tz_ppc_irq_clear(int level) "TZ PPC: int_clear = %d"
476
+tz_ppc_update_irq(int level) "TZ PPC: setting irq line to %d"
477
+tz_ppc_read_blocked(int n, hwaddr offset, bool secure, bool user) "TZ PPC: port %d offset 0x%" HWADDR_PRIx " read (secure %d user %d) blocked"
478
+tz_ppc_write_blocked(int n, hwaddr offset, bool secure, bool user) "TZ PPC: port %d offset 0x%" HWADDR_PRIx " write (secure %d user %d) blocked"
479
--
170
--
480
2.16.2
171
2.20.1
481
172
482
173
diff view generated by jsdifflib
1
Add a Cortex-M33 definition. The M33 is an M profile CPU
1
In arm_cpu_realizefn(), if the CPU has VFP or Neon disabled then we
2
which implements the ARM v8M architecture, including the
2
squash the ID register fields so that we don't advertise it to the
3
M profile Security Extension.
3
guest. This code was written for A-profile and needs some tweaks to
4
work correctly on M-profile:
4
5
6
* A-profile only fields should not be zeroed on M-profile:
7
- MVFR0.FPSHVEC,FPTRAP
8
- MVFR1.SIMDLS,SIMDINT,SIMDSP,SIMDHP
9
- MVFR2.SIMDMISC
10
* M-profile only fields should be zeroed on M-profile:
11
- MVFR1.FP16
12
13
In particular, because MVFR1.SIMDHP on A-profile is the same field as
14
MVFR1.FP16 on M-profile this code was incorrectly disabling FP16
15
support on an M-profile CPU (where has_neon is always false). This
16
isn't a visible bug yet because we don't have any M-profile CPUs with
17
FP16 support, but the change is necessary before we introduce any.
18
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Message-id: 20201019151301.2046-9-peter.maydell@linaro.org
7
Message-id: 20180220180325.29818-9-peter.maydell@linaro.org
8
---
22
---
9
target/arm/cpu.c | 31 +++++++++++++++++++++++++++++++
23
target/arm/cpu.c | 29 ++++++++++++++++++-----------
10
1 file changed, 31 insertions(+)
24
1 file changed, 18 insertions(+), 11 deletions(-)
11
25
12
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
26
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
13
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/cpu.c
28
--- a/target/arm/cpu.c
15
+++ b/target/arm/cpu.c
29
+++ b/target/arm/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void cortex_m4_initfn(Object *obj)
30
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
17
cpu->id_isar5 = 0x00000000;
31
u = cpu->isar.mvfr0;
18
}
32
u = FIELD_DP32(u, MVFR0, FPSP, 0);
19
33
u = FIELD_DP32(u, MVFR0, FPDP, 0);
20
+static void cortex_m33_initfn(Object *obj)
34
- u = FIELD_DP32(u, MVFR0, FPTRAP, 0);
21
+{
35
u = FIELD_DP32(u, MVFR0, FPDIVIDE, 0);
22
+ ARMCPU *cpu = ARM_CPU(obj);
36
u = FIELD_DP32(u, MVFR0, FPSQRT, 0);
23
+
37
- u = FIELD_DP32(u, MVFR0, FPSHVEC, 0);
24
+ set_feature(&cpu->env, ARM_FEATURE_V8);
38
u = FIELD_DP32(u, MVFR0, FPROUND, 0);
25
+ set_feature(&cpu->env, ARM_FEATURE_M);
39
+ if (!arm_feature(env, ARM_FEATURE_M)) {
26
+ set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
40
+ u = FIELD_DP32(u, MVFR0, FPTRAP, 0);
27
+ set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
41
+ u = FIELD_DP32(u, MVFR0, FPSHVEC, 0);
28
+ cpu->midr = 0x410fd213; /* r0p3 */
42
+ }
29
+ cpu->pmsav7_dregion = 16;
43
cpu->isar.mvfr0 = u;
30
+ cpu->sau_sregion = 8;
44
31
+ cpu->id_pfr0 = 0x00000030;
45
u = cpu->isar.mvfr1;
32
+ cpu->id_pfr1 = 0x00000210;
46
u = FIELD_DP32(u, MVFR1, FPFTZ, 0);
33
+ cpu->id_dfr0 = 0x00200000;
47
u = FIELD_DP32(u, MVFR1, FPDNAN, 0);
34
+ cpu->id_afr0 = 0x00000000;
48
u = FIELD_DP32(u, MVFR1, FPHP, 0);
35
+ cpu->id_mmfr0 = 0x00101F40;
49
+ if (arm_feature(env, ARM_FEATURE_M)) {
36
+ cpu->id_mmfr1 = 0x00000000;
50
+ u = FIELD_DP32(u, MVFR1, FP16, 0);
37
+ cpu->id_mmfr2 = 0x01000000;
51
+ }
38
+ cpu->id_mmfr3 = 0x00000000;
52
cpu->isar.mvfr1 = u;
39
+ cpu->id_isar0 = 0x01101110;
53
40
+ cpu->id_isar1 = 0x02212000;
54
u = cpu->isar.mvfr2;
41
+ cpu->id_isar2 = 0x20232232;
55
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
42
+ cpu->id_isar3 = 0x01111131;
56
u = FIELD_DP32(u, ID_ISAR6, FHM, 0);
43
+ cpu->id_isar4 = 0x01310132;
57
cpu->isar.id_isar6 = u;
44
+ cpu->id_isar5 = 0x00000000;
58
45
+ cpu->clidr = 0x00000000;
59
- u = cpu->isar.mvfr1;
46
+ cpu->ctr = 0x8000c000;
60
- u = FIELD_DP32(u, MVFR1, SIMDLS, 0);
47
+}
61
- u = FIELD_DP32(u, MVFR1, SIMDINT, 0);
48
+
62
- u = FIELD_DP32(u, MVFR1, SIMDSP, 0);
49
static void arm_v7m_class_init(ObjectClass *oc, void *data)
63
- u = FIELD_DP32(u, MVFR1, SIMDHP, 0);
50
{
64
- cpu->isar.mvfr1 = u;
51
CPUClass *cc = CPU_CLASS(oc);
65
+ if (!arm_feature(env, ARM_FEATURE_M)) {
52
@@ -XXX,XX +XXX,XX @@ static const ARMCPUInfo arm_cpus[] = {
66
+ u = cpu->isar.mvfr1;
53
.class_init = arm_v7m_class_init },
67
+ u = FIELD_DP32(u, MVFR1, SIMDLS, 0);
54
{ .name = "cortex-m4", .initfn = cortex_m4_initfn,
68
+ u = FIELD_DP32(u, MVFR1, SIMDINT, 0);
55
.class_init = arm_v7m_class_init },
69
+ u = FIELD_DP32(u, MVFR1, SIMDSP, 0);
56
+ { .name = "cortex-m33", .initfn = cortex_m33_initfn,
70
+ u = FIELD_DP32(u, MVFR1, SIMDHP, 0);
57
+ .class_init = arm_v7m_class_init },
71
+ cpu->isar.mvfr1 = u;
58
{ .name = "cortex-r5", .initfn = cortex_r5_initfn },
72
59
{ .name = "cortex-a7", .initfn = cortex_a7_initfn },
73
- u = cpu->isar.mvfr2;
60
{ .name = "cortex-a8", .initfn = cortex_a8_initfn },
74
- u = FIELD_DP32(u, MVFR2, SIMDMISC, 0);
75
- cpu->isar.mvfr2 = u;
76
+ u = cpu->isar.mvfr2;
77
+ u = FIELD_DP32(u, MVFR2, SIMDMISC, 0);
78
+ cpu->isar.mvfr2 = u;
79
+ }
80
}
81
82
if (!cpu->has_neon && !cpu->has_vfp) {
61
--
83
--
62
2.16.2
84
2.20.1
63
85
64
86
diff view generated by jsdifflib
1
Add a function load_ramdisk_as() which behaves like the existing
1
M-profile CPUs with half-precision floating point support should
2
load_ramdisk() but allows the caller to specify the AddressSpace
2
be able to write to FPSCR.FZ16, but an M-profile specific masking
3
to use. This matches the pattern we have already for various
3
of the value at the top of vfp_set_fpscr() currently prevents that.
4
other loader functions.
4
This is not yet an active bug because we have no M-profile
5
FP16 CPUs, but needs to be fixed before we can add any.
6
7
The bits that the masking is effectively preventing from being
8
set are the A-profile only short-vector Len and Stride fields,
9
plus the Neon QC bit. Rearrange the order of the function so
10
that those fields are handled earlier and only under a suitable
11
guard; this allows us to drop the M-profile specific masking,
12
making FZ16 writeable.
13
14
This change also makes the QC bit correctly RAZ/WI for older
15
no-Neon A-profile cores.
16
17
This refactoring also paves the way for the low-overhead-branch
18
LTPSIZE field, which uses some of the bits that are used for
19
A-profile Stride and Len.
5
20
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
22
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20180220180325.29818-2-peter.maydell@linaro.org
23
Message-id: 20201019151301.2046-10-peter.maydell@linaro.org
10
---
24
---
11
include/hw/loader.h | 12 +++++++++++-
25
target/arm/vfp_helper.c | 47 ++++++++++++++++++++++++-----------------
12
hw/core/loader.c | 8 +++++++-
26
1 file changed, 28 insertions(+), 19 deletions(-)
13
2 files changed, 18 insertions(+), 2 deletions(-)
14
27
15
diff --git a/include/hw/loader.h b/include/hw/loader.h
28
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
16
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/loader.h
30
--- a/target/arm/vfp_helper.c
18
+++ b/include/hw/loader.h
31
+++ b/target/arm/vfp_helper.c
19
@@ -XXX,XX +XXX,XX @@ int load_uimage(const char *filename, hwaddr *ep,
32
@@ -XXX,XX +XXX,XX @@ void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
20
void *translate_opaque);
33
val &= ~FPCR_FZ16;
21
34
}
22
/**
35
23
- * load_ramdisk:
36
- if (arm_feature(env, ARM_FEATURE_M)) {
24
+ * load_ramdisk_as:
37
+ vfp_set_fpscr_to_host(env, val);
25
* @filename: Path to the ramdisk image
26
* @addr: Memory address to load the ramdisk to
27
* @max_sz: Maximum allowed ramdisk size (for non-u-boot ramdisks)
28
+ * @as: The AddressSpace to load the ELF to. The value of address_space_memory
29
+ * is used if nothing is supplied here.
30
*
31
* Load a ramdisk image with U-Boot header to the specified memory
32
* address.
33
*
34
* Returns the size of the loaded image on success, -1 otherwise.
35
*/
36
+int load_ramdisk_as(const char *filename, hwaddr addr, uint64_t max_sz,
37
+ AddressSpace *as);
38
+
38
+
39
+/**
39
+ if (!arm_feature(env, ARM_FEATURE_M)) {
40
+ * load_ramdisk:
40
/*
41
+ * Same as load_ramdisk_as(), but doesn't allow the caller to specify
41
- * M profile FPSCR is RES0 for the QC, STRIDE, FZ16, LEN bits
42
+ * an AddressSpace.
42
- * and also for the trapped-exception-handling bits IxE.
43
+ */
43
+ * Short-vector length and stride; on M-profile these bits
44
int load_ramdisk(const char *filename, hwaddr addr, uint64_t max_sz);
44
+ * are used for different purposes.
45
45
+ * We can't make this conditional be "if MVFR0.FPShVec != 0",
46
ssize_t gunzip(void *dst, size_t dstlen, uint8_t *src, size_t srclen);
46
+ * because in v7A no-short-vector-support cores still had to
47
diff --git a/hw/core/loader.c b/hw/core/loader.c
47
+ * allow Stride/Len to be written with the only effect that
48
index XXXXXXX..XXXXXXX 100644
48
+ * some insns are required to UNDEF if the guest sets them.
49
--- a/hw/core/loader.c
49
+ *
50
+++ b/hw/core/loader.c
50
+ * TODO: if M-profile MVE implemented, set LTPSIZE.
51
@@ -XXX,XX +XXX,XX @@ int load_uimage_as(const char *filename, hwaddr *ep, hwaddr *loadaddr,
51
*/
52
52
- val &= 0xf7c0009f;
53
/* Load a ramdisk. */
53
+ env->vfp.vec_len = extract32(val, 16, 3);
54
int load_ramdisk(const char *filename, hwaddr addr, uint64_t max_sz)
54
+ env->vfp.vec_stride = extract32(val, 20, 2);
55
+{
55
}
56
+ return load_ramdisk_as(filename, addr, max_sz, NULL);
56
57
+}
57
- vfp_set_fpscr_to_host(env, val);
58
+
58
+ if (arm_feature(env, ARM_FEATURE_NEON)) {
59
+int load_ramdisk_as(const char *filename, hwaddr addr, uint64_t max_sz,
59
+ /*
60
+ AddressSpace *as)
60
+ * The bit we set within fpscr_q is arbitrary; the register as a
61
{
61
+ * whole being zero/non-zero is what counts.
62
return load_uboot_image(filename, NULL, &addr, NULL, IH_TYPE_RAMDISK,
62
+ * TODO: M-profile MVE also has a QC bit.
63
- NULL, NULL, NULL);
63
+ */
64
+ NULL, NULL, as);
64
+ env->vfp.qc[0] = val & FPCR_QC;
65
+ env->vfp.qc[1] = 0;
66
+ env->vfp.qc[2] = 0;
67
+ env->vfp.qc[3] = 0;
68
+ }
69
70
/*
71
* We don't implement trapped exception handling, so the
72
* trap enable bits, IDE|IXE|UFE|OFE|DZE|IOE are all RAZ/WI (not RES0!)
73
*
74
- * If we exclude the exception flags, IOC|DZC|OFC|UFC|IXC|IDC
75
- * (which are stored in fp_status), and the other RES0 bits
76
- * in between, then we clear all of the low 16 bits.
77
+ * The exception flags IOC|DZC|OFC|UFC|IXC|IDC are stored in
78
+ * fp_status; QC, Len and Stride are stored separately earlier.
79
+ * Clear out all of those and the RES0 bits: only NZCV, AHP, DN,
80
+ * FZ, RMode and FZ16 are kept in vfp.xregs[FPSCR].
81
*/
82
env->vfp.xregs[ARM_VFP_FPSCR] = val & 0xf7c80000;
83
- env->vfp.vec_len = (val >> 16) & 7;
84
- env->vfp.vec_stride = (val >> 20) & 3;
85
-
86
- /*
87
- * The bit we set within fpscr_q is arbitrary; the register as a
88
- * whole being zero/non-zero is what counts.
89
- */
90
- env->vfp.qc[0] = val & FPCR_QC;
91
- env->vfp.qc[1] = 0;
92
- env->vfp.qc[2] = 0;
93
- env->vfp.qc[3] = 0;
65
}
94
}
66
95
67
/* Load a gzip-compressed kernel to a dynamically allocated buffer. */
96
void vfp_set_fpscr(CPUARMState *env, uint32_t val)
68
--
97
--
69
2.16.2
98
2.20.1
70
99
71
100
diff view generated by jsdifflib
1
The Cortex-M33 allows the system to specify the reset value of the
1
If the M-profile low-overhead-branch extension is implemented, FPSCR
2
secure Vector Table Offset Register (VTOR) by asserting config
2
bits [18:16] are a new field LTPSIZE. If MVE is not implemented
3
signals. In particular, guest images for the MPS2 AN505 board rely
3
(currently always true for us) then this field always reads as 4 and
4
on the MPS2's initial VTOR being correct for that board.
4
ignores writes.
5
Implement a QEMU property so board and SoC code can set the reset
5
6
value to the correct value.
6
These bits used to be the vector-length field for the old
7
short-vector extension, so we need to take care that they are not
8
misinterpreted as setting vec_len. We do this with a rearrangement
9
of the vfp_set_fpscr() code that deals with vec_len, vec_stride
10
and also the QC bit; this obviates the need for the M-profile
11
only masking step that we used to have at the start of the function.
12
13
We provide a new field in CPUState for LTPSIZE, even though this
14
will always be 4, in preparation for MVE, so we don't have to
15
come back later and split it out of the vfp.xregs[FPSCR] value.
16
(This state struct field will be saved and restored as part of
17
the FPSCR value via the vmstate_fpscr in machine.c.)
7
18
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20180220180325.29818-7-peter.maydell@linaro.org
21
Message-id: 20201019151301.2046-11-peter.maydell@linaro.org
11
---
22
---
12
target/arm/cpu.h | 3 +++
23
target/arm/cpu.h | 1 +
13
target/arm/cpu.c | 18 ++++++++++++++----
24
target/arm/cpu.c | 9 +++++++++
14
2 files changed, 17 insertions(+), 4 deletions(-)
25
target/arm/vfp_helper.c | 6 ++++++
26
3 files changed, 16 insertions(+)
15
27
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
28
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu.h
30
--- a/target/arm/cpu.h
19
+++ b/target/arm/cpu.h
31
+++ b/target/arm/cpu.h
20
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
32
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
21
*/
33
uint32_t fpdscr[M_REG_NUM_BANKS];
22
uint32_t psci_conduit;
34
uint32_t cpacr[M_REG_NUM_BANKS];
23
35
uint32_t nsacr;
24
+ /* For v8M, initial value of the Secure VTOR */
36
+ int ltpsize;
25
+ uint32_t init_svtor;
37
} v7m;
26
+
38
27
/* [QEMU_]KVM_ARM_TARGET_* constant for this CPU, or
39
/* Information associated with an exception about to be taken:
28
* QEMU_KVM_ARM_TARGET_NONE if the kernel doesn't support this CPU type.
29
*/
30
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
40
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
31
index XXXXXXX..XXXXXXX 100644
41
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/cpu.c
42
--- a/target/arm/cpu.c
33
+++ b/target/arm/cpu.c
43
+++ b/target/arm/cpu.c
34
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
44
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
35
uint32_t initial_msp; /* Loaded from 0x0 */
36
uint32_t initial_pc; /* Loaded from 0x4 */
37
uint8_t *rom;
45
uint8_t *rom;
38
+ uint32_t vecbase;
46
uint32_t vecbase;
39
47
48
+ if (cpu_isar_feature(aa32_lob, cpu)) {
49
+ /*
50
+ * LTPSIZE is constant 4 if MVE not implemented, and resets
51
+ * to an UNKNOWN value if MVE is implemented. We choose to
52
+ * always reset to 4.
53
+ */
54
+ env->v7m.ltpsize = 4;
55
+ }
56
+
40
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
57
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
41
env->v7m.secure = true;
58
env->v7m.secure = true;
42
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
59
} else {
43
/* Unlike A/R profile, M profile defines the reset LR value */
60
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
44
env->regs[14] = 0xffffffff;
61
index XXXXXXX..XXXXXXX 100644
45
62
--- a/target/arm/vfp_helper.c
46
- /* Load the initial SP and PC from the vector table at address 0 */
63
+++ b/target/arm/vfp_helper.c
47
- rom = rom_ptr(0);
64
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(vfp_get_fpscr)(CPUARMState *env)
48
+ env->v7m.vecbase[M_REG_S] = cpu->init_svtor & 0xffffff80;
65
| (env->vfp.vec_len << 16)
66
| (env->vfp.vec_stride << 20);
67
68
+ /*
69
+ * M-profile LTPSIZE overlaps A-profile Stride; whichever of the
70
+ * two is not applicable to this CPU will always be zero.
71
+ */
72
+ fpscr |= env->v7m.ltpsize << 16;
49
+
73
+
50
+ /* Load the initial SP and PC from offset 0 and 4 in the vector table */
74
fpscr |= vfp_get_fpscr_from_host(env);
51
+ vecbase = env->v7m.vecbase[env->v7m.secure];
75
52
+ rom = rom_ptr(vecbase);
76
i = env->vfp.qc[0] | env->vfp.qc[1] | env->vfp.qc[2] | env->vfp.qc[3];
53
if (rom) {
54
/* Address zero is covered by ROM which hasn't yet been
55
* copied into physical memory.
56
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
57
* it got copied into memory. In the latter case, rom_ptr
58
* will return a NULL pointer and we should use ldl_phys instead.
59
*/
60
- initial_msp = ldl_phys(s->as, 0);
61
- initial_pc = ldl_phys(s->as, 4);
62
+ initial_msp = ldl_phys(s->as, vecbase);
63
+ initial_pc = ldl_phys(s->as, vecbase + 4);
64
}
65
66
env->regs[13] = initial_msp & 0xFFFFFFFC;
67
@@ -XXX,XX +XXX,XX @@ static Property arm_cpu_pmsav7_dregion_property =
68
pmsav7_dregion,
69
qdev_prop_uint32, uint32_t);
70
71
+/* M profile: initial value of the Secure VTOR */
72
+static Property arm_cpu_initsvtor_property =
73
+ DEFINE_PROP_UINT32("init-svtor", ARMCPU, init_svtor, 0);
74
+
75
static void arm_cpu_post_init(Object *obj)
76
{
77
ARMCPU *cpu = ARM_CPU(obj);
78
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_post_init(Object *obj)
79
qdev_prop_allow_set_link_before_realize,
80
OBJ_PROP_LINK_UNREF_ON_RELEASE,
81
&error_abort);
82
+ qdev_property_add_static(DEVICE(obj), &arm_cpu_initsvtor_property,
83
+ &error_abort);
84
}
85
86
qdev_property_add_static(DEVICE(obj), &arm_cpu_cfgend_property,
87
--
77
--
88
2.16.2
78
2.20.1
89
79
90
80
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
3
The kernel sets btype for the signal handler as if for a call.
4
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180228193125.20577-5-richard.henderson@linaro.org
7
Message-id: 20201016184207.786698-2-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
9
---
8
target/arm/Makefile.objs | 2 +-
10
linux-user/aarch64/signal.c | 10 ++++++++--
9
target/arm/helper.h | 4 ++
11
1 file changed, 8 insertions(+), 2 deletions(-)
10
target/arm/translate-a64.c | 84 ++++++++++++++++++++++++++++++++++
11
target/arm/vec_helper.c | 109 +++++++++++++++++++++++++++++++++++++++++++++
12
4 files changed, 198 insertions(+), 1 deletion(-)
13
create mode 100644 target/arm/vec_helper.c
14
12
15
diff --git a/target/arm/Makefile.objs b/target/arm/Makefile.objs
13
diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
16
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/Makefile.objs
15
--- a/linux-user/aarch64/signal.c
18
+++ b/target/arm/Makefile.objs
16
+++ b/linux-user/aarch64/signal.c
19
@@ -XXX,XX +XXX,XX @@ obj-$(call land,$(CONFIG_KVM),$(call lnot,$(TARGET_AARCH64))) += kvm32.o
17
@@ -XXX,XX +XXX,XX @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
20
obj-$(call land,$(CONFIG_KVM),$(TARGET_AARCH64)) += kvm64.o
18
+ offsetof(struct target_rt_frame_record, tramp);
21
obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o
19
}
22
obj-y += translate.o op_helper.o helper.o cpu.o
20
env->xregs[0] = usig;
23
-obj-y += neon_helper.o iwmmxt_helper.o
21
- env->xregs[31] = frame_addr;
24
+obj-y += neon_helper.o iwmmxt_helper.o vec_helper.o
22
env->xregs[29] = frame_addr + fr_ofs;
25
obj-y += gdbstub.o
23
- env->pc = ka->_sa_handler;
26
obj-$(TARGET_AARCH64) += cpu64.o translate-a64.o helper-a64.o gdbstub64.o
24
env->xregs[30] = return_addr;
27
obj-y += crypto_helper.o
25
+ env->xregs[31] = frame_addr;
28
diff --git a/target/arm/helper.h b/target/arm/helper.h
26
+ env->pc = ka->_sa_handler;
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/helper.h
31
+++ b/target/arm/helper.h
32
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_1(neon_rbit_u8, TCG_CALL_NO_RWG_SE, i32, i32)
33
34
DEF_HELPER_3(neon_qdmulh_s16, i32, env, i32, i32)
35
DEF_HELPER_3(neon_qrdmulh_s16, i32, env, i32, i32)
36
+DEF_HELPER_4(neon_qrdmlah_s16, i32, env, i32, i32, i32)
37
+DEF_HELPER_4(neon_qrdmlsh_s16, i32, env, i32, i32, i32)
38
DEF_HELPER_3(neon_qdmulh_s32, i32, env, i32, i32)
39
DEF_HELPER_3(neon_qrdmulh_s32, i32, env, i32, i32)
40
+DEF_HELPER_4(neon_qrdmlah_s32, i32, env, s32, s32, s32)
41
+DEF_HELPER_4(neon_qrdmlsh_s32, i32, env, s32, s32, s32)
42
43
DEF_HELPER_1(neon_narrow_u8, i32, i64)
44
DEF_HELPER_1(neon_narrow_u16, i32, i64)
45
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/target/arm/translate-a64.c
48
+++ b/target/arm/translate-a64.c
49
@@ -XXX,XX +XXX,XX @@ static void disas_simd_scalar_three_reg_same_fp16(DisasContext *s,
50
tcg_temp_free_ptr(fpst);
51
}
52
53
+/* AdvSIMD scalar three same extra
54
+ * 31 30 29 28 24 23 22 21 20 16 15 14 11 10 9 5 4 0
55
+ * +-----+---+-----------+------+---+------+---+--------+---+----+----+
56
+ * | 0 1 | U | 1 1 1 1 0 | size | 0 | Rm | 1 | opcode | 1 | Rn | Rd |
57
+ * +-----+---+-----------+------+---+------+---+--------+---+----+----+
58
+ */
59
+static void disas_simd_scalar_three_reg_same_extra(DisasContext *s,
60
+ uint32_t insn)
61
+{
62
+ int rd = extract32(insn, 0, 5);
63
+ int rn = extract32(insn, 5, 5);
64
+ int opcode = extract32(insn, 11, 4);
65
+ int rm = extract32(insn, 16, 5);
66
+ int size = extract32(insn, 22, 2);
67
+ bool u = extract32(insn, 29, 1);
68
+ TCGv_i32 ele1, ele2, ele3;
69
+ TCGv_i64 res;
70
+ int feature;
71
+
27
+
72
+ switch (u * 16 + opcode) {
28
+ /* Invoke the signal handler as if by indirect call. */
73
+ case 0x10: /* SQRDMLAH (vector) */
29
+ if (cpu_isar_feature(aa64_bti, env_archcpu(env))) {
74
+ case 0x11: /* SQRDMLSH (vector) */
30
+ env->btype = 2;
75
+ if (size != 1 && size != 2) {
76
+ unallocated_encoding(s);
77
+ return;
78
+ }
79
+ feature = ARM_FEATURE_V8_RDM;
80
+ break;
81
+ default:
82
+ unallocated_encoding(s);
83
+ return;
84
+ }
85
+ if (!arm_dc_feature(s, feature)) {
86
+ unallocated_encoding(s);
87
+ return;
88
+ }
89
+ if (!fp_access_check(s)) {
90
+ return;
91
+ }
31
+ }
92
+
32
+
93
+ /* Do a single operation on the lowest element in the vector.
33
if (info) {
94
+ * We use the standard Neon helpers and rely on 0 OP 0 == 0
34
tswap_siginfo(&frame->info, info);
95
+ * with no side effects for all these operations.
35
env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info);
96
+ * OPTME: special-purpose helpers would avoid doing some
97
+ * unnecessary work in the helper for the 16 bit cases.
98
+ */
99
+ ele1 = tcg_temp_new_i32();
100
+ ele2 = tcg_temp_new_i32();
101
+ ele3 = tcg_temp_new_i32();
102
+
103
+ read_vec_element_i32(s, ele1, rn, 0, size);
104
+ read_vec_element_i32(s, ele2, rm, 0, size);
105
+ read_vec_element_i32(s, ele3, rd, 0, size);
106
+
107
+ switch (opcode) {
108
+ case 0x0: /* SQRDMLAH */
109
+ if (size == 1) {
110
+ gen_helper_neon_qrdmlah_s16(ele3, cpu_env, ele1, ele2, ele3);
111
+ } else {
112
+ gen_helper_neon_qrdmlah_s32(ele3, cpu_env, ele1, ele2, ele3);
113
+ }
114
+ break;
115
+ case 0x1: /* SQRDMLSH */
116
+ if (size == 1) {
117
+ gen_helper_neon_qrdmlsh_s16(ele3, cpu_env, ele1, ele2, ele3);
118
+ } else {
119
+ gen_helper_neon_qrdmlsh_s32(ele3, cpu_env, ele1, ele2, ele3);
120
+ }
121
+ break;
122
+ default:
123
+ g_assert_not_reached();
124
+ }
125
+ tcg_temp_free_i32(ele1);
126
+ tcg_temp_free_i32(ele2);
127
+
128
+ res = tcg_temp_new_i64();
129
+ tcg_gen_extu_i32_i64(res, ele3);
130
+ tcg_temp_free_i32(ele3);
131
+
132
+ write_fp_dreg(s, rd, res);
133
+ tcg_temp_free_i64(res);
134
+}
135
+
136
static void handle_2misc_64(DisasContext *s, int opcode, bool u,
137
TCGv_i64 tcg_rd, TCGv_i64 tcg_rn,
138
TCGv_i32 tcg_rmode, TCGv_ptr tcg_fpstatus)
139
@@ -XXX,XX +XXX,XX @@ static const AArch64DecodeTable data_proc_simd[] = {
140
{ 0x0e000800, 0xbf208c00, disas_simd_zip_trn },
141
{ 0x2e000000, 0xbf208400, disas_simd_ext },
142
{ 0x5e200400, 0xdf200400, disas_simd_scalar_three_reg_same },
143
+ { 0x5e008400, 0xdf208400, disas_simd_scalar_three_reg_same_extra },
144
{ 0x5e200000, 0xdf200c00, disas_simd_scalar_three_reg_diff },
145
{ 0x5e200800, 0xdf3e0c00, disas_simd_scalar_two_reg_misc },
146
{ 0x5e300800, 0xdf3e0c00, disas_simd_scalar_pairwise },
147
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
148
new file mode 100644
149
index XXXXXXX..XXXXXXX
150
--- /dev/null
151
+++ b/target/arm/vec_helper.c
152
@@ -XXX,XX +XXX,XX @@
153
+/*
154
+ * ARM AdvSIMD / SVE Vector Operations
155
+ *
156
+ * Copyright (c) 2018 Linaro
157
+ *
158
+ * This library is free software; you can redistribute it and/or
159
+ * modify it under the terms of the GNU Lesser General Public
160
+ * License as published by the Free Software Foundation; either
161
+ * version 2 of the License, or (at your option) any later version.
162
+ *
163
+ * This library is distributed in the hope that it will be useful,
164
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
165
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
166
+ * Lesser General Public License for more details.
167
+ *
168
+ * You should have received a copy of the GNU Lesser General Public
169
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
170
+ */
171
+
172
+#include "qemu/osdep.h"
173
+#include "cpu.h"
174
+#include "exec/exec-all.h"
175
+#include "exec/helper-proto.h"
176
+#include "tcg/tcg-gvec-desc.h"
177
+
178
+
179
+#define SET_QC() env->vfp.xregs[ARM_VFP_FPSCR] |= CPSR_Q
180
+
181
+/* Signed saturating rounding doubling multiply-accumulate high half, 16-bit */
182
+static uint16_t inl_qrdmlah_s16(CPUARMState *env, int16_t src1,
183
+ int16_t src2, int16_t src3)
184
+{
185
+ /* Simplify:
186
+ * = ((a3 << 16) + ((e1 * e2) << 1) + (1 << 15)) >> 16
187
+ * = ((a3 << 15) + (e1 * e2) + (1 << 14)) >> 15
188
+ */
189
+ int32_t ret = (int32_t)src1 * src2;
190
+ ret = ((int32_t)src3 << 15) + ret + (1 << 14);
191
+ ret >>= 15;
192
+ if (ret != (int16_t)ret) {
193
+ SET_QC();
194
+ ret = (ret < 0 ? -0x8000 : 0x7fff);
195
+ }
196
+ return ret;
197
+}
198
+
199
+uint32_t HELPER(neon_qrdmlah_s16)(CPUARMState *env, uint32_t src1,
200
+ uint32_t src2, uint32_t src3)
201
+{
202
+ uint16_t e1 = inl_qrdmlah_s16(env, src1, src2, src3);
203
+ uint16_t e2 = inl_qrdmlah_s16(env, src1 >> 16, src2 >> 16, src3 >> 16);
204
+ return deposit32(e1, 16, 16, e2);
205
+}
206
+
207
+/* Signed saturating rounding doubling multiply-subtract high half, 16-bit */
208
+static uint16_t inl_qrdmlsh_s16(CPUARMState *env, int16_t src1,
209
+ int16_t src2, int16_t src3)
210
+{
211
+ /* Similarly, using subtraction:
212
+ * = ((a3 << 16) - ((e1 * e2) << 1) + (1 << 15)) >> 16
213
+ * = ((a3 << 15) - (e1 * e2) + (1 << 14)) >> 15
214
+ */
215
+ int32_t ret = (int32_t)src1 * src2;
216
+ ret = ((int32_t)src3 << 15) - ret + (1 << 14);
217
+ ret >>= 15;
218
+ if (ret != (int16_t)ret) {
219
+ SET_QC();
220
+ ret = (ret < 0 ? -0x8000 : 0x7fff);
221
+ }
222
+ return ret;
223
+}
224
+
225
+uint32_t HELPER(neon_qrdmlsh_s16)(CPUARMState *env, uint32_t src1,
226
+ uint32_t src2, uint32_t src3)
227
+{
228
+ uint16_t e1 = inl_qrdmlsh_s16(env, src1, src2, src3);
229
+ uint16_t e2 = inl_qrdmlsh_s16(env, src1 >> 16, src2 >> 16, src3 >> 16);
230
+ return deposit32(e1, 16, 16, e2);
231
+}
232
+
233
+/* Signed saturating rounding doubling multiply-accumulate high half, 32-bit */
234
+uint32_t HELPER(neon_qrdmlah_s32)(CPUARMState *env, int32_t src1,
235
+ int32_t src2, int32_t src3)
236
+{
237
+ /* Simplify similarly to int_qrdmlah_s16 above. */
238
+ int64_t ret = (int64_t)src1 * src2;
239
+ ret = ((int64_t)src3 << 31) + ret + (1 << 30);
240
+ ret >>= 31;
241
+ if (ret != (int32_t)ret) {
242
+ SET_QC();
243
+ ret = (ret < 0 ? INT32_MIN : INT32_MAX);
244
+ }
245
+ return ret;
246
+}
247
+
248
+/* Signed saturating rounding doubling multiply-subtract high half, 32-bit */
249
+uint32_t HELPER(neon_qrdmlsh_s32)(CPUARMState *env, int32_t src1,
250
+ int32_t src2, int32_t src3)
251
+{
252
+ /* Simplify similarly to int_qrdmlsh_s16 above. */
253
+ int64_t ret = (int64_t)src1 * src2;
254
+ ret = ((int64_t)src3 << 31) - ret + (1 << 30);
255
+ ret >>= 31;
256
+ if (ret != (int32_t)ret) {
257
+ SET_QC();
258
+ ret = (ret < 0 ? INT32_MIN : INT32_MAX);
259
+ }
260
+ return ret;
261
+}
262
--
36
--
263
2.16.2
37
2.20.1
264
38
265
39
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
3
Transform the prot bit to a qemu internal page bit, and save
4
it in the page tables.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180228193125.20577-7-richard.henderson@linaro.org
8
Message-id: 20201016184207.786698-3-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
10
---
8
target/arm/translate-a64.c | 29 +++++++++++++++++++++++++++++
11
include/exec/cpu-all.h | 2 ++
9
1 file changed, 29 insertions(+)
12
linux-user/syscall_defs.h | 4 ++++
13
target/arm/cpu.h | 5 +++++
14
linux-user/mmap.c | 16 ++++++++++++++++
15
target/arm/translate-a64.c | 6 +++---
16
5 files changed, 30 insertions(+), 3 deletions(-)
10
17
18
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/include/exec/cpu-all.h
21
+++ b/include/exec/cpu-all.h
22
@@ -XXX,XX +XXX,XX @@ extern intptr_t qemu_host_page_mask;
23
/* FIXME: Code that sets/uses this is broken and needs to go away. */
24
#define PAGE_RESERVED 0x0020
25
#endif
26
+/* Target-specific bits that will be used via page_get_flags(). */
27
+#define PAGE_TARGET_1 0x0080
28
29
#if defined(CONFIG_USER_ONLY)
30
void page_dump(FILE *f);
31
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
32
index XXXXXXX..XXXXXXX 100644
33
--- a/linux-user/syscall_defs.h
34
+++ b/linux-user/syscall_defs.h
35
@@ -XXX,XX +XXX,XX @@ struct target_winsize {
36
#define TARGET_PROT_SEM 0x08
37
#endif
38
39
+#ifdef TARGET_AARCH64
40
+#define TARGET_PROT_BTI 0x10
41
+#endif
42
+
43
/* Common */
44
#define TARGET_MAP_SHARED    0x01        /* Share changes */
45
#define TARGET_MAP_PRIVATE    0x02        /* Changes are private */
46
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/cpu.h
49
+++ b/target/arm/cpu.h
50
@@ -XXX,XX +XXX,XX @@ static inline MemTxAttrs *typecheck_memtxattrs(MemTxAttrs *x)
51
#define arm_tlb_bti_gp(x) (typecheck_memtxattrs(x)->target_tlb_bit0)
52
#define arm_tlb_mte_tagged(x) (typecheck_memtxattrs(x)->target_tlb_bit1)
53
54
+/*
55
+ * AArch64 usage of the PAGE_TARGET_* bits for linux-user.
56
+ */
57
+#define PAGE_BTI PAGE_TARGET_1
58
+
59
/*
60
* Naming convention for isar_feature functions:
61
* Functions which test 32-bit ID registers should have _aa32_ in
62
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
63
index XXXXXXX..XXXXXXX 100644
64
--- a/linux-user/mmap.c
65
+++ b/linux-user/mmap.c
66
@@ -XXX,XX +XXX,XX @@ static int validate_prot_to_pageflags(int *host_prot, int prot)
67
*host_prot = (prot & (PROT_READ | PROT_WRITE))
68
| (prot & PROT_EXEC ? PROT_READ : 0);
69
70
+#ifdef TARGET_AARCH64
71
+ /*
72
+ * The PROT_BTI bit is only accepted if the cpu supports the feature.
73
+ * Since this is the unusual case, don't bother checking unless
74
+ * the bit has been requested. If set and valid, record the bit
75
+ * within QEMU's page_flags.
76
+ */
77
+ if (prot & TARGET_PROT_BTI) {
78
+ ARMCPU *cpu = ARM_CPU(thread_cpu);
79
+ if (cpu_isar_feature(aa64_bti, cpu)) {
80
+ valid |= TARGET_PROT_BTI;
81
+ page_flags |= PAGE_BTI;
82
+ }
83
+ }
84
+#endif
85
+
86
return prot & ~valid ? 0 : page_flags;
87
}
88
11
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
89
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
12
index XXXXXXX..XXXXXXX 100644
90
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate-a64.c
91
--- a/target/arm/translate-a64.c
14
+++ b/target/arm/translate-a64.c
92
+++ b/target/arm/translate-a64.c
15
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
93
@@ -XXX,XX +XXX,XX @@ static void disas_data_proc_simd_fp(DisasContext *s, uint32_t insn)
16
case 0x19: /* FMULX */
94
*/
17
is_fp = true;
95
static bool is_guarded_page(CPUARMState *env, DisasContext *s)
18
break;
96
{
19
+ case 0x1d: /* SQRDMLAH */
97
-#ifdef CONFIG_USER_ONLY
20
+ case 0x1f: /* SQRDMLSH */
98
- return false; /* FIXME */
21
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_RDM)) {
99
-#else
22
+ unallocated_encoding(s);
100
uint64_t addr = s->base.pc_first;
23
+ return;
101
+#ifdef CONFIG_USER_ONLY
24
+ }
102
+ return page_get_flags(addr) & PAGE_BTI;
25
+ break;
103
+#else
26
default:
104
int mmu_idx = arm_to_core_mmu_idx(s->mmu_idx);
27
unallocated_encoding(s);
105
unsigned int index = tlb_index(env, mmu_idx, addr);
28
return;
106
CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
29
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
30
tcg_op, tcg_idx);
31
}
32
break;
33
+ case 0x1d: /* SQRDMLAH */
34
+ read_vec_element_i32(s, tcg_res, rd, pass,
35
+ is_scalar ? size : MO_32);
36
+ if (size == 1) {
37
+ gen_helper_neon_qrdmlah_s16(tcg_res, cpu_env,
38
+ tcg_op, tcg_idx, tcg_res);
39
+ } else {
40
+ gen_helper_neon_qrdmlah_s32(tcg_res, cpu_env,
41
+ tcg_op, tcg_idx, tcg_res);
42
+ }
43
+ break;
44
+ case 0x1f: /* SQRDMLSH */
45
+ read_vec_element_i32(s, tcg_res, rd, pass,
46
+ is_scalar ? size : MO_32);
47
+ if (size == 1) {
48
+ gen_helper_neon_qrdmlsh_s16(tcg_res, cpu_env,
49
+ tcg_op, tcg_idx, tcg_res);
50
+ } else {
51
+ gen_helper_neon_qrdmlsh_s32(tcg_res, cpu_env,
52
+ tcg_op, tcg_idx, tcg_res);
53
+ }
54
+ break;
55
default:
56
g_assert_not_reached();
57
}
58
--
107
--
59
2.16.2
108
2.20.1
60
109
61
110
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
3
These are all of the defines required to parse
4
GNU_PROPERTY_AARCH64_FEATURE_1_AND, copied from binutils.
5
Other missing defines related to other GNU program headers
6
and notes are elided for now.
2
7
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180228193125.20577-8-richard.henderson@linaro.org
10
Message-id: 20201016184207.786698-4-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
12
---
8
target/arm/translate.c | 86 +++++++++++++++++++++++++++++++++++++++-----------
13
include/elf.h | 22 ++++++++++++++++++++++
9
1 file changed, 67 insertions(+), 19 deletions(-)
14
1 file changed, 22 insertions(+)
10
15
11
diff --git a/target/arm/translate.c b/target/arm/translate.c
16
diff --git a/include/elf.h b/include/elf.h
12
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate.c
18
--- a/include/elf.h
14
+++ b/target/arm/translate.c
19
+++ b/include/elf.h
15
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ typedef int64_t Elf64_Sxword;
16
#include "disas/disas.h"
21
#define PT_NOTE 4
17
#include "exec/exec-all.h"
22
#define PT_SHLIB 5
18
#include "tcg-op.h"
23
#define PT_PHDR 6
19
+#include "tcg-op-gvec.h"
24
+#define PT_LOOS 0x60000000
20
#include "qemu/log.h"
25
+#define PT_HIOS 0x6fffffff
21
#include "qemu/bitops.h"
26
#define PT_LOPROC 0x70000000
22
#include "arm_ldst.h"
27
#define PT_HIPROC 0x7fffffff
23
@@ -XXX,XX +XXX,XX @@ static void gen_neon_narrow_op(int op, int u, int size,
28
24
#define NEON_3R_VPMAX 20
29
+#define PT_GNU_PROPERTY (PT_LOOS + 0x474e553)
25
#define NEON_3R_VPMIN 21
26
#define NEON_3R_VQDMULH_VQRDMULH 22
27
-#define NEON_3R_VPADD 23
28
+#define NEON_3R_VPADD_VQRDMLAH 23
29
#define NEON_3R_SHA 24 /* SHA1C,SHA1P,SHA1M,SHA1SU0,SHA256H{2},SHA256SU1 */
30
-#define NEON_3R_VFM 25 /* VFMA, VFMS : float fused multiply-add */
31
+#define NEON_3R_VFM_VQRDMLSH 25 /* VFMA, VFMS, VQRDMLSH */
32
#define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */
33
#define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */
34
#define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */
35
@@ -XXX,XX +XXX,XX @@ static const uint8_t neon_3r_sizes[] = {
36
[NEON_3R_VPMAX] = 0x7,
37
[NEON_3R_VPMIN] = 0x7,
38
[NEON_3R_VQDMULH_VQRDMULH] = 0x6,
39
- [NEON_3R_VPADD] = 0x7,
40
+ [NEON_3R_VPADD_VQRDMLAH] = 0x7,
41
[NEON_3R_SHA] = 0xf, /* size field encodes op type */
42
- [NEON_3R_VFM] = 0x5, /* size bit 1 encodes op */
43
+ [NEON_3R_VFM_VQRDMLSH] = 0x7, /* For VFM, size bit 1 encodes op */
44
[NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */
45
[NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */
46
[NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */
47
@@ -XXX,XX +XXX,XX @@ static const uint8_t neon_2rm_sizes[] = {
48
[NEON_2RM_VCVT_UF] = 0x4,
49
};
50
51
+
30
+
52
+/* Expand v8.1 simd helper. */
31
#define PT_MIPS_REGINFO 0x70000000
53
+static int do_v81_helper(DisasContext *s, gen_helper_gvec_3_ptr *fn,
32
#define PT_MIPS_RTPROC 0x70000001
54
+ int q, int rd, int rn, int rm)
33
#define PT_MIPS_OPTIONS 0x70000002
55
+{
34
@@ -XXX,XX +XXX,XX @@ typedef struct elf64_shdr {
56
+ if (arm_dc_feature(s, ARM_FEATURE_V8_RDM)) {
35
#define NT_ARM_SYSTEM_CALL 0x404 /* ARM system call number */
57
+ int opr_sz = (1 + q) * 8;
36
#define NT_ARM_SVE 0x405 /* ARM Scalable Vector Extension regs */
58
+ tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
37
59
+ vfp_reg_offset(1, rn),
38
+/* Defined note types for GNU systems. */
60
+ vfp_reg_offset(1, rm), cpu_env,
61
+ opr_sz, opr_sz, 0, fn);
62
+ return 0;
63
+ }
64
+ return 1;
65
+}
66
+
39
+
67
/* Translate a NEON data processing instruction. Return nonzero if the
40
+#define NT_GNU_PROPERTY_TYPE_0 5 /* Program property */
68
instruction is invalid.
69
We process data in a mixture of 32-bit and 64-bit chunks.
70
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
71
if (q && ((rd | rn | rm) & 1)) {
72
return 1;
73
}
74
- /*
75
- * The SHA-1/SHA-256 3-register instructions require special treatment
76
- * here, as their size field is overloaded as an op type selector, and
77
- * they all consume their input in a single pass.
78
- */
79
- if (op == NEON_3R_SHA) {
80
+ switch (op) {
81
+ case NEON_3R_SHA:
82
+ /* The SHA-1/SHA-256 3-register instructions require special
83
+ * treatment here, as their size field is overloaded as an
84
+ * op type selector, and they all consume their input in a
85
+ * single pass.
86
+ */
87
if (!q) {
88
return 1;
89
}
90
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
91
tcg_temp_free_ptr(ptr2);
92
tcg_temp_free_ptr(ptr3);
93
return 0;
94
+
41
+
95
+ case NEON_3R_VPADD_VQRDMLAH:
42
+/* Values used in GNU .note.gnu.property notes (NT_GNU_PROPERTY_TYPE_0). */
96
+ if (!u) {
97
+ break; /* VPADD */
98
+ }
99
+ /* VQRDMLAH */
100
+ switch (size) {
101
+ case 1:
102
+ return do_v81_helper(s, gen_helper_gvec_qrdmlah_s16,
103
+ q, rd, rn, rm);
104
+ case 2:
105
+ return do_v81_helper(s, gen_helper_gvec_qrdmlah_s32,
106
+ q, rd, rn, rm);
107
+ }
108
+ return 1;
109
+
43
+
110
+ case NEON_3R_VFM_VQRDMLSH:
44
+#define GNU_PROPERTY_STACK_SIZE 1
111
+ if (!u) {
45
+#define GNU_PROPERTY_NO_COPY_ON_PROTECTED 2
112
+ /* VFM, VFMS */
46
+
113
+ if (size == 1) {
47
+#define GNU_PROPERTY_LOPROC 0xc0000000
114
+ return 1;
48
+#define GNU_PROPERTY_HIPROC 0xdfffffff
115
+ }
49
+#define GNU_PROPERTY_LOUSER 0xe0000000
116
+ break;
50
+#define GNU_PROPERTY_HIUSER 0xffffffff
117
+ }
51
+
118
+ /* VQRDMLSH */
52
+#define GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000
119
+ switch (size) {
53
+#define GNU_PROPERTY_AARCH64_FEATURE_1_BTI (1u << 0)
120
+ case 1:
54
+#define GNU_PROPERTY_AARCH64_FEATURE_1_PAC (1u << 1)
121
+ return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s16,
55
+
122
+ q, rd, rn, rm);
56
/*
123
+ case 2:
57
* Physical entry point into the kernel.
124
+ return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s32,
58
*
125
+ q, rd, rn, rm);
126
+ }
127
+ return 1;
128
}
129
if (size == 3 && op != NEON_3R_LOGIC) {
130
/* 64-bit element instructions. */
131
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
132
rm = rtmp;
133
}
134
break;
135
- case NEON_3R_VPADD:
136
- if (u) {
137
- return 1;
138
- }
139
- /* Fall through */
140
+ case NEON_3R_VPADD_VQRDMLAH:
141
case NEON_3R_VPMAX:
142
case NEON_3R_VPMIN:
143
pairwise = 1;
144
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
145
return 1;
146
}
147
break;
148
- case NEON_3R_VFM:
149
- if (!arm_dc_feature(s, ARM_FEATURE_VFP4) || u) {
150
+ case NEON_3R_VFM_VQRDMLSH:
151
+ if (!arm_dc_feature(s, ARM_FEATURE_VFP4)) {
152
return 1;
153
}
154
break;
155
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
156
}
157
}
158
break;
159
- case NEON_3R_VPADD:
160
+ case NEON_3R_VPADD_VQRDMLAH:
161
switch (size) {
162
case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
163
case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
164
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
165
}
166
}
167
break;
168
- case NEON_3R_VFM:
169
+ case NEON_3R_VFM_VQRDMLSH:
170
{
171
/* VFMA, VFMS: fused multiply-add */
172
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
173
--
59
--
174
2.16.2
60
2.20.1
175
61
176
62
diff view generated by jsdifflib
1
Instead of loading guest images to the system address space, use the
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
CPU's address space. This is important if we're trying to load the
3
file to memory or via an alias memory region that is provided by an
4
SoC object and thus not mapped into the system address space.
5
2
3
Fix an unlikely memory leak in load_elf_image().
4
5
Fixes: bf858897b7 ("linux-user: Re-use load_elf_image for the main binary.")
6
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20201016184207.786698-5-richard.henderson@linaro.org
9
Message-Id: <20201003174944.1972444-1-f4bug@amsat.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20180220180325.29818-4-peter.maydell@linaro.org
10
---
13
---
11
hw/arm/armv7m.c | 17 ++++++++++++++---
14
linux-user/elfload.c | 8 ++++----
12
1 file changed, 14 insertions(+), 3 deletions(-)
15
1 file changed, 4 insertions(+), 4 deletions(-)
13
16
14
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
17
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
15
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/armv7m.c
19
--- a/linux-user/elfload.c
17
+++ b/hw/arm/armv7m.c
20
+++ b/linux-user/elfload.c
18
@@ -XXX,XX +XXX,XX @@ void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size)
21
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
19
uint64_t entry;
22
info->brk = vaddr_em;
20
uint64_t lowaddr;
23
}
21
int big_endian;
24
} else if (eppnt->p_type == PT_INTERP && pinterp_name) {
22
+ AddressSpace *as;
25
- char *interp_name;
23
+ int asidx;
26
+ g_autofree char *interp_name = NULL;
24
+ CPUState *cs = CPU(cpu);
27
25
28
if (*pinterp_name) {
26
#ifdef TARGET_WORDS_BIGENDIAN
29
errmsg = "Multiple PT_INTERP entries";
27
big_endian = 1;
30
goto exit_errmsg;
28
@@ -XXX,XX +XXX,XX @@ void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size)
31
}
29
exit(1);
32
- interp_name = malloc(eppnt->p_filesz);
33
+ interp_name = g_malloc(eppnt->p_filesz);
34
if (!interp_name) {
35
goto exit_perror;
36
}
37
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
38
errmsg = "Invalid PT_INTERP entry";
39
goto exit_errmsg;
40
}
41
- *pinterp_name = interp_name;
42
+ *pinterp_name = g_steal_pointer(&interp_name);
43
#ifdef TARGET_MIPS
44
} else if (eppnt->p_type == PT_MIPS_ABIFLAGS) {
45
Mips_elf_abiflags_v0 abiflags;
46
@@ -XXX,XX +XXX,XX @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
47
if (elf_interpreter) {
48
info->load_bias = interp_info.load_bias;
49
info->entry = interp_info.entry;
50
- free(elf_interpreter);
51
+ g_free(elf_interpreter);
30
}
52
}
31
53
32
+ if (arm_feature(&cpu->env, ARM_FEATURE_EL3)) {
54
#ifdef USE_ELF_CORE_DUMP
33
+ asidx = ARMASIdx_S;
34
+ } else {
35
+ asidx = ARMASIdx_NS;
36
+ }
37
+ as = cpu_get_address_space(cs, asidx);
38
+
39
if (kernel_filename) {
40
- image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr,
41
- NULL, big_endian, EM_ARM, 1, 0);
42
+ image_size = load_elf_as(kernel_filename, NULL, NULL, &entry, &lowaddr,
43
+ NULL, big_endian, EM_ARM, 1, 0, as);
44
if (image_size < 0) {
45
- image_size = load_image_targphys(kernel_filename, 0, mem_size);
46
+ image_size = load_image_targphys_as(kernel_filename, 0,
47
+ mem_size, as);
48
lowaddr = 0;
49
}
50
if (image_size < 0) {
51
--
55
--
52
2.16.2
56
2.20.1
53
57
54
58
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Not enabled anywhere yet.
3
Fixing this now will clarify following patches.
4
4
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180228193125.20577-11-richard.henderson@linaro.org
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20201016184207.786698-6-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
9
---
10
target/arm/cpu.h | 1 +
10
linux-user/elfload.c | 12 +++++++++---
11
linux-user/elfload.c | 1 +
11
1 file changed, 9 insertions(+), 3 deletions(-)
12
2 files changed, 2 insertions(+)
13
12
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.h
17
+++ b/target/arm/cpu.h
18
@@ -XXX,XX +XXX,XX @@ enum arm_features {
19
ARM_FEATURE_V8_SM4, /* implements SM4 part of v8 Crypto Extensions */
20
ARM_FEATURE_V8_RDM, /* implements v8.1 simd round multiply */
21
ARM_FEATURE_V8_FP16, /* implements v8.2 half-precision float */
22
+ ARM_FEATURE_V8_FCMA, /* has complex number part of v8.3 extensions. */
23
};
24
25
static inline int arm_feature(CPUARMState *env, int feature)
26
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
13
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
27
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
28
--- a/linux-user/elfload.c
15
--- a/linux-user/elfload.c
29
+++ b/linux-user/elfload.c
16
+++ b/linux-user/elfload.c
30
@@ -XXX,XX +XXX,XX @@ static uint32_t get_elf_hwcap(void)
17
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
31
GET_FEATURE(ARM_FEATURE_V8_FP16,
18
abi_ulong vaddr, vaddr_po, vaddr_ps, vaddr_ef, vaddr_em, vaddr_len;
32
ARM_HWCAP_A64_FPHP | ARM_HWCAP_A64_ASIMDHP);
19
int elf_prot = 0;
33
GET_FEATURE(ARM_FEATURE_V8_RDM, ARM_HWCAP_A64_ASIMDRDM);
20
34
+ GET_FEATURE(ARM_FEATURE_V8_FCMA, ARM_HWCAP_A64_FCMA);
21
- if (eppnt->p_flags & PF_R) elf_prot = PROT_READ;
35
#undef GET_FEATURE
22
- if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
36
23
- if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
37
return hwcaps;
24
+ if (eppnt->p_flags & PF_R) {
25
+ elf_prot |= PROT_READ;
26
+ }
27
+ if (eppnt->p_flags & PF_W) {
28
+ elf_prot |= PROT_WRITE;
29
+ }
30
+ if (eppnt->p_flags & PF_X) {
31
+ elf_prot |= PROT_EXEC;
32
+ }
33
34
vaddr = load_bias + eppnt->p_vaddr;
35
vaddr_po = TARGET_ELF_PAGEOFFSET(vaddr);
38
--
36
--
39
2.16.2
37
2.20.1
40
38
41
39
diff view generated by jsdifflib
1
Instead of loading kernels, device trees, and the like to
1
From: Richard Henderson <richard.henderson@linaro.org>
2
the system address space, use the CPU's address space. This
3
is important if we're trying to load the file to memory or
4
via an alias memory region that is provided by an SoC
5
object and thus not mapped into the system address space.
6
2
3
The second loop uses a loop induction variable, and the first
4
does not. Transform the first to match the second, to simplify
5
a following patch moving code between them.
6
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20201016184207.786698-7-richard.henderson@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20180220180325.29818-3-peter.maydell@linaro.org
11
---
11
---
12
hw/arm/boot.c | 119 +++++++++++++++++++++++++++++++++++++---------------------
12
linux-user/elfload.c | 9 +++++----
13
1 file changed, 76 insertions(+), 43 deletions(-)
13
1 file changed, 5 insertions(+), 4 deletions(-)
14
14
15
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
15
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/boot.c
17
--- a/linux-user/elfload.c
18
+++ b/hw/arm/boot.c
18
+++ b/linux-user/elfload.c
19
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
20
#define ARM64_TEXT_OFFSET_OFFSET 8
20
loaddr = -1, hiaddr = 0;
21
#define ARM64_MAGIC_OFFSET 56
21
info->alignment = 0;
22
22
for (i = 0; i < ehdr->e_phnum; ++i) {
23
+static AddressSpace *arm_boot_address_space(ARMCPU *cpu,
23
- if (phdr[i].p_type == PT_LOAD) {
24
+ const struct arm_boot_info *info)
24
- abi_ulong a = phdr[i].p_vaddr - phdr[i].p_offset;
25
+{
25
+ struct elf_phdr *eppnt = phdr + i;
26
+ /* Return the address space to use for bootloader reads and writes.
26
+ if (eppnt->p_type == PT_LOAD) {
27
+ * We prefer the secure address space if the CPU has it and we're
27
+ abi_ulong a = eppnt->p_vaddr - eppnt->p_offset;
28
+ * going to boot the guest into it.
28
if (a < loaddr) {
29
+ */
29
loaddr = a;
30
+ int asidx;
31
+ CPUState *cs = CPU(cpu);
32
+
33
+ if (arm_feature(&cpu->env, ARM_FEATURE_EL3) && info->secure_boot) {
34
+ asidx = ARMASIdx_S;
35
+ } else {
36
+ asidx = ARMASIdx_NS;
37
+ }
38
+
39
+ return cpu_get_address_space(cs, asidx);
40
+}
41
+
42
typedef enum {
43
FIXUP_NONE = 0, /* do nothing */
44
FIXUP_TERMINATOR, /* end of insns */
45
@@ -XXX,XX +XXX,XX @@ static const ARMInsnFixup smpboot[] = {
46
};
47
48
static void write_bootloader(const char *name, hwaddr addr,
49
- const ARMInsnFixup *insns, uint32_t *fixupcontext)
50
+ const ARMInsnFixup *insns, uint32_t *fixupcontext,
51
+ AddressSpace *as)
52
{
53
/* Fix up the specified bootloader fragment and write it into
54
* guest memory using rom_add_blob_fixed(). fixupcontext is
55
@@ -XXX,XX +XXX,XX @@ static void write_bootloader(const char *name, hwaddr addr,
56
code[i] = tswap32(insn);
57
}
58
59
- rom_add_blob_fixed(name, code, len * sizeof(uint32_t), addr);
60
+ rom_add_blob_fixed_as(name, code, len * sizeof(uint32_t), addr, as);
61
62
g_free(code);
63
}
64
@@ -XXX,XX +XXX,XX @@ static void default_write_secondary(ARMCPU *cpu,
65
const struct arm_boot_info *info)
66
{
67
uint32_t fixupcontext[FIXUP_MAX];
68
+ AddressSpace *as = arm_boot_address_space(cpu, info);
69
70
fixupcontext[FIXUP_GIC_CPU_IF] = info->gic_cpu_if_addr;
71
fixupcontext[FIXUP_BOOTREG] = info->smp_bootreg_addr;
72
@@ -XXX,XX +XXX,XX @@ static void default_write_secondary(ARMCPU *cpu,
73
}
74
75
write_bootloader("smpboot", info->smp_loader_start,
76
- smpboot, fixupcontext);
77
+ smpboot, fixupcontext, as);
78
}
79
80
void arm_write_secure_board_setup_dummy_smc(ARMCPU *cpu,
81
const struct arm_boot_info *info,
82
hwaddr mvbar_addr)
83
{
84
+ AddressSpace *as = arm_boot_address_space(cpu, info);
85
int n;
86
uint32_t mvbar_blob[] = {
87
/* mvbar_addr: secure monitor vectors
88
@@ -XXX,XX +XXX,XX @@ void arm_write_secure_board_setup_dummy_smc(ARMCPU *cpu,
89
for (n = 0; n < ARRAY_SIZE(mvbar_blob); n++) {
90
mvbar_blob[n] = tswap32(mvbar_blob[n]);
91
}
92
- rom_add_blob_fixed("board-setup-mvbar", mvbar_blob, sizeof(mvbar_blob),
93
- mvbar_addr);
94
+ rom_add_blob_fixed_as("board-setup-mvbar", mvbar_blob, sizeof(mvbar_blob),
95
+ mvbar_addr, as);
96
97
for (n = 0; n < ARRAY_SIZE(board_setup_blob); n++) {
98
board_setup_blob[n] = tswap32(board_setup_blob[n]);
99
}
100
- rom_add_blob_fixed("board-setup", board_setup_blob,
101
- sizeof(board_setup_blob), info->board_setup_addr);
102
+ rom_add_blob_fixed_as("board-setup", board_setup_blob,
103
+ sizeof(board_setup_blob), info->board_setup_addr, as);
104
}
105
106
static void default_reset_secondary(ARMCPU *cpu,
107
const struct arm_boot_info *info)
108
{
109
+ AddressSpace *as = arm_boot_address_space(cpu, info);
110
CPUState *cs = CPU(cpu);
111
112
- address_space_stl_notdirty(&address_space_memory, info->smp_bootreg_addr,
113
+ address_space_stl_notdirty(as, info->smp_bootreg_addr,
114
0, MEMTXATTRS_UNSPECIFIED, NULL);
115
cpu_set_pc(cs, info->smp_loader_start);
116
}
117
@@ -XXX,XX +XXX,XX @@ static inline bool have_dtb(const struct arm_boot_info *info)
118
}
119
120
#define WRITE_WORD(p, value) do { \
121
- address_space_stl_notdirty(&address_space_memory, p, value, \
122
+ address_space_stl_notdirty(as, p, value, \
123
MEMTXATTRS_UNSPECIFIED, NULL); \
124
p += 4; \
125
} while (0)
126
127
-static void set_kernel_args(const struct arm_boot_info *info)
128
+static void set_kernel_args(const struct arm_boot_info *info, AddressSpace *as)
129
{
130
int initrd_size = info->initrd_size;
131
hwaddr base = info->loader_start;
132
@@ -XXX,XX +XXX,XX @@ static void set_kernel_args(const struct arm_boot_info *info)
133
int cmdline_size;
134
135
cmdline_size = strlen(info->kernel_cmdline);
136
- cpu_physical_memory_write(p + 8, info->kernel_cmdline,
137
- cmdline_size + 1);
138
+ address_space_write(as, p + 8, MEMTXATTRS_UNSPECIFIED,
139
+ (const uint8_t *)info->kernel_cmdline,
140
+ cmdline_size + 1);
141
cmdline_size = (cmdline_size >> 2) + 1;
142
WRITE_WORD(p, cmdline_size + 2);
143
WRITE_WORD(p, 0x54410009);
144
@@ -XXX,XX +XXX,XX @@ static void set_kernel_args(const struct arm_boot_info *info)
145
atag_board_len = (info->atag_board(info, atag_board_buf) + 3) & ~3;
146
WRITE_WORD(p, (atag_board_len + 8) >> 2);
147
WRITE_WORD(p, 0x414f4d50);
148
- cpu_physical_memory_write(p, atag_board_buf, atag_board_len);
149
+ address_space_write(as, p, MEMTXATTRS_UNSPECIFIED,
150
+ atag_board_buf, atag_board_len);
151
p += atag_board_len;
152
}
153
/* ATAG_END */
154
@@ -XXX,XX +XXX,XX @@ static void set_kernel_args(const struct arm_boot_info *info)
155
WRITE_WORD(p, 0);
156
}
157
158
-static void set_kernel_args_old(const struct arm_boot_info *info)
159
+static void set_kernel_args_old(const struct arm_boot_info *info,
160
+ AddressSpace *as)
161
{
162
hwaddr p;
163
const char *s;
164
@@ -XXX,XX +XXX,XX @@ static void set_kernel_args_old(const struct arm_boot_info *info)
165
}
166
s = info->kernel_cmdline;
167
if (s) {
168
- cpu_physical_memory_write(p, s, strlen(s) + 1);
169
+ address_space_write(as, p, MEMTXATTRS_UNSPECIFIED,
170
+ (const uint8_t *)s, strlen(s) + 1);
171
} else {
172
WRITE_WORD(p, 0);
173
}
174
@@ -XXX,XX +XXX,XX @@ static void fdt_add_psci_node(void *fdt)
175
* @addr: the address to load the image at
176
* @binfo: struct describing the boot environment
177
* @addr_limit: upper limit of the available memory area at @addr
178
+ * @as: address space to load image to
179
*
180
* Load a device tree supplied by the machine or by the user with the
181
* '-dtb' command line option, and put it at offset @addr in target
182
@@ -XXX,XX +XXX,XX @@ static void fdt_add_psci_node(void *fdt)
183
* Note: Must not be called unless have_dtb(binfo) is true.
184
*/
185
static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
186
- hwaddr addr_limit)
187
+ hwaddr addr_limit, AddressSpace *as)
188
{
189
void *fdt = NULL;
190
int size, rc;
191
@@ -XXX,XX +XXX,XX @@ static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
192
/* Put the DTB into the memory map as a ROM image: this will ensure
193
* the DTB is copied again upon reset, even if addr points into RAM.
194
*/
195
- rom_add_blob_fixed("dtb", fdt, size, addr);
196
+ rom_add_blob_fixed_as("dtb", fdt, size, addr, as);
197
198
g_free(fdt);
199
200
@@ -XXX,XX +XXX,XX @@ static void do_cpu_reset(void *opaque)
201
}
30
}
202
31
- a = phdr[i].p_vaddr + phdr[i].p_memsz;
203
if (cs == first_cpu) {
32
+ a = eppnt->p_vaddr + eppnt->p_memsz;
204
+ AddressSpace *as = arm_boot_address_space(cpu, info);
33
if (a > hiaddr) {
205
+
34
hiaddr = a;
206
cpu_set_pc(cs, info->loader_start);
35
}
207
36
++info->nsegs;
208
if (!have_dtb(info)) {
37
- info->alignment |= phdr[i].p_align;
209
if (old_param) {
38
+ info->alignment |= eppnt->p_align;
210
- set_kernel_args_old(info);
211
+ set_kernel_args_old(info, as);
212
} else {
213
- set_kernel_args(info);
214
+ set_kernel_args(info, as);
215
}
216
}
217
} else {
218
@@ -XXX,XX +XXX,XX @@ static int do_arm_linux_init(Object *obj, void *opaque)
219
220
static uint64_t arm_load_elf(struct arm_boot_info *info, uint64_t *pentry,
221
uint64_t *lowaddr, uint64_t *highaddr,
222
- int elf_machine)
223
+ int elf_machine, AddressSpace *as)
224
{
225
bool elf_is64;
226
union {
227
@@ -XXX,XX +XXX,XX @@ static uint64_t arm_load_elf(struct arm_boot_info *info, uint64_t *pentry,
228
}
39
}
229
}
40
}
230
41
231
- ret = load_elf(info->kernel_filename, NULL, NULL,
232
- pentry, lowaddr, highaddr, big_endian, elf_machine,
233
- 1, data_swab);
234
+ ret = load_elf_as(info->kernel_filename, NULL, NULL,
235
+ pentry, lowaddr, highaddr, big_endian, elf_machine,
236
+ 1, data_swab, as);
237
if (ret <= 0) {
238
/* The header loaded but the image didn't */
239
exit(1);
240
@@ -XXX,XX +XXX,XX @@ static uint64_t arm_load_elf(struct arm_boot_info *info, uint64_t *pentry,
241
}
242
243
static uint64_t load_aarch64_image(const char *filename, hwaddr mem_base,
244
- hwaddr *entry)
245
+ hwaddr *entry, AddressSpace *as)
246
{
247
hwaddr kernel_load_offset = KERNEL64_LOAD_ADDR;
248
uint8_t *buffer;
249
@@ -XXX,XX +XXX,XX @@ static uint64_t load_aarch64_image(const char *filename, hwaddr mem_base,
250
}
251
252
*entry = mem_base + kernel_load_offset;
253
- rom_add_blob_fixed(filename, buffer, size, *entry);
254
+ rom_add_blob_fixed_as(filename, buffer, size, *entry, as);
255
256
g_free(buffer);
257
258
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
259
ARMCPU *cpu = n->cpu;
260
struct arm_boot_info *info =
261
container_of(n, struct arm_boot_info, load_kernel_notifier);
262
+ AddressSpace *as = arm_boot_address_space(cpu, info);
263
264
/* The board code is not supposed to set secure_board_setup unless
265
* running its code in secure mode is actually possible, and KVM
266
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
267
* the kernel is supposed to be loaded by the bootloader), copy the
268
* DTB to the base of RAM for the bootloader to pick up.
269
*/
270
- if (load_dtb(info->loader_start, info, 0) < 0) {
271
+ if (load_dtb(info->loader_start, info, 0, as) < 0) {
272
exit(1);
273
}
274
}
275
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
276
277
/* Assume that raw images are linux kernels, and ELF images are not. */
278
kernel_size = arm_load_elf(info, &elf_entry, &elf_low_addr,
279
- &elf_high_addr, elf_machine);
280
+ &elf_high_addr, elf_machine, as);
281
if (kernel_size > 0 && have_dtb(info)) {
282
/* If there is still some room left at the base of RAM, try and put
283
* the DTB there like we do for images loaded with -bios or -pflash.
284
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
285
if (elf_low_addr < info->loader_start) {
286
elf_low_addr = 0;
287
}
288
- if (load_dtb(info->loader_start, info, elf_low_addr) < 0) {
289
+ if (load_dtb(info->loader_start, info, elf_low_addr, as) < 0) {
290
exit(1);
291
}
292
}
293
}
294
entry = elf_entry;
295
if (kernel_size < 0) {
296
- kernel_size = load_uimage(info->kernel_filename, &entry, NULL,
297
- &is_linux, NULL, NULL);
298
+ kernel_size = load_uimage_as(info->kernel_filename, &entry, NULL,
299
+ &is_linux, NULL, NULL, as);
300
}
301
if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64) && kernel_size < 0) {
302
kernel_size = load_aarch64_image(info->kernel_filename,
303
- info->loader_start, &entry);
304
+ info->loader_start, &entry, as);
305
is_linux = 1;
306
} else if (kernel_size < 0) {
307
/* 32-bit ARM */
308
entry = info->loader_start + KERNEL_LOAD_ADDR;
309
- kernel_size = load_image_targphys(info->kernel_filename, entry,
310
- info->ram_size - KERNEL_LOAD_ADDR);
311
+ kernel_size = load_image_targphys_as(info->kernel_filename, entry,
312
+ info->ram_size - KERNEL_LOAD_ADDR,
313
+ as);
314
is_linux = 1;
315
}
316
if (kernel_size < 0) {
317
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
318
uint32_t fixupcontext[FIXUP_MAX];
319
320
if (info->initrd_filename) {
321
- initrd_size = load_ramdisk(info->initrd_filename,
322
- info->initrd_start,
323
- info->ram_size -
324
- info->initrd_start);
325
+ initrd_size = load_ramdisk_as(info->initrd_filename,
326
+ info->initrd_start,
327
+ info->ram_size - info->initrd_start,
328
+ as);
329
if (initrd_size < 0) {
330
- initrd_size = load_image_targphys(info->initrd_filename,
331
- info->initrd_start,
332
- info->ram_size -
333
- info->initrd_start);
334
+ initrd_size = load_image_targphys_as(info->initrd_filename,
335
+ info->initrd_start,
336
+ info->ram_size -
337
+ info->initrd_start,
338
+ as);
339
}
340
if (initrd_size < 0) {
341
error_report("could not load initrd '%s'",
342
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
343
344
/* Place the DTB after the initrd in memory with alignment. */
345
dtb_start = QEMU_ALIGN_UP(info->initrd_start + initrd_size, align);
346
- if (load_dtb(dtb_start, info, 0) < 0) {
347
+ if (load_dtb(dtb_start, info, 0, as) < 0) {
348
exit(1);
349
}
350
fixupcontext[FIXUP_ARGPTR] = dtb_start;
351
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
352
fixupcontext[FIXUP_ENTRYPOINT] = entry;
353
354
write_bootloader("bootloader", info->loader_start,
355
- primary_loader, fixupcontext);
356
+ primary_loader, fixupcontext, as);
357
358
if (info->nb_cpus > 1) {
359
info->write_secondary_boot(cpu, info);
360
--
42
--
361
2.16.2
43
2.20.1
362
44
363
45
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Happily, the bits are in the same places compared to a32.
3
For BTI, we need to know if the executable is static or dynamic,
4
which means looking for PT_INTERP earlier.
4
5
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20180228193125.20577-16-richard.henderson@linaro.org
7
Message-id: 20201016184207.786698-8-richard.henderson@linaro.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
---
10
target/arm/translate.c | 14 +++++++++++++-
11
linux-user/elfload.c | 60 +++++++++++++++++++++++---------------------
11
1 file changed, 13 insertions(+), 1 deletion(-)
12
1 file changed, 31 insertions(+), 29 deletions(-)
12
13
13
diff --git a/target/arm/translate.c b/target/arm/translate.c
14
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate.c
16
--- a/linux-user/elfload.c
16
+++ b/target/arm/translate.c
17
+++ b/linux-user/elfload.c
17
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
18
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
18
default_exception_el(s));
19
19
break;
20
mmap_lock();
21
22
- /* Find the maximum size of the image and allocate an appropriate
23
- amount of memory to handle that. */
24
+ /*
25
+ * Find the maximum size of the image and allocate an appropriate
26
+ * amount of memory to handle that. Locate the interpreter, if any.
27
+ */
28
loaddr = -1, hiaddr = 0;
29
info->alignment = 0;
30
for (i = 0; i < ehdr->e_phnum; ++i) {
31
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
32
}
33
++info->nsegs;
34
info->alignment |= eppnt->p_align;
35
+ } else if (eppnt->p_type == PT_INTERP && pinterp_name) {
36
+ g_autofree char *interp_name = NULL;
37
+
38
+ if (*pinterp_name) {
39
+ errmsg = "Multiple PT_INTERP entries";
40
+ goto exit_errmsg;
41
+ }
42
+ interp_name = g_malloc(eppnt->p_filesz);
43
+ if (!interp_name) {
44
+ goto exit_perror;
45
+ }
46
+
47
+ if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
48
+ memcpy(interp_name, bprm_buf + eppnt->p_offset,
49
+ eppnt->p_filesz);
50
+ } else {
51
+ retval = pread(image_fd, interp_name, eppnt->p_filesz,
52
+ eppnt->p_offset);
53
+ if (retval != eppnt->p_filesz) {
54
+ goto exit_perror;
55
+ }
56
+ }
57
+ if (interp_name[eppnt->p_filesz - 1] != 0) {
58
+ errmsg = "Invalid PT_INTERP entry";
59
+ goto exit_errmsg;
60
+ }
61
+ *pinterp_name = g_steal_pointer(&interp_name);
20
}
62
}
21
- if (((insn >> 24) & 3) == 3) {
63
}
22
+ if ((insn & 0xfe000a00) == 0xfc000800
64
23
+ && arm_dc_feature(s, ARM_FEATURE_V8)) {
65
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
24
+ /* The Thumb2 and ARM encodings are identical. */
66
if (vaddr_em > info->brk) {
25
+ if (disas_neon_insn_3same_ext(s, insn)) {
67
info->brk = vaddr_em;
26
+ goto illegal_op;
68
}
27
+ }
69
- } else if (eppnt->p_type == PT_INTERP && pinterp_name) {
28
+ } else if ((insn & 0xff000a00) == 0xfe000800
70
- g_autofree char *interp_name = NULL;
29
+ && arm_dc_feature(s, ARM_FEATURE_V8)) {
71
-
30
+ /* The Thumb2 and ARM encodings are identical. */
72
- if (*pinterp_name) {
31
+ if (disas_neon_insn_2reg_scalar_ext(s, insn)) {
73
- errmsg = "Multiple PT_INTERP entries";
32
+ goto illegal_op;
74
- goto exit_errmsg;
33
+ }
75
- }
34
+ } else if (((insn >> 24) & 3) == 3) {
76
- interp_name = g_malloc(eppnt->p_filesz);
35
/* Translate into the equivalent ARM encoding. */
77
- if (!interp_name) {
36
insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
78
- goto exit_perror;
37
if (disas_neon_data_insn(s, insn)) {
79
- }
80
-
81
- if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
82
- memcpy(interp_name, bprm_buf + eppnt->p_offset,
83
- eppnt->p_filesz);
84
- } else {
85
- retval = pread(image_fd, interp_name, eppnt->p_filesz,
86
- eppnt->p_offset);
87
- if (retval != eppnt->p_filesz) {
88
- goto exit_perror;
89
- }
90
- }
91
- if (interp_name[eppnt->p_filesz - 1] != 0) {
92
- errmsg = "Invalid PT_INTERP entry";
93
- goto exit_errmsg;
94
- }
95
- *pinterp_name = g_steal_pointer(&interp_name);
96
#ifdef TARGET_MIPS
97
} else if (eppnt->p_type == PT_MIPS_ABIFLAGS) {
98
Mips_elf_abiflags_v0 abiflags;
38
--
99
--
39
2.16.2
100
2.20.1
40
101
41
102
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Include the U bit in the switches rather than testing separately.
3
This is a bit clearer than open-coding some of this
4
with a bare c string.
4
5
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20180228193125.20577-3-richard.henderson@linaro.org
8
Message-id: 20201016184207.786698-9-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
---
10
target/arm/translate-a64.c | 129 +++++++++++++++++++++------------------------
11
linux-user/elfload.c | 37 ++++++++++++++++++++-----------------
11
1 file changed, 61 insertions(+), 68 deletions(-)
12
1 file changed, 20 insertions(+), 17 deletions(-)
12
13
13
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
14
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-a64.c
16
--- a/linux-user/elfload.c
16
+++ b/target/arm/translate-a64.c
17
+++ b/linux-user/elfload.c
17
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
18
@@ -XXX,XX +XXX,XX @@
18
int index;
19
#include "qemu/guest-random.h"
19
TCGv_ptr fpst;
20
#include "qemu/units.h"
20
21
#include "qemu/selfmap.h"
21
- switch (opcode) {
22
+#include "qapi/error.h"
22
- case 0x0: /* MLA */
23
23
- case 0x4: /* MLS */
24
#ifdef _ARCH_PPC64
24
- if (!u || is_scalar) {
25
#undef ARCH_DLINFO
25
+ switch (16 * u + opcode) {
26
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
26
+ case 0x08: /* MUL */
27
struct elf_phdr *phdr;
27
+ case 0x10: /* MLA */
28
abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
28
+ case 0x14: /* MLS */
29
int i, retval;
29
+ if (is_scalar) {
30
- const char *errmsg;
30
unallocated_encoding(s);
31
+ Error *err = NULL;
31
return;
32
32
}
33
/* First of all, some simple consistency checks */
33
break;
34
- errmsg = "Invalid ELF image for this architecture";
34
- case 0x2: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */
35
if (!elf_check_ident(ehdr)) {
35
- case 0x6: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */
36
+ error_setg(&err, "Invalid ELF image for this architecture");
36
- case 0xa: /* SMULL, SMULL2, UMULL, UMULL2 */
37
goto exit_errmsg;
37
+ case 0x02: /* SMLAL, SMLAL2 */
38
}
38
+ case 0x12: /* UMLAL, UMLAL2 */
39
bswap_ehdr(ehdr);
39
+ case 0x06: /* SMLSL, SMLSL2 */
40
if (!elf_check_ehdr(ehdr)) {
40
+ case 0x16: /* UMLSL, UMLSL2 */
41
+ error_setg(&err, "Invalid ELF image for this architecture");
41
+ case 0x0a: /* SMULL, SMULL2 */
42
goto exit_errmsg;
42
+ case 0x1a: /* UMULL, UMULL2 */
43
}
43
if (is_scalar) {
44
44
unallocated_encoding(s);
45
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
45
return;
46
g_autofree char *interp_name = NULL;
46
}
47
47
is_long = true;
48
if (*pinterp_name) {
48
break;
49
- errmsg = "Multiple PT_INTERP entries";
49
- case 0x3: /* SQDMLAL, SQDMLAL2 */
50
+ error_setg(&err, "Multiple PT_INTERP entries");
50
- case 0x7: /* SQDMLSL, SQDMLSL2 */
51
goto exit_errmsg;
51
- case 0xb: /* SQDMULL, SQDMULL2 */
52
+ case 0x03: /* SQDMLAL, SQDMLAL2 */
53
+ case 0x07: /* SQDMLSL, SQDMLSL2 */
54
+ case 0x0b: /* SQDMULL, SQDMULL2 */
55
is_long = true;
56
- /* fall through */
57
- case 0xc: /* SQDMULH */
58
- case 0xd: /* SQRDMULH */
59
- if (u) {
60
- unallocated_encoding(s);
61
- return;
62
- }
63
break;
64
- case 0x8: /* MUL */
65
- if (u || is_scalar) {
66
- unallocated_encoding(s);
67
- return;
68
- }
69
+ case 0x0c: /* SQDMULH */
70
+ case 0x0d: /* SQRDMULH */
71
break;
72
- case 0x1: /* FMLA */
73
- case 0x5: /* FMLS */
74
- if (u) {
75
- unallocated_encoding(s);
76
- return;
77
- }
78
- /* fall through */
79
- case 0x9: /* FMUL, FMULX */
80
+ case 0x01: /* FMLA */
81
+ case 0x05: /* FMLS */
82
+ case 0x09: /* FMUL */
83
+ case 0x19: /* FMULX */
84
if (size == 1) {
85
unallocated_encoding(s);
86
return;
87
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
88
89
read_vec_element(s, tcg_op, rn, pass, MO_64);
90
91
- switch (opcode) {
92
- case 0x5: /* FMLS */
93
+ switch (16 * u + opcode) {
94
+ case 0x05: /* FMLS */
95
/* As usual for ARM, separate negation for fused multiply-add */
96
gen_helper_vfp_negd(tcg_op, tcg_op);
97
/* fall through */
98
- case 0x1: /* FMLA */
99
+ case 0x01: /* FMLA */
100
read_vec_element(s, tcg_res, rd, pass, MO_64);
101
gen_helper_vfp_muladdd(tcg_res, tcg_op, tcg_idx, tcg_res, fpst);
102
break;
103
- case 0x9: /* FMUL, FMULX */
104
- if (u) {
105
- gen_helper_vfp_mulxd(tcg_res, tcg_op, tcg_idx, fpst);
106
- } else {
107
- gen_helper_vfp_muld(tcg_res, tcg_op, tcg_idx, fpst);
108
- }
109
+ case 0x09: /* FMUL */
110
+ gen_helper_vfp_muld(tcg_res, tcg_op, tcg_idx, fpst);
111
+ break;
112
+ case 0x19: /* FMULX */
113
+ gen_helper_vfp_mulxd(tcg_res, tcg_op, tcg_idx, fpst);
114
break;
115
default:
116
g_assert_not_reached();
117
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
118
119
read_vec_element_i32(s, tcg_op, rn, pass, is_scalar ? size : MO_32);
120
121
- switch (opcode) {
122
- case 0x0: /* MLA */
123
- case 0x4: /* MLS */
124
- case 0x8: /* MUL */
125
+ switch (16 * u + opcode) {
126
+ case 0x08: /* MUL */
127
+ case 0x10: /* MLA */
128
+ case 0x14: /* MLS */
129
{
130
static NeonGenTwoOpFn * const fns[2][2] = {
131
{ gen_helper_neon_add_u16, gen_helper_neon_sub_u16 },
132
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
133
genfn(tcg_res, tcg_op, tcg_res);
134
break;
135
}
52
}
136
- case 0x5: /* FMLS */
53
+
137
- case 0x1: /* FMLA */
54
interp_name = g_malloc(eppnt->p_filesz);
138
+ case 0x05: /* FMLS */
55
- if (!interp_name) {
139
+ case 0x01: /* FMLA */
56
- goto exit_perror;
140
read_vec_element_i32(s, tcg_res, rd, pass,
57
- }
141
is_scalar ? size : MO_32);
58
142
switch (size) {
59
if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
143
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
60
memcpy(interp_name, bprm_buf + eppnt->p_offset,
144
g_assert_not_reached();
61
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
62
retval = pread(image_fd, interp_name, eppnt->p_filesz,
63
eppnt->p_offset);
64
if (retval != eppnt->p_filesz) {
65
- goto exit_perror;
66
+ goto exit_read;
145
}
67
}
146
break;
68
}
147
- case 0x9: /* FMUL, FMULX */
69
if (interp_name[eppnt->p_filesz - 1] != 0) {
148
+ case 0x09: /* FMUL */
70
- errmsg = "Invalid PT_INTERP entry";
149
switch (size) {
71
+ error_setg(&err, "Invalid PT_INTERP entry");
150
case 1:
72
goto exit_errmsg;
151
- if (u) {
73
}
152
- if (is_scalar) {
74
*pinterp_name = g_steal_pointer(&interp_name);
153
- gen_helper_advsimd_mulxh(tcg_res, tcg_op,
75
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
154
- tcg_idx, fpst);
76
(ehdr->e_type == ET_EXEC ? MAP_FIXED : 0),
155
- } else {
77
-1, 0);
156
- gen_helper_advsimd_mulx2h(tcg_res, tcg_op,
78
if (load_addr == -1) {
157
- tcg_idx, fpst);
79
- goto exit_perror;
158
- }
80
+ goto exit_mmap;
159
+ if (is_scalar) {
81
}
160
+ gen_helper_advsimd_mulh(tcg_res, tcg_op,
82
load_bias = load_addr - loaddr;
161
+ tcg_idx, fpst);
83
162
} else {
84
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
163
- if (is_scalar) {
85
image_fd, eppnt->p_offset - vaddr_po);
164
- gen_helper_advsimd_mulh(tcg_res, tcg_op,
86
165
- tcg_idx, fpst);
87
if (error == -1) {
166
- } else {
88
- goto exit_perror;
167
- gen_helper_advsimd_mul2h(tcg_res, tcg_op,
89
+ goto exit_mmap;
168
- tcg_idx, fpst);
169
- }
170
+ gen_helper_advsimd_mul2h(tcg_res, tcg_op,
171
+ tcg_idx, fpst);
172
}
173
break;
174
case 2:
175
- if (u) {
176
- gen_helper_vfp_mulxs(tcg_res, tcg_op, tcg_idx, fpst);
177
- } else {
178
- gen_helper_vfp_muls(tcg_res, tcg_op, tcg_idx, fpst);
179
- }
180
+ gen_helper_vfp_muls(tcg_res, tcg_op, tcg_idx, fpst);
181
break;
182
default:
183
g_assert_not_reached();
184
}
90
}
185
break;
91
}
186
- case 0xc: /* SQDMULH */
92
187
+ case 0x19: /* FMULX */
93
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
188
+ switch (size) {
94
} else if (eppnt->p_type == PT_MIPS_ABIFLAGS) {
189
+ case 1:
95
Mips_elf_abiflags_v0 abiflags;
190
+ if (is_scalar) {
96
if (eppnt->p_filesz < sizeof(Mips_elf_abiflags_v0)) {
191
+ gen_helper_advsimd_mulxh(tcg_res, tcg_op,
97
- errmsg = "Invalid PT_MIPS_ABIFLAGS entry";
192
+ tcg_idx, fpst);
98
+ error_setg(&err, "Invalid PT_MIPS_ABIFLAGS entry");
193
+ } else {
99
goto exit_errmsg;
194
+ gen_helper_advsimd_mulx2h(tcg_res, tcg_op,
100
}
195
+ tcg_idx, fpst);
101
if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
196
+ }
102
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
197
+ break;
103
retval = pread(image_fd, &abiflags, sizeof(Mips_elf_abiflags_v0),
198
+ case 2:
104
eppnt->p_offset);
199
+ gen_helper_vfp_mulxs(tcg_res, tcg_op, tcg_idx, fpst);
105
if (retval != sizeof(Mips_elf_abiflags_v0)) {
200
+ break;
106
- goto exit_perror;
201
+ default:
107
+ goto exit_read;
202
+ g_assert_not_reached();
203
+ }
204
+ break;
205
+ case 0x0c: /* SQDMULH */
206
if (size == 1) {
207
gen_helper_neon_qdmulh_s16(tcg_res, cpu_env,
208
tcg_op, tcg_idx);
209
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
210
tcg_op, tcg_idx);
211
}
108
}
212
break;
109
}
213
- case 0xd: /* SQRDMULH */
110
bswap_mips_abiflags(&abiflags);
214
+ case 0x0d: /* SQRDMULH */
111
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
215
if (size == 1) {
112
216
gen_helper_neon_qrdmulh_s16(tcg_res, cpu_env,
113
exit_read:
217
tcg_op, tcg_idx);
114
if (retval >= 0) {
115
- errmsg = "Incomplete read of file header";
116
- goto exit_errmsg;
117
+ error_setg(&err, "Incomplete read of file header");
118
+ } else {
119
+ error_setg_errno(&err, errno, "Error reading file header");
120
}
121
- exit_perror:
122
- errmsg = strerror(errno);
123
+ goto exit_errmsg;
124
+ exit_mmap:
125
+ error_setg_errno(&err, errno, "Error mapping file");
126
+ goto exit_errmsg;
127
exit_errmsg:
128
- fprintf(stderr, "%s: %s\n", image_name, errmsg);
129
+ error_reportf_err(err, "%s: ", image_name);
130
exit(-1);
131
}
132
218
--
133
--
219
2.16.2
134
2.20.1
220
135
221
136
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
3
This is slightly clearer than just using strerror, though
4
the different forms produced by error_setg_file_open and
5
error_setg_errno isn't entirely convenient.
6
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180228193125.20577-12-richard.henderson@linaro.org
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20201016184207.786698-10-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
11
---
8
target/arm/helper.h | 7 ++++
12
linux-user/elfload.c | 15 ++++++++-------
9
target/arm/translate-a64.c | 48 ++++++++++++++++++++++-
13
1 file changed, 8 insertions(+), 7 deletions(-)
10
target/arm/vec_helper.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++
11
3 files changed, 151 insertions(+), 1 deletion(-)
12
14
13
diff --git a/target/arm/helper.h b/target/arm/helper.h
15
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
14
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.h
17
--- a/linux-user/elfload.c
16
+++ b/target/arm/helper.h
18
+++ b/linux-user/elfload.c
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_qrdmlah_s32, TCG_CALL_NO_RWG,
19
@@ -XXX,XX +XXX,XX @@ static void load_elf_interp(const char *filename, struct image_info *info,
18
DEF_HELPER_FLAGS_5(gvec_qrdmlsh_s32, TCG_CALL_NO_RWG,
20
char bprm_buf[BPRM_BUF_SIZE])
19
void, ptr, ptr, ptr, ptr, i32)
21
{
20
22
int fd, retval;
21
+DEF_HELPER_FLAGS_5(gvec_fcaddh, TCG_CALL_NO_RWG,
23
+ Error *err = NULL;
22
+ void, ptr, ptr, ptr, ptr, i32)
24
23
+DEF_HELPER_FLAGS_5(gvec_fcadds, TCG_CALL_NO_RWG,
25
fd = open(path(filename), O_RDONLY);
24
+ void, ptr, ptr, ptr, ptr, i32)
26
if (fd < 0) {
25
+DEF_HELPER_FLAGS_5(gvec_fcaddd, TCG_CALL_NO_RWG,
27
- goto exit_perror;
26
+ void, ptr, ptr, ptr, ptr, i32)
28
+ error_setg_file_open(&err, errno, filename);
29
+ error_report_err(err);
30
+ exit(-1);
31
}
32
33
retval = read(fd, bprm_buf, BPRM_BUF_SIZE);
34
if (retval < 0) {
35
- goto exit_perror;
36
+ error_setg_errno(&err, errno, "Error reading file header");
37
+ error_reportf_err(err, "%s: ", filename);
38
+ exit(-1);
39
}
27
+
40
+
28
#ifdef TARGET_AARCH64
41
if (retval < BPRM_BUF_SIZE) {
29
#include "helper-a64.h"
42
memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval);
30
#endif
43
}
31
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
44
32
index XXXXXXX..XXXXXXX 100644
45
load_elf_image(filename, fd, info, NULL, bprm_buf);
33
--- a/target/arm/translate-a64.c
46
- return;
34
+++ b/target/arm/translate-a64.c
47
-
35
@@ -XXX,XX +XXX,XX @@ static void gen_gvec_op3_env(DisasContext *s, bool is_q, int rd,
48
- exit_perror:
36
is_q ? 16 : 8, vec_full_reg_size(s), 0, fn);
49
- fprintf(stderr, "%s: %s\n", filename, strerror(errno));
50
- exit(-1);
37
}
51
}
38
52
39
+/* Expand a 3-operand + fpstatus pointer + simd data value operation using
53
static int symfind(const void *s0, const void *s1)
40
+ * an out-of-line helper.
41
+ */
42
+static void gen_gvec_op3_fpst(DisasContext *s, bool is_q, int rd, int rn,
43
+ int rm, bool is_fp16, int data,
44
+ gen_helper_gvec_3_ptr *fn)
45
+{
46
+ TCGv_ptr fpst = get_fpstatus_ptr(is_fp16);
47
+ tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
48
+ vec_full_reg_offset(s, rn),
49
+ vec_full_reg_offset(s, rm), fpst,
50
+ is_q ? 16 : 8, vec_full_reg_size(s), data, fn);
51
+ tcg_temp_free_ptr(fpst);
52
+}
53
+
54
/* Set ZF and NF based on a 64 bit result. This is alas fiddlier
55
* than the 32 bit equivalent.
56
*/
57
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
58
int size = extract32(insn, 22, 2);
59
bool u = extract32(insn, 29, 1);
60
bool is_q = extract32(insn, 30, 1);
61
- int feature;
62
+ int feature, rot;
63
64
switch (u * 16 + opcode) {
65
case 0x10: /* SQRDMLAH (vector) */
66
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
67
}
68
feature = ARM_FEATURE_V8_RDM;
69
break;
70
+ case 0xc: /* FCADD, #90 */
71
+ case 0xe: /* FCADD, #270 */
72
+ if (size == 0
73
+ || (size == 1 && !arm_dc_feature(s, ARM_FEATURE_V8_FP16))
74
+ || (size == 3 && !is_q)) {
75
+ unallocated_encoding(s);
76
+ return;
77
+ }
78
+ feature = ARM_FEATURE_V8_FCMA;
79
+ break;
80
default:
81
unallocated_encoding(s);
82
return;
83
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
84
}
85
return;
86
87
+ case 0xc: /* FCADD, #90 */
88
+ case 0xe: /* FCADD, #270 */
89
+ rot = extract32(opcode, 1, 1);
90
+ switch (size) {
91
+ case 1:
92
+ gen_gvec_op3_fpst(s, is_q, rd, rn, rm, size == 1, rot,
93
+ gen_helper_gvec_fcaddh);
94
+ break;
95
+ case 2:
96
+ gen_gvec_op3_fpst(s, is_q, rd, rn, rm, size == 1, rot,
97
+ gen_helper_gvec_fcadds);
98
+ break;
99
+ case 3:
100
+ gen_gvec_op3_fpst(s, is_q, rd, rn, rm, size == 1, rot,
101
+ gen_helper_gvec_fcaddd);
102
+ break;
103
+ default:
104
+ g_assert_not_reached();
105
+ }
106
+ return;
107
+
108
default:
109
g_assert_not_reached();
110
}
111
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
112
index XXXXXXX..XXXXXXX 100644
113
--- a/target/arm/vec_helper.c
114
+++ b/target/arm/vec_helper.c
115
@@ -XXX,XX +XXX,XX @@
116
#include "exec/exec-all.h"
117
#include "exec/helper-proto.h"
118
#include "tcg/tcg-gvec-desc.h"
119
+#include "fpu/softfloat.h"
120
121
122
+/* Note that vector data is stored in host-endian 64-bit chunks,
123
+ so addressing units smaller than that needs a host-endian fixup. */
124
+#ifdef HOST_WORDS_BIGENDIAN
125
+#define H1(x) ((x) ^ 7)
126
+#define H2(x) ((x) ^ 3)
127
+#define H4(x) ((x) ^ 1)
128
+#else
129
+#define H1(x) (x)
130
+#define H2(x) (x)
131
+#define H4(x) (x)
132
+#endif
133
+
134
#define SET_QC() env->vfp.xregs[ARM_VFP_FPSCR] |= CPSR_Q
135
136
static void clear_tail(void *vd, uintptr_t opr_sz, uintptr_t max_sz)
137
@@ -XXX,XX +XXX,XX @@ void HELPER(gvec_qrdmlsh_s32)(void *vd, void *vn, void *vm,
138
}
139
clear_tail(d, opr_sz, simd_maxsz(desc));
140
}
141
+
142
+void HELPER(gvec_fcaddh)(void *vd, void *vn, void *vm,
143
+ void *vfpst, uint32_t desc)
144
+{
145
+ uintptr_t opr_sz = simd_oprsz(desc);
146
+ float16 *d = vd;
147
+ float16 *n = vn;
148
+ float16 *m = vm;
149
+ float_status *fpst = vfpst;
150
+ uint32_t neg_real = extract32(desc, SIMD_DATA_SHIFT, 1);
151
+ uint32_t neg_imag = neg_real ^ 1;
152
+ uintptr_t i;
153
+
154
+ /* Shift boolean to the sign bit so we can xor to negate. */
155
+ neg_real <<= 15;
156
+ neg_imag <<= 15;
157
+
158
+ for (i = 0; i < opr_sz / 2; i += 2) {
159
+ float16 e0 = n[H2(i)];
160
+ float16 e1 = m[H2(i + 1)] ^ neg_imag;
161
+ float16 e2 = n[H2(i + 1)];
162
+ float16 e3 = m[H2(i)] ^ neg_real;
163
+
164
+ d[H2(i)] = float16_add(e0, e1, fpst);
165
+ d[H2(i + 1)] = float16_add(e2, e3, fpst);
166
+ }
167
+ clear_tail(d, opr_sz, simd_maxsz(desc));
168
+}
169
+
170
+void HELPER(gvec_fcadds)(void *vd, void *vn, void *vm,
171
+ void *vfpst, uint32_t desc)
172
+{
173
+ uintptr_t opr_sz = simd_oprsz(desc);
174
+ float32 *d = vd;
175
+ float32 *n = vn;
176
+ float32 *m = vm;
177
+ float_status *fpst = vfpst;
178
+ uint32_t neg_real = extract32(desc, SIMD_DATA_SHIFT, 1);
179
+ uint32_t neg_imag = neg_real ^ 1;
180
+ uintptr_t i;
181
+
182
+ /* Shift boolean to the sign bit so we can xor to negate. */
183
+ neg_real <<= 31;
184
+ neg_imag <<= 31;
185
+
186
+ for (i = 0; i < opr_sz / 4; i += 2) {
187
+ float32 e0 = n[H4(i)];
188
+ float32 e1 = m[H4(i + 1)] ^ neg_imag;
189
+ float32 e2 = n[H4(i + 1)];
190
+ float32 e3 = m[H4(i)] ^ neg_real;
191
+
192
+ d[H4(i)] = float32_add(e0, e1, fpst);
193
+ d[H4(i + 1)] = float32_add(e2, e3, fpst);
194
+ }
195
+ clear_tail(d, opr_sz, simd_maxsz(desc));
196
+}
197
+
198
+void HELPER(gvec_fcaddd)(void *vd, void *vn, void *vm,
199
+ void *vfpst, uint32_t desc)
200
+{
201
+ uintptr_t opr_sz = simd_oprsz(desc);
202
+ float64 *d = vd;
203
+ float64 *n = vn;
204
+ float64 *m = vm;
205
+ float_status *fpst = vfpst;
206
+ uint64_t neg_real = extract64(desc, SIMD_DATA_SHIFT, 1);
207
+ uint64_t neg_imag = neg_real ^ 1;
208
+ uintptr_t i;
209
+
210
+ /* Shift boolean to the sign bit so we can xor to negate. */
211
+ neg_real <<= 63;
212
+ neg_imag <<= 63;
213
+
214
+ for (i = 0; i < opr_sz / 8; i += 2) {
215
+ float64 e0 = n[i];
216
+ float64 e1 = m[i + 1] ^ neg_imag;
217
+ float64 e2 = n[i + 1];
218
+ float64 e3 = m[i] ^ neg_real;
219
+
220
+ d[i] = float64_add(e0, e1, fpst);
221
+ d[i + 1] = float64_add(e2, e3, fpst);
222
+ }
223
+ clear_tail(d, opr_sz, simd_maxsz(desc));
224
+}
225
--
54
--
226
2.16.2
55
2.20.1
227
56
228
57
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Allow the translate subroutines to return false for invalid insns.
3
This is generic support, with the code disabled for all targets.
4
5
At present we can of course invoke an invalid insn exception from within
6
the translate subroutine, but in the short term this consolidates code.
7
In the long term it would allow the decodetree language to support
8
overlapping patterns for ISA extensions.
9
4
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20180227232618.2908-1-richard.henderson@linaro.org
6
Message-id: 20201016184207.786698-11-richard.henderson@linaro.org
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
9
---
15
scripts/decodetree.py | 5 ++---
10
linux-user/qemu.h | 4 ++
16
1 file changed, 2 insertions(+), 3 deletions(-)
11
linux-user/elfload.c | 157 +++++++++++++++++++++++++++++++++++++++++++
17
12
2 files changed, 161 insertions(+)
18
diff --git a/scripts/decodetree.py b/scripts/decodetree.py
13
19
index XXXXXXX..XXXXXXX 100755
14
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
20
--- a/scripts/decodetree.py
15
index XXXXXXX..XXXXXXX 100644
21
+++ b/scripts/decodetree.py
16
--- a/linux-user/qemu.h
22
@@ -XXX,XX +XXX,XX @@ class Pattern(General):
17
+++ b/linux-user/qemu.h
23
global translate_prefix
18
@@ -XXX,XX +XXX,XX @@ struct image_info {
24
output('typedef ', self.base.base.struct_name(),
19
abi_ulong interpreter_loadmap_addr;
25
' arg_', self.name, ';\n')
20
abi_ulong interpreter_pt_dynamic_addr;
26
- output(translate_scope, 'void ', translate_prefix, '_', self.name,
21
struct image_info *other_info;
27
+ output(translate_scope, 'bool ', translate_prefix, '_', self.name,
22
+
28
'(DisasContext *ctx, arg_', self.name,
23
+ /* For target-specific processing of NT_GNU_PROPERTY_TYPE_0. */
29
' *a, ', insntype, ' insn);\n')
24
+ uint32_t note_flags;
30
25
+
31
@@ -XXX,XX +XXX,XX @@ class Pattern(General):
26
#ifdef TARGET_MIPS
32
output(ind, self.base.extract_name(), '(&u.f_', arg, ', insn);\n')
27
int fp_abi;
33
for n, f in self.fields.items():
28
int interp_fp_abi;
34
output(ind, 'u.f_', arg, '.', n, ' = ', f.str_extract(), ';\n')
29
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
35
- output(ind, translate_prefix, '_', self.name,
30
index XXXXXXX..XXXXXXX 100644
36
+ output(ind, 'return ', translate_prefix, '_', self.name,
31
--- a/linux-user/elfload.c
37
'(ctx, &u.f_', arg, ', insn);\n')
32
+++ b/linux-user/elfload.c
38
- output(ind, 'return true;\n')
33
@@ -XXX,XX +XXX,XX @@ static void elf_core_copy_regs(target_elf_gregset_t *regs,
39
# end Pattern
34
40
35
#include "elf.h"
36
37
+static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
38
+ const uint32_t *data,
39
+ struct image_info *info,
40
+ Error **errp)
41
+{
42
+ g_assert_not_reached();
43
+}
44
+#define ARCH_USE_GNU_PROPERTY 0
45
+
46
struct exec
47
{
48
unsigned int a_info; /* Use macros N_MAGIC, etc for access */
49
@@ -XXX,XX +XXX,XX @@ void probe_guest_base(const char *image_name, abi_ulong guest_loaddr,
50
"@ 0x%" PRIx64 "\n", (uint64_t)guest_base);
51
}
52
53
+enum {
54
+ /* The string "GNU\0" as a magic number. */
55
+ GNU0_MAGIC = const_le32('G' | 'N' << 8 | 'U' << 16),
56
+ NOTE_DATA_SZ = 1 * KiB,
57
+ NOTE_NAME_SZ = 4,
58
+ ELF_GNU_PROPERTY_ALIGN = ELF_CLASS == ELFCLASS32 ? 4 : 8,
59
+};
60
+
61
+/*
62
+ * Process a single gnu_property entry.
63
+ * Return false for error.
64
+ */
65
+static bool parse_elf_property(const uint32_t *data, int *off, int datasz,
66
+ struct image_info *info, bool have_prev_type,
67
+ uint32_t *prev_type, Error **errp)
68
+{
69
+ uint32_t pr_type, pr_datasz, step;
70
+
71
+ if (*off > datasz || !QEMU_IS_ALIGNED(*off, ELF_GNU_PROPERTY_ALIGN)) {
72
+ goto error_data;
73
+ }
74
+ datasz -= *off;
75
+ data += *off / sizeof(uint32_t);
76
+
77
+ if (datasz < 2 * sizeof(uint32_t)) {
78
+ goto error_data;
79
+ }
80
+ pr_type = data[0];
81
+ pr_datasz = data[1];
82
+ data += 2;
83
+ datasz -= 2 * sizeof(uint32_t);
84
+ step = ROUND_UP(pr_datasz, ELF_GNU_PROPERTY_ALIGN);
85
+ if (step > datasz) {
86
+ goto error_data;
87
+ }
88
+
89
+ /* Properties are supposed to be unique and sorted on pr_type. */
90
+ if (have_prev_type && pr_type <= *prev_type) {
91
+ if (pr_type == *prev_type) {
92
+ error_setg(errp, "Duplicate property in PT_GNU_PROPERTY");
93
+ } else {
94
+ error_setg(errp, "Unsorted property in PT_GNU_PROPERTY");
95
+ }
96
+ return false;
97
+ }
98
+ *prev_type = pr_type;
99
+
100
+ if (!arch_parse_elf_property(pr_type, pr_datasz, data, info, errp)) {
101
+ return false;
102
+ }
103
+
104
+ *off += 2 * sizeof(uint32_t) + step;
105
+ return true;
106
+
107
+ error_data:
108
+ error_setg(errp, "Ill-formed property in PT_GNU_PROPERTY");
109
+ return false;
110
+}
111
+
112
+/* Process NT_GNU_PROPERTY_TYPE_0. */
113
+static bool parse_elf_properties(int image_fd,
114
+ struct image_info *info,
115
+ const struct elf_phdr *phdr,
116
+ char bprm_buf[BPRM_BUF_SIZE],
117
+ Error **errp)
118
+{
119
+ union {
120
+ struct elf_note nhdr;
121
+ uint32_t data[NOTE_DATA_SZ / sizeof(uint32_t)];
122
+ } note;
123
+
124
+ int n, off, datasz;
125
+ bool have_prev_type;
126
+ uint32_t prev_type;
127
+
128
+ /* Unless the arch requires properties, ignore them. */
129
+ if (!ARCH_USE_GNU_PROPERTY) {
130
+ return true;
131
+ }
132
+
133
+ /* If the properties are crazy large, that's too bad. */
134
+ n = phdr->p_filesz;
135
+ if (n > sizeof(note)) {
136
+ error_setg(errp, "PT_GNU_PROPERTY too large");
137
+ return false;
138
+ }
139
+ if (n < sizeof(note.nhdr)) {
140
+ error_setg(errp, "PT_GNU_PROPERTY too small");
141
+ return false;
142
+ }
143
+
144
+ if (phdr->p_offset + n <= BPRM_BUF_SIZE) {
145
+ memcpy(&note, bprm_buf + phdr->p_offset, n);
146
+ } else {
147
+ ssize_t len = pread(image_fd, &note, n, phdr->p_offset);
148
+ if (len != n) {
149
+ error_setg_errno(errp, errno, "Error reading file header");
150
+ return false;
151
+ }
152
+ }
153
+
154
+ /*
155
+ * The contents of a valid PT_GNU_PROPERTY is a sequence
156
+ * of uint32_t -- swap them all now.
157
+ */
158
+#ifdef BSWAP_NEEDED
159
+ for (int i = 0; i < n / 4; i++) {
160
+ bswap32s(note.data + i);
161
+ }
162
+#endif
163
+
164
+ /*
165
+ * Note that nhdr is 3 words, and that the "name" described by namesz
166
+ * immediately follows nhdr and is thus at the 4th word. Further, all
167
+ * of the inputs to the kernel's round_up are multiples of 4.
168
+ */
169
+ if (note.nhdr.n_type != NT_GNU_PROPERTY_TYPE_0 ||
170
+ note.nhdr.n_namesz != NOTE_NAME_SZ ||
171
+ note.data[3] != GNU0_MAGIC) {
172
+ error_setg(errp, "Invalid note in PT_GNU_PROPERTY");
173
+ return false;
174
+ }
175
+ off = sizeof(note.nhdr) + NOTE_NAME_SZ;
176
+
177
+ datasz = note.nhdr.n_descsz + off;
178
+ if (datasz > n) {
179
+ error_setg(errp, "Invalid note size in PT_GNU_PROPERTY");
180
+ return false;
181
+ }
182
+
183
+ have_prev_type = false;
184
+ prev_type = 0;
185
+ while (1) {
186
+ if (off == datasz) {
187
+ return true; /* end, exit ok */
188
+ }
189
+ if (!parse_elf_property(note.data, &off, datasz, info,
190
+ have_prev_type, &prev_type, errp)) {
191
+ return false;
192
+ }
193
+ have_prev_type = true;
194
+ }
195
+}
196
+
197
/* Load an ELF image into the address space.
198
199
IMAGE_NAME is the filename of the image, to use in error messages.
200
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
201
goto exit_errmsg;
202
}
203
*pinterp_name = g_steal_pointer(&interp_name);
204
+ } else if (eppnt->p_type == PT_GNU_PROPERTY) {
205
+ if (!parse_elf_properties(image_fd, info, eppnt, bprm_buf, &err)) {
206
+ goto exit_errmsg;
207
+ }
208
}
209
}
41
210
42
--
211
--
43
2.16.2
212
2.20.1
44
213
45
214
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Not enabled anywhere yet.
3
Use the new generic support for NT_GNU_PROPERTY_TYPE_0.
4
4
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20201016184207.786698-12-richard.henderson@linaro.org
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180228193125.20577-2-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
9
---
11
target/arm/cpu.h | 1 +
10
linux-user/elfload.c | 48 ++++++++++++++++++++++++++++++++++++++++++--
12
linux-user/elfload.c | 1 +
11
1 file changed, 46 insertions(+), 2 deletions(-)
13
2 files changed, 2 insertions(+)
14
12
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/cpu.h
18
+++ b/target/arm/cpu.h
19
@@ -XXX,XX +XXX,XX @@ enum arm_features {
20
ARM_FEATURE_V8_SHA3, /* implements SHA3 part of v8 Crypto Extensions */
21
ARM_FEATURE_V8_SM3, /* implements SM3 part of v8 Crypto Extensions */
22
ARM_FEATURE_V8_SM4, /* implements SM4 part of v8 Crypto Extensions */
23
+ ARM_FEATURE_V8_RDM, /* implements v8.1 simd round multiply */
24
ARM_FEATURE_V8_FP16, /* implements v8.2 half-precision float */
25
};
26
27
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
13
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
28
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
29
--- a/linux-user/elfload.c
15
--- a/linux-user/elfload.c
30
+++ b/linux-user/elfload.c
16
+++ b/linux-user/elfload.c
31
@@ -XXX,XX +XXX,XX @@ static uint32_t get_elf_hwcap(void)
17
@@ -XXX,XX +XXX,XX @@ static void elf_core_copy_regs(target_elf_gregset_t *regs,
32
GET_FEATURE(ARM_FEATURE_V8_SHA512, ARM_HWCAP_A64_SHA512);
18
33
GET_FEATURE(ARM_FEATURE_V8_FP16,
19
#include "elf.h"
34
ARM_HWCAP_A64_FPHP | ARM_HWCAP_A64_ASIMDHP);
20
35
+ GET_FEATURE(ARM_FEATURE_V8_RDM, ARM_HWCAP_A64_ASIMDRDM);
21
+/* We must delay the following stanzas until after "elf.h". */
36
#undef GET_FEATURE
22
+#if defined(TARGET_AARCH64)
37
23
+
38
return hwcaps;
24
+static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
25
+ const uint32_t *data,
26
+ struct image_info *info,
27
+ Error **errp)
28
+{
29
+ if (pr_type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) {
30
+ if (pr_datasz != sizeof(uint32_t)) {
31
+ error_setg(errp, "Ill-formed GNU_PROPERTY_AARCH64_FEATURE_1_AND");
32
+ return false;
33
+ }
34
+ /* We will extract GNU_PROPERTY_AARCH64_FEATURE_1_BTI later. */
35
+ info->note_flags = *data;
36
+ }
37
+ return true;
38
+}
39
+#define ARCH_USE_GNU_PROPERTY 1
40
+
41
+#else
42
+
43
static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
44
const uint32_t *data,
45
struct image_info *info,
46
@@ -XXX,XX +XXX,XX @@ static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
47
}
48
#define ARCH_USE_GNU_PROPERTY 0
49
50
+#endif
51
+
52
struct exec
53
{
54
unsigned int a_info; /* Use macros N_MAGIC, etc for access */
55
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
56
struct elfhdr *ehdr = (struct elfhdr *)bprm_buf;
57
struct elf_phdr *phdr;
58
abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
59
- int i, retval;
60
+ int i, retval, prot_exec;
61
Error *err = NULL;
62
63
/* First of all, some simple consistency checks */
64
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
65
info->brk = 0;
66
info->elf_flags = ehdr->e_flags;
67
68
+ prot_exec = PROT_EXEC;
69
+#ifdef TARGET_AARCH64
70
+ /*
71
+ * If the BTI feature is present, this indicates that the executable
72
+ * pages of the startup binary should be mapped with PROT_BTI, so that
73
+ * branch targets are enforced.
74
+ *
75
+ * The startup binary is either the interpreter or the static executable.
76
+ * The interpreter is responsible for all pages of a dynamic executable.
77
+ *
78
+ * Elf notes are backward compatible to older cpus.
79
+ * Do not enable BTI unless it is supported.
80
+ */
81
+ if ((info->note_flags & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)
82
+ && (pinterp_name == NULL || *pinterp_name == 0)
83
+ && cpu_isar_feature(aa64_bti, ARM_CPU(thread_cpu))) {
84
+ prot_exec |= TARGET_PROT_BTI;
85
+ }
86
+#endif
87
+
88
for (i = 0; i < ehdr->e_phnum; i++) {
89
struct elf_phdr *eppnt = phdr + i;
90
if (eppnt->p_type == PT_LOAD) {
91
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
92
elf_prot |= PROT_WRITE;
93
}
94
if (eppnt->p_flags & PF_X) {
95
- elf_prot |= PROT_EXEC;
96
+ elf_prot |= prot_exec;
97
}
98
99
vaddr = load_bias + eppnt->p_vaddr;
39
--
100
--
40
2.16.2
101
2.20.1
41
102
42
103
diff view generated by jsdifflib
1
In some board or SoC models it is necessary to split a qemu_irq line
1
From: Richard Henderson <richard.henderson@linaro.org>
2
so that one input can feed multiple outputs. We currently have
2
3
qemu_irq_split() for this, but that has several deficiencies:
3
The note test requires gcc 10 for -mbranch-protection=standard.
4
* it can only handle splitting a line into two
4
The mmap test uses PROT_BTI and does not require special compiler support.
5
* it unavoidably leaks memory, so it can't be used
5
6
in a device that can be deleted
6
Acked-by: Alex Bennée <alex.bennee@linaro.org>
7
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Implement a qdev device that encapsulates splitting of IRQs, with a
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
configurable number of outputs. (This is in some ways the inverse of
9
Message-id: 20201016184207.786698-13-richard.henderson@linaro.org
10
the TYPE_OR_IRQ device.)
11
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20180220180325.29818-13-peter.maydell@linaro.org
15
---
11
---
16
hw/core/Makefile.objs | 1 +
12
tests/tcg/aarch64/bti-1.c | 62 +++++++++++++++++
17
include/hw/core/split-irq.h | 57 +++++++++++++++++++++++++++++
13
tests/tcg/aarch64/bti-2.c | 108 ++++++++++++++++++++++++++++++
18
include/hw/irq.h | 4 +-
14
tests/tcg/aarch64/bti-crt.inc.c | 51 ++++++++++++++
19
hw/core/split-irq.c | 89 +++++++++++++++++++++++++++++++++++++++++++++
15
tests/tcg/aarch64/Makefile.target | 10 +++
20
4 files changed, 150 insertions(+), 1 deletion(-)
16
tests/tcg/configure.sh | 4 ++
21
create mode 100644 include/hw/core/split-irq.h
17
5 files changed, 235 insertions(+)
22
create mode 100644 hw/core/split-irq.c
18
create mode 100644 tests/tcg/aarch64/bti-1.c
23
19
create mode 100644 tests/tcg/aarch64/bti-2.c
24
diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs
20
create mode 100644 tests/tcg/aarch64/bti-crt.inc.c
25
index XXXXXXX..XXXXXXX 100644
21
26
--- a/hw/core/Makefile.objs
22
diff --git a/tests/tcg/aarch64/bti-1.c b/tests/tcg/aarch64/bti-1.c
27
+++ b/hw/core/Makefile.objs
28
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_FITLOADER) += loader-fit.o
29
common-obj-$(CONFIG_SOFTMMU) += qdev-properties-system.o
30
common-obj-$(CONFIG_SOFTMMU) += register.o
31
common-obj-$(CONFIG_SOFTMMU) += or-irq.o
32
+common-obj-$(CONFIG_SOFTMMU) += split-irq.o
33
common-obj-$(CONFIG_PLATFORM_BUS) += platform-bus.o
34
35
obj-$(CONFIG_SOFTMMU) += generic-loader.o
36
diff --git a/include/hw/core/split-irq.h b/include/hw/core/split-irq.h
37
new file mode 100644
23
new file mode 100644
38
index XXXXXXX..XXXXXXX
24
index XXXXXXX..XXXXXXX
39
--- /dev/null
25
--- /dev/null
40
+++ b/include/hw/core/split-irq.h
26
+++ b/tests/tcg/aarch64/bti-1.c
41
@@ -XXX,XX +XXX,XX @@
27
@@ -XXX,XX +XXX,XX @@
42
+/*
28
+/*
43
+ * IRQ splitter device.
29
+ * Branch target identification, basic notskip cases.
44
+ *
45
+ * Copyright (c) 2018 Linaro Limited.
46
+ * Written by Peter Maydell
47
+ *
48
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
49
+ * of this software and associated documentation files (the "Software"), to deal
50
+ * in the Software without restriction, including without limitation the rights
51
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
52
+ * copies of the Software, and to permit persons to whom the Software is
53
+ * furnished to do so, subject to the following conditions:
54
+ *
55
+ * The above copyright notice and this permission notice shall be included in
56
+ * all copies or substantial portions of the Software.
57
+ *
58
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
59
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
60
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
61
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
62
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
63
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
64
+ * THE SOFTWARE.
65
+ */
30
+ */
66
+
31
+
67
+/* This is a simple device which has one GPIO input line and multiple
32
+#include "bti-crt.inc.c"
68
+ * GPIO output lines. Any change on the input line is forwarded to all
33
+
69
+ * of the outputs.
34
+static void skip2_sigill(int sig, siginfo_t *info, ucontext_t *uc)
70
+ *
35
+{
71
+ * QEMU interface:
36
+ uc->uc_mcontext.pc += 8;
72
+ * + one unnamed GPIO input: the input line
37
+ uc->uc_mcontext.pstate = 1;
73
+ * + N unnamed GPIO outputs: the output lines
38
+}
74
+ * + QOM property "num-lines": sets the number of output lines
39
+
75
+ */
40
+#define NOP "nop"
76
+#ifndef HW_SPLIT_IRQ_H
41
+#define BTI_N "hint #32"
77
+#define HW_SPLIT_IRQ_H
42
+#define BTI_C "hint #34"
78
+
43
+#define BTI_J "hint #36"
79
+#include "hw/irq.h"
44
+#define BTI_JC "hint #38"
80
+#include "hw/sysbus.h"
45
+
81
+#include "qom/object.h"
46
+#define BTYPE_1(DEST) \
82
+
47
+ asm("mov %0,#1; adr x16, 1f; br x16; 1: " DEST "; mov %0,#0" \
83
+#define TYPE_SPLIT_IRQ "split-irq"
48
+ : "=r"(skipped) : : "x16")
84
+
49
+
85
+#define MAX_SPLIT_LINES 16
50
+#define BTYPE_2(DEST) \
86
+
51
+ asm("mov %0,#1; adr x16, 1f; blr x16; 1: " DEST "; mov %0,#0" \
87
+typedef struct SplitIRQ SplitIRQ;
52
+ : "=r"(skipped) : : "x16", "x30")
88
+
53
+
89
+#define SPLIT_IRQ(obj) OBJECT_CHECK(SplitIRQ, (obj), TYPE_SPLIT_IRQ)
54
+#define BTYPE_3(DEST) \
90
+
55
+ asm("mov %0,#1; adr x15, 1f; br x15; 1: " DEST "; mov %0,#0" \
91
+struct SplitIRQ {
56
+ : "=r"(skipped) : : "x15")
92
+ DeviceState parent_obj;
57
+
93
+
58
+#define TEST(WHICH, DEST, EXPECT) \
94
+ qemu_irq out_irq[MAX_SPLIT_LINES];
59
+ do { WHICH(DEST); fail += skipped ^ EXPECT; } while (0)
95
+ uint16_t num_lines;
60
+
96
+};
61
+
97
+
62
+int main()
98
+#endif
63
+{
99
diff --git a/include/hw/irq.h b/include/hw/irq.h
64
+ int fail = 0;
100
index XXXXXXX..XXXXXXX 100644
65
+ int skipped;
101
--- a/include/hw/irq.h
66
+
102
+++ b/include/hw/irq.h
67
+ /* Signal-like with SA_SIGINFO. */
103
@@ -XXX,XX +XXX,XX @@ void qemu_free_irq(qemu_irq irq);
68
+ signal_info(SIGILL, skip2_sigill);
104
/* Returns a new IRQ with opposite polarity. */
69
+
105
qemu_irq qemu_irq_invert(qemu_irq irq);
70
+ TEST(BTYPE_1, NOP, 1);
106
71
+ TEST(BTYPE_1, BTI_N, 1);
107
-/* Returns a new IRQ which feeds into both the passed IRQs */
72
+ TEST(BTYPE_1, BTI_C, 0);
108
+/* Returns a new IRQ which feeds into both the passed IRQs.
73
+ TEST(BTYPE_1, BTI_J, 0);
109
+ * It's probably better to use the TYPE_SPLIT_IRQ device instead.
74
+ TEST(BTYPE_1, BTI_JC, 0);
110
+ */
75
+
111
qemu_irq qemu_irq_split(qemu_irq irq1, qemu_irq irq2);
76
+ TEST(BTYPE_2, NOP, 1);
112
77
+ TEST(BTYPE_2, BTI_N, 1);
113
/* Returns a new IRQ set which connects 1:1 to another IRQ set, which
78
+ TEST(BTYPE_2, BTI_C, 0);
114
diff --git a/hw/core/split-irq.c b/hw/core/split-irq.c
79
+ TEST(BTYPE_2, BTI_J, 1);
80
+ TEST(BTYPE_2, BTI_JC, 0);
81
+
82
+ TEST(BTYPE_3, NOP, 1);
83
+ TEST(BTYPE_3, BTI_N, 1);
84
+ TEST(BTYPE_3, BTI_C, 1);
85
+ TEST(BTYPE_3, BTI_J, 0);
86
+ TEST(BTYPE_3, BTI_JC, 0);
87
+
88
+ return fail;
89
+}
90
diff --git a/tests/tcg/aarch64/bti-2.c b/tests/tcg/aarch64/bti-2.c
115
new file mode 100644
91
new file mode 100644
116
index XXXXXXX..XXXXXXX
92
index XXXXXXX..XXXXXXX
117
--- /dev/null
93
--- /dev/null
118
+++ b/hw/core/split-irq.c
94
+++ b/tests/tcg/aarch64/bti-2.c
119
@@ -XXX,XX +XXX,XX @@
95
@@ -XXX,XX +XXX,XX @@
120
+/*
96
+/*
121
+ * IRQ splitter device.
97
+ * Branch target identification, basic notskip cases.
98
+ */
99
+
100
+#include <stdio.h>
101
+#include <signal.h>
102
+#include <string.h>
103
+#include <unistd.h>
104
+#include <sys/mman.h>
105
+
106
+#ifndef PROT_BTI
107
+#define PROT_BTI 0x10
108
+#endif
109
+
110
+static void skip2_sigill(int sig, siginfo_t *info, void *vuc)
111
+{
112
+ ucontext_t *uc = vuc;
113
+ uc->uc_mcontext.pc += 8;
114
+ uc->uc_mcontext.pstate = 1;
115
+}
116
+
117
+#define NOP "nop"
118
+#define BTI_N "hint #32"
119
+#define BTI_C "hint #34"
120
+#define BTI_J "hint #36"
121
+#define BTI_JC "hint #38"
122
+
123
+#define BTYPE_1(DEST) \
124
+ "mov x1, #1\n\t" \
125
+ "adr x16, 1f\n\t" \
126
+ "br x16\n" \
127
+"1: " DEST "\n\t" \
128
+ "mov x1, #0"
129
+
130
+#define BTYPE_2(DEST) \
131
+ "mov x1, #1\n\t" \
132
+ "adr x16, 1f\n\t" \
133
+ "blr x16\n" \
134
+"1: " DEST "\n\t" \
135
+ "mov x1, #0"
136
+
137
+#define BTYPE_3(DEST) \
138
+ "mov x1, #1\n\t" \
139
+ "adr x15, 1f\n\t" \
140
+ "br x15\n" \
141
+"1: " DEST "\n\t" \
142
+ "mov x1, #0"
143
+
144
+#define TEST(WHICH, DEST, EXPECT) \
145
+ WHICH(DEST) "\n" \
146
+ ".if " #EXPECT "\n\t" \
147
+ "eor x1, x1," #EXPECT "\n" \
148
+ ".endif\n\t" \
149
+ "add x0, x0, x1\n\t"
150
+
151
+extern char test_begin[], test_end[];
152
+
153
+asm("\n"
154
+"test_begin:\n\t"
155
+ BTI_C "\n\t"
156
+ "mov x2, x30\n\t"
157
+ "mov x0, #0\n\t"
158
+
159
+ TEST(BTYPE_1, NOP, 1)
160
+ TEST(BTYPE_1, BTI_N, 1)
161
+ TEST(BTYPE_1, BTI_C, 0)
162
+ TEST(BTYPE_1, BTI_J, 0)
163
+ TEST(BTYPE_1, BTI_JC, 0)
164
+
165
+ TEST(BTYPE_2, NOP, 1)
166
+ TEST(BTYPE_2, BTI_N, 1)
167
+ TEST(BTYPE_2, BTI_C, 0)
168
+ TEST(BTYPE_2, BTI_J, 1)
169
+ TEST(BTYPE_2, BTI_JC, 0)
170
+
171
+ TEST(BTYPE_3, NOP, 1)
172
+ TEST(BTYPE_3, BTI_N, 1)
173
+ TEST(BTYPE_3, BTI_C, 1)
174
+ TEST(BTYPE_3, BTI_J, 0)
175
+ TEST(BTYPE_3, BTI_JC, 0)
176
+
177
+ "ret x2\n"
178
+"test_end:"
179
+);
180
+
181
+int main()
182
+{
183
+ struct sigaction sa;
184
+
185
+ void *p = mmap(0, getpagesize(),
186
+ PROT_EXEC | PROT_READ | PROT_WRITE | PROT_BTI,
187
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
188
+ if (p == MAP_FAILED) {
189
+ perror("mmap");
190
+ return 1;
191
+ }
192
+
193
+ memset(&sa, 0, sizeof(sa));
194
+ sa.sa_sigaction = skip2_sigill;
195
+ sa.sa_flags = SA_SIGINFO;
196
+ if (sigaction(SIGILL, &sa, NULL) < 0) {
197
+ perror("sigaction");
198
+ return 1;
199
+ }
200
+
201
+ memcpy(p, test_begin, test_end - test_begin);
202
+ return ((int (*)(void))p)();
203
+}
204
diff --git a/tests/tcg/aarch64/bti-crt.inc.c b/tests/tcg/aarch64/bti-crt.inc.c
205
new file mode 100644
206
index XXXXXXX..XXXXXXX
207
--- /dev/null
208
+++ b/tests/tcg/aarch64/bti-crt.inc.c
209
@@ -XXX,XX +XXX,XX @@
210
+/*
211
+ * Minimal user-environment for testing BTI.
122
+ *
212
+ *
123
+ * Copyright (c) 2018 Linaro Limited.
213
+ * Normal libc is not (yet) built with BTI support enabled,
124
+ * Written by Peter Maydell
214
+ * and so could generate a BTI TRAP before ever reaching main.
125
+ *
126
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
127
+ * of this software and associated documentation files (the "Software"), to deal
128
+ * in the Software without restriction, including without limitation the rights
129
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
130
+ * copies of the Software, and to permit persons to whom the Software is
131
+ * furnished to do so, subject to the following conditions:
132
+ *
133
+ * The above copyright notice and this permission notice shall be included in
134
+ * all copies or substantial portions of the Software.
135
+ *
136
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
137
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
138
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
139
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
140
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
141
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
142
+ * THE SOFTWARE.
143
+ */
215
+ */
144
+
216
+
145
+#include "qemu/osdep.h"
217
+#include <stdlib.h>
146
+#include "hw/core/split-irq.h"
218
+#include <signal.h>
147
+#include "qapi/error.h"
219
+#include <ucontext.h>
148
+
220
+#include <asm/unistd.h>
149
+static void split_irq_handler(void *opaque, int n, int level)
221
+
150
+{
222
+int main(void);
151
+ SplitIRQ *s = SPLIT_IRQ(opaque);
223
+
152
+ int i;
224
+void _start(void)
153
+
225
+{
154
+ for (i = 0; i < s->num_lines; i++) {
226
+ exit(main());
155
+ qemu_set_irq(s->out_irq[i], level);
227
+}
156
+ }
228
+
157
+}
229
+void exit(int ret)
158
+
230
+{
159
+static void split_irq_init(Object *obj)
231
+ register int x0 __asm__("x0") = ret;
160
+{
232
+ register int x8 __asm__("x8") = __NR_exit;
161
+ qdev_init_gpio_in(DEVICE(obj), split_irq_handler, 1);
233
+
162
+}
234
+ asm volatile("svc #0" : : "r"(x0), "r"(x8));
163
+
235
+ __builtin_unreachable();
164
+static void split_irq_realize(DeviceState *dev, Error **errp)
236
+}
165
+{
237
+
166
+ SplitIRQ *s = SPLIT_IRQ(dev);
238
+/*
167
+
239
+ * Irritatingly, the user API struct sigaction does not match the
168
+ if (s->num_lines < 1 || s->num_lines >= MAX_SPLIT_LINES) {
240
+ * kernel API struct sigaction. So for simplicity, isolate the
169
+ error_setg(errp,
241
+ * kernel ABI here, and make this act like signal.
170
+ "IRQ splitter number of lines %d is not between 1 and %d",
242
+ */
171
+ s->num_lines, MAX_SPLIT_LINES);
243
+void signal_info(int sig, void (*fn)(int, siginfo_t *, ucontext_t *))
172
+ return;
244
+{
173
+ }
245
+ struct kernel_sigaction {
174
+
246
+ void (*handler)(int, siginfo_t *, ucontext_t *);
175
+ qdev_init_gpio_out(dev, s->out_irq, s->num_lines);
247
+ unsigned long flags;
176
+}
248
+ unsigned long restorer;
177
+
249
+ unsigned long mask;
178
+static Property split_irq_properties[] = {
250
+ } sa = { fn, SA_SIGINFO, 0, 0 };
179
+ DEFINE_PROP_UINT16("num-lines", SplitIRQ, num_lines, 1),
251
+
180
+ DEFINE_PROP_END_OF_LIST(),
252
+ register int x0 __asm__("x0") = sig;
181
+};
253
+ register void *x1 __asm__("x1") = &sa;
182
+
254
+ register void *x2 __asm__("x2") = 0;
183
+static void split_irq_class_init(ObjectClass *klass, void *data)
255
+ register int x3 __asm__("x3") = sizeof(unsigned long);
184
+{
256
+ register int x8 __asm__("x8") = __NR_rt_sigaction;
185
+ DeviceClass *dc = DEVICE_CLASS(klass);
257
+
186
+
258
+ asm volatile("svc #0"
187
+ /* No state to reset or migrate */
259
+ : : "r"(x0), "r"(x1), "r"(x2), "r"(x3), "r"(x8) : "memory");
188
+ dc->props = split_irq_properties;
260
+}
189
+ dc->realize = split_irq_realize;
261
diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
190
+
262
index XXXXXXX..XXXXXXX 100644
191
+ /* Reason: Needs to be wired up to work */
263
--- a/tests/tcg/aarch64/Makefile.target
192
+ dc->user_creatable = false;
264
+++ b/tests/tcg/aarch64/Makefile.target
193
+}
265
@@ -XXX,XX +XXX,XX @@ run-pauth-%: QEMU_OPTS += -cpu max
194
+
266
run-plugin-pauth-%: QEMU_OPTS += -cpu max
195
+static const TypeInfo split_irq_type_info = {
267
endif
196
+ .name = TYPE_SPLIT_IRQ,
268
197
+ .parent = TYPE_DEVICE,
269
+# BTI Tests
198
+ .instance_size = sizeof(SplitIRQ),
270
+# bti-1 tests the elf notes, so we require special compiler support.
199
+ .instance_init = split_irq_init,
271
+ifneq ($(DOCKER_IMAGE)$(CROSS_CC_HAS_ARMV8_BTI),)
200
+ .class_init = split_irq_class_init,
272
+AARCH64_TESTS += bti-1
201
+};
273
+bti-1: CFLAGS += -mbranch-protection=standard
202
+
274
+bti-1: LDFLAGS += -nostdlib
203
+static void split_irq_register_types(void)
275
+endif
204
+{
276
+# bti-2 tests PROT_BTI, so no special compiler support required.
205
+ type_register_static(&split_irq_type_info);
277
+AARCH64_TESTS += bti-2
206
+}
278
+
207
+
279
# Semihosting smoke test for linux-user
208
+type_init(split_irq_register_types)
280
AARCH64_TESTS += semihosting
281
run-semihosting: semihosting
282
diff --git a/tests/tcg/configure.sh b/tests/tcg/configure.sh
283
index XXXXXXX..XXXXXXX 100755
284
--- a/tests/tcg/configure.sh
285
+++ b/tests/tcg/configure.sh
286
@@ -XXX,XX +XXX,XX @@ for target in $target_list; do
287
-march=armv8.3-a -o $TMPE $TMPC; then
288
echo "CROSS_CC_HAS_ARMV8_3=y" >> $config_target_mak
289
fi
290
+ if do_compiler "$target_compiler" $target_compiler_cflags \
291
+ -mbranch-protection=standard -o $TMPE $TMPC; then
292
+ echo "CROSS_CC_HAS_ARMV8_BTI=y" >> $config_target_mak
293
+ fi
294
;;
295
esac
296
209
--
297
--
210
2.16.2
298
2.20.1
211
299
212
300
diff view generated by jsdifflib