1
ARM queue for 2.10 soft freeze...
1
The following changes since commit 4c41341af76cfc85b5a6c0f87de4838672ab9f89:
2
2
3
thanks
3
Merge remote-tracking branch 'remotes/aperard/tags/pull-xen-20201020' into staging (2020-10-20 11:20:36 +0100)
4
-- PMM
5
4
6
The following changes since commit 6632f6ff96f0537fc34cdc00c760656fc62e23c5:
5
are available in the Git repository at:
7
6
8
Merge remote-tracking branch 'remotes/famz/tags/block-and-testing-pull-request' into staging (2017-07-17 11:46:36 +0100)
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20201020
9
8
10
are available in the git repository at:
9
for you to fetch changes up to 6358890cb939192f6169fdf7664d903bf9b1d338:
11
10
12
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20170717
11
tests/tcg/aarch64: Add bti smoke tests (2020-10-20 16:12:02 +0100)
13
14
for you to fetch changes up to e5a6a6e64e82a132cebef023d867085b0a2993d7:
15
16
MAINTAINERS: Add entries for MPS2 board (2017-07-17 13:36:09 +0100)
17
12
18
----------------------------------------------------------------
13
----------------------------------------------------------------
19
target-arm queue:
14
target-arm queue:
20
* new model of the ARM MPS2/MPS2+ FPGA based development board
15
* Fix AArch32 SMLAD incorrect setting of Q bit
21
* clean up DISAS_* exit conditions and fix various regressions
16
* AArch32 VCVT fixed-point to float is always round-to-nearest
22
since commits e75449a346 8a6b28c7b5 (in particular including
17
* strongarm: Fix 'time to transmit a char' unit comment
23
ones which broke OP-TEE guests)
18
* Restrict APEI tables generation to the 'virt' machine
24
* make Cortex-M3 and M4 correctly default to 8 PMSA regions
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
25
29
26
----------------------------------------------------------------
30
----------------------------------------------------------------
27
Alex Bennée (6):
31
Emanuele Giuseppe Esposito (1):
28
include/exec/exec-all: document common exit conditions
32
loads-stores.rst: add footnote that clarifies GETPC usage
29
target/arm/translate: make DISAS_UPDATE match declared semantics
33
30
target/arm/translate.h: expand comment on DISAS_EXIT
34
Havard Skinnemoen (1):
31
target/arm/translate: ensure gen_goto_tb sets exit flags
35
tests/qtest: Add npcm7xx timer test
32
target/arm: use gen_goto_tb for ISB handling
36
33
target/arm: use DISAS_EXIT for eret handling
37
Peng Liang (1):
38
microbit_i2c: Fix coredump when dump-vmstate
34
39
35
Peter Maydell (12):
40
Peter Maydell (12):
36
qdev-properties.h: Explicitly set the default value for arraylen properties
41
target/arm: Fix SMLAD incorrect setting of Q bit
37
qdev: support properties which don't set a default value
42
target/arm: AArch32 VCVT fixed-point to float is always round-to-nearest
38
target/arm: Make Cortex-M3 and M4 default to 8 PMSA regions
43
decodetree: Fix codegen for non-overlapping group inside overlapping group
39
hw/arm/mps2: Implement skeleton mps2-an385 and mps2-an511 board models
44
target/arm: Implement v8.1M NOCP handling
40
hw/char/cmsdk-apb-uart.c: Implement CMSDK APB UART
45
target/arm: Implement v8.1M conditional-select insns
41
hw/arm/mps2: Add UARTs
46
target/arm: Make the t32 insn[25:23]=111 group non-overlapping
42
hw/char/cmsdk-apb-timer: Implement CMSDK APB timer device
47
target/arm: Don't allow BLX imm for M-profile
43
hw/arm/mps2: Add timers
48
target/arm: Implement v8.1M branch-future insns (as NOPs)
44
hw/misc/mps2_scc: Implement MPS2 Serial Communication Controller
49
target/arm: Implement v8.1M low-overhead-loop instructions
45
hw/arm/mps2: Add SCC
50
target/arm: Fix has_vfp/has_neon ID reg squashing for M-profile
46
hw/arm/mps2: Add ethernet
51
target/arm: Allow M-profile CPUs with FP16 to set FPSCR.FP16
47
MAINTAINERS: Add entries for MPS2 board
52
target/arm: Implement FPSCR.LTPSIZE for M-profile LOB extension
48
53
49
hw/arm/Makefile.objs | 1 +
54
Philippe Mathieu-Daudé (10):
50
hw/char/Makefile.objs | 1 +
55
hw/arm/strongarm: Fix 'time to transmit a char' unit comment
51
hw/misc/Makefile.objs | 1 +
56
hw/arm: Restrict APEI tables generation to the 'virt' machine
52
hw/timer/Makefile.objs | 1 +
57
hw/timer/bcm2835: Introduce BCM2835_SYSTIMER_COUNT definition
53
include/exec/exec-all.h | 29 ++-
58
hw/timer/bcm2835: Rename variable holding CTRL_STATUS register
54
include/hw/char/cmsdk-apb-uart.h | 78 +++++++
59
hw/timer/bcm2835: Support the timer COMPARE registers
55
include/hw/misc/mps2-scc.h | 43 ++++
60
hw/arm/bcm2835_peripherals: Correctly wire the SYS_timer IRQs
56
include/hw/qdev-core.h | 10 +
61
hw/intc/bcm2835_ic: Trace GPU/CPU IRQ handlers
57
include/hw/qdev-properties.h | 21 ++
62
hw/intc/bcm2836_control: Use IRQ definitions instead of magic numbers
58
include/hw/timer/cmsdk-apb-timer.h | 59 ++++++
63
hw/arm/nseries: Fix loading kernel image on n8x0 machines
59
target/arm/translate.h | 5 +-
64
linux-user/elfload: Avoid leaking interp_name using GLib memory API
60
hw/arm/mps2.c | 385 +++++++++++++++++++++++++++++++++++
61
hw/char/cmsdk-apb-uart.c | 403 +++++++++++++++++++++++++++++++++++++
62
hw/core/qdev.c | 2 +-
63
hw/misc/mps2-scc.c | 310 ++++++++++++++++++++++++++++
64
hw/timer/cmsdk-apb-timer.c | 253 +++++++++++++++++++++++
65
target/arm/cpu.c | 12 +-
66
target/arm/translate-a64.c | 19 +-
67
target/arm/translate.c | 22 +-
68
MAINTAINERS | 14 +-
69
default-configs/arm-softmmu.mak | 6 +
70
hw/char/trace-events | 9 +
71
hw/misc/trace-events | 8 +
72
hw/timer/trace-events | 5 +
73
24 files changed, 1673 insertions(+), 24 deletions(-)
74
create mode 100644 include/hw/char/cmsdk-apb-uart.h
75
create mode 100644 include/hw/misc/mps2-scc.h
76
create mode 100644 include/hw/timer/cmsdk-apb-timer.h
77
create mode 100644 hw/arm/mps2.c
78
create mode 100644 hw/char/cmsdk-apb-uart.c
79
create mode 100644 hw/misc/mps2-scc.c
80
create mode 100644 hw/timer/cmsdk-apb-timer.c
81
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
New patch
1
The SMLAD instruction is supposed to:
2
* signed multiply Rn[15:0] * Rm[15:0]
3
* signed multiply Rn[31:16] * Rm[31:16]
4
* perform a signed addition of the products and Ra
5
* set Rd to the low 32 bits of the theoretical
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)
1
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.
28
29
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
30
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
31
Message-id: 20201009144712.11187-1-peter.maydell@linaro.org
32
---
33
target/arm/translate.c | 58 ++++++++++++++++++++++++++++++++++--------
34
1 file changed, 48 insertions(+), 10 deletions(-)
35
36
diff --git a/target/arm/translate.c b/target/arm/translate.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/translate.c
39
+++ b/target/arm/translate.c
40
@@ -XXX,XX +XXX,XX @@ static bool op_smlad(DisasContext *s, arg_rrrr *a, bool m_swap, bool sub)
41
gen_smul_dual(t1, t2);
42
43
if (sub) {
44
- /* This subtraction cannot overflow. */
45
+ /*
46
+ * This subtraction cannot overflow, so we can do a simple
47
+ * 32-bit subtraction and then a possible 32-bit saturating
48
+ * addition of Ra.
49
+ */
50
tcg_gen_sub_i32(t1, t1, t2);
51
+ tcg_temp_free_i32(t2);
52
+
53
+ if (a->ra != 15) {
54
+ t2 = load_reg(s, a->ra);
55
+ gen_helper_add_setq(t1, cpu_env, t1, t2);
56
+ tcg_temp_free_i32(t2);
57
+ }
58
+ } else if (a->ra == 15) {
59
+ /* Single saturation-checking addition */
60
+ gen_helper_add_setq(t1, cpu_env, t1, t2);
61
+ tcg_temp_free_i32(t2);
62
} else {
63
/*
64
- * This addition cannot overflow 32 bits; however it may
65
- * overflow considered as a signed operation, in which case
66
- * we must set the Q flag.
67
+ * We need to add the products and Ra together and then
68
+ * determine whether the final result overflowed. Doing
69
+ * this as two separate add-and-check-overflow steps incorrectly
70
+ * sets Q for cases like (-32768 * -32768) + (-32768 * -32768) + -1.
71
+ * Do all the arithmetic at 64-bits and then check for overflow.
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);
91
+
92
+ tcg_gen_extr_i64_i32(t1, t2, p64);
93
+ tcg_temp_free_i64(p64);
94
+ /*
95
+ * t1 is the low half of the result which goes into Rd.
96
+ * We have overflow and must set Q if the high half (t2)
97
+ * is different from the sign-extension of t1.
98
+ */
99
+ t3 = tcg_temp_new_i32();
100
+ tcg_gen_sari_i32(t3, t1, 31);
101
+ qf = load_cpu_field(QF);
102
+ one = tcg_const_i32(1);
103
+ tcg_gen_movcond_i32(TCG_COND_NE, qf, t2, t3, one, qf);
104
+ store_cpu_field(qf, QF);
105
+ tcg_temp_free_i32(one);
106
+ tcg_temp_free_i32(t3);
107
tcg_temp_free_i32(t2);
108
}
109
store_reg(s, a->rd, t1);
110
--
111
2.20.1
112
113
diff view generated by jsdifflib
1
Add the UARTs to the MPS2 board models.
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
Unfortunately the details of the wiring of the interrupts through
6
Implement this by providing _round_to_nearest versions of the
4
various OR gates differ between AN511 and AN385 so this can't
7
relevant helpers which set the rounding mode temporarily when making
5
be purely a data-driven difference.
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.
6
14
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 1500029487-14822-4-git-send-email-peter.maydell@linaro.org
17
Message-id: 20201013103532.13391-1-peter.maydell@linaro.org
10
---
18
---
11
hw/arm/mps2.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++
19
target/arm/helper.h | 13 +++++++++++++
12
hw/char/cmsdk-apb-uart.c | 2 +-
20
target/arm/vfp_helper.c | 23 ++++++++++++++++++++++-
13
2 files changed, 89 insertions(+), 1 deletion(-)
21
target/arm/translate-vfp.c.inc | 24 ++++++++++++------------
22
3 files changed, 47 insertions(+), 13 deletions(-)
14
23
15
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
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/hw/arm/mps2.c
26
--- a/target/arm/helper.h
18
+++ b/hw/arm/mps2.c
27
+++ b/target/arm/helper.h
19
@@ -XXX,XX +XXX,XX @@
28
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(vfp_ultoh, f16, i32, i32, ptr)
20
#include "qemu/error-report.h"
29
DEF_HELPER_3(vfp_sqtoh, f16, i64, i32, ptr)
21
#include "hw/arm/arm.h"
30
DEF_HELPER_3(vfp_uqtoh, f16, i64, i32, ptr)
22
#include "hw/arm/armv7m.h"
31
23
+#include "hw/or-irq.h"
32
+DEF_HELPER_3(vfp_shtos_round_to_nearest, f32, i32, i32, ptr)
24
#include "hw/boards.h"
33
+DEF_HELPER_3(vfp_sltos_round_to_nearest, f32, i32, i32, ptr)
25
#include "exec/address-spaces.h"
34
+DEF_HELPER_3(vfp_uhtos_round_to_nearest, f32, i32, i32, ptr)
26
+#include "sysemu/sysemu.h"
35
+DEF_HELPER_3(vfp_ultos_round_to_nearest, f32, i32, i32, ptr)
27
#include "hw/misc/unimp.h"
36
+DEF_HELPER_3(vfp_shtod_round_to_nearest, f64, i64, i32, ptr)
28
+#include "hw/char/cmsdk-apb-uart.h"
37
+DEF_HELPER_3(vfp_sltod_round_to_nearest, f64, i64, i32, ptr)
29
38
+DEF_HELPER_3(vfp_uhtod_round_to_nearest, f64, i64, i32, ptr)
30
typedef enum MPS2FPGAType {
39
+DEF_HELPER_3(vfp_ultod_round_to_nearest, f64, i64, i32, ptr)
31
FPGA_AN385,
40
+DEF_HELPER_3(vfp_shtoh_round_to_nearest, f16, i32, i32, ptr)
32
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
41
+DEF_HELPER_3(vfp_uhtoh_round_to_nearest, f16, i32, i32, ptr)
33
create_unimplemented_device("Ethernet", 0x40200000, 0x00100000);
42
+DEF_HELPER_3(vfp_sltoh_round_to_nearest, f16, i32, i32, ptr)
34
create_unimplemented_device("VGA", 0x41000000, 0x0200000);
43
+DEF_HELPER_3(vfp_ultoh_round_to_nearest, f16, i32, i32, ptr)
35
36
+ switch (mmc->fpga_type) {
37
+ case FPGA_AN385:
38
+ {
39
+ /* The overflow IRQs for UARTs 0, 1 and 2 are ORed together.
40
+ * Overflow for UARTs 4 and 5 doesn't trigger any interrupt.
41
+ */
42
+ Object *orgate;
43
+ DeviceState *orgate_dev;
44
+ int i;
45
+
44
+
46
+ orgate = object_new(TYPE_OR_IRQ);
45
DEF_HELPER_FLAGS_2(set_rmode, TCG_CALL_NO_RWG, i32, i32, ptr)
47
+ object_property_set_int(orgate, 6, "num-lines", &error_fatal);
46
48
+ object_property_set_bool(orgate, true, "realized", &error_fatal);
47
DEF_HELPER_FLAGS_3(vfp_fcvt_f16_to_f32, TCG_CALL_NO_RWG, f32, f16, ptr, i32)
49
+ orgate_dev = DEVICE(orgate);
48
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
50
+ qdev_connect_gpio_out(orgate_dev, 0, qdev_get_gpio_in(armv7m, 12));
49
index XXXXXXX..XXXXXXX 100644
51
+
50
--- a/target/arm/vfp_helper.c
52
+ for (i = 0; i < 5; i++) {
51
+++ b/target/arm/vfp_helper.c
53
+ static const hwaddr uartbase[] = {0x40004000, 0x40005000,
52
@@ -XXX,XX +XXX,XX @@ float32 VFP_HELPER(fcvts, d)(float64 x, CPUARMState *env)
54
+ 0x40006000, 0x40007000,
53
return float64_to_float32(x, &env->vfp.fp_status);
55
+ 0x40009000};
54
}
56
+ Chardev *uartchr = i < MAX_SERIAL_PORTS ? serial_hds[i] : NULL;
55
57
+ /* RX irq number; TX irq is always one greater */
56
-/* VFP3 fixed point conversion. */
58
+ static const int uartirq[] = {0, 2, 4, 18, 20};
57
+/*
59
+ qemu_irq txovrint = NULL, rxovrint = NULL;
58
+ * VFP3 fixed point conversion. The AArch32 versions of fix-to-float
60
+
59
+ * must always round-to-nearest; the AArch64 ones honour the FPSCR
61
+ if (i < 3) {
60
+ * rounding mode. (For AArch32 Neon the standard-FPSCR is set to
62
+ txovrint = qdev_get_gpio_in(orgate_dev, i * 2);
61
+ * round-to-nearest so either helper will work.) AArch32 float-to-fix
63
+ rxovrint = qdev_get_gpio_in(orgate_dev, i * 2 + 1);
62
+ * must round-to-zero.
64
+ }
63
+ */
65
+
64
#define VFP_CONV_FIX_FLOAT(name, p, fsz, ftype, isz, itype) \
66
+ cmsdk_apb_uart_create(uartbase[i],
65
ftype HELPER(vfp_##name##to##p)(uint##isz##_t x, uint32_t shift, \
67
+ qdev_get_gpio_in(armv7m, uartirq[i] + 1),
66
void *fpstp) \
68
+ qdev_get_gpio_in(armv7m, uartirq[i]),
67
{ return itype##_to_##float##fsz##_scalbn(x, -shift, fpstp); }
69
+ txovrint, rxovrint,
68
70
+ NULL,
69
+#define VFP_CONV_FIX_FLOAT_ROUND(name, p, fsz, ftype, isz, itype) \
71
+ uartchr, SYSCLK_FRQ);
70
+ ftype HELPER(vfp_##name##to##p##_round_to_nearest)(uint##isz##_t x, \
72
+ }
71
+ uint32_t shift, \
73
+ break;
72
+ void *fpstp) \
74
+ }
73
+ { \
75
+ case FPGA_AN511:
74
+ ftype ret; \
76
+ {
75
+ float_status *fpst = fpstp; \
77
+ /* The overflow IRQs for all UARTs are ORed together.
76
+ FloatRoundMode oldmode = fpst->float_rounding_mode; \
78
+ * Tx and Rx IRQs for each UART are ORed together.
77
+ fpst->float_rounding_mode = float_round_nearest_even; \
79
+ */
78
+ ret = itype##_to_##float##fsz##_scalbn(x, -shift, fpstp); \
80
+ Object *orgate;
79
+ fpst->float_rounding_mode = oldmode; \
81
+ DeviceState *orgate_dev;
80
+ return ret; \
82
+ int i;
83
+
84
+ orgate = object_new(TYPE_OR_IRQ);
85
+ object_property_set_int(orgate, 10, "num-lines", &error_fatal);
86
+ object_property_set_bool(orgate, true, "realized", &error_fatal);
87
+ orgate_dev = DEVICE(orgate);
88
+ qdev_connect_gpio_out(orgate_dev, 0, qdev_get_gpio_in(armv7m, 12));
89
+
90
+ for (i = 0; i < 5; i++) {
91
+ /* system irq numbers for the combined tx/rx for each UART */
92
+ static const int uart_txrx_irqno[] = {0, 2, 45, 46, 56};
93
+ static const hwaddr uartbase[] = {0x40004000, 0x40005000,
94
+ 0x4002c000, 0x4002d000,
95
+ 0x4002e000};
96
+ Chardev *uartchr = i < MAX_SERIAL_PORTS ? serial_hds[i] : NULL;
97
+ Object *txrx_orgate;
98
+ DeviceState *txrx_orgate_dev;
99
+
100
+ txrx_orgate = object_new(TYPE_OR_IRQ);
101
+ object_property_set_int(txrx_orgate, 2, "num-lines", &error_fatal);
102
+ object_property_set_bool(txrx_orgate, true, "realized",
103
+ &error_fatal);
104
+ txrx_orgate_dev = DEVICE(txrx_orgate);
105
+ qdev_connect_gpio_out(txrx_orgate_dev, 0,
106
+ qdev_get_gpio_in(armv7m, uart_txrx_irqno[i]));
107
+ cmsdk_apb_uart_create(uartbase[i],
108
+ qdev_get_gpio_in(txrx_orgate_dev, 0),
109
+ qdev_get_gpio_in(txrx_orgate_dev, 1),
110
+ qdev_get_gpio_in(orgate_dev, 0),
111
+ qdev_get_gpio_in(orgate_dev, 1),
112
+ NULL,
113
+ uartchr, SYSCLK_FRQ);
114
+ }
115
+ break;
116
+ }
117
+ default:
118
+ g_assert_not_reached();
119
+ }
81
+ }
120
+
82
+
121
system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ;
83
#define VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, ROUND, suff) \
122
84
uint##isz##_t HELPER(vfp_to##name##p##suff)(ftype x, uint32_t shift, \
123
armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
85
void *fpst) \
124
diff --git a/hw/char/cmsdk-apb-uart.c b/hw/char/cmsdk-apb-uart.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
125
index XXXXXXX..XXXXXXX 100644
95
index XXXXXXX..XXXXXXX 100644
126
--- a/hw/char/cmsdk-apb-uart.c
96
--- a/target/arm/translate-vfp.c.inc
127
+++ b/hw/char/cmsdk-apb-uart.c
97
+++ b/target/arm/translate-vfp.c.inc
128
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_uart_realize(DeviceState *dev, Error **errp)
98
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_hp(DisasContext *s, arg_VCVT_fix_sp *a)
129
* an event handler to deal with CHR_EVENT_BREAK.
99
/* Switch on op:U:sx bits */
130
*/
100
switch (a->opc) {
131
qemu_chr_fe_set_handlers(&s->chr, uart_can_receive, uart_receive,
101
case 0:
132
- NULL, s, NULL, true);
102
- gen_helper_vfp_shtoh(vd, vd, shift, fpst);
133
+ NULL, NULL, s, NULL, true);
103
+ gen_helper_vfp_shtoh_round_to_nearest(vd, vd, shift, fpst);
134
}
104
break;
135
105
case 1:
136
static int cmsdk_apb_uart_post_load(void *opaque, int version_id)
106
- gen_helper_vfp_sltoh(vd, vd, shift, fpst);
107
+ gen_helper_vfp_sltoh_round_to_nearest(vd, vd, shift, fpst);
108
break;
109
case 2:
110
- gen_helper_vfp_uhtoh(vd, vd, shift, fpst);
111
+ gen_helper_vfp_uhtoh_round_to_nearest(vd, vd, shift, fpst);
112
break;
113
case 3:
114
- gen_helper_vfp_ultoh(vd, vd, shift, fpst);
115
+ gen_helper_vfp_ultoh_round_to_nearest(vd, vd, shift, fpst);
116
break;
117
case 4:
118
gen_helper_vfp_toshh_round_to_zero(vd, vd, shift, fpst);
119
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_sp(DisasContext *s, arg_VCVT_fix_sp *a)
120
/* Switch on op:U:sx bits */
121
switch (a->opc) {
122
case 0:
123
- gen_helper_vfp_shtos(vd, vd, shift, fpst);
124
+ gen_helper_vfp_shtos_round_to_nearest(vd, vd, shift, fpst);
125
break;
126
case 1:
127
- gen_helper_vfp_sltos(vd, vd, shift, fpst);
128
+ gen_helper_vfp_sltos_round_to_nearest(vd, vd, shift, fpst);
129
break;
130
case 2:
131
- gen_helper_vfp_uhtos(vd, vd, shift, fpst);
132
+ gen_helper_vfp_uhtos_round_to_nearest(vd, vd, shift, fpst);
133
break;
134
case 3:
135
- gen_helper_vfp_ultos(vd, vd, shift, fpst);
136
+ gen_helper_vfp_ultos_round_to_nearest(vd, vd, shift, fpst);
137
break;
138
case 4:
139
gen_helper_vfp_toshs_round_to_zero(vd, vd, shift, fpst);
140
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a)
141
/* Switch on op:U:sx bits */
142
switch (a->opc) {
143
case 0:
144
- gen_helper_vfp_shtod(vd, vd, shift, fpst);
145
+ gen_helper_vfp_shtod_round_to_nearest(vd, vd, shift, fpst);
146
break;
147
case 1:
148
- gen_helper_vfp_sltod(vd, vd, shift, fpst);
149
+ gen_helper_vfp_sltod_round_to_nearest(vd, vd, shift, fpst);
150
break;
151
case 2:
152
- gen_helper_vfp_uhtod(vd, vd, shift, fpst);
153
+ gen_helper_vfp_uhtod_round_to_nearest(vd, vd, shift, fpst);
154
break;
155
case 3:
156
- gen_helper_vfp_ultod(vd, vd, shift, fpst);
157
+ gen_helper_vfp_ultod_round_to_nearest(vd, vd, shift, fpst);
158
break;
159
case 4:
160
gen_helper_vfp_toshd_round_to_zero(vd, vd, shift, fpst);
137
--
161
--
138
2.7.4
162
2.20.1
139
163
140
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
New patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
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
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
include/hw/timer/bcm2835_systmr.h | 4 +++-
13
hw/timer/bcm2835_systmr.c | 3 ++-
14
2 files changed, 5 insertions(+), 2 deletions(-)
15
16
diff --git a/include/hw/timer/bcm2835_systmr.h b/include/hw/timer/bcm2835_systmr.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/timer/bcm2835_systmr.h
19
+++ b/include/hw/timer/bcm2835_systmr.h
20
@@ -XXX,XX +XXX,XX @@
21
#define TYPE_BCM2835_SYSTIMER "bcm2835-sys-timer"
22
OBJECT_DECLARE_SIMPLE_TYPE(BCM2835SystemTimerState, BCM2835_SYSTIMER)
23
24
+#define BCM2835_SYSTIMER_COUNT 4
25
+
26
struct BCM2835SystemTimerState {
27
/*< private >*/
28
SysBusDevice parent_obj;
29
@@ -XXX,XX +XXX,XX @@ struct BCM2835SystemTimerState {
30
31
struct {
32
uint32_t status;
33
- uint32_t compare[4];
34
+ uint32_t compare[BCM2835_SYSTIMER_COUNT];
35
} reg;
36
};
37
38
diff --git a/hw/timer/bcm2835_systmr.c b/hw/timer/bcm2835_systmr.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/hw/timer/bcm2835_systmr.c
41
+++ b/hw/timer/bcm2835_systmr.c
42
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription bcm2835_systmr_vmstate = {
43
.minimum_version_id = 1,
44
.fields = (VMStateField[]) {
45
VMSTATE_UINT32(reg.status, BCM2835SystemTimerState),
46
- VMSTATE_UINT32_ARRAY(reg.compare, BCM2835SystemTimerState, 4),
47
+ VMSTATE_UINT32_ARRAY(reg.compare, BCM2835SystemTimerState,
48
+ BCM2835_SYSTIMER_COUNT),
49
VMSTATE_END_OF_LIST()
50
}
51
};
52
--
53
2.20.1
54
55
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
2
3
The variable holding the CTRL_STATUS register is misnamed
4
'status'. Rename it 'ctrl_status' to make it more obvious
5
this register is also used to control the peripheral.
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
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
include/hw/timer/bcm2835_systmr.h | 2 +-
14
hw/timer/bcm2835_systmr.c | 8 ++++----
15
2 files changed, 5 insertions(+), 5 deletions(-)
16
17
diff --git a/include/hw/timer/bcm2835_systmr.h b/include/hw/timer/bcm2835_systmr.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/timer/bcm2835_systmr.h
20
+++ b/include/hw/timer/bcm2835_systmr.h
21
@@ -XXX,XX +XXX,XX @@ struct BCM2835SystemTimerState {
22
qemu_irq irq;
23
24
struct {
25
- uint32_t status;
26
+ uint32_t ctrl_status;
27
uint32_t compare[BCM2835_SYSTIMER_COUNT];
28
} reg;
29
};
30
diff --git a/hw/timer/bcm2835_systmr.c b/hw/timer/bcm2835_systmr.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/timer/bcm2835_systmr.c
33
+++ b/hw/timer/bcm2835_systmr.c
34
@@ -XXX,XX +XXX,XX @@ REG32(COMPARE3, 0x18)
35
36
static void bcm2835_systmr_update_irq(BCM2835SystemTimerState *s)
37
{
38
- bool enable = !!s->reg.status;
39
+ bool enable = !!s->reg.ctrl_status;
40
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()
70
--
71
2.20.1
72
73
diff view generated by jsdifflib
1
Implement a model of the simple timer device found in the CMSDK.
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
This peripheral has 1 free-running timer and 4 compare registers.
4
5
Only the free-running timer is implemented. Add support the
6
COMPARE registers (each register is wired to an IRQ).
7
8
Reference: "BCM2835 ARM Peripherals" datasheet [*]
9
chapter 12 "System Timer":
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
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Message-id: 1500029487-14822-5-git-send-email-peter.maydell@linaro.org
6
---
28
---
7
hw/timer/Makefile.objs | 1 +
29
include/hw/timer/bcm2835_systmr.h | 11 +++++--
8
include/hw/timer/cmsdk-apb-timer.h | 59 +++++++++
30
hw/timer/bcm2835_systmr.c | 48 ++++++++++++++++++++-----------
9
hw/timer/cmsdk-apb-timer.c | 253 +++++++++++++++++++++++++++++++++++++
31
hw/timer/trace-events | 6 ++--
10
default-configs/arm-softmmu.mak | 1 +
32
3 files changed, 44 insertions(+), 21 deletions(-)
11
hw/timer/trace-events | 5 +
12
5 files changed, 319 insertions(+)
13
create mode 100644 include/hw/timer/cmsdk-apb-timer.h
14
create mode 100644 hw/timer/cmsdk-apb-timer.c
15
33
16
diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs
34
diff --git a/include/hw/timer/bcm2835_systmr.h b/include/hw/timer/bcm2835_systmr.h
17
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/timer/Makefile.objs
36
--- a/include/hw/timer/bcm2835_systmr.h
19
+++ b/hw/timer/Makefile.objs
37
+++ b/include/hw/timer/bcm2835_systmr.h
20
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_STM32F2XX_TIMER) += stm32f2xx_timer.o
21
common-obj-$(CONFIG_ASPEED_SOC) += aspeed_timer.o
22
23
common-obj-$(CONFIG_SUN4V_RTC) += sun4v-rtc.o
24
+common-obj-$(CONFIG_CMSDK_APB_TIMER) += cmsdk-apb-timer.o
25
diff --git a/include/hw/timer/cmsdk-apb-timer.h b/include/hw/timer/cmsdk-apb-timer.h
26
new file mode 100644
27
index XXXXXXX..XXXXXXX
28
--- /dev/null
29
+++ b/include/hw/timer/cmsdk-apb-timer.h
30
@@ -XXX,XX +XXX,XX @@
38
@@ -XXX,XX +XXX,XX @@
31
+/*
39
32
+ * ARM CMSDK APB timer emulation
40
#include "hw/sysbus.h"
33
+ *
41
#include "hw/irq.h"
34
+ * Copyright (c) 2017 Linaro Limited
42
+#include "qemu/timer.h"
35
+ * Written by Peter Maydell
43
#include "qom/object.h"
36
+ *
44
37
+ * This program is free software; you can redistribute it and/or modify
45
#define TYPE_BCM2835_SYSTIMER "bcm2835-sys-timer"
38
+ * it under the terms of the GNU General Public License version 2 or
46
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(BCM2835SystemTimerState, BCM2835_SYSTIMER)
39
+ * (at your option) any later version.
47
40
+ */
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;
41
+
56
+
42
+#ifndef CMSDK_APB_TIMER_H
57
struct BCM2835SystemTimerState {
43
+#define CMSDK_APB_TIMER_H
58
/*< private >*/
59
SysBusDevice parent_obj;
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
74
index XXXXXXX..XXXXXXX 100644
75
--- a/hw/timer/bcm2835_systmr.c
76
+++ b/hw/timer/bcm2835_systmr.c
77
@@ -XXX,XX +XXX,XX @@ REG32(COMPARE1, 0x10)
78
REG32(COMPARE2, 0x14)
79
REG32(COMPARE3, 0x18)
80
81
-static void bcm2835_systmr_update_irq(BCM2835SystemTimerState *s)
82
+static void bcm2835_systmr_timer_expire(void *opaque)
83
{
84
- bool enable = !!s->reg.ctrl_status;
85
+ BCM2835SystemTimerCompare *tmr = opaque;
86
87
- trace_bcm2835_systmr_irq(enable);
88
- qemu_set_irq(s->irq, enable);
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);
100
}
101
102
static uint64_t bcm2835_systmr_read(void *opaque, hwaddr offset,
103
@@ -XXX,XX +XXX,XX @@ static uint64_t bcm2835_systmr_read(void *opaque, hwaddr offset,
104
}
105
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);
44
+
146
+
45
+#include "hw/sysbus.h"
147
+ for (size_t i = 0; i < ARRAY_SIZE(s->tmr); i++) {
46
+#include "hw/ptimer.h"
148
+ s->tmr[i].id = i;
47
+
149
+ s->tmr[i].state = s;
48
+#define TYPE_CMSDK_APB_TIMER "cmsdk-apb-timer"
150
+ sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->tmr[i].irq);
49
+#define CMSDK_APB_TIMER(obj) OBJECT_CHECK(CMSDKAPBTIMER, (obj), \
151
+ timer_init_us(&s->tmr[i].timer, QEMU_CLOCK_VIRTUAL,
50
+ TYPE_CMSDK_APB_TIMER)
152
+ bcm2835_systmr_timer_expire, &s->tmr[i]);
51
+
52
+typedef struct {
53
+ /*< private >*/
54
+ SysBusDevice parent_obj;
55
+
56
+ /*< public >*/
57
+ MemoryRegion iomem;
58
+ qemu_irq timerint;
59
+ uint32_t pclk_frq;
60
+ struct ptimer_state *timer;
61
+
62
+ uint32_t ctrl;
63
+ uint32_t value;
64
+ uint32_t reload;
65
+ uint32_t intstatus;
66
+} CMSDKAPBTIMER;
67
+
68
+/**
69
+ * cmsdk_apb_timer_create - convenience function to create TYPE_CMSDK_APB_TIMER
70
+ * @addr: location in system memory to map registers
71
+ * @pclk_frq: frequency in Hz of the PCLK clock (used for calculating baud rate)
72
+ */
73
+static inline DeviceState *cmsdk_apb_timer_create(hwaddr addr,
74
+ qemu_irq timerint,
75
+ uint32_t pclk_frq)
76
+{
77
+ DeviceState *dev;
78
+ SysBusDevice *s;
79
+
80
+ dev = qdev_create(NULL, TYPE_CMSDK_APB_TIMER);
81
+ s = SYS_BUS_DEVICE(dev);
82
+ qdev_prop_set_uint32(dev, "pclk-frq", pclk_frq);
83
+ qdev_init_nofail(dev);
84
+ sysbus_mmio_map(s, 0, addr);
85
+ sysbus_connect_irq(s, 0, timerint);
86
+ return dev;
87
+}
88
+
89
+#endif
90
diff --git a/hw/timer/cmsdk-apb-timer.c b/hw/timer/cmsdk-apb-timer.c
91
new file mode 100644
92
index XXXXXXX..XXXXXXX
93
--- /dev/null
94
+++ b/hw/timer/cmsdk-apb-timer.c
95
@@ -XXX,XX +XXX,XX @@
96
+/*
97
+ * ARM CMSDK APB timer emulation
98
+ *
99
+ * Copyright (c) 2017 Linaro Limited
100
+ * Written by Peter Maydell
101
+ *
102
+ * This program is free software; you can redistribute it and/or modify
103
+ * it under the terms of the GNU General Public License version 2 or
104
+ * (at your option) any later version.
105
+ */
106
+
107
+/* This is a model of the "APB timer" which is part of the Cortex-M
108
+ * System Design Kit (CMSDK) and documented in the Cortex-M System
109
+ * Design Kit Technical Reference Manual (ARM DDI0479C):
110
+ * https://developer.arm.com/products/system-design/system-design-kits/cortex-m-system-design-kit
111
+ *
112
+ * The hardware has an EXTIN input wire, which can be configured
113
+ * by the guest to act either as a 'timer enable' (timer does not run
114
+ * when EXTIN is low), or as a 'timer clock' (timer runs at frequency
115
+ * of EXTIN clock, not PCLK frequency). We don't model this.
116
+ *
117
+ * The documentation is not very clear about the exact behaviour;
118
+ * we choose to implement that the interrupt is triggered when
119
+ * the counter goes from 1 to 0, that the counter then holds at 0
120
+ * for one clock cycle before reloading from the RELOAD register,
121
+ * and that if the RELOAD register is 0 this does not cause an
122
+ * interrupt (as there is no further 1->0 transition).
123
+ */
124
+
125
+#include "qemu/osdep.h"
126
+#include "qemu/log.h"
127
+#include "qemu/main-loop.h"
128
+#include "qapi/error.h"
129
+#include "trace.h"
130
+#include "hw/sysbus.h"
131
+#include "hw/registerfields.h"
132
+#include "hw/timer/cmsdk-apb-timer.h"
133
+
134
+REG32(CTRL, 0)
135
+ FIELD(CTRL, EN, 0, 1)
136
+ FIELD(CTRL, SELEXTEN, 1, 1)
137
+ FIELD(CTRL, SELEXTCLK, 2, 1)
138
+ FIELD(CTRL, IRQEN, 3, 1)
139
+REG32(VALUE, 4)
140
+REG32(RELOAD, 8)
141
+REG32(INTSTATUS, 0xc)
142
+ FIELD(INTSTATUS, IRQ, 0, 1)
143
+REG32(PID4, 0xFD0)
144
+REG32(PID5, 0xFD4)
145
+REG32(PID6, 0xFD8)
146
+REG32(PID7, 0xFDC)
147
+REG32(PID0, 0xFE0)
148
+REG32(PID1, 0xFE4)
149
+REG32(PID2, 0xFE8)
150
+REG32(PID3, 0xFEC)
151
+REG32(CID0, 0xFF0)
152
+REG32(CID1, 0xFF4)
153
+REG32(CID2, 0xFF8)
154
+REG32(CID3, 0xFFC)
155
+
156
+/* PID/CID values */
157
+static const int timer_id[] = {
158
+ 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
159
+ 0x22, 0xb8, 0x1b, 0x00, /* PID0..PID3 */
160
+ 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
161
+};
162
+
163
+static void cmsdk_apb_timer_update(CMSDKAPBTIMER *s)
164
+{
165
+ qemu_set_irq(s->timerint, !!(s->intstatus & R_INTSTATUS_IRQ_MASK));
166
+}
167
+
168
+static uint64_t cmsdk_apb_timer_read(void *opaque, hwaddr offset, unsigned size)
169
+{
170
+ CMSDKAPBTIMER *s = CMSDK_APB_TIMER(opaque);
171
+ uint64_t r;
172
+
173
+ switch (offset) {
174
+ case A_CTRL:
175
+ r = s->ctrl;
176
+ break;
177
+ case A_VALUE:
178
+ r = ptimer_get_count(s->timer);
179
+ break;
180
+ case A_RELOAD:
181
+ r = ptimer_get_limit(s->timer);
182
+ break;
183
+ case A_INTSTATUS:
184
+ r = s->intstatus;
185
+ break;
186
+ case A_PID4 ... A_CID3:
187
+ r = timer_id[(offset - A_PID4) / 4];
188
+ break;
189
+ default:
190
+ qemu_log_mask(LOG_GUEST_ERROR,
191
+ "CMSDK APB timer read: bad offset %x\n", (int) offset);
192
+ r = 0;
193
+ break;
194
+ }
153
+ }
195
+ trace_cmsdk_apb_timer_read(offset, r, size);
154
}
196
+ return r;
155
197
+}
156
static const VMStateDescription bcm2835_systmr_vmstate = {
198
+
199
+static void cmsdk_apb_timer_write(void *opaque, hwaddr offset, uint64_t value,
200
+ unsigned size)
201
+{
202
+ CMSDKAPBTIMER *s = CMSDK_APB_TIMER(opaque);
203
+
204
+ trace_cmsdk_apb_timer_write(offset, value, size);
205
+
206
+ switch (offset) {
207
+ case A_CTRL:
208
+ if (value & 6) {
209
+ /* Bits [1] and [2] enable using EXTIN as either clock or
210
+ * an enable line. We don't model this.
211
+ */
212
+ qemu_log_mask(LOG_UNIMP,
213
+ "CMSDK APB timer: EXTIN input not supported\n");
214
+ }
215
+ s->ctrl = value & 0xf;
216
+ if (s->ctrl & R_CTRL_EN_MASK) {
217
+ ptimer_run(s->timer, 0);
218
+ } else {
219
+ ptimer_stop(s->timer);
220
+ }
221
+ break;
222
+ case A_RELOAD:
223
+ /* Writing to reload also sets the current timer value */
224
+ ptimer_set_limit(s->timer, value, 1);
225
+ break;
226
+ case A_VALUE:
227
+ ptimer_set_count(s->timer, value);
228
+ break;
229
+ case A_INTSTATUS:
230
+ /* Just one bit, which is W1C. */
231
+ value &= 1;
232
+ s->intstatus &= ~value;
233
+ cmsdk_apb_timer_update(s);
234
+ break;
235
+ case A_PID4 ... A_CID3:
236
+ qemu_log_mask(LOG_GUEST_ERROR,
237
+ "CMSDK APB timer write: write to RO offset 0x%x\n",
238
+ (int)offset);
239
+ break;
240
+ default:
241
+ qemu_log_mask(LOG_GUEST_ERROR,
242
+ "CMSDK APB timer write: bad offset 0x%x\n", (int) offset);
243
+ break;
244
+ }
245
+}
246
+
247
+static const MemoryRegionOps cmsdk_apb_timer_ops = {
248
+ .read = cmsdk_apb_timer_read,
249
+ .write = cmsdk_apb_timer_write,
250
+ .endianness = DEVICE_LITTLE_ENDIAN,
251
+};
252
+
253
+static void cmsdk_apb_timer_tick(void *opaque)
254
+{
255
+ CMSDKAPBTIMER *s = CMSDK_APB_TIMER(opaque);
256
+
257
+ if (s->ctrl & R_CTRL_IRQEN_MASK) {
258
+ s->intstatus |= R_INTSTATUS_IRQ_MASK;
259
+ cmsdk_apb_timer_update(s);
260
+ }
261
+}
262
+
263
+static void cmsdk_apb_timer_reset(DeviceState *dev)
264
+{
265
+ CMSDKAPBTIMER *s = CMSDK_APB_TIMER(dev);
266
+
267
+ trace_cmsdk_apb_timer_reset();
268
+ s->ctrl = 0;
269
+ s->intstatus = 0;
270
+ ptimer_stop(s->timer);
271
+ /* Set the limit and the count */
272
+ ptimer_set_limit(s->timer, 0, 1);
273
+}
274
+
275
+static void cmsdk_apb_timer_init(Object *obj)
276
+{
277
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
278
+ CMSDKAPBTIMER *s = CMSDK_APB_TIMER(obj);
279
+
280
+ memory_region_init_io(&s->iomem, obj, &cmsdk_apb_timer_ops,
281
+ s, "cmsdk-apb-timer", 0x1000);
282
+ sysbus_init_mmio(sbd, &s->iomem);
283
+ sysbus_init_irq(sbd, &s->timerint);
284
+}
285
+
286
+static void cmsdk_apb_timer_realize(DeviceState *dev, Error **errp)
287
+{
288
+ CMSDKAPBTIMER *s = CMSDK_APB_TIMER(dev);
289
+ QEMUBH *bh;
290
+
291
+ if (s->pclk_frq == 0) {
292
+ error_setg(errp, "CMSDK APB timer: pclk-frq property must be set");
293
+ return;
294
+ }
295
+
296
+ bh = qemu_bh_new(cmsdk_apb_timer_tick, s);
297
+ s->timer = ptimer_init(bh,
298
+ PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD |
299
+ PTIMER_POLICY_NO_IMMEDIATE_TRIGGER |
300
+ PTIMER_POLICY_NO_IMMEDIATE_RELOAD |
301
+ PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
302
+
303
+ ptimer_set_freq(s->timer, s->pclk_frq);
304
+}
305
+
306
+static const VMStateDescription cmsdk_apb_timer_vmstate = {
307
+ .name = "cmsdk-apb-timer",
308
+ .version_id = 1,
309
+ .minimum_version_id = 1,
310
+ .fields = (VMStateField[]) {
311
+ VMSTATE_PTIMER(timer, CMSDKAPBTIMER),
312
+ VMSTATE_UINT32(ctrl, CMSDKAPBTIMER),
313
+ VMSTATE_UINT32(value, CMSDKAPBTIMER),
314
+ VMSTATE_UINT32(reload, CMSDKAPBTIMER),
315
+ VMSTATE_UINT32(intstatus, CMSDKAPBTIMER),
316
+ VMSTATE_END_OF_LIST()
317
+ }
318
+};
319
+
320
+static Property cmsdk_apb_timer_properties[] = {
321
+ DEFINE_PROP_UINT32("pclk-frq", CMSDKAPBTIMER, pclk_frq, 0),
322
+ DEFINE_PROP_END_OF_LIST(),
323
+};
324
+
325
+static void cmsdk_apb_timer_class_init(ObjectClass *klass, void *data)
326
+{
327
+ DeviceClass *dc = DEVICE_CLASS(klass);
328
+
329
+ dc->realize = cmsdk_apb_timer_realize;
330
+ dc->vmsd = &cmsdk_apb_timer_vmstate;
331
+ dc->reset = cmsdk_apb_timer_reset;
332
+ dc->props = cmsdk_apb_timer_properties;
333
+}
334
+
335
+static const TypeInfo cmsdk_apb_timer_info = {
336
+ .name = TYPE_CMSDK_APB_TIMER,
337
+ .parent = TYPE_SYS_BUS_DEVICE,
338
+ .instance_size = sizeof(CMSDKAPBTIMER),
339
+ .instance_init = cmsdk_apb_timer_init,
340
+ .class_init = cmsdk_apb_timer_class_init,
341
+};
342
+
343
+static void cmsdk_apb_timer_register_types(void)
344
+{
345
+ type_register_static(&cmsdk_apb_timer_info);
346
+}
347
+
348
+type_init(cmsdk_apb_timer_register_types);
349
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
350
index XXXXXXX..XXXXXXX 100644
351
--- a/default-configs/arm-softmmu.mak
352
+++ b/default-configs/arm-softmmu.mak
353
@@ -XXX,XX +XXX,XX @@ CONFIG_STM32F2XX_ADC=y
354
CONFIG_STM32F2XX_SPI=y
355
CONFIG_STM32F205_SOC=y
356
357
+CONFIG_CMSDK_APB_TIMER=y
358
CONFIG_CMSDK_APB_UART=y
359
360
CONFIG_VERSATILE_PCI=y
361
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
362
index XXXXXXX..XXXXXXX 100644
158
index XXXXXXX..XXXXXXX 100644
363
--- a/hw/timer/trace-events
159
--- a/hw/timer/trace-events
364
+++ b/hw/timer/trace-events
160
+++ b/hw/timer/trace-events
365
@@ -XXX,XX +XXX,XX @@ systick_reload(void) "systick reload"
161
@@ -XXX,XX +XXX,XX @@ nrf51_timer_write(uint8_t timer_id, uint64_t addr, uint32_t value, unsigned size
366
systick_timer_tick(void) "systick reload"
162
nrf51_timer_set_count(uint8_t timer_id, uint8_t counter_id, uint32_t value) "timer %u counter %u count 0x%" PRIx32
367
systick_read(uint64_t addr, uint32_t value, unsigned size) "systick read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
163
368
systick_write(uint64_t addr, uint32_t value, unsigned size) "systick write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
164
# bcm2835_systmr.c
369
+
165
-bcm2835_systmr_irq(bool enable) "timer irq state %u"
370
+# hw/char/cmsdk_apb_timer.c
166
+bcm2835_systmr_timer_expired(unsigned id) "timer #%u expired"
371
+cmsdk_apb_timer_read(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB timer read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
167
+bcm2835_systmr_irq_ack(unsigned id) "timer #%u acked"
372
+cmsdk_apb_timer_write(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB timer write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
168
bcm2835_systmr_read(uint64_t offset, uint64_t data) "timer read: offset 0x%" PRIx64 " data 0x%" PRIx64
373
+cmsdk_apb_timer_reset(void) "CMSDK APB timer: reset"
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"
374
--
175
--
375
2.7.4
176
2.20.1
376
177
377
178
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
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
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
hw/arm/bcm2835_peripherals.c | 13 +++++++++++--
14
1 file changed, 11 insertions(+), 2 deletions(-)
15
16
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/bcm2835_peripherals.c
19
+++ b/hw/arm/bcm2835_peripherals.c
20
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
21
memory_region_add_subregion(&s->peri_mr, ST_OFFSET,
22
sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->systmr), 0));
23
sysbus_connect_irq(SYS_BUS_DEVICE(&s->systmr), 0,
24
- qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_ARM_IRQ,
25
- INTERRUPT_ARM_TIMER));
26
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
27
+ INTERRUPT_TIMER0));
28
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->systmr), 1,
29
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
30
+ INTERRUPT_TIMER1));
31
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->systmr), 2,
32
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
33
+ INTERRUPT_TIMER2));
34
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->systmr), 3,
35
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
36
+ INTERRUPT_TIMER3));
37
38
/* UART0 */
39
qdev_prop_set_chr(DEVICE(&s->uart0), "chardev", serial_hd(0));
40
--
41
2.20.1
42
43
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
As a precursor to later patches attempt to come up with a more
3
On ARM, the Top Byte Ignore feature means that only 56 bits of
4
concrete wording for what each of the common exit cases would be.
4
the address are significant in the virtual address. We are
5
5
required to give the entire 64-bit address to FAR_ELx on fault,
6
CC: Emilio G. Cota <cota@braap.org>
6
which means that we do not "clean" the top byte early in TCG.
7
CC: Richard Henderson <rth@twiddle.net>
7
8
CC: Lluís Vilanova <vilanova@ac.upc.edu>
8
This new interface allows us to flush all 256 possible aliases
9
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
9
for a given page, currently missed by tlb_flush_page*.
10
Reviewed-by: Richard Henderson <rth@twiddle.net>
10
11
Message-id: 20170713141928.25419-2-alex.bennee@linaro.org
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Message-id: 20201016210754.818257-2-richard.henderson@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
16
---
14
include/exec/exec-all.h | 29 ++++++++++++++++++++++++++---
17
include/exec/exec-all.h | 36 ++++++
15
1 file changed, 26 insertions(+), 3 deletions(-)
18
accel/tcg/cputlb.c | 275 ++++++++++++++++++++++++++++++++++++++--
19
2 files changed, 302 insertions(+), 9 deletions(-)
16
20
17
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
21
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
18
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
19
--- a/include/exec/exec-all.h
23
--- a/include/exec/exec-all.h
20
+++ b/include/exec/exec-all.h
24
+++ b/include/exec/exec-all.h
21
@@ -XXX,XX +XXX,XX @@ typedef abi_ulong tb_page_addr_t;
25
@@ -XXX,XX +XXX,XX @@ void tlb_flush_by_mmuidx_all_cpus(CPUState *cpu, uint16_t idxmap);
22
typedef ram_addr_t tb_page_addr_t;
26
* depend on when the guests translation ends the TB.
27
*/
28
void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *cpu, uint16_t idxmap);
29
+
30
+/**
31
+ * tlb_flush_page_bits_by_mmuidx
32
+ * @cpu: CPU whose TLB should be flushed
33
+ * @addr: virtual address of page to be flushed
34
+ * @idxmap: bitmap of mmu indexes to flush
35
+ * @bits: number of significant bits in address
36
+ *
37
+ * Similar to tlb_flush_page_mask, but with a bitmap of indexes.
38
+ */
39
+void tlb_flush_page_bits_by_mmuidx(CPUState *cpu, target_ulong addr,
40
+ uint16_t idxmap, unsigned bits);
41
+
42
+/* Similarly, with broadcast and syncing. */
43
+void tlb_flush_page_bits_by_mmuidx_all_cpus(CPUState *cpu, target_ulong addr,
44
+ uint16_t idxmap, unsigned bits);
45
+void tlb_flush_page_bits_by_mmuidx_all_cpus_synced
46
+ (CPUState *cpu, target_ulong addr, uint16_t idxmap, unsigned bits);
47
+
48
/**
49
* tlb_set_page_with_attrs:
50
* @cpu: CPU to add this TLB entry for
51
@@ -XXX,XX +XXX,XX @@ static inline void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *cpu,
52
uint16_t idxmap)
53
{
54
}
55
+static inline void tlb_flush_page_bits_by_mmuidx(CPUState *cpu,
56
+ target_ulong addr,
57
+ uint16_t idxmap,
58
+ unsigned bits)
59
+{
60
+}
61
+static inline void tlb_flush_page_bits_by_mmuidx_all_cpus(CPUState *cpu,
62
+ target_ulong addr,
63
+ uint16_t idxmap,
64
+ unsigned bits)
65
+{
66
+}
67
+static inline void
68
+tlb_flush_page_bits_by_mmuidx_all_cpus_synced(CPUState *cpu, target_ulong addr,
69
+ uint16_t idxmap, unsigned bits)
70
+{
71
+}
23
#endif
72
#endif
24
73
/**
25
-/* is_jmp field values */
74
* probe_access:
26
+/* DisasContext is_jmp field values
75
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
27
+ *
76
index XXXXXXX..XXXXXXX 100644
28
+ * is_jmp starts as DISAS_NEXT. The translator will keep processing
77
--- a/accel/tcg/cputlb.c
29
+ * instructions until an exit condition is reached. If we reach the
78
+++ b/accel/tcg/cputlb.c
30
+ * exit condition and is_jmp is still DISAS_NEXT (because of some
79
@@ -XXX,XX +XXX,XX @@ void tlb_flush_all_cpus_synced(CPUState *src_cpu)
31
+ * other condition) we simply "jump" to the next address.
80
tlb_flush_by_mmuidx_all_cpus_synced(src_cpu, ALL_MMUIDX_BITS);
32
+ * The remaining exit cases are:
81
}
33
+ *
82
34
+ * DISAS_JUMP - Only the PC was modified dynamically (e.g computed)
83
+static bool tlb_hit_page_mask_anyprot(CPUTLBEntry *tlb_entry,
35
+ * DISAS_TB_JUMP - Only the PC was modified statically (e.g. branch)
84
+ target_ulong page, target_ulong mask)
36
+ *
85
+{
37
+ * In these cases as long as the PC is updated we can chain to the
86
+ page &= mask;
38
+ * next TB either by exiting the loop or looking up the next TB via
87
+ mask &= TARGET_PAGE_MASK | TLB_INVALID_MASK;
39
+ * the loookup helper.
88
+
40
+ *
89
+ return (page == (tlb_entry->addr_read & mask) ||
41
+ * DISAS_UPDATE - CPU State was modified dynamically
90
+ page == (tlb_addr_write(tlb_entry) & mask) ||
42
+ *
91
+ page == (tlb_entry->addr_code & mask));
43
+ * This covers any other CPU state which necessities us exiting the
92
+}
44
+ * TCG code to the main run-loop. Typically this includes anything
93
+
45
+ * that might change the interrupt state.
94
static inline bool tlb_hit_page_anyprot(CPUTLBEntry *tlb_entry,
46
+ *
95
target_ulong page)
47
+ * Individual translators may define additional exit cases to deal
96
{
48
+ * with per-target special conditions.
97
- return tlb_hit_page(tlb_entry->addr_read, page) ||
49
+ */
98
- tlb_hit_page(tlb_addr_write(tlb_entry), page) ||
50
#define DISAS_NEXT 0 /* next instruction can be analyzed */
99
- tlb_hit_page(tlb_entry->addr_code, page);
51
#define DISAS_JUMP 1 /* only pc was modified dynamically */
100
+ return tlb_hit_page_mask_anyprot(tlb_entry, page, -1);
52
-#define DISAS_UPDATE 2 /* cpu state was modified dynamically */
101
}
53
-#define DISAS_TB_JUMP 3 /* only pc was modified statically */
102
54
+#define DISAS_TB_JUMP 2 /* only pc was modified statically */
103
/**
55
+#define DISAS_UPDATE 3 /* cpu state was modified dynamically */
104
@@ -XXX,XX +XXX,XX @@ static inline bool tlb_entry_is_empty(const CPUTLBEntry *te)
56
105
}
57
#include "qemu/log.h"
106
58
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);
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);
289
+ } else {
290
+ TLBFlushPageBitsByMMUIdxData *p
291
+ = g_new(TLBFlushPageBitsByMMUIdxData, 1);
292
+
293
+ /* Otherwise allocate a structure, freed by the worker. */
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
+ }
339
+ }
340
+ }
341
+
342
+ tlb_flush_page_bits_by_mmuidx_async_0(src_cpu, d);
343
+}
344
+
345
+void tlb_flush_page_bits_by_mmuidx_all_cpus_synced(CPUState *src_cpu,
346
+ target_ulong addr,
347
+ uint16_t idxmap,
348
+ unsigned bits)
349
+{
350
+ TLBFlushPageBitsByMMUIdxData d;
351
+ run_on_cpu_data runon;
352
+
353
+ /* If all bits are significant, this devolves to tlb_flush_page. */
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
+ }
385
+ }
386
+
387
+ p = g_new(TLBFlushPageBitsByMMUIdxData, 1);
388
+ *p = d;
389
+ async_safe_run_on_cpu(src_cpu, tlb_flush_page_bits_by_mmuidx_async_2,
390
+ RUN_ON_CPU_HOST_PTR(p));
391
+ }
392
+}
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)
59
--
397
--
60
2.7.4
398
2.20.1
61
399
62
400
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
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>
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Message-id: 20201016210754.818257-3-richard.henderson@linaro.org
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
target/arm/helper.c | 46 ++++++++++++++++++++++++++++++++++++++-------
19
1 file changed, 39 insertions(+), 7 deletions(-)
20
21
diff --git a/target/arm/helper.c b/target/arm/helper.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/helper.c
24
+++ b/target/arm/helper.c
25
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
26
#endif
27
28
static void switch_mode(CPUARMState *env, int mode);
29
+static int aa64_va_parameter_tbi(uint64_t tcr, ARMMMUIdx mmu_idx);
30
31
static int vfp_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg)
32
{
33
@@ -XXX,XX +XXX,XX @@ static int vae1_tlbmask(CPUARMState *env)
34
}
35
}
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);
44
+
45
+ return (tbi >> select) & 1 ? 56 : 64;
46
+}
47
+
48
+static int vae1_tlbbits(CPUARMState *env, uint64_t addr)
49
+{
50
+ ARMMMUIdx mmu_idx;
51
+
52
+ /* Only the regime of the mmu_idx below is significant. */
53
+ if (arm_is_secure_below_el3(env)) {
54
+ mmu_idx = ARMMMUIdx_SE10_0;
55
+ } else if ((env->cp15.hcr_el2 & (HCR_E2H | HCR_TGE))
56
+ == (HCR_E2H | HCR_TGE)) {
57
+ mmu_idx = ARMMMUIdx_E20_0;
58
+ } else {
59
+ mmu_idx = ARMMMUIdx_E10_0;
60
+ }
61
+ return tlbbits_for_regime(env, mmu_idx, addr);
62
+}
63
+
64
static void tlbi_aa64_vmalle1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
65
uint64_t value)
66
{
67
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
68
CPUState *cs = env_cpu(env);
69
int mask = vae1_tlbmask(env);
70
uint64_t pageaddr = sextract64(value << 12, 0, 56);
71
+ int bits = vae1_tlbbits(env, pageaddr);
72
73
- tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, mask);
74
+ tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, mask, bits);
75
}
76
77
static void tlbi_aa64_vae1_write(CPUARMState *env, const ARMCPRegInfo *ri,
78
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae1_write(CPUARMState *env, const ARMCPRegInfo *ri,
79
CPUState *cs = env_cpu(env);
80
int mask = vae1_tlbmask(env);
81
uint64_t pageaddr = sextract64(value << 12, 0, 56);
82
+ int bits = vae1_tlbbits(env, pageaddr);
83
84
if (tlb_force_broadcast(env)) {
85
- tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, mask);
86
+ tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, mask, bits);
87
} else {
88
- tlb_flush_page_by_mmuidx(cs, pageaddr, mask);
89
+ tlb_flush_page_bits_by_mmuidx(cs, pageaddr, mask, bits);
90
}
91
}
92
93
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae2is_write(CPUARMState *env, const ARMCPRegInfo *ri,
94
{
95
CPUState *cs = env_cpu(env);
96
uint64_t pageaddr = sextract64(value << 12, 0, 56);
97
+ int bits = tlbbits_for_regime(env, ARMMMUIdx_E2, pageaddr);
98
99
- tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
100
- ARMMMUIdxBit_E2);
101
+ tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr,
102
+ ARMMMUIdxBit_E2, bits);
103
}
104
105
static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
106
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
107
{
108
CPUState *cs = env_cpu(env);
109
uint64_t pageaddr = sextract64(value << 12, 0, 56);
110
+ int bits = tlbbits_for_regime(env, ARMMMUIdx_SE3, pageaddr);
111
112
- tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
113
- ARMMMUIdxBit_SE3);
114
+ tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr,
115
+ ARMMMUIdxBit_SE3, bits);
116
}
117
118
static CPAccessResult aa64_zva_access(CPUARMState *env, const ARMCPRegInfo *ri,
119
--
120
2.20.1
121
122
diff view generated by jsdifflib
New patch
1
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
3
This test exercises the various modes of the npcm7xx timer. In
4
particular, it triggers the bug found by the fuzzer, as reported here:
5
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
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
19
tests/qtest/npcm7xx_timer-test.c | 562 +++++++++++++++++++++++++++++++
20
tests/qtest/meson.build | 1 +
21
2 files changed, 563 insertions(+)
22
create mode 100644 tests/qtest/npcm7xx_timer-test.c
23
24
diff --git a/tests/qtest/npcm7xx_timer-test.c b/tests/qtest/npcm7xx_timer-test.c
25
new file mode 100644
26
index XXXXXXX..XXXXXXX
27
--- /dev/null
28
+++ b/tests/qtest/npcm7xx_timer-test.c
29
@@ -XXX,XX +XXX,XX @@
30
+/*
31
+ * QTest testcase for the Nuvoton NPCM7xx Timer
32
+ *
33
+ * Copyright 2020 Google LLC
34
+ *
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.
39
+ *
40
+ * This program is distributed in the hope that it will be useful, but WITHOUT
41
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
42
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
43
+ * for more details.
44
+ */
45
+
46
+#include "qemu/osdep.h"
47
+#include "qemu/timer.h"
48
+#include "libqtest-single.h"
49
+
50
+#define TIM_REF_HZ (25000000)
51
+
52
+/* Bits in TCSRx */
53
+#define CEN BIT(30)
54
+#define IE BIT(29)
55
+#define MODE_ONESHOT (0 << 27)
56
+#define MODE_PERIODIC (1 << 27)
57
+#define CRST BIT(26)
58
+#define CACT BIT(25)
59
+#define PRESCALE(x) (x)
60
+
61
+/* Registers shared between all timers in a module. */
62
+#define TISR 0x18
63
+#define WTCR 0x1c
64
+# define WTCLK(x) ((x) << 10)
65
+
66
+/* Power-on default; used to re-initialize timers before each test. */
67
+#define TCSR_DEFAULT PRESCALE(5)
68
+
69
+/* Register offsets for a timer within a timer block. */
70
+typedef struct Timer {
71
+ unsigned int tcsr_offset;
72
+ unsigned int ticr_offset;
73
+ unsigned int tdr_offset;
74
+} Timer;
75
+
76
+/* A timer block containing 5 timers. */
77
+typedef struct TimerBlock {
78
+ int irq_base;
79
+ uint64_t base_addr;
80
+} TimerBlock;
81
+
82
+/* Testdata for testing a particular timer within a timer block. */
83
+typedef struct TestData {
84
+ const TimerBlock *tim;
85
+ const Timer *timer;
86
+} TestData;
87
+
88
+const TimerBlock timer_block[] = {
89
+ {
90
+ .irq_base = 32,
91
+ .base_addr = 0xf0008000,
92
+ },
93
+ {
94
+ .irq_base = 37,
95
+ .base_addr = 0xf0009000,
96
+ },
97
+ {
98
+ .irq_base = 42,
99
+ .base_addr = 0xf000a000,
100
+ },
101
+};
102
+
103
+const Timer timer[] = {
104
+ {
105
+ .tcsr_offset = 0x00,
106
+ .ticr_offset = 0x08,
107
+ .tdr_offset = 0x10,
108
+ }, {
109
+ .tcsr_offset = 0x04,
110
+ .ticr_offset = 0x0c,
111
+ .tdr_offset = 0x14,
112
+ }, {
113
+ .tcsr_offset = 0x20,
114
+ .ticr_offset = 0x28,
115
+ .tdr_offset = 0x30,
116
+ }, {
117
+ .tcsr_offset = 0x24,
118
+ .ticr_offset = 0x2c,
119
+ .tdr_offset = 0x34,
120
+ }, {
121
+ .tcsr_offset = 0x40,
122
+ .ticr_offset = 0x48,
123
+ .tdr_offset = 0x50,
124
+ },
125
+};
126
+
127
+/* Returns the index of the timer block. */
128
+static int tim_index(const TimerBlock *tim)
129
+{
130
+ ptrdiff_t diff = tim - timer_block;
131
+
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);
215
+ }
216
+}
217
+
218
+/* Verifies the reset state of a timer. */
219
+static void test_reset(gconstpointer test_data)
220
+{
221
+ const TestData *td = test_data;
222
+
223
+ tim_reset(td);
224
+
225
+ g_assert_cmphex(tim_read_tcsr(td), ==, TCSR_DEFAULT);
226
+ g_assert_cmphex(tim_read_ticr(td), ==, 0);
227
+ g_assert_cmphex(tim_read_tdr(td), ==, 0);
228
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
229
+ g_assert_cmphex(tim_read(td, WTCR), ==, WTCLK(1));
230
+}
231
+
232
+/* Verifies that CRST wins if both CEN and CRST are set. */
233
+static void test_reset_overrides_enable(gconstpointer test_data)
234
+{
235
+ const TestData *td = test_data;
236
+
237
+ tim_reset(td);
238
+
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']
604
--
605
2.20.1
606
607
diff view generated by jsdifflib
New patch
1
From: Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com>
1
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>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
docs/devel/loads-stores.rst | 8 +++++++-
13
1 file changed, 7 insertions(+), 1 deletion(-)
14
15
diff --git a/docs/devel/loads-stores.rst b/docs/devel/loads-stores.rst
16
index XXXXXXX..XXXXXXX 100644
17
--- a/docs/devel/loads-stores.rst
18
+++ b/docs/devel/loads-stores.rst
19
@@ -XXX,XX +XXX,XX @@ guest CPU state in case of a guest CPU exception. This is passed
20
to ``cpu_restore_state()``. Therefore the value should either be 0,
21
to indicate that the guest CPU state is already synchronized, or
22
the result of ``GETPC()`` from the top level ``HELPER(foo)``
23
-function, which is a return address into the generated code.
24
+function, which is a return address into the generated code [#gpc]_.
25
+
26
+.. [#gpc] Note that ``GETPC()`` should be used with great care: calling
27
+ it in other functions that are *not* the top level
28
+ ``HELPER(foo)`` will cause unexpected behavior. Instead, the
29
+ value of ``GETPC()`` should be read from the helper and passed
30
+ if needed to the functions that the helper calls.
31
32
Function names follow the pattern:
33
34
--
35
2.20.1
36
37
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
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
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
hw/intc/bcm2835_ic.c | 4 +++-
11
hw/intc/trace-events | 4 ++++
12
2 files changed, 7 insertions(+), 1 deletion(-)
13
14
diff --git a/hw/intc/bcm2835_ic.c b/hw/intc/bcm2835_ic.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/intc/bcm2835_ic.c
17
+++ b/hw/intc/bcm2835_ic.c
18
@@ -XXX,XX +XXX,XX @@
19
#include "migration/vmstate.h"
20
#include "qemu/log.h"
21
#include "qemu/module.h"
22
+#include "trace.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"
58
+
59
+# bcm2835_ic.c
60
+bcm2835_ic_set_gpu_irq(int irq, int level) "GPU irq #%d level %d"
61
+bcm2835_ic_set_cpu_irq(int irq, int level) "CPU irq #%d level %d"
62
--
63
2.20.1
64
65
diff view generated by jsdifflib
1
Add the SCC to the MPS2 board models.
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
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
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Message-id: 1500029487-14822-8-git-send-email-peter.maydell@linaro.org
6
---
10
---
7
hw/arm/mps2.c | 17 ++++++++++++++++-
11
hw/intc/bcm2836_control.c | 8 ++++----
8
1 file changed, 16 insertions(+), 1 deletion(-)
12
1 file changed, 4 insertions(+), 4 deletions(-)
9
13
10
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
14
diff --git a/hw/intc/bcm2836_control.c b/hw/intc/bcm2836_control.c
11
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
12
--- a/hw/arm/mps2.c
16
--- a/hw/intc/bcm2836_control.c
13
+++ b/hw/arm/mps2.c
17
+++ b/hw/intc/bcm2836_control.c
14
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ static void bcm2836_control_set_local_irq(void *opaque, int core, int local_irq,
15
#include "hw/misc/unimp.h"
19
16
#include "hw/char/cmsdk-apb-uart.h"
20
static void bcm2836_control_set_local_irq0(void *opaque, int core, int level)
17
#include "hw/timer/cmsdk-apb-timer.h"
21
{
18
+#include "hw/misc/mps2-scc.h"
22
- bcm2836_control_set_local_irq(opaque, core, 0, level);
19
23
+ bcm2836_control_set_local_irq(opaque, core, IRQ_CNTPSIRQ, level);
20
typedef enum MPS2FPGAType {
21
FPGA_AN385,
22
@@ -XXX,XX +XXX,XX @@ typedef struct {
23
MachineClass parent;
24
MPS2FPGAType fpga_type;
25
const char *cpu_model;
26
+ uint32_t scc_id;
27
} MPS2MachineClass;
28
29
typedef struct {
30
@@ -XXX,XX +XXX,XX @@ typedef struct {
31
MemoryRegion blockram_m2;
32
MemoryRegion blockram_m3;
33
MemoryRegion sram;
34
+ MPS2SCC scc;
35
} MPS2MachineState;
36
37
#define TYPE_MPS2_MACHINE "mps2"
38
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
39
MPS2MachineState *mms = MPS2_MACHINE(machine);
40
MPS2MachineClass *mmc = MPS2_MACHINE_GET_CLASS(machine);
41
MemoryRegion *system_memory = get_system_memory();
42
- DeviceState *armv7m;
43
+ DeviceState *armv7m, *sccdev;
44
45
if (!machine->cpu_model) {
46
machine->cpu_model = mmc->cpu_model;
47
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
48
cmsdk_apb_timer_create(0x40000000, qdev_get_gpio_in(armv7m, 8), SYSCLK_FRQ);
49
cmsdk_apb_timer_create(0x40001000, qdev_get_gpio_in(armv7m, 9), SYSCLK_FRQ);
50
51
+ object_initialize(&mms->scc, sizeof(mms->scc), TYPE_MPS2_SCC);
52
+ sccdev = DEVICE(&mms->scc);
53
+ qdev_set_parent_bus(armv7m, sysbus_get_default());
54
+ qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2);
55
+ qdev_prop_set_uint32(sccdev, "scc-aid", 0x02000008);
56
+ qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id);
57
+ object_property_set_bool(OBJECT(&mms->scc), true, "realized",
58
+ &error_fatal);
59
+ sysbus_mmio_map(SYS_BUS_DEVICE(sccdev), 0, 0x4002f000);
60
+
61
system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ;
62
63
armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
64
@@ -XXX,XX +XXX,XX @@ static void mps2_an385_class_init(ObjectClass *oc, void *data)
65
mc->desc = "ARM MPS2 with AN385 FPGA image for Cortex-M3";
66
mmc->fpga_type = FPGA_AN385;
67
mmc->cpu_model = "cortex-m3";
68
+ mmc->scc_id = 0x41040000 | (385 << 4);
69
}
24
}
70
25
71
static void mps2_an511_class_init(ObjectClass *oc, void *data)
26
static void bcm2836_control_set_local_irq1(void *opaque, int core, int level)
72
@@ -XXX,XX +XXX,XX @@ static void mps2_an511_class_init(ObjectClass *oc, void *data)
27
{
73
mc->desc = "ARM MPS2 with AN511 DesignStart FPGA image for Cortex-M3";
28
- bcm2836_control_set_local_irq(opaque, core, 1, level);
74
mmc->fpga_type = FPGA_AN511;
29
+ bcm2836_control_set_local_irq(opaque, core, IRQ_CNTPNSIRQ, level);
75
mmc->cpu_model = "cortex-m3";
76
+ mmc->scc_id = 0x4104000 | (511 << 4);
77
}
30
}
78
31
79
static const TypeInfo mps2_info = {
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)
80
--
45
--
81
2.7.4
46
2.20.1
82
47
83
48
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
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.
10
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.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
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
target/arm/mte_helper.c | 3 +--
19
1 file changed, 1 insertion(+), 2 deletions(-)
20
21
diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/mte_helper.c
24
+++ b/target/arm/mte_helper.c
25
@@ -XXX,XX +XXX,XX @@ static void mte_check_fail(CPUARMState *env, uint32_t desc,
26
27
case 2:
28
/* Tag check fail causes asynchronous flag set. */
29
- mmu_idx = arm_mmu_idx_el(env, el);
30
- if (regime_has_2_ranges(mmu_idx)) {
31
+ if (regime_has_2_ranges(arm_mmu_idx)) {
32
select = extract64(dirty_ptr, 55, 1);
33
} else {
34
select = 0;
35
--
36
2.20.1
37
38
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
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>
11
Signed-off-by: Richard Henderson <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
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
17
target/arm/mte_helper.c | 10 +++-------
18
1 file changed, 3 insertions(+), 7 deletions(-)
19
20
diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/mte_helper.c
23
+++ b/target/arm/mte_helper.c
24
@@ -XXX,XX +XXX,XX @@ static void mte_check_fail(CPUARMState *env, uint32_t desc,
25
reg_el = regime_el(env, arm_mmu_idx);
26
sctlr = env->cp15.sctlr_el[reg_el];
27
28
- switch (arm_mmu_idx) {
29
- case ARMMMUIdx_E10_0:
30
- case ARMMMUIdx_E20_0:
31
- el = 0;
32
+ el = arm_current_el(env);
33
+ if (el == 0) {
34
tcf = extract64(sctlr, 38, 2);
35
- break;
36
- default:
37
- el = reg_el;
38
+ } else {
39
tcf = extract64(sctlr, 40, 2);
40
}
41
42
--
43
2.20.1
44
45
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
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.
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>
12
Signed-off-by: Richard Henderson <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-4-richard.henderson@linaro.org
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
target/arm/internals.h | 9 +++++----
19
target/arm/helper.c | 9 +++++----
20
2 files changed, 10 insertions(+), 8 deletions(-)
21
22
diff --git a/target/arm/internals.h b/target/arm/internals.h
23
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/internals.h
25
+++ b/target/arm/internals.h
26
@@ -XXX,XX +XXX,XX @@ static inline bool allocation_tag_access_enabled(CPUARMState *env, int el,
27
&& !(env->cp15.scr_el3 & SCR_ATA)) {
28
return false;
29
}
30
- if (el < 2
31
- && arm_feature(env, ARM_FEATURE_EL2)
32
- && !(arm_hcr_el2_eff(env) & HCR_ATA)) {
33
- return false;
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
43
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/helper.c
45
+++ b/target/arm/helper.c
46
@@ -XXX,XX +XXX,XX @@ static CPAccessResult access_mte(CPUARMState *env, const ARMCPRegInfo *ri,
47
{
48
int el = arm_current_el(env);
49
50
- if (el < 2 &&
51
- arm_feature(env, ARM_FEATURE_EL2) &&
52
- !(arm_hcr_el2_eff(env) & HCR_ATA)) {
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) &&
62
--
63
2.20.1
64
65
diff view generated by jsdifflib
1
In some situations it's useful to have a qdev property which doesn't
1
From: Peng Liang <liangpeng10@huawei.com>
2
automatically set its default value when qdev_property_add_static is
3
called (for instance when the default value is not constant).
4
2
5
Support this by adding a flag to the Property struct indicating
3
VMStateDescription.fields should be end with VMSTATE_END_OF_LIST().
6
whether to set the default value. This replaces the existing test
4
However, microbit_i2c_vmstate doesn't follow it. Let's change it.
7
for whether the PropertyInfo set_default_value function pointer is
8
NULL, and we set the .set_default field to true for all those cases
9
of struct Property which use a PropertyInfo with a non-NULL
10
set_default_value, so behaviour remains the same as before.
11
5
12
This gives us the semantics of:
6
Fixes: 9d68bf564e ("arm: Stub out NRF51 TWI magnetometer/accelerometer detection")
13
* if .set_default is true, then .info->set_default_value must
7
Reported-by: Euler Robot <euler.robot@huawei.com>
14
be not NULL, and .defval is used as the the default value of
8
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
15
the property
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
16
* otherwise, the property system does not set any default, and
10
Message-id: 20201019093401.2993833-1-liangpeng10@huawei.com
17
the field will retain whatever initial value it was given by
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
the device's .instance_init method
12
---
13
hw/i2c/microbit_i2c.c | 1 +
14
1 file changed, 1 insertion(+)
19
15
20
We define two new macros DEFINE_PROP_SIGNED_NODEFAULT and
16
diff --git a/hw/i2c/microbit_i2c.c b/hw/i2c/microbit_i2c.c
21
DEFINE_PROP_UNSIGNED_NODEFAULT, to cover the most plausible use cases
22
of wanting to set an integer property with no default value.
23
24
Suggested-by: Markus Armbruster <armbru@redhat.com>
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
27
Reviewed-by: Markus Armbruster <armbru@redhat.com>
28
Message-id: 1499788408-10096-3-git-send-email-peter.maydell@linaro.org
29
---
30
include/hw/qdev-core.h | 10 ++++++++++
31
include/hw/qdev-properties.h | 20 ++++++++++++++++++++
32
hw/core/qdev.c | 2 +-
33
3 files changed, 31 insertions(+), 1 deletion(-)
34
35
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
36
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
37
--- a/include/hw/qdev-core.h
18
--- a/hw/i2c/microbit_i2c.c
38
+++ b/include/hw/qdev-core.h
19
+++ b/hw/i2c/microbit_i2c.c
39
@@ -XXX,XX +XXX,XX @@ struct BusState {
20
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription microbit_i2c_vmstate = {
40
QLIST_ENTRY(BusState) sibling;
21
.fields = (VMStateField[]) {
22
VMSTATE_UINT32_ARRAY(regs, MicrobitI2CState, MICROBIT_I2C_NREGS),
23
VMSTATE_UINT32(read_idx, MicrobitI2CState),
24
+ VMSTATE_END_OF_LIST()
25
},
41
};
26
};
42
27
43
+/**
44
+ * Property:
45
+ * @set_default: true if the default value should be set from @defval,
46
+ * in which case @info->set_default_value must not be NULL
47
+ * (if false then no default value is set by the property system
48
+ * and the field retains whatever value it was given by instance_init).
49
+ * @defval: default value for the property. This is used only if @set_default
50
+ * is true.
51
+ */
52
struct Property {
53
const char *name;
54
const PropertyInfo *info;
55
ptrdiff_t offset;
56
uint8_t bitnr;
57
+ bool set_default;
58
union {
59
int64_t i;
60
uint64_t u;
61
diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
62
index XXXXXXX..XXXXXXX 100644
63
--- a/include/hw/qdev-properties.h
64
+++ b/include/hw/qdev-properties.h
65
@@ -XXX,XX +XXX,XX @@ extern const PropertyInfo qdev_prop_link;
66
.info = &(_prop), \
67
.offset = offsetof(_state, _field) \
68
+ type_check(_type,typeof_field(_state, _field)), \
69
+ .set_default = true, \
70
.defval.i = (_type)_defval, \
71
}
72
73
+#define DEFINE_PROP_SIGNED_NODEFAULT(_name, _state, _field, _prop, _type) { \
74
+ .name = (_name), \
75
+ .info = &(_prop), \
76
+ .offset = offsetof(_state, _field) \
77
+ + type_check(_type, typeof_field(_state, _field)), \
78
+ }
79
+
80
#define DEFINE_PROP_BIT(_name, _state, _field, _bit, _defval) { \
81
.name = (_name), \
82
.info = &(qdev_prop_bit), \
83
.bitnr = (_bit), \
84
.offset = offsetof(_state, _field) \
85
+ type_check(uint32_t,typeof_field(_state, _field)), \
86
+ .set_default = true, \
87
.defval.u = (bool)_defval, \
88
}
89
90
@@ -XXX,XX +XXX,XX @@ extern const PropertyInfo qdev_prop_link;
91
.info = &(_prop), \
92
.offset = offsetof(_state, _field) \
93
+ type_check(_type, typeof_field(_state, _field)), \
94
+ .set_default = true, \
95
.defval.u = (_type)_defval, \
96
}
97
98
+#define DEFINE_PROP_UNSIGNED_NODEFAULT(_name, _state, _field, _prop, _type) { \
99
+ .name = (_name), \
100
+ .info = &(_prop), \
101
+ .offset = offsetof(_state, _field) \
102
+ + type_check(_type, typeof_field(_state, _field)), \
103
+ }
104
+
105
#define DEFINE_PROP_BIT64(_name, _state, _field, _bit, _defval) { \
106
.name = (_name), \
107
.info = &(qdev_prop_bit64), \
108
.bitnr = (_bit), \
109
.offset = offsetof(_state, _field) \
110
+ type_check(uint64_t, typeof_field(_state, _field)), \
111
+ .set_default = true, \
112
.defval.u = (bool)_defval, \
113
}
114
115
@@ -XXX,XX +XXX,XX @@ extern const PropertyInfo qdev_prop_link;
116
.info = &(qdev_prop_bool), \
117
.offset = offsetof(_state, _field) \
118
+ type_check(bool, typeof_field(_state, _field)), \
119
+ .set_default = true, \
120
.defval.u = (bool)_defval, \
121
}
122
123
@@ -XXX,XX +XXX,XX @@ extern const PropertyInfo qdev_prop_link;
124
_arrayfield, _arrayprop, _arraytype) { \
125
.name = (PROP_ARRAY_LEN_PREFIX _name), \
126
.info = &(qdev_prop_arraylen), \
127
+ .set_default = true, \
128
.defval.u = 0, \
129
.offset = offsetof(_state, _field) \
130
+ type_check(uint32_t, typeof_field(_state, _field)), \
131
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
132
index XXXXXXX..XXXXXXX 100644
133
--- a/hw/core/qdev.c
134
+++ b/hw/core/qdev.c
135
@@ -XXX,XX +XXX,XX @@ void qdev_property_add_static(DeviceState *dev, Property *prop,
136
prop->info->description,
137
&error_abort);
138
139
- if (prop->info->set_default_value) {
140
+ if (prop->set_default) {
141
prop->info->set_default_value(obj, prop);
142
}
143
}
144
--
28
--
145
2.7.4
29
2.20.1
146
30
147
31
diff view generated by jsdifflib
1
In DEFINE_PROP_ARRAY, because we use a PropertyInfo (qdev_prop_arraylen)
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
which has a .set_default_value member we will set the field to a default
3
value. That default value will be zero, by the C rule that struct
4
initialization sets unmentioned members to zero if at least one member
5
is initialized. However it's clearer to state it explicitly.
6
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
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
9
Message-id: 1499788408-10096-2-git-send-email-peter.maydell@linaro.org
10
---
21
---
11
include/hw/qdev-properties.h | 1 +
22
hw/arm/nseries.c | 1 +
12
1 file changed, 1 insertion(+)
23
1 file changed, 1 insertion(+)
13
24
14
diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.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/qdev-properties.h
27
--- a/hw/arm/nseries.c
17
+++ b/include/hw/qdev-properties.h
28
+++ b/hw/arm/nseries.c
18
@@ -XXX,XX +XXX,XX @@ extern const PropertyInfo qdev_prop_link;
29
@@ -XXX,XX +XXX,XX @@ static void n8x0_init(MachineState *machine,
19
_arrayfield, _arrayprop, _arraytype) { \
30
g_free(sz);
20
.name = (PROP_ARRAY_LEN_PREFIX _name), \
31
exit(EXIT_FAILURE);
21
.info = &(qdev_prop_arraylen), \
32
}
22
+ .defval.u = 0, \
33
+ binfo->ram_size = machine->ram_size;
23
.offset = offsetof(_state, _field) \
34
24
+ type_check(uint32_t, typeof_field(_state, _field)), \
35
memory_region_add_subregion(get_system_memory(), OMAP2_Q2_BASE,
25
.arrayinfo = &(_arrayprop), \
36
machine->ram);
26
--
37
--
27
2.7.4
38
2.20.1
28
39
29
40
diff view generated by jsdifflib
New patch
1
For nested groups like:
1
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>
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
28
Message-id: 20201019151301.2046-2-peter.maydell@linaro.org
29
---
30
scripts/decodetree.py | 2 +-
31
1 file changed, 1 insertion(+), 1 deletion(-)
32
33
diff --git a/scripts/decodetree.py b/scripts/decodetree.py
34
index XXXXXXX..XXXXXXX 100644
35
--- a/scripts/decodetree.py
36
+++ b/scripts/decodetree.py
37
@@ -XXX,XX +XXX,XX @@ class Tree:
38
output(ind, ' /* ',
39
str_match_bits(innerbits, innermask), ' */\n')
40
s.output_code(i + 4, extracted, innerbits, innermask)
41
- output(ind, ' return false;\n')
42
+ output(ind, ' break;\n')
43
output(ind, '}\n')
44
# end Tree
45
46
--
47
2.20.1
48
49
diff view generated by jsdifflib
1
The MPS2 FPGA images support ethernet via a LAN9220. We use
1
From v8.1M, disabled-coprocessor handling changes slightly:
2
QEMU's LAN9118 model, which is software compatible except
2
* coprocessors 8, 9, 14 and 15 are also governed by the
3
that it is missing the checksum-offload feature.
3
cp10 enable bit, like cp11
4
* an extra range of instruction patterns is considered
5
to be inside the coprocessor space
6
7
We previously marked these up with TODO comments; implement the
8
correct behaviour.
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.
4
16
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Message-id: 1500029487-14822-9-git-send-email-peter.maydell@linaro.org
18
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
19
Message-id: 20201019151301.2046-3-peter.maydell@linaro.org
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
---
20
---
10
hw/arm/mps2.c | 10 +++++++++-
21
target/arm/cpu.h | 1 +
11
1 file changed, 9 insertions(+), 1 deletion(-)
22
target/arm/m-nocp.decode | 10 ++++++----
23
target/arm/translate-vfp.c.inc | 17 +++++++++++++++--
24
3 files changed, 22 insertions(+), 6 deletions(-)
12
25
13
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
26
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/mps2.c
28
--- a/target/arm/cpu.h
16
+++ b/hw/arm/mps2.c
29
+++ b/target/arm/cpu.h
30
@@ -XXX,XX +XXX,XX @@ enum arm_features {
31
ARM_FEATURE_VBAR, /* has cp15 VBAR */
32
ARM_FEATURE_M_SECURITY, /* M profile Security Extension */
33
ARM_FEATURE_M_MAIN, /* M profile Main Extension */
34
+ ARM_FEATURE_V8_1M, /* M profile extras only in v8.1M and later */
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
17
@@ -XXX,XX +XXX,XX @@
42
@@ -XXX,XX +XXX,XX @@
18
#include "hw/char/cmsdk-apb-uart.h"
43
# If the coprocessor is not present or disabled then we will generate
19
#include "hw/timer/cmsdk-apb-timer.h"
44
# the NOCP exception; otherwise we let the insn through to the main decode.
20
#include "hw/misc/mps2-scc.h"
45
21
+#include "hw/devices.h"
46
+&nocp cp
22
+#include "net/net.h"
23
24
typedef enum MPS2FPGAType {
25
FPGA_AN385,
26
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
27
create_unimplemented_device("Extra peripheral region @0x40020000",
28
0x40020000, 0x00010000);
29
create_unimplemented_device("RESERVED 4", 0x40030000, 0x001D0000);
30
- create_unimplemented_device("Ethernet", 0x40200000, 0x00100000);
31
create_unimplemented_device("VGA", 0x41000000, 0x0200000);
32
33
switch (mmc->fpga_type) {
34
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
35
&error_fatal);
36
sysbus_mmio_map(SYS_BUS_DEVICE(sccdev), 0, 0x4002f000);
37
38
+ /* In hardware this is a LAN9220; the LAN9118 is software compatible
39
+ * except that it doesn't support the checksum-offload feature.
40
+ */
41
+ lan9118_init(&nd_table[0], 0x40200000,
42
+ qdev_get_gpio_in(armv7m,
43
+ mmc->fpga_type == FPGA_AN385 ? 13 : 47));
44
+
47
+
45
system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ;
48
{
46
49
# Special cases which do not take an early NOCP: VLLDM and VLSTM
47
armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
50
VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 0000 0000
51
# TODO: VSCCLRM (new in v8.1M) is similar:
52
#VSCCLRM 1110 1100 1-01 1111 ---- 1011 ---- ---0
53
54
- NOCP 111- 1110 ---- ---- ---- cp:4 ---- ----
55
- NOCP 111- 110- ---- ---- ---- cp:4 ---- ----
56
- # TODO: From v8.1M onwards we will also want this range to NOCP
57
- #NOCP_8_1 111- 1111 ---- ---- ---- ---- ---- ---- cp=10
58
+ NOCP 111- 1110 ---- ---- ---- cp:4 ---- ---- &nocp
59
+ NOCP 111- 110- ---- ---- ---- cp:4 ---- ---- &nocp
60
+ # From v8.1M onwards this range will also NOCP:
61
+ NOCP_8_1 111- 1111 ---- ---- ---- ---- ---- ---- &nocp cp=10
62
}
63
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
64
index XXXXXXX..XXXXXXX 100644
65
--- a/target/arm/translate-vfp.c.inc
66
+++ b/target/arm/translate-vfp.c.inc
67
@@ -XXX,XX +XXX,XX @@ static bool trans_VLLDM_VLSTM(DisasContext *s, arg_VLLDM_VLSTM *a)
68
return true;
69
}
70
71
-static bool trans_NOCP(DisasContext *s, arg_NOCP *a)
72
+static bool trans_NOCP(DisasContext *s, arg_nocp *a)
73
{
74
/*
75
* Handle M-profile early check for disabled coprocessor:
76
@@ -XXX,XX +XXX,XX @@ static bool trans_NOCP(DisasContext *s, arg_NOCP *a)
77
if (a->cp == 11) {
78
a->cp = 10;
79
}
80
- /* TODO: in v8.1M cp 8, 9, 14, 15 also are governed by the cp10 enable */
81
+ if (arm_dc_feature(s, ARM_FEATURE_V8_1M) &&
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
+}
101
+
102
static bool trans_VINS(DisasContext *s, arg_VINS *a)
103
{
104
TCGv_i32 rd, rm;
48
--
105
--
49
2.7.4
106
2.20.1
50
107
51
108
diff view generated by jsdifflib
1
Model the ARM MPS2/MPS2+ FPGA based development board.
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
The MPS2 and MPS2+ dev boards are FPGA based (the 2+ has a bigger
7
Implement these.
4
FPGA but is otherwise the same as the 2). Since the CPU itself
5
and most of the devices are in the FPGA, the details of the board
6
as seen by the guest depend significantly on the FPGA image.
7
8
8
We model the following FPGA images:
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
"mps2_an385" -- Cortex-M3 as documented in ARM Application Note AN385
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
"mps2_an511" -- Cortex-M3 'DesignStart' as documented in AN511
11
Message-id: 20201019151301.2046-4-peter.maydell@linaro.org
12
---
13
target/arm/t32.decode | 3 +++
14
target/arm/translate.c | 60 ++++++++++++++++++++++++++++++++++++++++++
15
2 files changed, 63 insertions(+)
11
16
12
They are fairly similar but differ in the details for some
17
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
13
peripherals.
14
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Message-id: 1500029487-14822-2-git-send-email-peter.maydell@linaro.org
17
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
18
---
19
hw/arm/Makefile.objs | 1 +
20
hw/arm/mps2.c | 270 ++++++++++++++++++++++++++++++++++++++++
21
default-configs/arm-softmmu.mak | 1 +
22
3 files changed, 272 insertions(+)
23
create mode 100644 hw/arm/mps2.c
24
25
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
26
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/arm/Makefile.objs
19
--- a/target/arm/t32.decode
28
+++ b/hw/arm/Makefile.objs
20
+++ b/target/arm/t32.decode
29
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o
21
@@ -XXX,XX +XXX,XX @@ SBC_rrri 1110101 1011 . .... 0 ... .... .... .... @s_rrr_shi
30
obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o
22
}
31
obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o
23
RSB_rrri 1110101 1110 . .... 0 ... .... .... .... @s_rrr_shi
32
obj-$(CONFIG_ASPEED_SOC) += aspeed_soc.o aspeed.o
24
33
+obj-$(CONFIG_MPS2) += mps2.o
25
+# v8.1M CSEL and friends
34
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
26
+CSEL 1110101 0010 1 rn:4 10 op:2 rd:4 fcond:4 rm:4
35
new file mode 100644
36
index XXXXXXX..XXXXXXX
37
--- /dev/null
38
+++ b/hw/arm/mps2.c
39
@@ -XXX,XX +XXX,XX @@
40
+/*
41
+ * ARM V2M MPS2 board emulation.
42
+ *
43
+ * Copyright (c) 2017 Linaro Limited
44
+ * Written by Peter Maydell
45
+ *
46
+ * This program is free software; you can redistribute it and/or modify
47
+ * it under the terms of the GNU General Public License version 2 or
48
+ * (at your option) any later version.
49
+ */
50
+
27
+
51
+/* The MPS2 and MPS2+ dev boards are FPGA based (the 2+ has a bigger
28
# Data-processing (register-shifted register)
52
+ * FPGA but is otherwise the same as the 2). Since the CPU itself
29
53
+ * and most of the devices are in the FPGA, the details of the board
30
MOV_rxrr 1111 1010 0 shty:2 s:1 rm:4 1111 rd:4 0000 rs:4 \
54
+ * as seen by the guest depend significantly on the FPGA image.
31
diff --git a/target/arm/translate.c b/target/arm/translate.c
55
+ * We model the following FPGA images:
32
index XXXXXXX..XXXXXXX 100644
56
+ * "mps2-an385" -- Cortex-M3 as documented in ARM Application Note AN385
33
--- a/target/arm/translate.c
57
+ * "mps2-an511" -- Cortex-M3 'DesignStart' as documented in AN511
34
+++ b/target/arm/translate.c
58
+ *
35
@@ -XXX,XX +XXX,XX @@ static bool trans_IT(DisasContext *s, arg_IT *a)
59
+ * Links to the TRM for the board itself and to the various Application
36
return true;
60
+ * Notes which document the FPGA images can be found here:
37
}
61
+ * https://developer.arm.com/products/system-design/development-boards/cortex-m-prototyping-system
38
62
+ */
39
+/* v8.1M CSEL/CSINC/CSNEG/CSINV */
40
+static bool trans_CSEL(DisasContext *s, arg_CSEL *a)
41
+{
42
+ TCGv_i32 rn, rm, zero;
43
+ DisasCompare c;
63
+
44
+
64
+#include "qemu/osdep.h"
45
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
65
+#include "qapi/error.h"
46
+ return false;
66
+#include "qemu/error-report.h"
67
+#include "hw/arm/arm.h"
68
+#include "hw/arm/armv7m.h"
69
+#include "hw/boards.h"
70
+#include "exec/address-spaces.h"
71
+#include "hw/misc/unimp.h"
72
+
73
+typedef enum MPS2FPGAType {
74
+ FPGA_AN385,
75
+ FPGA_AN511,
76
+} MPS2FPGAType;
77
+
78
+typedef struct {
79
+ MachineClass parent;
80
+ MPS2FPGAType fpga_type;
81
+ const char *cpu_model;
82
+} MPS2MachineClass;
83
+
84
+typedef struct {
85
+ MachineState parent;
86
+
87
+ ARMv7MState armv7m;
88
+ MemoryRegion psram;
89
+ MemoryRegion ssram1;
90
+ MemoryRegion ssram1_m;
91
+ MemoryRegion ssram23;
92
+ MemoryRegion ssram23_m;
93
+ MemoryRegion blockram;
94
+ MemoryRegion blockram_m1;
95
+ MemoryRegion blockram_m2;
96
+ MemoryRegion blockram_m3;
97
+ MemoryRegion sram;
98
+} MPS2MachineState;
99
+
100
+#define TYPE_MPS2_MACHINE "mps2"
101
+#define TYPE_MPS2_AN385_MACHINE MACHINE_TYPE_NAME("mps2-an385")
102
+#define TYPE_MPS2_AN511_MACHINE MACHINE_TYPE_NAME("mps2-an511")
103
+
104
+#define MPS2_MACHINE(obj) \
105
+ OBJECT_CHECK(MPS2MachineState, obj, TYPE_MPS2_MACHINE)
106
+#define MPS2_MACHINE_GET_CLASS(obj) \
107
+ OBJECT_GET_CLASS(MPS2MachineClass, obj, TYPE_MPS2_MACHINE)
108
+#define MPS2_MACHINE_CLASS(klass) \
109
+ OBJECT_CLASS_CHECK(MPS2MachineClass, klass, TYPE_MPS2_MACHINE)
110
+
111
+/* Main SYSCLK frequency in Hz */
112
+#define SYSCLK_FRQ 25000000
113
+
114
+/* Initialize the auxiliary RAM region @mr and map it into
115
+ * the memory map at @base.
116
+ */
117
+static void make_ram(MemoryRegion *mr, const char *name,
118
+ hwaddr base, hwaddr size)
119
+{
120
+ memory_region_init_ram(mr, NULL, name, size, &error_fatal);
121
+ memory_region_add_subregion(get_system_memory(), base, mr);
122
+}
123
+
124
+/* Create an alias of an entire original MemoryRegion @orig
125
+ * located at @base in the memory map.
126
+ */
127
+static void make_ram_alias(MemoryRegion *mr, const char *name,
128
+ MemoryRegion *orig, hwaddr base)
129
+{
130
+ memory_region_init_alias(mr, NULL, name, orig, 0,
131
+ memory_region_size(orig));
132
+ memory_region_add_subregion(get_system_memory(), base, mr);
133
+}
134
+
135
+static void mps2_common_init(MachineState *machine)
136
+{
137
+ MPS2MachineState *mms = MPS2_MACHINE(machine);
138
+ MPS2MachineClass *mmc = MPS2_MACHINE_GET_CLASS(machine);
139
+ MemoryRegion *system_memory = get_system_memory();
140
+ DeviceState *armv7m;
141
+
142
+ if (!machine->cpu_model) {
143
+ machine->cpu_model = mmc->cpu_model;
144
+ }
47
+ }
145
+
48
+
146
+ if (strcmp(machine->cpu_model, mmc->cpu_model) != 0) {
49
+ if (a->rm == 13) {
147
+ error_report("This board can only be used with CPU %s", mmc->cpu_model);
50
+ /* SEE "Related encodings" (MVE shifts) */
148
+ exit(1);
51
+ return false;
149
+ }
52
+ }
150
+
53
+
151
+ /* The FPGA images have an odd combination of different RAMs,
54
+ if (a->rd == 13 || a->rd == 15 || a->rn == 13 || a->fcond >= 14) {
152
+ * because in hardware they are different implementations and
55
+ /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */
153
+ * connected to different buses, giving varying performance/size
56
+ return false;
154
+ * tradeoffs. For QEMU they're all just RAM, though. We arbitrarily
57
+ }
155
+ * call the 16MB our "system memory", as it's the largest lump.
156
+ *
157
+ * Common to both boards:
158
+ * 0x21000000..0x21ffffff : PSRAM (16MB)
159
+ * AN385 only:
160
+ * 0x00000000 .. 0x003fffff : ZBT SSRAM1
161
+ * 0x00400000 .. 0x007fffff : mirror of ZBT SSRAM1
162
+ * 0x20000000 .. 0x203fffff : ZBT SSRAM 2&3
163
+ * 0x20400000 .. 0x207fffff : mirror of ZBT SSRAM 2&3
164
+ * 0x01000000 .. 0x01003fff : block RAM (16K)
165
+ * 0x01004000 .. 0x01007fff : mirror of above
166
+ * 0x01008000 .. 0x0100bfff : mirror of above
167
+ * 0x0100c000 .. 0x0100ffff : mirror of above
168
+ * AN511 only:
169
+ * 0x00000000 .. 0x0003ffff : FPGA block RAM
170
+ * 0x00400000 .. 0x007fffff : ZBT SSRAM1
171
+ * 0x20000000 .. 0x2001ffff : SRAM
172
+ * 0x20400000 .. 0x207fffff : ZBT SSRAM 2&3
173
+ *
174
+ * The AN385 has a feature where the lowest 16K can be mapped
175
+ * either to the bottom of the ZBT SSRAM1 or to the block RAM.
176
+ * This is of no use for QEMU so we don't implement it (as if
177
+ * zbt_boot_ctrl is always zero).
178
+ */
179
+ memory_region_allocate_system_memory(&mms->psram,
180
+ NULL, "mps.ram", 0x1000000);
181
+ memory_region_add_subregion(system_memory, 0x21000000, &mms->psram);
182
+
58
+
183
+ switch (mmc->fpga_type) {
59
+ /* In this insn input reg fields of 0b1111 mean "zero", not "PC" */
184
+ case FPGA_AN385:
60
+ if (a->rn == 15) {
185
+ make_ram(&mms->ssram1, "mps.ssram1", 0x0, 0x400000);
61
+ rn = tcg_const_i32(0);
186
+ make_ram_alias(&mms->ssram1_m, "mps.ssram1_m", &mms->ssram1, 0x400000);
62
+ } else {
187
+ make_ram(&mms->ssram23, "mps.ssram23", 0x20000000, 0x400000);
63
+ rn = load_reg(s, a->rn);
188
+ make_ram_alias(&mms->ssram23_m, "mps.ssram23_m",
64
+ }
189
+ &mms->ssram23, 0x20400000);
65
+ if (a->rm == 15) {
190
+ make_ram(&mms->blockram, "mps.blockram", 0x01000000, 0x4000);
66
+ rm = tcg_const_i32(0);
191
+ make_ram_alias(&mms->blockram_m1, "mps.blockram_m1",
67
+ } else {
192
+ &mms->blockram, 0x01004000);
68
+ rm = load_reg(s, a->rm);
193
+ make_ram_alias(&mms->blockram_m2, "mps.blockram_m2",
69
+ }
194
+ &mms->blockram, 0x01008000);
70
+
195
+ make_ram_alias(&mms->blockram_m3, "mps.blockram_m3",
71
+ switch (a->op) {
196
+ &mms->blockram, 0x0100c000);
72
+ case 0: /* CSEL */
197
+ break;
73
+ break;
198
+ case FPGA_AN511:
74
+ case 1: /* CSINC */
199
+ make_ram(&mms->blockram, "mps.blockram", 0x0, 0x40000);
75
+ tcg_gen_addi_i32(rm, rm, 1);
200
+ make_ram(&mms->ssram1, "mps.ssram1", 0x00400000, 0x00800000);
76
+ break;
201
+ make_ram(&mms->sram, "mps.sram", 0x20000000, 0x20000);
77
+ case 2: /* CSINV */
202
+ make_ram(&mms->ssram23, "mps.ssram23", 0x20400000, 0x400000);
78
+ tcg_gen_not_i32(rm, rm);
79
+ break;
80
+ case 3: /* CSNEG */
81
+ tcg_gen_neg_i32(rm, rm);
203
+ break;
82
+ break;
204
+ default:
83
+ default:
205
+ g_assert_not_reached();
84
+ g_assert_not_reached();
206
+ }
85
+ }
207
+
86
+
208
+ object_initialize(&mms->armv7m, sizeof(mms->armv7m), TYPE_ARMV7M);
87
+ arm_test_cc(&c, a->fcond);
209
+ armv7m = DEVICE(&mms->armv7m);
88
+ zero = tcg_const_i32(0);
210
+ qdev_set_parent_bus(armv7m, sysbus_get_default());
89
+ tcg_gen_movcond_i32(c.cond, rn, c.value, zero, rn, rm);
211
+ switch (mmc->fpga_type) {
90
+ arm_free_cc(&c);
212
+ case FPGA_AN385:
91
+ tcg_temp_free_i32(zero);
213
+ qdev_prop_set_uint32(armv7m, "num-irq", 32);
214
+ break;
215
+ case FPGA_AN511:
216
+ qdev_prop_set_uint32(armv7m, "num-irq", 64);
217
+ break;
218
+ default:
219
+ g_assert_not_reached();
220
+ }
221
+ qdev_prop_set_string(armv7m, "cpu-model", machine->cpu_model);
222
+ object_property_set_link(OBJECT(&mms->armv7m), OBJECT(system_memory),
223
+ "memory", &error_abort);
224
+ object_property_set_bool(OBJECT(&mms->armv7m), true, "realized",
225
+ &error_fatal);
226
+
92
+
227
+ create_unimplemented_device("zbtsmram mirror", 0x00400000, 0x00400000);
93
+ store_reg(s, a->rd, rn);
228
+ create_unimplemented_device("RESERVED 1", 0x00800000, 0x00800000);
94
+ tcg_temp_free_i32(rm);
229
+ create_unimplemented_device("Block RAM", 0x01000000, 0x00010000);
230
+ create_unimplemented_device("RESERVED 2", 0x01010000, 0x1EFF0000);
231
+ create_unimplemented_device("RESERVED 3", 0x20800000, 0x00800000);
232
+ create_unimplemented_device("PSRAM", 0x21000000, 0x01000000);
233
+ /* These three ranges all cover multiple devices; we may implement
234
+ * some of them below (in which case the real device takes precedence
235
+ * over the unimplemented-region mapping).
236
+ */
237
+ create_unimplemented_device("CMSDK APB peripheral region @0x40000000",
238
+ 0x40000000, 0x00010000);
239
+ create_unimplemented_device("CMSDK peripheral region @0x40010000",
240
+ 0x40010000, 0x00010000);
241
+ create_unimplemented_device("Extra peripheral region @0x40020000",
242
+ 0x40020000, 0x00010000);
243
+ create_unimplemented_device("RESERVED 4", 0x40030000, 0x001D0000);
244
+ create_unimplemented_device("Ethernet", 0x40200000, 0x00100000);
245
+ create_unimplemented_device("VGA", 0x41000000, 0x0200000);
246
+
95
+
247
+ system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ;
96
+ return true;
248
+
249
+ armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
250
+ 0x400000);
251
+}
97
+}
252
+
98
+
253
+static void mps2_class_init(ObjectClass *oc, void *data)
99
/*
254
+{
100
* Legacy decoder.
255
+ MachineClass *mc = MACHINE_CLASS(oc);
101
*/
256
+
257
+ mc->init = mps2_common_init;
258
+ mc->max_cpus = 1;
259
+}
260
+
261
+static void mps2_an385_class_init(ObjectClass *oc, void *data)
262
+{
263
+ MachineClass *mc = MACHINE_CLASS(oc);
264
+ MPS2MachineClass *mmc = MPS2_MACHINE_CLASS(oc);
265
+
266
+ mc->desc = "ARM MPS2 with AN385 FPGA image for Cortex-M3";
267
+ mmc->fpga_type = FPGA_AN385;
268
+ mmc->cpu_model = "cortex-m3";
269
+}
270
+
271
+static void mps2_an511_class_init(ObjectClass *oc, void *data)
272
+{
273
+ MachineClass *mc = MACHINE_CLASS(oc);
274
+ MPS2MachineClass *mmc = MPS2_MACHINE_CLASS(oc);
275
+
276
+ mc->desc = "ARM MPS2 with AN511 DesignStart FPGA image for Cortex-M3";
277
+ mmc->fpga_type = FPGA_AN511;
278
+ mmc->cpu_model = "cortex-m3";
279
+}
280
+
281
+static const TypeInfo mps2_info = {
282
+ .name = TYPE_MPS2_MACHINE,
283
+ .parent = TYPE_MACHINE,
284
+ .abstract = true,
285
+ .instance_size = sizeof(MPS2MachineState),
286
+ .class_size = sizeof(MPS2MachineClass),
287
+ .class_init = mps2_class_init,
288
+};
289
+
290
+static const TypeInfo mps2_an385_info = {
291
+ .name = TYPE_MPS2_AN385_MACHINE,
292
+ .parent = TYPE_MPS2_MACHINE,
293
+ .class_init = mps2_an385_class_init,
294
+};
295
+
296
+static const TypeInfo mps2_an511_info = {
297
+ .name = TYPE_MPS2_AN511_MACHINE,
298
+ .parent = TYPE_MPS2_MACHINE,
299
+ .class_init = mps2_an511_class_init,
300
+};
301
+
302
+static void mps2_machine_init(void)
303
+{
304
+ type_register_static(&mps2_info);
305
+ type_register_static(&mps2_an385_info);
306
+ type_register_static(&mps2_an511_info);
307
+}
308
+
309
+type_init(mps2_machine_init);
310
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
311
index XXXXXXX..XXXXXXX 100644
312
--- a/default-configs/arm-softmmu.mak
313
+++ b/default-configs/arm-softmmu.mak
314
@@ -XXX,XX +XXX,XX @@ CONFIG_ONENAND=y
315
CONFIG_TUSB6010=y
316
CONFIG_IMX=y
317
CONFIG_MAINSTONE=y
318
+CONFIG_MPS2=y
319
CONFIG_NSERIES=y
320
CONFIG_RASPI=y
321
CONFIG_REALVIEW=y
322
--
102
--
323
2.7.4
103
2.20.1
324
104
325
105
diff view generated by jsdifflib
New patch
1
The t32 decode has a group which represents a set of insns
2
which overlap with B_cond_thumb because they have [25:23]=111
3
(which is an invalid condition code field for the branch insn).
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.
1
7
8
For this to be valid syntactically, CPS must move into the same
9
overlapping-group as the hint insns (CPS vs hints was the
10
only actual use of the overlap facility for the group).
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>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Message-id: 20201019151301.2046-5-peter.maydell@linaro.org
19
---
20
target/arm/t32.decode | 26 ++++++++++++--------------
21
1 file changed, 12 insertions(+), 14 deletions(-)
22
23
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
24
index XXXXXXX..XXXXXXX 100644
25
--- a/target/arm/t32.decode
26
+++ b/target/arm/t32.decode
27
@@ -XXX,XX +XXX,XX @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm
28
{
29
# Group insn[25:23] = 111, which is cond=111x for the branch below,
30
# or unconditional, which would be illegal for the branch.
31
- {
32
- # Hints
33
+ [
34
+ # Hints, and CPS
35
{
36
YIELD 1111 0011 1010 1111 1000 0000 0000 0001
37
WFE 1111 0011 1010 1111 1000 0000 0000 0010
38
@@ -XXX,XX +XXX,XX @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm
39
# The canonical nop ends in 0000 0000, but the whole rest
40
# of the space is "reserved hint, behaves as nop".
41
NOP 1111 0011 1010 1111 1000 0000 ---- ----
42
+
43
+ # If imod == '00' && M == '0' then SEE "Hint instructions", above.
44
+ CPS 1111 0011 1010 1111 1000 0 imod:2 M:1 A:1 I:1 F:1 mode:5 \
45
+ &cps
46
}
47
48
- # If imod == '00' && M == '0' then SEE "Hint instructions", above.
49
- CPS 1111 0011 1010 1111 1000 0 imod:2 M:1 A:1 I:1 F:1 mode:5 \
50
- &cps
51
-
52
# Miscellaneous control
53
- [
54
- CLREX 1111 0011 1011 1111 1000 1111 0010 1111
55
- DSB 1111 0011 1011 1111 1000 1111 0100 ----
56
- DMB 1111 0011 1011 1111 1000 1111 0101 ----
57
- ISB 1111 0011 1011 1111 1000 1111 0110 ----
58
- SB 1111 0011 1011 1111 1000 1111 0111 0000
59
- ]
60
+ CLREX 1111 0011 1011 1111 1000 1111 0010 1111
61
+ DSB 1111 0011 1011 1111 1000 1111 0100 ----
62
+ DMB 1111 0011 1011 1111 1000 1111 0101 ----
63
+ ISB 1111 0011 1011 1111 1000 1111 0110 ----
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
75
}
76
77
--
78
2.20.1
79
80
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@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
As the gen_goto_tb function can do both static and dynamic jumps it
6
(This part of the encoding space is used for the branch-future
4
should also set the is_jmp field. This matches the behaviour of the
7
and low-overhead-loop insns in v8.1M.)
5
a64 code.
6
8
7
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <rth@twiddle.net>
9
Message-id: 20170713141928.25419-5-alex.bennee@linaro.org
10
[tweak to multiline comment formatting]
11
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
12
---
12
---
13
target/arm/translate.c | 6 +++++-
13
target/arm/translate.c | 8 ++++++++
14
1 file changed, 5 insertions(+), 1 deletion(-)
14
1 file changed, 8 insertions(+)
15
15
16
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
17
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/translate.c
18
--- a/target/arm/translate.c
19
+++ b/target/arm/translate.c
19
+++ b/target/arm/translate.c
20
@@ -XXX,XX +XXX,XX @@ static void gen_goto_ptr(void)
20
@@ -XXX,XX +XXX,XX @@ static bool trans_BLX_i(DisasContext *s, arg_BLX_i *a)
21
tcg_temp_free(addr);
22
}
23
24
+/* This will end the TB but doesn't guarantee we'll return to
25
+ * cpu_loop_exec. Any live exit_requests will be processed as we
26
+ * enter the next TB.
27
+ */
28
static void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
29
{
21
{
30
if (use_goto_tb(s, dest)) {
22
TCGv_i32 tmp;
31
@@ -XXX,XX +XXX,XX @@ static void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
23
32
gen_set_pc_im(s, dest);
24
+ /*
33
gen_goto_ptr();
25
+ * BLX <imm> would be useless on M-profile; the encoding space
34
}
26
+ * is used for other insns from v8.1M onward, and UNDEFs before that.
35
+ s->is_jmp = DISAS_TB_JUMP;
27
+ */
36
}
28
+ if (arm_dc_feature(s, ARM_FEATURE_M)) {
37
29
+ return false;
38
static inline void gen_jmp (DisasContext *s, uint32_t dest)
30
+ }
39
@@ -XXX,XX +XXX,XX @@ static inline void gen_jmp (DisasContext *s, uint32_t dest)
31
+
40
gen_bx_im(s, dest);
32
/* For A32, ARM_FEATURE_V5 is checked near the start of the uncond block. */
41
} else {
33
if (s->thumb && (a->imm & 2)) {
42
gen_goto_tb(s, 0, dest);
34
return false;
43
- s->is_jmp = DISAS_TB_JUMP;
44
}
45
}
46
47
--
35
--
48
2.7.4
36
2.20.1
49
37
50
38
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
v8.1M implements a new 'branch future' feature, which is a
2
set of instructions that request the CPU to perform a branch
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).
2
13
3
Previously DISAS_JUMP did ensure this but with the optimisation of
14
For QEMU, implementing this caching of branch information
4
8a6b28c7 (optimize indirect branches) we might not leave the loop.
15
would be complicated and would not improve the speed of
5
This means if any pending interrupts are cleared by changing IRQ flags
16
execution at all, so we make the IMPDEF choice to implement
6
we might never get around to servicing them. You usually notice this
17
all BF insns as NOPs.
7
by seeing the lookup_tb_ptr() helper gainfully chaining TBs together
8
while cpu->interrupt_request remains high and the exit_request has not
9
been set.
10
18
11
This breaks amongst other things the OPTEE test suite which executes
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
an eret from the secure world after a non-secure world IRQ has gone
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
pending which then never gets serviced.
21
Message-id: 20201019151301.2046-7-peter.maydell@linaro.org
22
---
23
target/arm/cpu.h | 6 ++++++
24
target/arm/t32.decode | 13 ++++++++++++-
25
target/arm/translate.c | 20 ++++++++++++++++++++
26
3 files changed, 38 insertions(+), 1 deletion(-)
14
27
15
Instead of using the previously implied semantics of DISAS_JUMP we use
28
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
DISAS_EXIT which will always exit the run-loop.
17
18
CC: Etienne Carriere <etienne.carriere@linaro.org>
19
CC: Joakim Bech <joakim.bech@linaro.org>
20
CC: Jaroslaw Pelczar <j.pelczar@samsung.com>
21
CC: Peter Maydell <peter.maydell@linaro.org>
22
CC: Emilio G. Cota <cota@braap.org>
23
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
24
Reviewed-by: Richard Henderson <rth@twiddle.net>
25
Message-id: 20170713141928.25419-7-alex.bennee@linaro.org
26
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
---
28
target/arm/translate-a64.c | 3 ++-
29
target/arm/translate.c | 6 ++++--
30
2 files changed, 6 insertions(+), 3 deletions(-)
31
32
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
33
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/translate-a64.c
30
--- a/target/arm/cpu.h
35
+++ b/target/arm/translate-a64.c
31
+++ b/target/arm/cpu.h
36
@@ -XXX,XX +XXX,XX @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
32
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_arm_div(const ARMISARegisters *id)
37
return;
33
return FIELD_EX32(id->id_isar0, ID_ISAR0, DIVIDE) > 1;
38
}
34
}
39
gen_helper_exception_return(cpu_env);
35
40
- s->is_jmp = DISAS_JUMP;
36
+static inline bool isar_feature_aa32_lob(const ARMISARegisters *id)
41
+ /* Must exit loop to check un-masked IRQs */
37
+{
42
+ s->is_jmp = DISAS_EXIT;
38
+ /* (M-profile) low-overhead loops and branch future */
43
return;
39
+ return FIELD_EX32(id->id_isar0, ID_ISAR0, CMPBRANCH) >= 3;
44
case 5: /* DRPS */
40
+}
45
if (rn != 0x1f) {
41
+
42
static inline bool isar_feature_aa32_jazelle(const ARMISARegisters *id)
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
54
+{
55
+ # BLX_i is non-M-profile only
56
+ BLX_i 1111 0. .......... 11.0 ............ @branch24
57
+ # M-profile only: loop and branch insns
58
+ [
59
+ # All these BF insns have boff != 0b0000; we NOP them all
60
+ BF 1111 0 boff:4 ------- 1100 - ---------- 1 # BFL
61
+ BF 1111 0 boff:4 0 ------ 1110 - ---------- 1 # BFCSEL
62
+ BF 1111 0 boff:4 10 ----- 1110 - ---------- 1 # BF
63
+ BF 1111 0 boff:4 11 ----- 1110 0 0000000000 1 # BFX, BFLX
64
+ ]
65
+}
46
diff --git a/target/arm/translate.c b/target/arm/translate.c
66
diff --git a/target/arm/translate.c b/target/arm/translate.c
47
index XXXXXXX..XXXXXXX 100644
67
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/translate.c
68
--- a/target/arm/translate.c
49
+++ b/target/arm/translate.c
69
+++ b/target/arm/translate.c
50
@@ -XXX,XX +XXX,XX @@ static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr)
70
@@ -XXX,XX +XXX,XX @@ static bool trans_BLX_suffix(DisasContext *s, arg_BLX_suffix *a)
51
*/
71
return true;
52
gen_helper_cpsr_write_eret(cpu_env, cpsr);
53
tcg_temp_free_i32(cpsr);
54
- s->is_jmp = DISAS_JUMP;
55
+ /* Must exit loop to check un-masked IRQs */
56
+ s->is_jmp = DISAS_EXIT;
57
}
72
}
58
73
59
/* Generate an old-style exception return. Marks pc as dead. */
74
+static bool trans_BF(DisasContext *s, arg_BF *a)
60
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
75
+{
61
tmp = load_cpu_field(spsr);
76
+ /*
62
gen_helper_cpsr_write_eret(cpu_env, tmp);
77
+ * M-profile branch future insns. The architecture permits an
63
tcg_temp_free_i32(tmp);
78
+ * implementation to implement these as NOPs (equivalent to
64
- s->is_jmp = DISAS_JUMP;
79
+ * discarding the LO_BRANCH_INFO cache immediately), and we
65
+ /* Must exit loop to check un-masked IRQs */
80
+ * take that IMPDEF option because for QEMU a "real" implementation
66
+ s->is_jmp = DISAS_EXIT;
81
+ * would be complicated and wouldn't execute any faster.
67
}
82
+ */
68
}
83
+ if (!dc_isar_feature(aa32_lob, s)) {
69
break;
84
+ return false;
85
+ }
86
+ if (a->boff == 0) {
87
+ /* SEE "Related encodings" (loop insns) */
88
+ return false;
89
+ }
90
+ /* Handle as NOP */
91
+ return true;
92
+}
93
+
94
static bool op_tbranch(DisasContext *s, arg_tbranch *a, bool half)
95
{
96
TCGv_i32 addr, tmp;
70
--
97
--
71
2.7.4
98
2.20.1
72
99
73
100
diff view generated by jsdifflib
1
Implement a model of the Serial Communication Controller (SCC) found
1
v8.1M's "low-overhead-loop" extension has three instructions
2
in MPS2 FPGA images.
2
for looping:
3
* DLS (start of a do-loop)
4
* WLS (start of a while-loop)
5
* LE (end of a loop)
3
6
4
The primary purpose of this device is to communicate with the
7
The loop-start instructions are both simple operations to start a
5
Motherboard Configuration Controller (MCC) which is located on
8
loop whose iteration count (if any) is in LR. The loop-end
6
the MPS board itself, outside the FPGA image. This is used
9
instruction handles "decrement iteration count and jump back to loop
7
for programming the MPS clock generators. The SCC also has
10
start"; it also caches the information about the branch back to the
8
some basic ID registers and an output for the board LEDs.
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.)
9
24
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
26
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 1500029487-14822-7-git-send-email-peter.maydell@linaro.org
27
Message-id: 20201019151301.2046-8-peter.maydell@linaro.org
13
---
28
---
14
hw/misc/Makefile.objs | 1 +
29
target/arm/t32.decode | 8 ++++
15
include/hw/misc/mps2-scc.h | 43 ++++++
30
target/arm/translate.c | 93 +++++++++++++++++++++++++++++++++++++++++-
16
hw/misc/mps2-scc.c | 310 ++++++++++++++++++++++++++++++++++++++++
31
2 files changed, 99 insertions(+), 2 deletions(-)
17
default-configs/arm-softmmu.mak | 2 +
18
hw/misc/trace-events | 8 ++
19
5 files changed, 364 insertions(+)
20
create mode 100644 include/hw/misc/mps2-scc.h
21
create mode 100644 hw/misc/mps2-scc.c
22
32
23
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
24
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
25
--- a/hw/misc/Makefile.objs
35
--- a/target/arm/t32.decode
26
+++ b/hw/misc/Makefile.objs
36
+++ b/target/arm/t32.decode
27
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_STM32F2XX_SYSCFG) += stm32f2xx_syscfg.o
37
@@ -XXX,XX +XXX,XX @@ BL 1111 0. .......... 11.1 ............ @branch24
28
obj-$(CONFIG_MIPS_CPS) += mips_cmgcr.o
38
BF 1111 0 boff:4 10 ----- 1110 - ---------- 1 # BF
29
obj-$(CONFIG_MIPS_CPS) += mips_cpc.o
39
BF 1111 0 boff:4 11 ----- 1110 0 0000000000 1 # BFX, BFLX
30
obj-$(CONFIG_MIPS_ITU) += mips_itu.o
40
]
31
+obj-$(CONFIG_MPS2_SCC) += mps2-scc.o
41
+ [
32
42
+ # LE and WLS immediate
33
obj-$(CONFIG_PVPANIC) += pvpanic.o
43
+ %lob_imm 1:10 11:1 !function=times_2
34
obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
35
diff --git a/include/hw/misc/mps2-scc.h b/include/hw/misc/mps2-scc.h
36
new file mode 100644
37
index XXXXXXX..XXXXXXX
38
--- /dev/null
39
+++ b/include/hw/misc/mps2-scc.h
40
@@ -XXX,XX +XXX,XX @@
41
+/*
42
+ * ARM MPS2 SCC emulation
43
+ *
44
+ * Copyright (c) 2017 Linaro Limited
45
+ * Written by Peter Maydell
46
+ *
47
+ * This program is free software; you can redistribute it and/or modify
48
+ * it under the terms of the GNU General Public License version 2 or
49
+ * (at your option) any later version.
50
+ */
51
+
44
+
52
+#ifndef MPS2_SCC_H
45
+ DLS 1111 0 0000 100 rn:4 1110 0000 0000 0001
53
+#define MPS2_SCC_H
46
+ WLS 1111 0 0000 100 rn:4 1100 . .......... 1 imm=%lob_imm
47
+ LE 1111 0 0000 0 f:1 0 1111 1100 . .......... 1 imm=%lob_imm
48
+ ]
49
}
50
diff --git a/target/arm/translate.c b/target/arm/translate.c
51
index XXXXXXX..XXXXXXX 100644
52
--- a/target/arm/translate.c
53
+++ b/target/arm/translate.c
54
@@ -XXX,XX +XXX,XX @@ static void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
55
s->base.is_jmp = DISAS_NORETURN;
56
}
57
58
-static inline void gen_jmp (DisasContext *s, uint32_t dest)
59
+/* Jump, specifying which TB number to use if we gen_goto_tb() */
60
+static inline void gen_jmp_tb(DisasContext *s, uint32_t dest, int tbno)
61
{
62
if (unlikely(is_singlestepping(s))) {
63
/* An indirect jump so that we still trigger the debug exception. */
64
gen_set_pc_im(s, dest);
65
s->base.is_jmp = DISAS_JUMP;
66
} else {
67
- gen_goto_tb(s, 0, dest);
68
+ gen_goto_tb(s, tbno, dest);
69
}
70
}
71
72
+static inline void gen_jmp(DisasContext *s, uint32_t dest)
73
+{
74
+ gen_jmp_tb(s, dest, 0);
75
+}
54
+
76
+
55
+#include "hw/sysbus.h"
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)
85
+{
86
+ /* M-profile low-overhead loop start */
87
+ TCGv_i32 tmp;
56
+
88
+
57
+#define TYPE_MPS2_SCC "mps2-scc"
89
+ if (!dc_isar_feature(aa32_lob, s)) {
58
+#define MPS2_SCC(obj) OBJECT_CHECK(MPS2SCC, (obj), TYPE_MPS2_SCC)
90
+ return false;
59
+
91
+ }
60
+#define NUM_OSCCLK 3
92
+ if (a->rn == 13 || a->rn == 15) {
61
+
93
+ /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */
62
+typedef struct {
63
+ /*< private >*/
64
+ SysBusDevice parent_obj;
65
+
66
+ /*< public >*/
67
+ MemoryRegion iomem;
68
+
69
+ uint32_t cfg0;
70
+ uint32_t cfg1;
71
+ uint32_t cfg4;
72
+ uint32_t cfgdata_rtn;
73
+ uint32_t cfgdata_out;
74
+ uint32_t cfgctrl;
75
+ uint32_t cfgstat;
76
+ uint32_t dll;
77
+ uint32_t aid;
78
+ uint32_t id;
79
+ uint32_t oscclk[NUM_OSCCLK];
80
+ uint32_t oscclk_reset[NUM_OSCCLK];
81
+} MPS2SCC;
82
+
83
+#endif
84
diff --git a/hw/misc/mps2-scc.c b/hw/misc/mps2-scc.c
85
new file mode 100644
86
index XXXXXXX..XXXXXXX
87
--- /dev/null
88
+++ b/hw/misc/mps2-scc.c
89
@@ -XXX,XX +XXX,XX @@
90
+/*
91
+ * ARM MPS2 SCC emulation
92
+ *
93
+ * Copyright (c) 2017 Linaro Limited
94
+ * Written by Peter Maydell
95
+ *
96
+ * This program is free software; you can redistribute it and/or modify
97
+ * it under the terms of the GNU General Public License version 2 or
98
+ * (at your option) any later version.
99
+ */
100
+
101
+/* This is a model of the SCC (Serial Communication Controller)
102
+ * found in the FPGA images of MPS2 development boards.
103
+ *
104
+ * Documentation of it can be found in the MPS2 TRM:
105
+ * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.100112_0100_03_en/index.html
106
+ * and also in the Application Notes documenting individual FPGA images.
107
+ */
108
+
109
+#include "qemu/osdep.h"
110
+#include "qemu/log.h"
111
+#include "qapi/error.h"
112
+#include "trace.h"
113
+#include "hw/sysbus.h"
114
+#include "hw/registerfields.h"
115
+#include "hw/misc/mps2-scc.h"
116
+
117
+REG32(CFG0, 0)
118
+REG32(CFG1, 4)
119
+REG32(CFG3, 0xc)
120
+REG32(CFG4, 0x10)
121
+REG32(CFGDATA_RTN, 0xa0)
122
+REG32(CFGDATA_OUT, 0xa4)
123
+REG32(CFGCTRL, 0xa8)
124
+ FIELD(CFGCTRL, DEVICE, 0, 12)
125
+ FIELD(CFGCTRL, RES1, 12, 8)
126
+ FIELD(CFGCTRL, FUNCTION, 20, 6)
127
+ FIELD(CFGCTRL, RES2, 26, 4)
128
+ FIELD(CFGCTRL, WRITE, 30, 1)
129
+ FIELD(CFGCTRL, START, 31, 1)
130
+REG32(CFGSTAT, 0xac)
131
+ FIELD(CFGSTAT, DONE, 0, 1)
132
+ FIELD(CFGSTAT, ERROR, 1, 1)
133
+REG32(DLL, 0x100)
134
+REG32(AID, 0xFF8)
135
+REG32(ID, 0xFFC)
136
+
137
+/* Handle a write via the SYS_CFG channel to the specified function/device.
138
+ * Return false on error (reported to guest via SYS_CFGCTRL ERROR bit).
139
+ */
140
+static bool scc_cfg_write(MPS2SCC *s, unsigned function,
141
+ unsigned device, uint32_t value)
142
+{
143
+ trace_mps2_scc_cfg_write(function, device, value);
144
+
145
+ if (function != 1 || device >= NUM_OSCCLK) {
146
+ qemu_log_mask(LOG_GUEST_ERROR,
147
+ "MPS2 SCC config write: bad function %d device %d\n",
148
+ function, device);
149
+ return false;
94
+ return false;
150
+ }
95
+ }
151
+
96
+
152
+ s->oscclk[device] = value;
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);
153
+ return true;
100
+ return true;
154
+}
101
+}
155
+
102
+
156
+/* Handle a read via the SYS_CFG channel to the specified function/device.
103
+static bool trans_WLS(DisasContext *s, arg_WLS *a)
157
+ * Return false on error (reported to guest via SYS_CFGCTRL ERROR bit),
158
+ * or set *value on success.
159
+ */
160
+static bool scc_cfg_read(MPS2SCC *s, unsigned function,
161
+ unsigned device, uint32_t *value)
162
+{
104
+{
163
+ if (function != 1 || device >= NUM_OSCCLK) {
105
+ /* M-profile low-overhead while-loop start */
164
+ qemu_log_mask(LOG_GUEST_ERROR,
106
+ TCGv_i32 tmp;
165
+ "MPS2 SCC config read: bad function %d device %d\n",
107
+ TCGLabel *nextlabel;
166
+ function, device);
108
+
109
+ if (!dc_isar_feature(aa32_lob, s)) {
110
+ return false;
111
+ }
112
+ if (a->rn == 13 || a->rn == 15) {
113
+ /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */
114
+ return false;
115
+ }
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)) {
167
+ return false;
150
+ return false;
168
+ }
151
+ }
169
+
152
+
170
+ *value = s->oscclk[device];
153
+ if (!a->f) {
171
+
154
+ /* Not loop-forever. If LR <= 1 this is the last loop: do nothing. */
172
+ trace_mps2_scc_cfg_read(function, device, *value);
155
+ arm_gen_condlabel(s);
156
+ tcg_gen_brcondi_i32(TCG_COND_LEU, cpu_R[14], 1, s->condlabel);
157
+ /* Decrement LR */
158
+ tmp = load_reg(s, 14);
159
+ tcg_gen_addi_i32(tmp, tmp, -1);
160
+ store_reg(s, 14, tmp);
161
+ }
162
+ /* Jump back to the loop start */
163
+ gen_jmp(s, read_pc(s) - a->imm);
173
+ return true;
164
+ return true;
174
+}
165
+}
175
+
166
+
176
+static uint64_t mps2_scc_read(void *opaque, hwaddr offset, unsigned size)
167
static bool op_tbranch(DisasContext *s, arg_tbranch *a, bool half)
177
+{
168
{
178
+ MPS2SCC *s = MPS2_SCC(opaque);
169
TCGv_i32 addr, tmp;
179
+ uint64_t r;
180
+
181
+ switch (offset) {
182
+ case A_CFG0:
183
+ r = s->cfg0;
184
+ break;
185
+ case A_CFG1:
186
+ r = s->cfg1;
187
+ break;
188
+ case A_CFG3:
189
+ /* These are user-settable DIP switches on the board. We don't
190
+ * model that, so just return zeroes.
191
+ */
192
+ r = 0;
193
+ break;
194
+ case A_CFG4:
195
+ r = s->cfg4;
196
+ break;
197
+ case A_CFGDATA_RTN:
198
+ r = s->cfgdata_rtn;
199
+ break;
200
+ case A_CFGDATA_OUT:
201
+ r = s->cfgdata_out;
202
+ break;
203
+ case A_CFGCTRL:
204
+ r = s->cfgctrl;
205
+ break;
206
+ case A_CFGSTAT:
207
+ r = s->cfgstat;
208
+ break;
209
+ case A_DLL:
210
+ r = s->dll;
211
+ break;
212
+ case A_AID:
213
+ r = s->aid;
214
+ break;
215
+ case A_ID:
216
+ r = s->id;
217
+ break;
218
+ default:
219
+ qemu_log_mask(LOG_GUEST_ERROR,
220
+ "MPS2 SCC read: bad offset %x\n", (int) offset);
221
+ r = 0;
222
+ break;
223
+ }
224
+
225
+ trace_mps2_scc_read(offset, r, size);
226
+ return r;
227
+}
228
+
229
+static void mps2_scc_write(void *opaque, hwaddr offset, uint64_t value,
230
+ unsigned size)
231
+{
232
+ MPS2SCC *s = MPS2_SCC(opaque);
233
+
234
+ trace_mps2_scc_write(offset, value, size);
235
+
236
+ switch (offset) {
237
+ case A_CFG0:
238
+ /* TODO on some boards bit 0 controls RAM remapping */
239
+ s->cfg0 = value;
240
+ break;
241
+ case A_CFG1:
242
+ /* CFG1 bits [7:0] control the board LEDs. We don't currently have
243
+ * a mechanism for displaying this graphically, so use a trace event.
244
+ */
245
+ trace_mps2_scc_leds(value & 0x80 ? '*' : '.',
246
+ value & 0x40 ? '*' : '.',
247
+ value & 0x20 ? '*' : '.',
248
+ value & 0x10 ? '*' : '.',
249
+ value & 0x08 ? '*' : '.',
250
+ value & 0x04 ? '*' : '.',
251
+ value & 0x02 ? '*' : '.',
252
+ value & 0x01 ? '*' : '.');
253
+ s->cfg1 = value;
254
+ break;
255
+ case A_CFGDATA_OUT:
256
+ s->cfgdata_out = value;
257
+ break;
258
+ case A_CFGCTRL:
259
+ /* Writing to CFGCTRL clears SYS_CFGSTAT */
260
+ s->cfgstat = 0;
261
+ s->cfgctrl = value & ~(R_CFGCTRL_RES1_MASK |
262
+ R_CFGCTRL_RES2_MASK |
263
+ R_CFGCTRL_START_MASK);
264
+
265
+ if (value & R_CFGCTRL_START_MASK) {
266
+ /* Start bit set -- do a read or write (instantaneously) */
267
+ int device = extract32(s->cfgctrl, R_CFGCTRL_DEVICE_SHIFT,
268
+ R_CFGCTRL_DEVICE_LENGTH);
269
+ int function = extract32(s->cfgctrl, R_CFGCTRL_FUNCTION_SHIFT,
270
+ R_CFGCTRL_FUNCTION_LENGTH);
271
+
272
+ s->cfgstat = R_CFGSTAT_DONE_MASK;
273
+ if (s->cfgctrl & R_CFGCTRL_WRITE_MASK) {
274
+ if (!scc_cfg_write(s, function, device, s->cfgdata_out)) {
275
+ s->cfgstat |= R_CFGSTAT_ERROR_MASK;
276
+ }
277
+ } else {
278
+ uint32_t result;
279
+ if (!scc_cfg_read(s, function, device, &result)) {
280
+ s->cfgstat |= R_CFGSTAT_ERROR_MASK;
281
+ } else {
282
+ s->cfgdata_rtn = result;
283
+ }
284
+ }
285
+ }
286
+ break;
287
+ case A_DLL:
288
+ /* DLL stands for Digital Locked Loop.
289
+ * Bits [31:24] (DLL_LOCK_MASK) are writable, and indicate a
290
+ * mask of which of the DLL_LOCKED bits [16:23] should be ORed
291
+ * together to determine the ALL_UNMASKED_DLLS_LOCKED bit [0].
292
+ * For QEMU, our DLLs are always locked, so we can leave bit 0
293
+ * as 1 always and don't need to recalculate it.
294
+ */
295
+ s->dll = deposit32(s->dll, 24, 8, extract32(value, 24, 8));
296
+ break;
297
+ default:
298
+ qemu_log_mask(LOG_GUEST_ERROR,
299
+ "MPS2 SCC write: bad offset 0x%x\n", (int) offset);
300
+ break;
301
+ }
302
+}
303
+
304
+static const MemoryRegionOps mps2_scc_ops = {
305
+ .read = mps2_scc_read,
306
+ .write = mps2_scc_write,
307
+ .endianness = DEVICE_LITTLE_ENDIAN,
308
+};
309
+
310
+static void mps2_scc_reset(DeviceState *dev)
311
+{
312
+ MPS2SCC *s = MPS2_SCC(dev);
313
+ int i;
314
+
315
+ trace_mps2_scc_reset();
316
+ s->cfg0 = 0;
317
+ s->cfg1 = 0;
318
+ s->cfgdata_rtn = 0;
319
+ s->cfgdata_out = 0;
320
+ s->cfgctrl = 0x100000;
321
+ s->cfgstat = 0;
322
+ s->dll = 0xffff0001;
323
+ for (i = 0; i < NUM_OSCCLK; i++) {
324
+ s->oscclk[i] = s->oscclk_reset[i];
325
+ }
326
+}
327
+
328
+static void mps2_scc_init(Object *obj)
329
+{
330
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
331
+ MPS2SCC *s = MPS2_SCC(obj);
332
+
333
+ memory_region_init_io(&s->iomem, obj, &mps2_scc_ops, s, "mps2-scc", 0x1000);
334
+ sysbus_init_mmio(sbd, &s->iomem);
335
+}
336
+
337
+static void mps2_scc_realize(DeviceState *dev, Error **errp)
338
+{
339
+}
340
+
341
+static const VMStateDescription mps2_scc_vmstate = {
342
+ .name = "mps2-scc",
343
+ .version_id = 1,
344
+ .minimum_version_id = 1,
345
+ .fields = (VMStateField[]) {
346
+ VMSTATE_UINT32(cfg0, MPS2SCC),
347
+ VMSTATE_UINT32(cfg1, MPS2SCC),
348
+ VMSTATE_UINT32(cfgdata_rtn, MPS2SCC),
349
+ VMSTATE_UINT32(cfgdata_out, MPS2SCC),
350
+ VMSTATE_UINT32(cfgctrl, MPS2SCC),
351
+ VMSTATE_UINT32(cfgstat, MPS2SCC),
352
+ VMSTATE_UINT32(dll, MPS2SCC),
353
+ VMSTATE_UINT32_ARRAY(oscclk, MPS2SCC, NUM_OSCCLK),
354
+ VMSTATE_END_OF_LIST()
355
+ }
356
+};
357
+
358
+static Property mps2_scc_properties[] = {
359
+ /* Values for various read-only ID registers (which are specific
360
+ * to the board model or FPGA image)
361
+ */
362
+ DEFINE_PROP_UINT32("scc-cfg4", MPS2SCC, aid, 0),
363
+ DEFINE_PROP_UINT32("scc-aid", MPS2SCC, aid, 0),
364
+ DEFINE_PROP_UINT32("scc-id", MPS2SCC, aid, 0),
365
+ /* These are the initial settings for the source clocks on the board.
366
+ * In hardware they can be configured via a config file read by the
367
+ * motherboard configuration controller to suit the FPGA image.
368
+ * These default values are used by most of the standard FPGA images.
369
+ */
370
+ DEFINE_PROP_UINT32("oscclk0", MPS2SCC, oscclk_reset[0], 50000000),
371
+ DEFINE_PROP_UINT32("oscclk1", MPS2SCC, oscclk_reset[1], 24576000),
372
+ DEFINE_PROP_UINT32("oscclk2", MPS2SCC, oscclk_reset[2], 25000000),
373
+ DEFINE_PROP_END_OF_LIST(),
374
+};
375
+
376
+static void mps2_scc_class_init(ObjectClass *klass, void *data)
377
+{
378
+ DeviceClass *dc = DEVICE_CLASS(klass);
379
+
380
+ dc->realize = mps2_scc_realize;
381
+ dc->vmsd = &mps2_scc_vmstate;
382
+ dc->reset = mps2_scc_reset;
383
+ dc->props = mps2_scc_properties;
384
+}
385
+
386
+static const TypeInfo mps2_scc_info = {
387
+ .name = TYPE_MPS2_SCC,
388
+ .parent = TYPE_SYS_BUS_DEVICE,
389
+ .instance_size = sizeof(MPS2SCC),
390
+ .instance_init = mps2_scc_init,
391
+ .class_init = mps2_scc_class_init,
392
+};
393
+
394
+static void mps2_scc_register_types(void)
395
+{
396
+ type_register_static(&mps2_scc_info);
397
+}
398
+
399
+type_init(mps2_scc_register_types);
400
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
401
index XXXXXXX..XXXXXXX 100644
402
--- a/default-configs/arm-softmmu.mak
403
+++ b/default-configs/arm-softmmu.mak
404
@@ -XXX,XX +XXX,XX @@ CONFIG_STM32F205_SOC=y
405
CONFIG_CMSDK_APB_TIMER=y
406
CONFIG_CMSDK_APB_UART=y
407
408
+CONFIG_MPS2_SCC=y
409
+
410
CONFIG_VERSATILE_PCI=y
411
CONFIG_VERSATILE_I2C=y
412
413
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
414
index XXXXXXX..XXXXXXX 100644
415
--- a/hw/misc/trace-events
416
+++ b/hw/misc/trace-events
417
@@ -XXX,XX +XXX,XX @@ milkymist_pfpu_pulse_irq(void) "Pulse IRQ"
418
419
# hw/misc/aspeed_scu.c
420
aspeed_scu_write(uint64_t offset, unsigned size, uint32_t data) "To 0x%" PRIx64 " of size %u: 0x%" PRIx32
421
+
422
+# hw/misc/mps2_scc.c
423
+mps2_scc_read(uint64_t offset, uint64_t data, unsigned size) "MPS2 SCC read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
424
+mps2_scc_write(uint64_t offset, uint64_t data, unsigned size) "MPS2 SCC write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
425
+mps2_scc_reset(void) "MPS2 SCC: reset"
426
+mps2_scc_leds(char led7, char led6, char led5, char led4, char led3, char led2, char led1, char led0) "MPS2 SCC LEDs: %c%c%c%c%c%c%c%c"
427
+mps2_scc_cfg_write(unsigned function, unsigned device, uint32_t value) "MPS2 SCC config write: function %d device %d data 0x%" PRIx32
428
+mps2_scc_cfg_read(unsigned function, unsigned device, uint32_t value) "MPS2 SCC config read: function %d device %d data 0x%" PRIx32
429
--
170
--
430
2.7.4
171
2.20.1
431
172
432
173
diff view generated by jsdifflib
1
The Cortex-M3 and M4 CPUs always have 8 PMSA MPU regions (this isn't
1
In arm_cpu_realizefn(), if the CPU has VFP or Neon disabled then we
2
a configurable option for the hardware). Make the default value of
2
squash the ID register fields so that we don't advertise it to the
3
the pmsav7-dregion property be set per-cpu, so we don't need to have
3
guest. This code was written for A-profile and needs some tweaks to
4
every user of these CPUs set it manually. (The existing default of
4
work correctly on M-profile:
5
16 is correct for the other PMSAv7 core, the Cortex-R5.)
6
5
7
This fixes a bug where we were creating the M3 and M4 with
6
* A-profile only fields should not be zeroed on M-profile:
8
too many regions; most guest software would not notice or
7
- MVFR0.FPSHVEC,FPTRAP
9
care, though, since it would just not use the registers
8
- MVFR1.SIMDLS,SIMDINT,SIMDSP,SIMDHP
10
associated with the unexpected extra regions.
9
- MVFR2.SIMDMISC
10
* M-profile only fields should be zeroed on M-profile:
11
- MVFR1.FP16
11
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>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
21
Message-id: 20201019151301.2046-9-peter.maydell@linaro.org
14
Message-id: 1499788408-10096-4-git-send-email-peter.maydell@linaro.org
15
---
22
---
16
target/arm/cpu.c | 12 +++++++++++-
23
target/arm/cpu.c | 29 ++++++++++++++++++-----------
17
1 file changed, 11 insertions(+), 1 deletion(-)
24
1 file changed, 18 insertions(+), 11 deletions(-)
18
25
19
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
20
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/cpu.c
28
--- a/target/arm/cpu.c
22
+++ b/target/arm/cpu.c
29
+++ b/target/arm/cpu.c
23
@@ -XXX,XX +XXX,XX @@ static Property arm_cpu_has_pmu_property =
30
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
24
static Property arm_cpu_has_mpu_property =
31
u = cpu->isar.mvfr0;
25
DEFINE_PROP_BOOL("has-mpu", ARMCPU, has_mpu, true);
32
u = FIELD_DP32(u, MVFR0, FPSP, 0);
26
33
u = FIELD_DP32(u, MVFR0, FPDP, 0);
27
+/* This is like DEFINE_PROP_UINT32 but it doesn't set the default value,
34
- u = FIELD_DP32(u, MVFR0, FPTRAP, 0);
28
+ * because the CPU initfn will have already set cpu->pmsav7_dregion to
35
u = FIELD_DP32(u, MVFR0, FPDIVIDE, 0);
29
+ * the right value for that particular CPU type, and we don't want
36
u = FIELD_DP32(u, MVFR0, FPSQRT, 0);
30
+ * to override that with an incorrect constant value.
37
- u = FIELD_DP32(u, MVFR0, FPSHVEC, 0);
31
+ */
38
u = FIELD_DP32(u, MVFR0, FPROUND, 0);
32
static Property arm_cpu_pmsav7_dregion_property =
39
+ if (!arm_feature(env, ARM_FEATURE_M)) {
33
- DEFINE_PROP_UINT32("pmsav7-dregion", ARMCPU, pmsav7_dregion, 16);
40
+ u = FIELD_DP32(u, MVFR0, FPTRAP, 0);
34
+ DEFINE_PROP_UNSIGNED_NODEFAULT("pmsav7-dregion", ARMCPU,
41
+ u = FIELD_DP32(u, MVFR0, FPSHVEC, 0);
35
+ pmsav7_dregion,
42
+ }
36
+ qdev_prop_uint32, uint32_t);
43
cpu->isar.mvfr0 = u;
37
44
38
static void arm_cpu_post_init(Object *obj)
45
u = cpu->isar.mvfr1;
39
{
46
u = FIELD_DP32(u, MVFR1, FPFTZ, 0);
40
@@ -XXX,XX +XXX,XX @@ static void cortex_m3_initfn(Object *obj)
47
u = FIELD_DP32(u, MVFR1, FPDNAN, 0);
41
set_feature(&cpu->env, ARM_FEATURE_V7);
48
u = FIELD_DP32(u, MVFR1, FPHP, 0);
42
set_feature(&cpu->env, ARM_FEATURE_M);
49
+ if (arm_feature(env, ARM_FEATURE_M)) {
43
cpu->midr = 0x410fc231;
50
+ u = FIELD_DP32(u, MVFR1, FP16, 0);
44
+ cpu->pmsav7_dregion = 8;
51
+ }
45
}
52
cpu->isar.mvfr1 = u;
46
53
47
static void cortex_m4_initfn(Object *obj)
54
u = cpu->isar.mvfr2;
48
@@ -XXX,XX +XXX,XX @@ static void cortex_m4_initfn(Object *obj)
55
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
49
set_feature(&cpu->env, ARM_FEATURE_M);
56
u = FIELD_DP32(u, ID_ISAR6, FHM, 0);
50
set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
57
cpu->isar.id_isar6 = u;
51
cpu->midr = 0x410fc240; /* r0p0 */
58
52
+ cpu->pmsav7_dregion = 8;
59
- u = cpu->isar.mvfr1;
53
}
60
- u = FIELD_DP32(u, MVFR1, SIMDLS, 0);
54
static void arm_v7m_class_init(ObjectClass *oc, void *data)
61
- u = FIELD_DP32(u, MVFR1, SIMDINT, 0);
55
{
62
- u = FIELD_DP32(u, MVFR1, SIMDSP, 0);
56
@@ -XXX,XX +XXX,XX @@ static void cortex_r5_initfn(Object *obj)
63
- u = FIELD_DP32(u, MVFR1, SIMDHP, 0);
57
cpu->id_isar4 = 0x0010142;
64
- cpu->isar.mvfr1 = u;
58
cpu->id_isar5 = 0x0;
65
+ if (!arm_feature(env, ARM_FEATURE_M)) {
59
cpu->mp_is_up = true;
66
+ u = cpu->isar.mvfr1;
60
+ cpu->pmsav7_dregion = 16;
67
+ u = FIELD_DP32(u, MVFR1, SIMDLS, 0);
61
define_arm_cp_regs(cpu, cortexr5_cp_reginfo);
68
+ u = FIELD_DP32(u, MVFR1, SIMDINT, 0);
62
}
69
+ u = FIELD_DP32(u, MVFR1, SIMDSP, 0);
63
70
+ u = FIELD_DP32(u, MVFR1, SIMDHP, 0);
71
+ cpu->isar.mvfr1 = u;
72
73
- u = cpu->isar.mvfr2;
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) {
64
--
83
--
65
2.7.4
84
2.20.1
66
85
67
86
diff view generated by jsdifflib
1
Add the CMSDK APB timers to the MPS2 board.
1
M-profile CPUs with half-precision floating point support should
2
be able to write to FPSCR.FZ16, but an M-profile specific masking
3
of the value at the top of vfp_set_fpscr() currently prevents that.
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.
2
20
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
22
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 1500029487-14822-6-git-send-email-peter.maydell@linaro.org
23
Message-id: 20201019151301.2046-10-peter.maydell@linaro.org
6
---
24
---
7
hw/arm/mps2.c | 4 ++++
25
target/arm/vfp_helper.c | 47 ++++++++++++++++++++++++-----------------
8
1 file changed, 4 insertions(+)
26
1 file changed, 28 insertions(+), 19 deletions(-)
9
27
10
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
28
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
11
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
12
--- a/hw/arm/mps2.c
30
--- a/target/arm/vfp_helper.c
13
+++ b/hw/arm/mps2.c
31
+++ b/target/arm/vfp_helper.c
14
@@ -XXX,XX +XXX,XX @@
32
@@ -XXX,XX +XXX,XX @@ void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
15
#include "sysemu/sysemu.h"
33
val &= ~FPCR_FZ16;
16
#include "hw/misc/unimp.h"
17
#include "hw/char/cmsdk-apb-uart.h"
18
+#include "hw/timer/cmsdk-apb-timer.h"
19
20
typedef enum MPS2FPGAType {
21
FPGA_AN385,
22
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
23
g_assert_not_reached();
24
}
34
}
25
35
26
+ cmsdk_apb_timer_create(0x40000000, qdev_get_gpio_in(armv7m, 8), SYSCLK_FRQ);
36
- if (arm_feature(env, ARM_FEATURE_M)) {
27
+ cmsdk_apb_timer_create(0x40001000, qdev_get_gpio_in(armv7m, 9), SYSCLK_FRQ);
37
+ vfp_set_fpscr_to_host(env, val);
28
+
38
+
29
system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ;
39
+ if (!arm_feature(env, ARM_FEATURE_M)) {
30
40
/*
31
armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
41
- * M profile FPSCR is RES0 for the QC, STRIDE, FZ16, LEN bits
42
- * and also for the trapped-exception-handling bits IxE.
43
+ * Short-vector length and stride; on M-profile these bits
44
+ * are used for different purposes.
45
+ * We can't make this conditional be "if MVFR0.FPShVec != 0",
46
+ * because in v7A no-short-vector-support cores still had to
47
+ * allow Stride/Len to be written with the only effect that
48
+ * some insns are required to UNDEF if the guest sets them.
49
+ *
50
+ * TODO: if M-profile MVE implemented, set LTPSIZE.
51
*/
52
- val &= 0xf7c0009f;
53
+ env->vfp.vec_len = extract32(val, 16, 3);
54
+ env->vfp.vec_stride = extract32(val, 20, 2);
55
}
56
57
- vfp_set_fpscr_to_host(env, val);
58
+ if (arm_feature(env, ARM_FEATURE_NEON)) {
59
+ /*
60
+ * The bit we set within fpscr_q is arbitrary; the register as a
61
+ * whole being zero/non-zero is what counts.
62
+ * TODO: M-profile MVE also has a QC bit.
63
+ */
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;
94
}
95
96
void vfp_set_fpscr(CPUARMState *env, uint32_t val)
32
--
97
--
33
2.7.4
98
2.20.1
34
99
35
100
diff view generated by jsdifflib
1
Add entries to the MAINTAINERS file for the new MPS2
1
If the M-profile low-overhead-branch extension is implemented, FPSCR
2
board and devices.
2
bits [18:16] are a new field LTPSIZE. If MVE is not implemented
3
(currently always true for us) then this field always reads as 4 and
4
ignores writes.
3
5
4
Since the CMSDK devices are not specific to the MPS2 board,
6
These bits used to be the vector-length field for the old
5
extend the existing 'PrimeCell' section to cover CMSDK
7
short-vector extension, so we need to take care that they are not
6
devices as well; in both cases these are devices implemented
8
misinterpreted as setting vec_len. We do this with a rearrangement
7
by ARM and provided as RTL that may be used in multiple
9
of the vfp_set_fpscr() code that deals with vec_len, vec_stride
8
SoCs and boards.
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.)
9
18
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 1500029487-14822-10-git-send-email-peter.maydell@linaro.org
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
21
Message-id: 20201019151301.2046-11-peter.maydell@linaro.org
13
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
---
22
---
15
MAINTAINERS | 14 +++++++++++++-
23
target/arm/cpu.h | 1 +
16
1 file changed, 13 insertions(+), 1 deletion(-)
24
target/arm/cpu.c | 9 +++++++++
25
target/arm/vfp_helper.c | 6 ++++++
26
3 files changed, 16 insertions(+)
17
27
18
diff --git a/MAINTAINERS b/MAINTAINERS
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/MAINTAINERS
30
--- a/target/arm/cpu.h
21
+++ b/MAINTAINERS
31
+++ b/target/arm/cpu.h
22
@@ -XXX,XX +XXX,XX @@ F: hw/*/allwinner*
32
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
23
F: include/hw/*/allwinner*
33
uint32_t fpdscr[M_REG_NUM_BANKS];
24
F: hw/arm/cubieboard.c
34
uint32_t cpacr[M_REG_NUM_BANKS];
25
35
uint32_t nsacr;
26
-ARM PrimeCell
36
+ int ltpsize;
27
+ARM PrimeCell and CMSDK devices
37
} v7m;
28
M: Peter Maydell <peter.maydell@linaro.org>
38
29
L: qemu-arm@nongnu.org
39
/* Information associated with an exception about to be taken:
30
S: Maintained
40
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
31
@@ -XXX,XX +XXX,XX @@ F: hw/intc/pl190.c
41
index XXXXXXX..XXXXXXX 100644
32
F: hw/sd/pl181.c
42
--- a/target/arm/cpu.c
33
F: hw/timer/pl031.c
43
+++ b/target/arm/cpu.c
34
F: include/hw/arm/primecell.h
44
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
35
+F: hw/timer/cmsdk-apb-timer.c
45
uint8_t *rom;
36
+F: include/hw/timer/cmsdk-apb-timer.h
46
uint32_t vecbase;
37
+F: hw/char/cmsdk-apb-uart.c
47
38
+F: include/hw/char/cmsdk-apb-uart.h
48
+ if (cpu_isar_feature(aa32_lob, cpu)) {
39
49
+ /*
40
ARM cores
50
+ * LTPSIZE is constant 4 if MVE not implemented, and resets
41
M: Peter Maydell <peter.maydell@linaro.org>
51
+ * to an UNKNOWN value if MVE is implemented. We choose to
42
@@ -XXX,XX +XXX,XX @@ S: Maintained
52
+ * always reset to 4.
43
F: hw/arm/integratorcp.c
53
+ */
44
F: hw/misc/arm_integrator_debug.c
54
+ env->v7m.ltpsize = 4;
45
55
+ }
46
+MPS2
47
+M: Peter Maydell <peter.maydell@linaro.org>
48
+L: qemu-arm@nongnu.org
49
+S: Maintained
50
+F: hw/arm/mps2.c
51
+F: hw/misc/mps2-scc.c
52
+F: include/hw/misc/mps2-scc.h
53
+
56
+
54
Musicpal
57
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
55
M: Jan Kiszka <jan.kiszka@web.de>
58
env->v7m.secure = true;
56
L: qemu-arm@nongnu.org
59
} else {
60
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/target/arm/vfp_helper.c
63
+++ b/target/arm/vfp_helper.c
64
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(vfp_get_fpscr)(CPUARMState *env)
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;
73
+
74
fpscr |= vfp_get_fpscr_from_host(env);
75
76
i = env->vfp.qc[0] | env->vfp.qc[1] | env->vfp.qc[2] | env->vfp.qc[3];
57
--
77
--
58
2.7.4
78
2.20.1
59
79
60
80
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
The kernel sets btype for the signal handler as if for a call.
4
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20201016184207.786698-2-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
linux-user/aarch64/signal.c | 10 ++++++++--
11
1 file changed, 8 insertions(+), 2 deletions(-)
12
13
diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/linux-user/aarch64/signal.c
16
+++ b/linux-user/aarch64/signal.c
17
@@ -XXX,XX +XXX,XX @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
18
+ offsetof(struct target_rt_frame_record, tramp);
19
}
20
env->xregs[0] = usig;
21
- env->xregs[31] = frame_addr;
22
env->xregs[29] = frame_addr + fr_ofs;
23
- env->pc = ka->_sa_handler;
24
env->xregs[30] = return_addr;
25
+ env->xregs[31] = frame_addr;
26
+ env->pc = ka->_sa_handler;
27
+
28
+ /* Invoke the signal handler as if by indirect call. */
29
+ if (cpu_isar_feature(aa64_bti, env_archcpu(env))) {
30
+ env->btype = 2;
31
+ }
32
+
33
if (info) {
34
tswap_siginfo(&frame->info, info);
35
env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info);
36
--
37
2.20.1
38
39
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
While an ISB will ensure any raised IRQs happen on the next
3
Transform the prot bit to a qemu internal page bit, and save
4
instruction it doesn't cause any to get raised by itself. We can
4
it in the page tables.
5
therefore use a simple tb exit for ISB instructions and rely on the
6
exit_request check at the top of each TB to deal with exiting if
7
needed.
8
5
9
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <rth@twiddle.net>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20170713141928.25419-6-alex.bennee@linaro.org
8
Message-id: 20201016184207.786698-3-richard.henderson@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
10
---
14
target/arm/translate-a64.c | 2 +-
11
include/exec/cpu-all.h | 2 ++
15
target/arm/translate.c | 4 ++--
12
linux-user/syscall_defs.h | 4 ++++
16
2 files changed, 3 insertions(+), 3 deletions(-)
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(-)
17
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
18
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
19
index XXXXXXX..XXXXXXX 100644
90
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/translate-a64.c
91
--- a/target/arm/translate-a64.c
21
+++ b/target/arm/translate-a64.c
92
+++ b/target/arm/translate-a64.c
22
@@ -XXX,XX +XXX,XX @@ static void handle_sync(DisasContext *s, uint32_t insn,
93
@@ -XXX,XX +XXX,XX @@ static void disas_data_proc_simd_fp(DisasContext *s, uint32_t insn)
23
* a self-modified code correctly and also to take
94
*/
24
* any pending interrupts immediately.
95
static bool is_guarded_page(CPUARMState *env, DisasContext *s)
25
*/
96
{
26
- s->is_jmp = DISAS_UPDATE;
97
-#ifdef CONFIG_USER_ONLY
27
+ gen_goto_tb(s, 0, s->pc);
98
- return false; /* FIXME */
28
return;
99
-#else
29
default:
100
uint64_t addr = s->base.pc_first;
30
unallocated_encoding(s);
101
+#ifdef CONFIG_USER_ONLY
31
diff --git a/target/arm/translate.c b/target/arm/translate.c
102
+ return page_get_flags(addr) & PAGE_BTI;
32
index XXXXXXX..XXXXXXX 100644
103
+#else
33
--- a/target/arm/translate.c
104
int mmu_idx = arm_to_core_mmu_idx(s->mmu_idx);
34
+++ b/target/arm/translate.c
105
unsigned int index = tlb_index(env, mmu_idx, addr);
35
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
106
CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
36
* self-modifying code correctly and also to take
37
* any pending interrupts immediately.
38
*/
39
- gen_lookup_tb(s);
40
+ gen_goto_tb(s, 0, s->pc & ~1);
41
return;
42
default:
43
goto illegal_op;
44
@@ -XXX,XX +XXX,XX @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
45
* and also to take any pending interrupts
46
* immediately.
47
*/
48
- gen_lookup_tb(s);
49
+ gen_goto_tb(s, 0, s->pc & ~1);
50
break;
51
default:
52
goto illegal_op;
53
--
107
--
54
2.7.4
108
2.20.1
55
109
56
110
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
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.
7
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20201016184207.786698-4-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
include/elf.h | 22 ++++++++++++++++++++++
14
1 file changed, 22 insertions(+)
15
16
diff --git a/include/elf.h b/include/elf.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/elf.h
19
+++ b/include/elf.h
20
@@ -XXX,XX +XXX,XX @@ typedef int64_t Elf64_Sxword;
21
#define PT_NOTE 4
22
#define PT_SHLIB 5
23
#define PT_PHDR 6
24
+#define PT_LOOS 0x60000000
25
+#define PT_HIOS 0x6fffffff
26
#define PT_LOPROC 0x70000000
27
#define PT_HIPROC 0x7fffffff
28
29
+#define PT_GNU_PROPERTY (PT_LOOS + 0x474e553)
30
+
31
#define PT_MIPS_REGINFO 0x70000000
32
#define PT_MIPS_RTPROC 0x70000001
33
#define PT_MIPS_OPTIONS 0x70000002
34
@@ -XXX,XX +XXX,XX @@ typedef struct elf64_shdr {
35
#define NT_ARM_SYSTEM_CALL 0x404 /* ARM system call number */
36
#define NT_ARM_SVE 0x405 /* ARM Scalable Vector Extension regs */
37
38
+/* Defined note types for GNU systems. */
39
+
40
+#define NT_GNU_PROPERTY_TYPE_0 5 /* Program property */
41
+
42
+/* Values used in GNU .note.gnu.property notes (NT_GNU_PROPERTY_TYPE_0). */
43
+
44
+#define GNU_PROPERTY_STACK_SIZE 1
45
+#define GNU_PROPERTY_NO_COPY_ON_PROTECTED 2
46
+
47
+#define GNU_PROPERTY_LOPROC 0xc0000000
48
+#define GNU_PROPERTY_HIPROC 0xdfffffff
49
+#define GNU_PROPERTY_LOUSER 0xe0000000
50
+#define GNU_PROPERTY_HIUSER 0xffffffff
51
+
52
+#define GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000
53
+#define GNU_PROPERTY_AARCH64_FEATURE_1_BTI (1u << 0)
54
+#define GNU_PROPERTY_AARCH64_FEATURE_1_PAC (1u << 1)
55
+
56
/*
57
* Physical entry point into the kernel.
58
*
59
--
60
2.20.1
61
62
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
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>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
linux-user/elfload.c | 8 ++++----
15
1 file changed, 4 insertions(+), 4 deletions(-)
16
17
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/linux-user/elfload.c
20
+++ b/linux-user/elfload.c
21
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
22
info->brk = vaddr_em;
23
}
24
} else if (eppnt->p_type == PT_INTERP && pinterp_name) {
25
- char *interp_name;
26
+ g_autofree char *interp_name = NULL;
27
28
if (*pinterp_name) {
29
errmsg = "Multiple PT_INTERP entries";
30
goto exit_errmsg;
31
}
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);
52
}
53
54
#ifdef USE_ELF_CORE_DUMP
55
--
56
2.20.1
57
58
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
Fixing this now will clarify following patches.
4
5
Signed-off-by: Richard Henderson <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>
9
---
10
linux-user/elfload.c | 12 +++++++++---
11
1 file changed, 9 insertions(+), 3 deletions(-)
12
13
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/linux-user/elfload.c
16
+++ b/linux-user/elfload.c
17
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
18
abi_ulong vaddr, vaddr_po, vaddr_ps, vaddr_ef, vaddr_em, vaddr_len;
19
int elf_prot = 0;
20
21
- if (eppnt->p_flags & PF_R) elf_prot = PROT_READ;
22
- if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
23
- if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
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);
36
--
37
2.20.1
38
39
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
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
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
linux-user/elfload.c | 9 +++++----
13
1 file changed, 5 insertions(+), 4 deletions(-)
14
15
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/linux-user/elfload.c
18
+++ b/linux-user/elfload.c
19
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
20
loaddr = -1, hiaddr = 0;
21
info->alignment = 0;
22
for (i = 0; i < ehdr->e_phnum; ++i) {
23
- if (phdr[i].p_type == PT_LOAD) {
24
- abi_ulong a = phdr[i].p_vaddr - phdr[i].p_offset;
25
+ struct elf_phdr *eppnt = phdr + i;
26
+ if (eppnt->p_type == PT_LOAD) {
27
+ abi_ulong a = eppnt->p_vaddr - eppnt->p_offset;
28
if (a < loaddr) {
29
loaddr = a;
30
}
31
- a = phdr[i].p_vaddr + phdr[i].p_memsz;
32
+ a = eppnt->p_vaddr + eppnt->p_memsz;
33
if (a > hiaddr) {
34
hiaddr = a;
35
}
36
++info->nsegs;
37
- info->alignment |= phdr[i].p_align;
38
+ info->alignment |= eppnt->p_align;
39
}
40
}
41
42
--
43
2.20.1
44
45
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
DISAS_UPDATE should be used when the wider CPU state other than just
3
For BTI, we need to know if the executable is static or dynamic,
4
the PC has been updated and we should therefore exit the TCG runtime
4
which means looking for PT_INTERP earlier.
5
and return to the main execution loop rather assuming DISAS_JUMP would
6
do that.
7
5
8
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Richard Henderson <rth@twiddle.net>
7
Message-id: 20201016184207.786698-8-richard.henderson@linaro.org
10
Message-id: 20170713141928.25419-3-alex.bennee@linaro.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
10
---
13
target/arm/translate-a64.c | 14 +++++++-------
11
linux-user/elfload.c | 60 +++++++++++++++++++++++---------------------
14
target/arm/translate.c | 6 +++---
12
1 file changed, 31 insertions(+), 29 deletions(-)
15
2 files changed, 10 insertions(+), 10 deletions(-)
16
13
17
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
18
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/translate-a64.c
16
--- a/linux-user/elfload.c
20
+++ b/target/arm/translate-a64.c
17
+++ b/linux-user/elfload.c
21
@@ -XXX,XX +XXX,XX @@ void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb)
18
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
22
case DISAS_NEXT:
19
23
gen_goto_tb(dc, 1, dc->pc);
20
mmap_lock();
24
break;
21
25
- default:
22
- /* Find the maximum size of the image and allocate an appropriate
26
- case DISAS_UPDATE:
23
- amount of memory to handle that. */
27
- gen_a64_set_pc_im(dc->pc);
24
+ /*
28
- /* fall through */
25
+ * Find the maximum size of the image and allocate an appropriate
29
case DISAS_JUMP:
26
+ * amount of memory to handle that. Locate the interpreter, if any.
30
tcg_gen_lookup_and_goto_ptr(cpu_pc);
27
+ */
31
break;
28
loaddr = -1, hiaddr = 0;
32
- case DISAS_EXIT:
29
info->alignment = 0;
33
- tcg_gen_exit_tb(0);
30
for (i = 0; i < ehdr->e_phnum; ++i) {
34
- break;
31
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
35
case DISAS_TB_JUMP:
32
}
36
case DISAS_EXC:
33
++info->nsegs;
37
case DISAS_SWI:
34
info->alignment |= eppnt->p_align;
38
@@ -XXX,XX +XXX,XX @@ void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb)
35
+ } else if (eppnt->p_type == PT_INTERP && pinterp_name) {
39
*/
36
+ g_autofree char *interp_name = NULL;
40
tcg_gen_exit_tb(0);
37
+
41
break;
38
+ if (*pinterp_name) {
42
+ case DISAS_UPDATE:
39
+ errmsg = "Multiple PT_INTERP entries";
43
+ gen_a64_set_pc_im(dc->pc);
40
+ goto exit_errmsg;
44
+ /* fall through */
41
+ }
45
+ case DISAS_EXIT:
42
+ interp_name = g_malloc(eppnt->p_filesz);
46
+ default:
43
+ if (!interp_name) {
47
+ tcg_gen_exit_tb(0);
44
+ goto exit_perror;
48
+ break;
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);
49
}
62
}
50
}
63
}
51
64
52
diff --git a/target/arm/translate.c b/target/arm/translate.c
65
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
53
index XXXXXXX..XXXXXXX 100644
66
if (vaddr_em > info->brk) {
54
--- a/target/arm/translate.c
67
info->brk = vaddr_em;
55
+++ b/target/arm/translate.c
68
}
56
@@ -XXX,XX +XXX,XX @@ void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
69
- } else if (eppnt->p_type == PT_INTERP && pinterp_name) {
57
case DISAS_NEXT:
70
- g_autofree char *interp_name = NULL;
58
gen_goto_tb(dc, 1, dc->pc);
71
-
59
break;
72
- if (*pinterp_name) {
60
- case DISAS_UPDATE:
73
- errmsg = "Multiple PT_INTERP entries";
61
- gen_set_pc_im(dc, dc->pc);
74
- goto exit_errmsg;
62
- /* fall through */
75
- }
63
case DISAS_JUMP:
76
- interp_name = g_malloc(eppnt->p_filesz);
64
gen_goto_ptr();
77
- if (!interp_name) {
65
break;
78
- goto exit_perror;
66
+ case DISAS_UPDATE:
79
- }
67
+ gen_set_pc_im(dc, dc->pc);
80
-
68
+ /* fall through */
81
- if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
69
default:
82
- memcpy(interp_name, bprm_buf + eppnt->p_offset,
70
/* indicate that the hash table must be used to find the next TB */
83
- eppnt->p_filesz);
71
tcg_gen_exit_tb(0);
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;
72
--
99
--
73
2.7.4
100
2.20.1
74
101
75
102
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
We already have an exit condition, DISAS_UPDATE which will exit the
3
This is a bit clearer than open-coding some of this
4
run-loop. Expand on the difference with DISAS_EXIT in the comments.
4
with a bare c string.
5
5
6
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <rth@twiddle.net>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20170713141928.25419-4-alex.bennee@linaro.org
8
Message-id: 20201016184207.786698-9-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
10
---
11
target/arm/translate.h | 5 ++++-
11
linux-user/elfload.c | 37 ++++++++++++++++++++-----------------
12
1 file changed, 4 insertions(+), 1 deletion(-)
12
1 file changed, 20 insertions(+), 17 deletions(-)
13
13
14
diff --git a/target/arm/translate.h b/target/arm/translate.h
14
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/translate.h
16
--- a/linux-user/elfload.c
17
+++ b/target/arm/translate.h
17
+++ b/linux-user/elfload.c
18
@@ -XXX,XX +XXX,XX @@ static void disas_set_insn_syndrome(DisasContext *s, uint32_t syn)
18
@@ -XXX,XX +XXX,XX @@
19
*/
19
#include "qemu/guest-random.h"
20
#define DISAS_BX_EXCRET 11
20
#include "qemu/units.h"
21
/* For instructions which want an immediate exit to the main loop,
21
#include "qemu/selfmap.h"
22
- * as opposed to attempting to use lookup_and_goto_ptr.
22
+#include "qapi/error.h"
23
+ * as opposed to attempting to use lookup_and_goto_ptr. Unlike
23
24
+ * DISAS_UPDATE this doesn't write the PC on exiting the translation
24
#ifdef _ARCH_PPC64
25
+ * loop so you need to ensure something (gen_a64_set_pc_im or runtime
25
#undef ARCH_DLINFO
26
+ * helper) has done so before we reach return from cpu_tb_exec.
26
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
27
*/
27
struct elf_phdr *phdr;
28
#define DISAS_EXIT 12
28
abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
29
int i, retval;
30
- const char *errmsg;
31
+ Error *err = NULL;
32
33
/* First of all, some simple consistency checks */
34
- errmsg = "Invalid ELF image for this architecture";
35
if (!elf_check_ident(ehdr)) {
36
+ error_setg(&err, "Invalid ELF image for this architecture");
37
goto exit_errmsg;
38
}
39
bswap_ehdr(ehdr);
40
if (!elf_check_ehdr(ehdr)) {
41
+ error_setg(&err, "Invalid ELF image for this architecture");
42
goto exit_errmsg;
43
}
44
45
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
46
g_autofree char *interp_name = NULL;
47
48
if (*pinterp_name) {
49
- errmsg = "Multiple PT_INTERP entries";
50
+ error_setg(&err, "Multiple PT_INTERP entries");
51
goto exit_errmsg;
52
}
53
+
54
interp_name = g_malloc(eppnt->p_filesz);
55
- if (!interp_name) {
56
- goto exit_perror;
57
- }
58
59
if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
60
memcpy(interp_name, bprm_buf + eppnt->p_offset,
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;
67
}
68
}
69
if (interp_name[eppnt->p_filesz - 1] != 0) {
70
- errmsg = "Invalid PT_INTERP entry";
71
+ error_setg(&err, "Invalid PT_INTERP entry");
72
goto exit_errmsg;
73
}
74
*pinterp_name = g_steal_pointer(&interp_name);
75
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
76
(ehdr->e_type == ET_EXEC ? MAP_FIXED : 0),
77
-1, 0);
78
if (load_addr == -1) {
79
- goto exit_perror;
80
+ goto exit_mmap;
81
}
82
load_bias = load_addr - loaddr;
83
84
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
85
image_fd, eppnt->p_offset - vaddr_po);
86
87
if (error == -1) {
88
- goto exit_perror;
89
+ goto exit_mmap;
90
}
91
}
92
93
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
94
} else if (eppnt->p_type == PT_MIPS_ABIFLAGS) {
95
Mips_elf_abiflags_v0 abiflags;
96
if (eppnt->p_filesz < sizeof(Mips_elf_abiflags_v0)) {
97
- errmsg = "Invalid PT_MIPS_ABIFLAGS entry";
98
+ error_setg(&err, "Invalid PT_MIPS_ABIFLAGS entry");
99
goto exit_errmsg;
100
}
101
if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
102
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
103
retval = pread(image_fd, &abiflags, sizeof(Mips_elf_abiflags_v0),
104
eppnt->p_offset);
105
if (retval != sizeof(Mips_elf_abiflags_v0)) {
106
- goto exit_perror;
107
+ goto exit_read;
108
}
109
}
110
bswap_mips_abiflags(&abiflags);
111
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
112
113
exit_read:
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
}
29
132
30
--
133
--
31
2.7.4
134
2.20.1
32
135
33
136
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
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
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20201016184207.786698-10-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
linux-user/elfload.c | 15 ++++++++-------
13
1 file changed, 8 insertions(+), 7 deletions(-)
14
15
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/linux-user/elfload.c
18
+++ b/linux-user/elfload.c
19
@@ -XXX,XX +XXX,XX @@ static void load_elf_interp(const char *filename, struct image_info *info,
20
char bprm_buf[BPRM_BUF_SIZE])
21
{
22
int fd, retval;
23
+ Error *err = NULL;
24
25
fd = open(path(filename), O_RDONLY);
26
if (fd < 0) {
27
- goto exit_perror;
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
}
40
+
41
if (retval < BPRM_BUF_SIZE) {
42
memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval);
43
}
44
45
load_elf_image(filename, fd, info, NULL, bprm_buf);
46
- return;
47
-
48
- exit_perror:
49
- fprintf(stderr, "%s: %s\n", filename, strerror(errno));
50
- exit(-1);
51
}
52
53
static int symfind(const void *s0, const void *s1)
54
--
55
2.20.1
56
57
diff view generated by jsdifflib
New patch
1
1
From: Richard Henderson <richard.henderson@linaro.org>
2
3
This is generic support, with the code disabled for all targets.
4
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20201016184207.786698-11-richard.henderson@linaro.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
linux-user/qemu.h | 4 ++
11
linux-user/elfload.c | 157 +++++++++++++++++++++++++++++++++++++++++++
12
2 files changed, 161 insertions(+)
13
14
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/linux-user/qemu.h
17
+++ b/linux-user/qemu.h
18
@@ -XXX,XX +XXX,XX @@ struct image_info {
19
abi_ulong interpreter_loadmap_addr;
20
abi_ulong interpreter_pt_dynamic_addr;
21
struct image_info *other_info;
22
+
23
+ /* For target-specific processing of NT_GNU_PROPERTY_TYPE_0. */
24
+ uint32_t note_flags;
25
+
26
#ifdef TARGET_MIPS
27
int fp_abi;
28
int interp_fp_abi;
29
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/linux-user/elfload.c
32
+++ b/linux-user/elfload.c
33
@@ -XXX,XX +XXX,XX @@ static void elf_core_copy_regs(target_elf_gregset_t *regs,
34
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
}
210
211
--
212
2.20.1
213
214
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
Use the new generic support for NT_GNU_PROPERTY_TYPE_0.
4
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20201016184207.786698-12-richard.henderson@linaro.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
linux-user/elfload.c | 48 ++++++++++++++++++++++++++++++++++++++++++--
11
1 file changed, 46 insertions(+), 2 deletions(-)
12
13
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/linux-user/elfload.c
16
+++ b/linux-user/elfload.c
17
@@ -XXX,XX +XXX,XX @@ static void elf_core_copy_regs(target_elf_gregset_t *regs,
18
19
#include "elf.h"
20
21
+/* We must delay the following stanzas until after "elf.h". */
22
+#if defined(TARGET_AARCH64)
23
+
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;
100
--
101
2.20.1
102
103
diff view generated by jsdifflib
1
Implement a model of the simple "APB UART" provided in
1
From: Richard Henderson <richard.henderson@linaro.org>
2
the Cortex-M System Design Kit (CMSDK).
2
3
3
The note test requires gcc 10 for -mbranch-protection=standard.
4
The mmap test uses PROT_BTI and does not require special compiler support.
5
6
Acked-by: Alex Bennée <alex.bennee@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20201016184207.786698-13-richard.henderson@linaro.org
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Message-id: 1500029487-14822-3-git-send-email-peter.maydell@linaro.org
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
---
11
---
8
hw/char/Makefile.objs | 1 +
12
tests/tcg/aarch64/bti-1.c | 62 +++++++++++++++++
9
include/hw/char/cmsdk-apb-uart.h | 78 ++++++++
13
tests/tcg/aarch64/bti-2.c | 108 ++++++++++++++++++++++++++++++
10
hw/char/cmsdk-apb-uart.c | 403 +++++++++++++++++++++++++++++++++++++++
14
tests/tcg/aarch64/bti-crt.inc.c | 51 ++++++++++++++
11
default-configs/arm-softmmu.mak | 2 +
15
tests/tcg/aarch64/Makefile.target | 10 +++
12
hw/char/trace-events | 9 +
16
tests/tcg/configure.sh | 4 ++
13
5 files changed, 493 insertions(+)
17
5 files changed, 235 insertions(+)
14
create mode 100644 include/hw/char/cmsdk-apb-uart.h
18
create mode 100644 tests/tcg/aarch64/bti-1.c
15
create mode 100644 hw/char/cmsdk-apb-uart.c
19
create mode 100644 tests/tcg/aarch64/bti-2.c
16
20
create mode 100644 tests/tcg/aarch64/bti-crt.inc.c
17
diff --git a/hw/char/Makefile.objs b/hw/char/Makefile.objs
21
18
index XXXXXXX..XXXXXXX 100644
22
diff --git a/tests/tcg/aarch64/bti-1.c b/tests/tcg/aarch64/bti-1.c
19
--- a/hw/char/Makefile.objs
20
+++ b/hw/char/Makefile.objs
21
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_DIGIC) += digic-uart.o
22
obj-$(CONFIG_STM32F2XX_USART) += stm32f2xx_usart.o
23
obj-$(CONFIG_RASPI) += bcm2835_aux.o
24
25
+common-obj-$(CONFIG_CMSDK_APB_UART) += cmsdk-apb-uart.o
26
common-obj-$(CONFIG_ETRAXFS) += etraxfs_ser.o
27
common-obj-$(CONFIG_ISA_DEBUG) += debugcon.o
28
common-obj-$(CONFIG_GRLIB) += grlib_apbuart.o
29
diff --git a/include/hw/char/cmsdk-apb-uart.h b/include/hw/char/cmsdk-apb-uart.h
30
new file mode 100644
23
new file mode 100644
31
index XXXXXXX..XXXXXXX
24
index XXXXXXX..XXXXXXX
32
--- /dev/null
25
--- /dev/null
33
+++ b/include/hw/char/cmsdk-apb-uart.h
26
+++ b/tests/tcg/aarch64/bti-1.c
34
@@ -XXX,XX +XXX,XX @@
27
@@ -XXX,XX +XXX,XX @@
35
+/*
28
+/*
36
+ * ARM CMSDK APB UART emulation
29
+ * Branch target identification, basic notskip cases.
37
+ *
38
+ * Copyright (c) 2017 Linaro Limited
39
+ * Written by Peter Maydell
40
+ *
41
+ * This program is free software; you can redistribute it and/or modify
42
+ * it under the terms of the GNU General Public License version 2 or
43
+ * (at your option) any later version.
44
+ */
30
+ */
45
+
31
+
46
+#ifndef CMSDK_APB_UART_H
32
+#include "bti-crt.inc.c"
47
+#define CMSDK_APB_UART_H
33
+
48
+
34
+static void skip2_sigill(int sig, siginfo_t *info, ucontext_t *uc)
49
+#include "hw/sysbus.h"
35
+{
50
+#include "chardev/char-fe.h"
36
+ uc->uc_mcontext.pc += 8;
51
+
37
+ uc->uc_mcontext.pstate = 1;
52
+#define TYPE_CMSDK_APB_UART "cmsdk-apb-uart"
38
+}
53
+#define CMSDK_APB_UART(obj) OBJECT_CHECK(CMSDKAPBUART, (obj), \
39
+
54
+ TYPE_CMSDK_APB_UART)
40
+#define NOP "nop"
55
+
41
+#define BTI_N "hint #32"
56
+typedef struct {
42
+#define BTI_C "hint #34"
57
+ /*< private >*/
43
+#define BTI_J "hint #36"
58
+ SysBusDevice parent_obj;
44
+#define BTI_JC "hint #38"
59
+
45
+
60
+ /*< public >*/
46
+#define BTYPE_1(DEST) \
61
+ MemoryRegion iomem;
47
+ asm("mov %0,#1; adr x16, 1f; br x16; 1: " DEST "; mov %0,#0" \
62
+ CharBackend chr;
48
+ : "=r"(skipped) : : "x16")
63
+ qemu_irq txint;
49
+
64
+ qemu_irq rxint;
50
+#define BTYPE_2(DEST) \
65
+ qemu_irq txovrint;
51
+ asm("mov %0,#1; adr x16, 1f; blr x16; 1: " DEST "; mov %0,#0" \
66
+ qemu_irq rxovrint;
52
+ : "=r"(skipped) : : "x16", "x30")
67
+ qemu_irq uartint;
53
+
68
+ guint watch_tag;
54
+#define BTYPE_3(DEST) \
69
+ uint32_t pclk_frq;
55
+ asm("mov %0,#1; adr x15, 1f; br x15; 1: " DEST "; mov %0,#0" \
70
+
56
+ : "=r"(skipped) : : "x15")
71
+ uint32_t state;
57
+
72
+ uint32_t ctrl;
58
+#define TEST(WHICH, DEST, EXPECT) \
73
+ uint32_t intstatus;
59
+ do { WHICH(DEST); fail += skipped ^ EXPECT; } while (0)
74
+ uint32_t bauddiv;
60
+
75
+ /* This UART has no FIFO, only a 1-character buffer for each of Tx and Rx */
61
+
76
+ uint8_t txbuf;
62
+int main()
77
+ uint8_t rxbuf;
63
+{
78
+} CMSDKAPBUART;
64
+ int fail = 0;
79
+
65
+ int skipped;
80
+/**
66
+
81
+ * cmsdk_apb_uart_create - convenience function to create TYPE_CMSDK_APB_UART
67
+ /* Signal-like with SA_SIGINFO. */
82
+ * @addr: location in system memory to map registers
68
+ signal_info(SIGILL, skip2_sigill);
83
+ * @chr: Chardev backend to connect UART to, or NULL if no backend
69
+
84
+ * @pclk_frq: frequency in Hz of the PCLK clock (used for calculating baud rate)
70
+ TEST(BTYPE_1, NOP, 1);
85
+ */
71
+ TEST(BTYPE_1, BTI_N, 1);
86
+static inline DeviceState *cmsdk_apb_uart_create(hwaddr addr,
72
+ TEST(BTYPE_1, BTI_C, 0);
87
+ qemu_irq txint,
73
+ TEST(BTYPE_1, BTI_J, 0);
88
+ qemu_irq rxint,
74
+ TEST(BTYPE_1, BTI_JC, 0);
89
+ qemu_irq txovrint,
75
+
90
+ qemu_irq rxovrint,
76
+ TEST(BTYPE_2, NOP, 1);
91
+ qemu_irq uartint,
77
+ TEST(BTYPE_2, BTI_N, 1);
92
+ Chardev *chr,
78
+ TEST(BTYPE_2, BTI_C, 0);
93
+ uint32_t pclk_frq)
79
+ TEST(BTYPE_2, BTI_J, 1);
94
+{
80
+ TEST(BTYPE_2, BTI_JC, 0);
95
+ DeviceState *dev;
81
+
96
+ SysBusDevice *s;
82
+ TEST(BTYPE_3, NOP, 1);
97
+
83
+ TEST(BTYPE_3, BTI_N, 1);
98
+ dev = qdev_create(NULL, TYPE_CMSDK_APB_UART);
84
+ TEST(BTYPE_3, BTI_C, 1);
99
+ s = SYS_BUS_DEVICE(dev);
85
+ TEST(BTYPE_3, BTI_J, 0);
100
+ qdev_prop_set_chr(dev, "chardev", chr);
86
+ TEST(BTYPE_3, BTI_JC, 0);
101
+ qdev_prop_set_uint32(dev, "pclk-frq", pclk_frq);
87
+
102
+ qdev_init_nofail(dev);
88
+ return fail;
103
+ sysbus_mmio_map(s, 0, addr);
89
+}
104
+ sysbus_connect_irq(s, 0, txint);
90
diff --git a/tests/tcg/aarch64/bti-2.c b/tests/tcg/aarch64/bti-2.c
105
+ sysbus_connect_irq(s, 1, rxint);
106
+ sysbus_connect_irq(s, 2, txovrint);
107
+ sysbus_connect_irq(s, 3, rxovrint);
108
+ sysbus_connect_irq(s, 4, uartint);
109
+ return dev;
110
+}
111
+
112
+#endif
113
diff --git a/hw/char/cmsdk-apb-uart.c b/hw/char/cmsdk-apb-uart.c
114
new file mode 100644
91
new file mode 100644
115
index XXXXXXX..XXXXXXX
92
index XXXXXXX..XXXXXXX
116
--- /dev/null
93
--- /dev/null
117
+++ b/hw/char/cmsdk-apb-uart.c
94
+++ b/tests/tcg/aarch64/bti-2.c
118
@@ -XXX,XX +XXX,XX @@
95
@@ -XXX,XX +XXX,XX @@
119
+/*
96
+/*
120
+ * ARM CMSDK APB UART emulation
97
+ * Branch target identification, basic notskip cases.
121
+ *
122
+ * Copyright (c) 2017 Linaro Limited
123
+ * Written by Peter Maydell
124
+ *
125
+ * This program is free software; you can redistribute it and/or modify
126
+ * it under the terms of the GNU General Public License version 2 or
127
+ * (at your option) any later version.
128
+ */
98
+ */
129
+
99
+
130
+/* This is a model of the "APB UART" which is part of the Cortex-M
100
+#include <stdio.h>
131
+ * System Design Kit (CMSDK) and documented in the Cortex-M System
101
+#include <signal.h>
132
+ * Design Kit Technical Reference Manual (ARM DDI0479C):
102
+#include <string.h>
133
+ * https://developer.arm.com/products/system-design/system-design-kits/cortex-m-system-design-kit
103
+#include <unistd.h>
134
+ */
104
+#include <sys/mman.h>
135
+
105
+
136
+#include "qemu/osdep.h"
106
+#ifndef PROT_BTI
137
+#include "qemu/log.h"
107
+#define PROT_BTI 0x10
138
+#include "qapi/error.h"
108
+#endif
139
+#include "trace.h"
109
+
140
+#include "hw/sysbus.h"
110
+static void skip2_sigill(int sig, siginfo_t *info, void *vuc)
141
+#include "hw/registerfields.h"
111
+{
142
+#include "chardev/char-fe.h"
112
+ ucontext_t *uc = vuc;
143
+#include "chardev/char-serial.h"
113
+ uc->uc_mcontext.pc += 8;
144
+#include "hw/char/cmsdk-apb-uart.h"
114
+ uc->uc_mcontext.pstate = 1;
145
+
115
+}
146
+REG32(DATA, 0)
116
+
147
+REG32(STATE, 4)
117
+#define NOP "nop"
148
+ FIELD(STATE, TXFULL, 0, 1)
118
+#define BTI_N "hint #32"
149
+ FIELD(STATE, RXFULL, 1, 1)
119
+#define BTI_C "hint #34"
150
+ FIELD(STATE, TXOVERRUN, 2, 1)
120
+#define BTI_J "hint #36"
151
+ FIELD(STATE, RXOVERRUN, 3, 1)
121
+#define BTI_JC "hint #38"
152
+REG32(CTRL, 8)
122
+
153
+ FIELD(CTRL, TX_EN, 0, 1)
123
+#define BTYPE_1(DEST) \
154
+ FIELD(CTRL, RX_EN, 1, 1)
124
+ "mov x1, #1\n\t" \
155
+ FIELD(CTRL, TX_INTEN, 2, 1)
125
+ "adr x16, 1f\n\t" \
156
+ FIELD(CTRL, RX_INTEN, 3, 1)
126
+ "br x16\n" \
157
+ FIELD(CTRL, TXO_INTEN, 4, 1)
127
+"1: " DEST "\n\t" \
158
+ FIELD(CTRL, RXO_INTEN, 5, 1)
128
+ "mov x1, #0"
159
+ FIELD(CTRL, HSTEST, 6, 1)
129
+
160
+REG32(INTSTATUS, 0xc)
130
+#define BTYPE_2(DEST) \
161
+ FIELD(INTSTATUS, TX, 0, 1)
131
+ "mov x1, #1\n\t" \
162
+ FIELD(INTSTATUS, RX, 1, 1)
132
+ "adr x16, 1f\n\t" \
163
+ FIELD(INTSTATUS, TXO, 2, 1)
133
+ "blr x16\n" \
164
+ FIELD(INTSTATUS, RXO, 3, 1)
134
+"1: " DEST "\n\t" \
165
+REG32(BAUDDIV, 0x10)
135
+ "mov x1, #0"
166
+REG32(PID4, 0xFD0)
136
+
167
+REG32(PID5, 0xFD4)
137
+#define BTYPE_3(DEST) \
168
+REG32(PID6, 0xFD8)
138
+ "mov x1, #1\n\t" \
169
+REG32(PID7, 0xFDC)
139
+ "adr x15, 1f\n\t" \
170
+REG32(PID0, 0xFE0)
140
+ "br x15\n" \
171
+REG32(PID1, 0xFE4)
141
+"1: " DEST "\n\t" \
172
+REG32(PID2, 0xFE8)
142
+ "mov x1, #0"
173
+REG32(PID3, 0xFEC)
143
+
174
+REG32(CID0, 0xFF0)
144
+#define TEST(WHICH, DEST, EXPECT) \
175
+REG32(CID1, 0xFF4)
145
+ WHICH(DEST) "\n" \
176
+REG32(CID2, 0xFF8)
146
+ ".if " #EXPECT "\n\t" \
177
+REG32(CID3, 0xFFC)
147
+ "eor x1, x1," #EXPECT "\n" \
178
+
148
+ ".endif\n\t" \
179
+/* PID/CID values */
149
+ "add x0, x0, x1\n\t"
180
+static const int uart_id[] = {
150
+
181
+ 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
151
+extern char test_begin[], test_end[];
182
+ 0x21, 0xb8, 0x1b, 0x00, /* PID0..PID3 */
152
+
183
+ 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
153
+asm("\n"
184
+};
154
+"test_begin:\n\t"
185
+
155
+ BTI_C "\n\t"
186
+static bool uart_baudrate_ok(CMSDKAPBUART *s)
156
+ "mov x2, x30\n\t"
187
+{
157
+ "mov x0, #0\n\t"
188
+ /* The minimum permitted bauddiv setting is 16, so we just ignore
158
+
189
+ * settings below that (usually this means the device has just
159
+ TEST(BTYPE_1, NOP, 1)
190
+ * been reset and not yet programmed).
160
+ TEST(BTYPE_1, BTI_N, 1)
191
+ */
161
+ TEST(BTYPE_1, BTI_C, 0)
192
+ return s->bauddiv >= 16 && s->bauddiv <= s->pclk_frq;
162
+ TEST(BTYPE_1, BTI_J, 0)
193
+}
163
+ TEST(BTYPE_1, BTI_JC, 0)
194
+
164
+
195
+static void uart_update_parameters(CMSDKAPBUART *s)
165
+ TEST(BTYPE_2, NOP, 1)
196
+{
166
+ TEST(BTYPE_2, BTI_N, 1)
197
+ QEMUSerialSetParams ssp;
167
+ TEST(BTYPE_2, BTI_C, 0)
198
+
168
+ TEST(BTYPE_2, BTI_J, 1)
199
+ /* This UART is always 8N1 but the baud rate is programmable. */
169
+ TEST(BTYPE_2, BTI_JC, 0)
200
+ if (!uart_baudrate_ok(s)) {
170
+
201
+ return;
171
+ TEST(BTYPE_3, NOP, 1)
202
+ }
172
+ TEST(BTYPE_3, BTI_N, 1)
203
+
173
+ TEST(BTYPE_3, BTI_C, 1)
204
+ ssp.data_bits = 8;
174
+ TEST(BTYPE_3, BTI_J, 0)
205
+ ssp.parity = 'N';
175
+ TEST(BTYPE_3, BTI_JC, 0)
206
+ ssp.stop_bits = 1;
176
+
207
+ ssp.speed = s->pclk_frq / s->bauddiv;
177
+ "ret x2\n"
208
+ qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
178
+"test_end:"
209
+ trace_cmsdk_apb_uart_set_params(ssp.speed);
179
+);
210
+}
180
+
211
+
181
+int main()
212
+static void cmsdk_apb_uart_update(CMSDKAPBUART *s)
182
+{
213
+{
183
+ struct sigaction sa;
214
+ /* update outbound irqs, including handling the way the rxo and txo
184
+
215
+ * interrupt status bits are just logical AND of the overrun bit in
185
+ void *p = mmap(0, getpagesize(),
216
+ * STATE and the overrun interrupt enable bit in CTRL.
186
+ PROT_EXEC | PROT_READ | PROT_WRITE | PROT_BTI,
217
+ */
187
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
218
+ uint32_t omask = (R_INTSTATUS_RXO_MASK | R_INTSTATUS_TXO_MASK);
188
+ if (p == MAP_FAILED) {
219
+ s->intstatus &= ~omask;
189
+ perror("mmap");
220
+ s->intstatus |= (s->state & (s->ctrl >> 2) & omask);
221
+
222
+ qemu_set_irq(s->txint, !!(s->intstatus & R_INTSTATUS_TX_MASK));
223
+ qemu_set_irq(s->rxint, !!(s->intstatus & R_INTSTATUS_RX_MASK));
224
+ qemu_set_irq(s->txovrint, !!(s->intstatus & R_INTSTATUS_TXO_MASK));
225
+ qemu_set_irq(s->rxovrint, !!(s->intstatus & R_INTSTATUS_RXO_MASK));
226
+ qemu_set_irq(s->uartint, !!(s->intstatus));
227
+}
228
+
229
+static int uart_can_receive(void *opaque)
230
+{
231
+ CMSDKAPBUART *s = CMSDK_APB_UART(opaque);
232
+
233
+ /* We can take a char if RX is enabled and the buffer is empty */
234
+ if (s->ctrl & R_CTRL_RX_EN_MASK && !(s->state & R_STATE_RXFULL_MASK)) {
235
+ return 1;
190
+ return 1;
236
+ }
191
+ }
237
+ return 0;
192
+
238
+}
193
+ memset(&sa, 0, sizeof(sa));
239
+
194
+ sa.sa_sigaction = skip2_sigill;
240
+static void uart_receive(void *opaque, const uint8_t *buf, int size)
195
+ sa.sa_flags = SA_SIGINFO;
241
+{
196
+ if (sigaction(SIGILL, &sa, NULL) < 0) {
242
+ CMSDKAPBUART *s = CMSDK_APB_UART(opaque);
197
+ perror("sigaction");
243
+
198
+ return 1;
244
+ trace_cmsdk_apb_uart_receive(*buf);
245
+
246
+ /* In fact uart_can_receive() ensures that we can't be
247
+ * called unless RX is enabled and the buffer is empty,
248
+ * but we include this logic as documentation of what the
249
+ * hardware does if a character arrives in these circumstances.
250
+ */
251
+ if (!(s->ctrl & R_CTRL_RX_EN_MASK)) {
252
+ /* Just drop the character on the floor */
253
+ return;
254
+ }
199
+ }
255
+
200
+
256
+ if (s->state & R_STATE_RXFULL_MASK) {
201
+ memcpy(p, test_begin, test_end - test_begin);
257
+ s->state |= R_STATE_RXOVERRUN_MASK;
202
+ return ((int (*)(void))p)();
258
+ }
203
+}
259
+
204
diff --git a/tests/tcg/aarch64/bti-crt.inc.c b/tests/tcg/aarch64/bti-crt.inc.c
260
+ s->rxbuf = *buf;
205
new file mode 100644
261
+ s->state |= R_STATE_RXFULL_MASK;
206
index XXXXXXX..XXXXXXX
262
+ if (s->ctrl & R_CTRL_RX_INTEN_MASK) {
207
--- /dev/null
263
+ s->intstatus |= R_INTSTATUS_RX_MASK;
208
+++ b/tests/tcg/aarch64/bti-crt.inc.c
264
+ }
209
@@ -XXX,XX +XXX,XX @@
265
+ cmsdk_apb_uart_update(s);
210
+/*
266
+}
211
+ * Minimal user-environment for testing BTI.
267
+
212
+ *
268
+static uint64_t uart_read(void *opaque, hwaddr offset, unsigned size)
213
+ * Normal libc is not (yet) built with BTI support enabled,
269
+{
214
+ * and so could generate a BTI TRAP before ever reaching main.
270
+ CMSDKAPBUART *s = CMSDK_APB_UART(opaque);
271
+ uint64_t r;
272
+
273
+ switch (offset) {
274
+ case A_DATA:
275
+ r = s->rxbuf;
276
+ s->state &= ~R_STATE_RXFULL_MASK;
277
+ cmsdk_apb_uart_update(s);
278
+ break;
279
+ case A_STATE:
280
+ r = s->state;
281
+ break;
282
+ case A_CTRL:
283
+ r = s->ctrl;
284
+ break;
285
+ case A_INTSTATUS:
286
+ r = s->intstatus;
287
+ break;
288
+ case A_BAUDDIV:
289
+ r = s->bauddiv;
290
+ break;
291
+ case A_PID4 ... A_CID3:
292
+ r = uart_id[(offset - A_PID4) / 4];
293
+ break;
294
+ default:
295
+ qemu_log_mask(LOG_GUEST_ERROR,
296
+ "CMSDK APB UART read: bad offset %x\n", (int) offset);
297
+ r = 0;
298
+ break;
299
+ }
300
+ trace_cmsdk_apb_uart_read(offset, r, size);
301
+ return r;
302
+}
303
+
304
+/* Try to send tx data, and arrange to be called back later if
305
+ * we can't (ie the char backend is busy/blocking).
306
+ */
215
+ */
307
+static gboolean uart_transmit(GIOChannel *chan, GIOCondition cond, void *opaque)
216
+
308
+{
217
+#include <stdlib.h>
309
+ CMSDKAPBUART *s = CMSDK_APB_UART(opaque);
218
+#include <signal.h>
310
+ int ret;
219
+#include <ucontext.h>
311
+
220
+#include <asm/unistd.h>
312
+ s->watch_tag = 0;
221
+
313
+
222
+int main(void);
314
+ if (!(s->ctrl & R_CTRL_TX_EN_MASK) || !(s->state & R_STATE_TXFULL_MASK)) {
223
+
315
+ return FALSE;
224
+void _start(void)
316
+ }
225
+{
317
+
226
+ exit(main());
318
+ ret = qemu_chr_fe_write(&s->chr, &s->txbuf, 1);
227
+}
319
+ if (ret <= 0) {
228
+
320
+ s->watch_tag = qemu_chr_fe_add_watch(&s->chr, G_IO_OUT | G_IO_HUP,
229
+void exit(int ret)
321
+ uart_transmit, s);
230
+{
322
+ if (!s->watch_tag) {
231
+ register int x0 __asm__("x0") = ret;
323
+ /* Most common reason to be here is "no chardev backend":
232
+ register int x8 __asm__("x8") = __NR_exit;
324
+ * just insta-drain the buffer, so the serial output
233
+
325
+ * goes into a void, rather than blocking the guest.
234
+ asm volatile("svc #0" : : "r"(x0), "r"(x8));
326
+ */
235
+ __builtin_unreachable();
327
+ goto buffer_drained;
236
+}
328
+ }
237
+
329
+ /* Transmit pending */
238
+/*
330
+ trace_cmsdk_apb_uart_tx_pending();
239
+ * Irritatingly, the user API struct sigaction does not match the
331
+ return FALSE;
240
+ * kernel API struct sigaction. So for simplicity, isolate the
332
+ }
241
+ * kernel ABI here, and make this act like signal.
333
+
242
+ */
334
+buffer_drained:
243
+void signal_info(int sig, void (*fn)(int, siginfo_t *, ucontext_t *))
335
+ /* Character successfully sent */
244
+{
336
+ trace_cmsdk_apb_uart_tx(s->txbuf);
245
+ struct kernel_sigaction {
337
+ s->state &= ~R_STATE_TXFULL_MASK;
246
+ void (*handler)(int, siginfo_t *, ucontext_t *);
338
+ /* Going from TXFULL set to clear triggers the tx interrupt */
247
+ unsigned long flags;
339
+ if (s->ctrl & R_CTRL_TX_INTEN_MASK) {
248
+ unsigned long restorer;
340
+ s->intstatus |= R_INTSTATUS_TX_MASK;
249
+ unsigned long mask;
341
+ }
250
+ } sa = { fn, SA_SIGINFO, 0, 0 };
342
+ cmsdk_apb_uart_update(s);
251
+
343
+ return FALSE;
252
+ register int x0 __asm__("x0") = sig;
344
+}
253
+ register void *x1 __asm__("x1") = &sa;
345
+
254
+ register void *x2 __asm__("x2") = 0;
346
+static void uart_cancel_transmit(CMSDKAPBUART *s)
255
+ register int x3 __asm__("x3") = sizeof(unsigned long);
347
+{
256
+ register int x8 __asm__("x8") = __NR_rt_sigaction;
348
+ if (s->watch_tag) {
257
+
349
+ g_source_remove(s->watch_tag);
258
+ asm volatile("svc #0"
350
+ s->watch_tag = 0;
259
+ : : "r"(x0), "r"(x1), "r"(x2), "r"(x3), "r"(x8) : "memory");
351
+ }
260
+}
352
+}
261
diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
353
+
354
+static void uart_write(void *opaque, hwaddr offset, uint64_t value,
355
+ unsigned size)
356
+{
357
+ CMSDKAPBUART *s = CMSDK_APB_UART(opaque);
358
+
359
+ trace_cmsdk_apb_uart_write(offset, value, size);
360
+
361
+ switch (offset) {
362
+ case A_DATA:
363
+ s->txbuf = value;
364
+ if (s->state & R_STATE_TXFULL_MASK) {
365
+ /* Buffer already full -- note the overrun and let the
366
+ * existing pending transmit callback handle the new char.
367
+ */
368
+ s->state |= R_STATE_TXOVERRUN_MASK;
369
+ cmsdk_apb_uart_update(s);
370
+ } else {
371
+ s->state |= R_STATE_TXFULL_MASK;
372
+ uart_transmit(NULL, G_IO_OUT, s);
373
+ }
374
+ break;
375
+ case A_STATE:
376
+ /* Bits 0 and 1 are read only; bits 2 and 3 are W1C */
377
+ s->state &= ~(value &
378
+ (R_STATE_TXOVERRUN_MASK | R_STATE_RXOVERRUN_MASK));
379
+ cmsdk_apb_uart_update(s);
380
+ break;
381
+ case A_CTRL:
382
+ s->ctrl = value & 0x7f;
383
+ if ((s->ctrl & R_CTRL_TX_EN_MASK) && !uart_baudrate_ok(s)) {
384
+ qemu_log_mask(LOG_GUEST_ERROR,
385
+ "CMSDK APB UART: Tx enabled with invalid baudrate\n");
386
+ }
387
+ cmsdk_apb_uart_update(s);
388
+ break;
389
+ case A_INTSTATUS:
390
+ /* All bits are W1C. Clearing the overrun interrupt bits really
391
+ * clears the overrun status bits in the STATE register (which
392
+ * is then reflected into the intstatus value by the update function).
393
+ */
394
+ s->state &= ~(value & (R_INTSTATUS_TXO_MASK | R_INTSTATUS_RXO_MASK));
395
+ cmsdk_apb_uart_update(s);
396
+ break;
397
+ case A_BAUDDIV:
398
+ s->bauddiv = value & 0xFFFFF;
399
+ uart_update_parameters(s);
400
+ break;
401
+ case A_PID4 ... A_CID3:
402
+ qemu_log_mask(LOG_GUEST_ERROR,
403
+ "CMSDK APB UART write: write to RO offset 0x%x\n",
404
+ (int)offset);
405
+ break;
406
+ default:
407
+ qemu_log_mask(LOG_GUEST_ERROR,
408
+ "CMSDK APB UART write: bad offset 0x%x\n", (int) offset);
409
+ break;
410
+ }
411
+}
412
+
413
+static const MemoryRegionOps uart_ops = {
414
+ .read = uart_read,
415
+ .write = uart_write,
416
+ .endianness = DEVICE_LITTLE_ENDIAN,
417
+};
418
+
419
+static void cmsdk_apb_uart_reset(DeviceState *dev)
420
+{
421
+ CMSDKAPBUART *s = CMSDK_APB_UART(dev);
422
+
423
+ trace_cmsdk_apb_uart_reset();
424
+ uart_cancel_transmit(s);
425
+ s->state = 0;
426
+ s->ctrl = 0;
427
+ s->intstatus = 0;
428
+ s->bauddiv = 0;
429
+ s->txbuf = 0;
430
+ s->rxbuf = 0;
431
+}
432
+
433
+static void cmsdk_apb_uart_init(Object *obj)
434
+{
435
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
436
+ CMSDKAPBUART *s = CMSDK_APB_UART(obj);
437
+
438
+ memory_region_init_io(&s->iomem, obj, &uart_ops, s, "uart", 0x1000);
439
+ sysbus_init_mmio(sbd, &s->iomem);
440
+ sysbus_init_irq(sbd, &s->txint);
441
+ sysbus_init_irq(sbd, &s->rxint);
442
+ sysbus_init_irq(sbd, &s->txovrint);
443
+ sysbus_init_irq(sbd, &s->rxovrint);
444
+ sysbus_init_irq(sbd, &s->uartint);
445
+}
446
+
447
+static void cmsdk_apb_uart_realize(DeviceState *dev, Error **errp)
448
+{
449
+ CMSDKAPBUART *s = CMSDK_APB_UART(dev);
450
+
451
+ if (s->pclk_frq == 0) {
452
+ error_setg(errp, "CMSDK APB UART: pclk-frq property must be set");
453
+ return;
454
+ }
455
+
456
+ /* This UART has no flow control, so we do not need to register
457
+ * an event handler to deal with CHR_EVENT_BREAK.
458
+ */
459
+ qemu_chr_fe_set_handlers(&s->chr, uart_can_receive, uart_receive,
460
+ NULL, s, NULL, true);
461
+}
462
+
463
+static int cmsdk_apb_uart_post_load(void *opaque, int version_id)
464
+{
465
+ CMSDKAPBUART *s = CMSDK_APB_UART(opaque);
466
+
467
+ /* If we have a pending character, arrange to resend it. */
468
+ if (s->state & R_STATE_TXFULL_MASK) {
469
+ s->watch_tag = qemu_chr_fe_add_watch(&s->chr, G_IO_OUT | G_IO_HUP,
470
+ uart_transmit, s);
471
+ }
472
+ uart_update_parameters(s);
473
+ return 0;
474
+}
475
+
476
+static const VMStateDescription cmsdk_apb_uart_vmstate = {
477
+ .name = "cmsdk-apb-uart",
478
+ .version_id = 1,
479
+ .minimum_version_id = 1,
480
+ .post_load = cmsdk_apb_uart_post_load,
481
+ .fields = (VMStateField[]) {
482
+ VMSTATE_UINT32(state, CMSDKAPBUART),
483
+ VMSTATE_UINT32(ctrl, CMSDKAPBUART),
484
+ VMSTATE_UINT32(intstatus, CMSDKAPBUART),
485
+ VMSTATE_UINT32(bauddiv, CMSDKAPBUART),
486
+ VMSTATE_UINT8(txbuf, CMSDKAPBUART),
487
+ VMSTATE_UINT8(rxbuf, CMSDKAPBUART),
488
+ VMSTATE_END_OF_LIST()
489
+ }
490
+};
491
+
492
+static Property cmsdk_apb_uart_properties[] = {
493
+ DEFINE_PROP_CHR("chardev", CMSDKAPBUART, chr),
494
+ DEFINE_PROP_UINT32("pclk-frq", CMSDKAPBUART, pclk_frq, 0),
495
+ DEFINE_PROP_END_OF_LIST(),
496
+};
497
+
498
+static void cmsdk_apb_uart_class_init(ObjectClass *klass, void *data)
499
+{
500
+ DeviceClass *dc = DEVICE_CLASS(klass);
501
+
502
+ dc->realize = cmsdk_apb_uart_realize;
503
+ dc->vmsd = &cmsdk_apb_uart_vmstate;
504
+ dc->reset = cmsdk_apb_uart_reset;
505
+ dc->props = cmsdk_apb_uart_properties;
506
+}
507
+
508
+static const TypeInfo cmsdk_apb_uart_info = {
509
+ .name = TYPE_CMSDK_APB_UART,
510
+ .parent = TYPE_SYS_BUS_DEVICE,
511
+ .instance_size = sizeof(CMSDKAPBUART),
512
+ .instance_init = cmsdk_apb_uart_init,
513
+ .class_init = cmsdk_apb_uart_class_init,
514
+};
515
+
516
+static void cmsdk_apb_uart_register_types(void)
517
+{
518
+ type_register_static(&cmsdk_apb_uart_info);
519
+}
520
+
521
+type_init(cmsdk_apb_uart_register_types);
522
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
523
index XXXXXXX..XXXXXXX 100644
262
index XXXXXXX..XXXXXXX 100644
524
--- a/default-configs/arm-softmmu.mak
263
--- a/tests/tcg/aarch64/Makefile.target
525
+++ b/default-configs/arm-softmmu.mak
264
+++ b/tests/tcg/aarch64/Makefile.target
526
@@ -XXX,XX +XXX,XX @@ CONFIG_STM32F2XX_ADC=y
265
@@ -XXX,XX +XXX,XX @@ run-pauth-%: QEMU_OPTS += -cpu max
527
CONFIG_STM32F2XX_SPI=y
266
run-plugin-pauth-%: QEMU_OPTS += -cpu max
528
CONFIG_STM32F205_SOC=y
267
endif
529
268
530
+CONFIG_CMSDK_APB_UART=y
269
+# BTI Tests
531
+
270
+# bti-1 tests the elf notes, so we require special compiler support.
532
CONFIG_VERSATILE_PCI=y
271
+ifneq ($(DOCKER_IMAGE)$(CROSS_CC_HAS_ARMV8_BTI),)
533
CONFIG_VERSATILE_I2C=y
272
+AARCH64_TESTS += bti-1
534
273
+bti-1: CFLAGS += -mbranch-protection=standard
535
diff --git a/hw/char/trace-events b/hw/char/trace-events
274
+bti-1: LDFLAGS += -nostdlib
536
index XXXXXXX..XXXXXXX 100644
275
+endif
537
--- a/hw/char/trace-events
276
+# bti-2 tests PROT_BTI, so no special compiler support required.
538
+++ b/hw/char/trace-events
277
+AARCH64_TESTS += bti-2
539
@@ -XXX,XX +XXX,XX @@ pl011_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
278
+
540
pl011_can_receive(uint32_t lcr, int read_count, int r) "LCR %08x read_count %d returning %d"
279
# Semihosting smoke test for linux-user
541
pl011_put_fifo(uint32_t c, int read_count) "new char 0x%x read_count now %d"
280
AARCH64_TESTS += semihosting
542
pl011_put_fifo_full(void) "FIFO now full, RXFF set"
281
run-semihosting: semihosting
543
+
282
diff --git a/tests/tcg/configure.sh b/tests/tcg/configure.sh
544
+# hw/char/cmsdk_apb_uart.c
283
index XXXXXXX..XXXXXXX 100755
545
+cmsdk_apb_uart_read(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB UART read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
284
--- a/tests/tcg/configure.sh
546
+cmsdk_apb_uart_write(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB UART write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
285
+++ b/tests/tcg/configure.sh
547
+cmsdk_apb_uart_reset(void) "CMSDK APB UART: reset"
286
@@ -XXX,XX +XXX,XX @@ for target in $target_list; do
548
+cmsdk_apb_uart_receive(uint8_t c) "CMSDK APB UART: got character 0x%x from backend"
287
-march=armv8.3-a -o $TMPE $TMPC; then
549
+cmsdk_apb_uart_tx_pending(void) "CMSDK APB UART: character send to backend pending"
288
echo "CROSS_CC_HAS_ARMV8_3=y" >> $config_target_mak
550
+cmsdk_apb_uart_tx(uint8_t c) "CMSDK APB UART: character 0x%x sent to backend"
289
fi
551
+cmsdk_apb_uart_set_params(int speed) "CMSDK APB UART: params set to %d 8N1"
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
552
--
297
--
553
2.7.4
298
2.20.1
554
299
555
300
diff view generated by jsdifflib