1
The following changes since commit 4c41341af76cfc85b5a6c0f87de4838672ab9f89:
1
First pullreq for 6.0: mostly my v8.1M work, plus some other
2
bits and pieces. (I still have a lot of stuff in my to-review
3
folder, which I may or may not get to before the Christmas break...)
2
4
3
Merge remote-tracking branch 'remotes/aperard/tags/pull-xen-20201020' into staging (2020-10-20 11:20:36 +0100)
5
thanks
6
-- PMM
7
8
The following changes since commit 5e7b204dbfae9a562fc73684986f936b97f63877:
9
10
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging (2020-12-09 20:08:54 +0000)
4
11
5
are available in the Git repository at:
12
are available in the Git repository at:
6
13
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20201020
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20201210
8
15
9
for you to fetch changes up to 6358890cb939192f6169fdf7664d903bf9b1d338:
16
for you to fetch changes up to 71f916be1c7e9ede0e37d9cabc781b5a9e8638ff:
10
17
11
tests/tcg/aarch64: Add bti smoke tests (2020-10-20 16:12:02 +0100)
18
hw/arm/armv7m: Correct typo in QOM object name (2020-12-10 11:44:56 +0000)
12
19
13
----------------------------------------------------------------
20
----------------------------------------------------------------
14
target-arm queue:
21
target-arm queue:
15
* Fix AArch32 SMLAD incorrect setting of Q bit
22
* hw/arm/smmuv3: Fix up L1STD_SPAN decoding
16
* AArch32 VCVT fixed-point to float is always round-to-nearest
23
* xlnx-zynqmp: Support Xilinx ZynqMP CAN controllers
17
* strongarm: Fix 'time to transmit a char' unit comment
24
* sbsa-ref: allow to use Cortex-A53/57/72 cpus
18
* Restrict APEI tables generation to the 'virt' machine
25
* Various minor code cleanups
19
* bcm2835: minor code cleanups
26
* hw/intc/armv7m_nvic: Make all of system PPB range be RAZWI/BusFault
20
* correctly flush TLBs when TBI is enabled
27
* Implement more pieces of ARMv8.1M support
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
29
28
30
----------------------------------------------------------------
29
----------------------------------------------------------------
31
Emanuele Giuseppe Esposito (1):
30
Alex Chen (4):
32
loads-stores.rst: add footnote that clarifies GETPC usage
31
i.MX25: Fix bad printf format specifiers
32
i.MX31: Fix bad printf format specifiers
33
i.MX6: Fix bad printf format specifiers
34
i.MX6ul: Fix bad printf format specifiers
33
35
34
Havard Skinnemoen (1):
36
Havard Skinnemoen (1):
35
tests/qtest: Add npcm7xx timer test
37
tests/qtest/npcm7xx_rng-test: dump random data on failure
36
38
37
Peng Liang (1):
39
Kunkun Jiang (1):
38
microbit_i2c: Fix coredump when dump-vmstate
40
hw/arm/smmuv3: Fix up L1STD_SPAN decoding
39
41
40
Peter Maydell (12):
42
Marcin Juszkiewicz (1):
41
target/arm: Fix SMLAD incorrect setting of Q bit
43
sbsa-ref: allow to use Cortex-A53/57/72 cpus
42
target/arm: AArch32 VCVT fixed-point to float is always round-to-nearest
43
decodetree: Fix codegen for non-overlapping group inside overlapping group
44
target/arm: Implement v8.1M NOCP handling
45
target/arm: Implement v8.1M conditional-select insns
46
target/arm: Make the t32 insn[25:23]=111 group non-overlapping
47
target/arm: Don't allow BLX imm for M-profile
48
target/arm: Implement v8.1M branch-future insns (as NOPs)
49
target/arm: Implement v8.1M low-overhead-loop instructions
50
target/arm: Fix has_vfp/has_neon ID reg squashing for M-profile
51
target/arm: Allow M-profile CPUs with FP16 to set FPSCR.FP16
52
target/arm: Implement FPSCR.LTPSIZE for M-profile LOB extension
53
44
54
Philippe Mathieu-Daudé (10):
45
Peter Maydell (25):
55
hw/arm/strongarm: Fix 'time to transmit a char' unit comment
46
hw/intc/armv7m_nvic: Make all of system PPB range be RAZWI/BusFault
56
hw/arm: Restrict APEI tables generation to the 'virt' machine
47
target/arm: Implement v8.1M PXN extension
57
hw/timer/bcm2835: Introduce BCM2835_SYSTIMER_COUNT definition
48
target/arm: Don't clobber ID_PFR1.Security on M-profile cores
58
hw/timer/bcm2835: Rename variable holding CTRL_STATUS register
49
target/arm: Implement VSCCLRM insn
59
hw/timer/bcm2835: Support the timer COMPARE registers
50
target/arm: Implement CLRM instruction
60
hw/arm/bcm2835_peripherals: Correctly wire the SYS_timer IRQs
51
target/arm: Enforce M-profile VMRS/VMSR register restrictions
61
hw/intc/bcm2835_ic: Trace GPU/CPU IRQ handlers
52
target/arm: Refactor M-profile VMSR/VMRS handling
62
hw/intc/bcm2836_control: Use IRQ definitions instead of magic numbers
53
target/arm: Move general-use constant expanders up in translate.c
63
hw/arm/nseries: Fix loading kernel image on n8x0 machines
54
target/arm: Implement VLDR/VSTR system register
64
linux-user/elfload: Avoid leaking interp_name using GLib memory API
55
target/arm: Implement M-profile FPSCR_nzcvqc
56
target/arm: Use new FPCR_NZCV_MASK constant
57
target/arm: Factor out preserve-fp-state from full_vfp_access_check()
58
target/arm: Implement FPCXT_S fp system register
59
hw/intc/armv7m_nvic: Update FPDSCR masking for v8.1M
60
target/arm: For v8.1M, always clear R0-R3, R12, APSR, EPSR on exception entry
61
target/arm: In v8.1M, don't set HFSR.FORCED on vector table fetch failures
62
target/arm: Implement v8.1M REVIDR register
63
target/arm: Implement new v8.1M NOCP check for exception return
64
target/arm: Implement new v8.1M VLLDM and VLSTM encodings
65
hw/intc/armv7m_nvic: Support v8.1M CCR.TRD bit
66
target/arm: Implement CCR_S.TRD behaviour for SG insns
67
hw/intc/armv7m_nvic: Fix "return from inactive handler" check
68
target/arm: Implement M-profile "minimal RAS implementation"
69
hw/intc/armv7m_nvic: Implement read/write for RAS register block
70
hw/arm/armv7m: Correct typo in QOM object name
65
71
66
Richard Henderson (16):
72
Vikram Garhwal (4):
67
accel/tcg: Add tlb_flush_page_bits_by_mmuidx*
73
hw/net/can: Introduce Xilinx ZynqMP CAN controller
68
target/arm: Use tlb_flush_page_bits_by_mmuidx*
74
xlnx-zynqmp: Connect Xilinx ZynqMP CAN controllers
69
target/arm: Remove redundant mmu_idx lookup
75
tests/qtest: Introduce tests for Xilinx ZynqMP CAN controller
70
target/arm: Fix reported EL for mte_check_fail
76
MAINTAINERS: Add maintainer entry for Xilinx ZynqMP CAN controller
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
77
84
docs/devel/loads-stores.rst | 8 +-
78
meson.build | 1 +
85
default-configs/devices/arm-softmmu.mak | 1 -
79
hw/arm/smmuv3-internal.h | 2 +-
86
include/elf.h | 22 ++
80
hw/net/can/trace.h | 1 +
87
include/exec/cpu-all.h | 2 +
81
include/hw/arm/xlnx-zynqmp.h | 8 +
88
include/exec/exec-all.h | 36 ++
82
include/hw/intc/armv7m_nvic.h | 2 +
89
include/hw/timer/bcm2835_systmr.h | 17 +-
83
include/hw/net/xlnx-zynqmp-can.h | 78 +++
90
linux-user/qemu.h | 4 +
84
target/arm/cpu.h | 46 ++
91
linux-user/syscall_defs.h | 4 +
85
target/arm/m-nocp.decode | 10 +-
92
target/arm/cpu.h | 13 +
86
target/arm/t32.decode | 10 +-
93
target/arm/helper.h | 13 +
87
target/arm/vfp.decode | 14 +
94
target/arm/internals.h | 9 +-
88
hw/arm/armv7m.c | 4 +-
95
target/arm/m-nocp.decode | 10 +-
89
hw/arm/sbsa-ref.c | 23 +-
96
target/arm/t32.decode | 50 ++-
90
hw/arm/xlnx-zcu102.c | 20 +
97
accel/tcg/cputlb.c | 275 +++++++++++++++-
91
hw/arm/xlnx-zynqmp.c | 34 ++
98
hw/arm/bcm2835_peripherals.c | 13 +-
92
hw/intc/armv7m_nvic.c | 246 ++++++--
99
hw/arm/nseries.c | 1 +
93
hw/misc/imx25_ccm.c | 12 +-
100
hw/arm/strongarm.c | 2 +-
94
hw/misc/imx31_ccm.c | 14 +-
101
hw/i2c/microbit_i2c.c | 1 +
95
hw/misc/imx6_ccm.c | 20 +-
102
hw/intc/bcm2835_ic.c | 4 +-
96
hw/misc/imx6_src.c | 2 +-
103
hw/intc/bcm2836_control.c | 8 +-
97
hw/misc/imx6ul_ccm.c | 4 +-
104
hw/timer/bcm2835_systmr.c | 57 ++--
98
hw/misc/imx_ccm.c | 4 +-
105
linux-user/aarch64/signal.c | 10 +-
99
hw/net/can/xlnx-zynqmp-can.c | 1161 ++++++++++++++++++++++++++++++++++++++
106
linux-user/elfload.c | 326 ++++++++++++++----
100
target/arm/cpu.c | 5 +-
107
linux-user/mmap.c | 16 +
101
target/arm/helper.c | 7 +-
108
target/arm/cpu.c | 38 ++-
102
target/arm/m_helper.c | 130 ++++-
109
target/arm/helper.c | 55 +++-
103
target/arm/translate.c | 105 +++-
110
target/arm/mte_helper.c | 13 +-
104
tests/qtest/npcm7xx_rng-test.c | 12 +
111
target/arm/translate-a64.c | 6 +-
105
tests/qtest/xlnx-can-test.c | 360 ++++++++++++
112
target/arm/translate.c | 239 +++++++++++++-
106
MAINTAINERS | 8 +
113
target/arm/vfp_helper.c | 76 +++--
107
hw/Kconfig | 1 +
114
tests/qtest/npcm7xx_timer-test.c | 562 ++++++++++++++++++++++++++++++++
108
hw/net/can/meson.build | 1 +
115
tests/tcg/aarch64/bti-1.c | 62 ++++
109
hw/net/can/trace-events | 9 +
116
tests/tcg/aarch64/bti-2.c | 108 ++++++
110
target/arm/translate-vfp.c.inc | 511 ++++++++++++++++-
117
tests/tcg/aarch64/bti-crt.inc.c | 51 +++
111
tests/qtest/meson.build | 1 +
118
hw/arm/Kconfig | 1 +
112
34 files changed, 2713 insertions(+), 153 deletions(-)
119
hw/intc/trace-events | 4 +
113
create mode 100644 hw/net/can/trace.h
120
hw/timer/trace-events | 6 +-
114
create mode 100644 include/hw/net/xlnx-zynqmp-can.h
121
scripts/decodetree.py | 2 +-
115
create mode 100644 hw/net/can/xlnx-zynqmp-can.c
122
target/arm/translate-vfp.c.inc | 41 ++-
116
create mode 100644 tests/qtest/xlnx-can-test.c
123
tests/qtest/meson.build | 1 +
117
create mode 100644 hw/net/can/trace-events
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
118
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Kunkun Jiang <jiangkunkun@huawei.com>
2
2
3
Add trace events for GPU and CPU IRQs.
3
Accroding to the SMMUv3 spec, the SPAN field of Level1 Stream Table
4
Descriptor is 5 bits([4:0]).
4
5
5
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
6
Fixes: 9bde7f0674f(hw/arm/smmuv3: Implement translate callback)
6
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Signed-off-by: Kunkun Jiang <jiangkunkun@huawei.com>
7
Message-id: 20201017180731.1165871-2-f4bug@amsat.org
8
Message-id: 20201124023711.1184-1-jiangkunkun@huawei.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Acked-by: Eric Auger <eric.auger@redhat.com>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
12
---
10
hw/intc/bcm2835_ic.c | 4 +++-
13
hw/arm/smmuv3-internal.h | 2 +-
11
hw/intc/trace-events | 4 ++++
14
1 file changed, 1 insertion(+), 1 deletion(-)
12
2 files changed, 7 insertions(+), 1 deletion(-)
13
15
14
diff --git a/hw/intc/bcm2835_ic.c b/hw/intc/bcm2835_ic.c
16
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
15
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/intc/bcm2835_ic.c
18
--- a/hw/arm/smmuv3-internal.h
17
+++ b/hw/intc/bcm2835_ic.c
19
+++ b/hw/arm/smmuv3-internal.h
18
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ static inline uint64_t l1std_l2ptr(STEDesc *desc)
19
#include "migration/vmstate.h"
21
return hi << 32 | lo;
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
}
22
}
32
23
33
static void bcm2835_ic_set_gpu_irq(void *opaque, int irq, int level)
24
-#define L1STD_SPAN(stm) (extract32((stm)->word[0], 0, 4))
34
@@ -XXX,XX +XXX,XX @@ static void bcm2835_ic_set_gpu_irq(void *opaque, int irq, int level)
25
+#define L1STD_SPAN(stm) (extract32((stm)->word[0], 0, 5))
35
BCM2835ICState *s = opaque;
26
36
27
#endif
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
--
28
--
63
2.20.1
29
2.20.1
64
30
65
31
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
2
2
3
The note test requires gcc 10 for -mbranch-protection=standard.
3
The Xilinx ZynqMP CAN controller is developed based on SocketCAN, QEMU CAN bus
4
The mmap test uses PROT_BTI and does not require special compiler support.
4
implementation. Bus connection and socketCAN connection for each CAN module
5
can be set through command lines.
5
6
6
Acked-by: Alex Bennée <alex.bennee@linaro.org>
7
Example for using single CAN:
8
-object can-bus,id=canbus0 \
9
-machine xlnx-zcu102.canbus0=canbus0 \
10
-object can-host-socketcan,id=socketcan0,if=vcan0,canbus=canbus0
11
12
Example for connecting both CAN to same virtual CAN on host machine:
13
-object can-bus,id=canbus0 -object can-bus,id=canbus1 \
14
-machine xlnx-zcu102.canbus0=canbus0 \
15
-machine xlnx-zcu102.canbus1=canbus1 \
16
-object can-host-socketcan,id=socketcan0,if=vcan0,canbus=canbus0 \
17
-object can-host-socketcan,id=socketcan1,if=vcan0,canbus=canbus1
18
19
To create virtual CAN on the host machine, please check the QEMU CAN docs:
20
https://github.com/qemu/qemu/blob/master/docs/can.txt
21
22
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
23
Message-id: 1605728926-352690-2-git-send-email-fnu.vikram@xilinx.com
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
24
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
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
26
---
12
tests/tcg/aarch64/bti-1.c | 62 +++++++++++++++++
27
meson.build | 1 +
13
tests/tcg/aarch64/bti-2.c | 108 ++++++++++++++++++++++++++++++
28
hw/net/can/trace.h | 1 +
14
tests/tcg/aarch64/bti-crt.inc.c | 51 ++++++++++++++
29
include/hw/net/xlnx-zynqmp-can.h | 78 ++
15
tests/tcg/aarch64/Makefile.target | 10 +++
30
hw/net/can/xlnx-zynqmp-can.c | 1161 ++++++++++++++++++++++++++++++
16
tests/tcg/configure.sh | 4 ++
31
hw/Kconfig | 1 +
17
5 files changed, 235 insertions(+)
32
hw/net/can/meson.build | 1 +
18
create mode 100644 tests/tcg/aarch64/bti-1.c
33
hw/net/can/trace-events | 9 +
19
create mode 100644 tests/tcg/aarch64/bti-2.c
34
7 files changed, 1252 insertions(+)
20
create mode 100644 tests/tcg/aarch64/bti-crt.inc.c
35
create mode 100644 hw/net/can/trace.h
36
create mode 100644 include/hw/net/xlnx-zynqmp-can.h
37
create mode 100644 hw/net/can/xlnx-zynqmp-can.c
38
create mode 100644 hw/net/can/trace-events
21
39
22
diff --git a/tests/tcg/aarch64/bti-1.c b/tests/tcg/aarch64/bti-1.c
40
diff --git a/meson.build b/meson.build
41
index XXXXXXX..XXXXXXX 100644
42
--- a/meson.build
43
+++ b/meson.build
44
@@ -XXX,XX +XXX,XX @@ if have_system
45
'hw/misc',
46
'hw/misc/macio',
47
'hw/net',
48
+ 'hw/net/can',
49
'hw/nvram',
50
'hw/pci',
51
'hw/pci-host',
52
diff --git a/hw/net/can/trace.h b/hw/net/can/trace.h
23
new file mode 100644
53
new file mode 100644
24
index XXXXXXX..XXXXXXX
54
index XXXXXXX..XXXXXXX
25
--- /dev/null
55
--- /dev/null
26
+++ b/tests/tcg/aarch64/bti-1.c
56
+++ b/hw/net/can/trace.h
27
@@ -XXX,XX +XXX,XX @@
57
@@ -0,0 +1 @@
28
+/*
58
+#include "trace/trace-hw_net_can.h"
29
+ * Branch target identification, basic notskip cases.
59
diff --git a/include/hw/net/xlnx-zynqmp-can.h b/include/hw/net/xlnx-zynqmp-can.h
30
+ */
31
+
32
+#include "bti-crt.inc.c"
33
+
34
+static void skip2_sigill(int sig, siginfo_t *info, ucontext_t *uc)
35
+{
36
+ uc->uc_mcontext.pc += 8;
37
+ uc->uc_mcontext.pstate = 1;
38
+}
39
+
40
+#define NOP "nop"
41
+#define BTI_N "hint #32"
42
+#define BTI_C "hint #34"
43
+#define BTI_J "hint #36"
44
+#define BTI_JC "hint #38"
45
+
46
+#define BTYPE_1(DEST) \
47
+ asm("mov %0,#1; adr x16, 1f; br x16; 1: " DEST "; mov %0,#0" \
48
+ : "=r"(skipped) : : "x16")
49
+
50
+#define BTYPE_2(DEST) \
51
+ asm("mov %0,#1; adr x16, 1f; blr x16; 1: " DEST "; mov %0,#0" \
52
+ : "=r"(skipped) : : "x16", "x30")
53
+
54
+#define BTYPE_3(DEST) \
55
+ asm("mov %0,#1; adr x15, 1f; br x15; 1: " DEST "; mov %0,#0" \
56
+ : "=r"(skipped) : : "x15")
57
+
58
+#define TEST(WHICH, DEST, EXPECT) \
59
+ do { WHICH(DEST); fail += skipped ^ EXPECT; } while (0)
60
+
61
+
62
+int main()
63
+{
64
+ int fail = 0;
65
+ int skipped;
66
+
67
+ /* Signal-like with SA_SIGINFO. */
68
+ signal_info(SIGILL, skip2_sigill);
69
+
70
+ TEST(BTYPE_1, NOP, 1);
71
+ TEST(BTYPE_1, BTI_N, 1);
72
+ TEST(BTYPE_1, BTI_C, 0);
73
+ TEST(BTYPE_1, BTI_J, 0);
74
+ TEST(BTYPE_1, BTI_JC, 0);
75
+
76
+ TEST(BTYPE_2, NOP, 1);
77
+ TEST(BTYPE_2, BTI_N, 1);
78
+ TEST(BTYPE_2, BTI_C, 0);
79
+ TEST(BTYPE_2, BTI_J, 1);
80
+ TEST(BTYPE_2, BTI_JC, 0);
81
+
82
+ TEST(BTYPE_3, NOP, 1);
83
+ TEST(BTYPE_3, BTI_N, 1);
84
+ TEST(BTYPE_3, BTI_C, 1);
85
+ TEST(BTYPE_3, BTI_J, 0);
86
+ TEST(BTYPE_3, BTI_JC, 0);
87
+
88
+ return fail;
89
+}
90
diff --git a/tests/tcg/aarch64/bti-2.c b/tests/tcg/aarch64/bti-2.c
91
new file mode 100644
60
new file mode 100644
92
index XXXXXXX..XXXXXXX
61
index XXXXXXX..XXXXXXX
93
--- /dev/null
62
--- /dev/null
94
+++ b/tests/tcg/aarch64/bti-2.c
63
+++ b/include/hw/net/xlnx-zynqmp-can.h
95
@@ -XXX,XX +XXX,XX @@
64
@@ -XXX,XX +XXX,XX @@
96
+/*
65
+/*
97
+ * Branch target identification, basic notskip cases.
66
+ * QEMU model of the Xilinx ZynqMP CAN controller.
67
+ *
68
+ * Copyright (c) 2020 Xilinx Inc.
69
+ *
70
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
71
+ *
72
+ * Based on QEMU CAN Device emulation implemented by Jin Yang, Deniz Eren and
73
+ * Pavel Pisa.
74
+ *
75
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
76
+ * of this software and associated documentation files (the "Software"), to deal
77
+ * in the Software without restriction, including without limitation the rights
78
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
79
+ * copies of the Software, and to permit persons to whom the Software is
80
+ * furnished to do so, subject to the following conditions:
81
+ *
82
+ * The above copyright notice and this permission notice shall be included in
83
+ * all copies or substantial portions of the Software.
84
+ *
85
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
86
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
87
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
88
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
89
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
90
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
91
+ * THE SOFTWARE.
98
+ */
92
+ */
99
+
93
+
100
+#include <stdio.h>
94
+#ifndef XLNX_ZYNQMP_CAN_H
101
+#include <signal.h>
95
+#define XLNX_ZYNQMP_CAN_H
102
+#include <string.h>
96
+
103
+#include <unistd.h>
97
+#include "hw/register.h"
104
+#include <sys/mman.h>
98
+#include "net/can_emu.h"
105
+
99
+#include "net/can_host.h"
106
+#ifndef PROT_BTI
100
+#include "qemu/fifo32.h"
107
+#define PROT_BTI 0x10
101
+#include "hw/ptimer.h"
102
+#include "hw/qdev-clock.h"
103
+
104
+#define TYPE_XLNX_ZYNQMP_CAN "xlnx.zynqmp-can"
105
+
106
+#define XLNX_ZYNQMP_CAN(obj) \
107
+ OBJECT_CHECK(XlnxZynqMPCANState, (obj), TYPE_XLNX_ZYNQMP_CAN)
108
+
109
+#define MAX_CAN_CTRLS 2
110
+#define XLNX_ZYNQMP_CAN_R_MAX (0x84 / 4)
111
+#define MAILBOX_CAPACITY 64
112
+#define CAN_TIMER_MAX 0XFFFFUL
113
+#define CAN_DEFAULT_CLOCK (24 * 1000 * 1000)
114
+
115
+/* Each CAN_FRAME will have 4 * 32bit size. */
116
+#define CAN_FRAME_SIZE 4
117
+#define RXFIFO_SIZE (MAILBOX_CAPACITY * CAN_FRAME_SIZE)
118
+
119
+typedef struct XlnxZynqMPCANState {
120
+ SysBusDevice parent_obj;
121
+ MemoryRegion iomem;
122
+
123
+ qemu_irq irq;
124
+
125
+ CanBusClientState bus_client;
126
+ CanBusState *canbus;
127
+
128
+ struct {
129
+ uint32_t ext_clk_freq;
130
+ } cfg;
131
+
132
+ RegisterInfo reg_info[XLNX_ZYNQMP_CAN_R_MAX];
133
+ uint32_t regs[XLNX_ZYNQMP_CAN_R_MAX];
134
+
135
+ Fifo32 rx_fifo;
136
+ Fifo32 tx_fifo;
137
+ Fifo32 txhpb_fifo;
138
+
139
+ ptimer_state *can_timer;
140
+} XlnxZynqMPCANState;
141
+
108
+#endif
142
+#endif
109
+
143
diff --git a/hw/net/can/xlnx-zynqmp-can.c b/hw/net/can/xlnx-zynqmp-can.c
110
+static void skip2_sigill(int sig, siginfo_t *info, void *vuc)
111
+{
112
+ ucontext_t *uc = vuc;
113
+ uc->uc_mcontext.pc += 8;
114
+ uc->uc_mcontext.pstate = 1;
115
+}
116
+
117
+#define NOP "nop"
118
+#define BTI_N "hint #32"
119
+#define BTI_C "hint #34"
120
+#define BTI_J "hint #36"
121
+#define BTI_JC "hint #38"
122
+
123
+#define BTYPE_1(DEST) \
124
+ "mov x1, #1\n\t" \
125
+ "adr x16, 1f\n\t" \
126
+ "br x16\n" \
127
+"1: " DEST "\n\t" \
128
+ "mov x1, #0"
129
+
130
+#define BTYPE_2(DEST) \
131
+ "mov x1, #1\n\t" \
132
+ "adr x16, 1f\n\t" \
133
+ "blr x16\n" \
134
+"1: " DEST "\n\t" \
135
+ "mov x1, #0"
136
+
137
+#define BTYPE_3(DEST) \
138
+ "mov x1, #1\n\t" \
139
+ "adr x15, 1f\n\t" \
140
+ "br x15\n" \
141
+"1: " DEST "\n\t" \
142
+ "mov x1, #0"
143
+
144
+#define TEST(WHICH, DEST, EXPECT) \
145
+ WHICH(DEST) "\n" \
146
+ ".if " #EXPECT "\n\t" \
147
+ "eor x1, x1," #EXPECT "\n" \
148
+ ".endif\n\t" \
149
+ "add x0, x0, x1\n\t"
150
+
151
+extern char test_begin[], test_end[];
152
+
153
+asm("\n"
154
+"test_begin:\n\t"
155
+ BTI_C "\n\t"
156
+ "mov x2, x30\n\t"
157
+ "mov x0, #0\n\t"
158
+
159
+ TEST(BTYPE_1, NOP, 1)
160
+ TEST(BTYPE_1, BTI_N, 1)
161
+ TEST(BTYPE_1, BTI_C, 0)
162
+ TEST(BTYPE_1, BTI_J, 0)
163
+ TEST(BTYPE_1, BTI_JC, 0)
164
+
165
+ TEST(BTYPE_2, NOP, 1)
166
+ TEST(BTYPE_2, BTI_N, 1)
167
+ TEST(BTYPE_2, BTI_C, 0)
168
+ TEST(BTYPE_2, BTI_J, 1)
169
+ TEST(BTYPE_2, BTI_JC, 0)
170
+
171
+ TEST(BTYPE_3, NOP, 1)
172
+ TEST(BTYPE_3, BTI_N, 1)
173
+ TEST(BTYPE_3, BTI_C, 1)
174
+ TEST(BTYPE_3, BTI_J, 0)
175
+ TEST(BTYPE_3, BTI_JC, 0)
176
+
177
+ "ret x2\n"
178
+"test_end:"
179
+);
180
+
181
+int main()
182
+{
183
+ struct sigaction sa;
184
+
185
+ void *p = mmap(0, getpagesize(),
186
+ PROT_EXEC | PROT_READ | PROT_WRITE | PROT_BTI,
187
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
188
+ if (p == MAP_FAILED) {
189
+ perror("mmap");
190
+ return 1;
191
+ }
192
+
193
+ memset(&sa, 0, sizeof(sa));
194
+ sa.sa_sigaction = skip2_sigill;
195
+ sa.sa_flags = SA_SIGINFO;
196
+ if (sigaction(SIGILL, &sa, NULL) < 0) {
197
+ perror("sigaction");
198
+ return 1;
199
+ }
200
+
201
+ memcpy(p, test_begin, test_end - test_begin);
202
+ return ((int (*)(void))p)();
203
+}
204
diff --git a/tests/tcg/aarch64/bti-crt.inc.c b/tests/tcg/aarch64/bti-crt.inc.c
205
new file mode 100644
144
new file mode 100644
206
index XXXXXXX..XXXXXXX
145
index XXXXXXX..XXXXXXX
207
--- /dev/null
146
--- /dev/null
208
+++ b/tests/tcg/aarch64/bti-crt.inc.c
147
+++ b/hw/net/can/xlnx-zynqmp-can.c
209
@@ -XXX,XX +XXX,XX @@
148
@@ -XXX,XX +XXX,XX @@
210
+/*
149
+/*
211
+ * Minimal user-environment for testing BTI.
150
+ * QEMU model of the Xilinx ZynqMP CAN controller.
151
+ * This implementation is based on the following datasheet:
152
+ * https://www.xilinx.com/support/documentation/user_guides/ug1085-zynq-ultrascale-trm.pdf
212
+ *
153
+ *
213
+ * Normal libc is not (yet) built with BTI support enabled,
154
+ * Copyright (c) 2020 Xilinx Inc.
214
+ * and so could generate a BTI TRAP before ever reaching main.
155
+ *
156
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
157
+ *
158
+ * Based on QEMU CAN Device emulation implemented by Jin Yang, Deniz Eren and
159
+ * Pavel Pisa
160
+ *
161
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
162
+ * of this software and associated documentation files (the "Software"), to deal
163
+ * in the Software without restriction, including without limitation the rights
164
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
165
+ * copies of the Software, and to permit persons to whom the Software is
166
+ * furnished to do so, subject to the following conditions:
167
+ *
168
+ * The above copyright notice and this permission notice shall be included in
169
+ * all copies or substantial portions of the Software.
170
+ *
171
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
172
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
173
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
174
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
175
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
176
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
177
+ * THE SOFTWARE.
215
+ */
178
+ */
216
+
179
+
217
+#include <stdlib.h>
180
+#include "qemu/osdep.h"
218
+#include <signal.h>
181
+#include "hw/sysbus.h"
219
+#include <ucontext.h>
182
+#include "hw/register.h"
220
+#include <asm/unistd.h>
183
+#include "hw/irq.h"
221
+
184
+#include "qapi/error.h"
222
+int main(void);
185
+#include "qemu/bitops.h"
223
+
186
+#include "qemu/log.h"
224
+void _start(void)
187
+#include "qemu/cutils.h"
225
+{
188
+#include "sysemu/sysemu.h"
226
+ exit(main());
189
+#include "migration/vmstate.h"
227
+}
190
+#include "hw/qdev-properties.h"
228
+
191
+#include "net/can_emu.h"
229
+void exit(int ret)
192
+#include "net/can_host.h"
230
+{
193
+#include "qemu/event_notifier.h"
231
+ register int x0 __asm__("x0") = ret;
194
+#include "qom/object_interfaces.h"
232
+ register int x8 __asm__("x8") = __NR_exit;
195
+#include "hw/net/xlnx-zynqmp-can.h"
233
+
196
+#include "trace.h"
234
+ asm volatile("svc #0" : : "r"(x0), "r"(x8));
197
+
235
+ __builtin_unreachable();
198
+#ifndef XLNX_ZYNQMP_CAN_ERR_DEBUG
236
+}
199
+#define XLNX_ZYNQMP_CAN_ERR_DEBUG 0
237
+
200
+#endif
238
+/*
201
+
239
+ * Irritatingly, the user API struct sigaction does not match the
202
+#define MAX_DLC 8
240
+ * kernel API struct sigaction. So for simplicity, isolate the
203
+#undef ERROR
241
+ * kernel ABI here, and make this act like signal.
204
+
242
+ */
205
+REG32(SOFTWARE_RESET_REGISTER, 0x0)
243
+void signal_info(int sig, void (*fn)(int, siginfo_t *, ucontext_t *))
206
+ FIELD(SOFTWARE_RESET_REGISTER, CEN, 1, 1)
244
+{
207
+ FIELD(SOFTWARE_RESET_REGISTER, SRST, 0, 1)
245
+ struct kernel_sigaction {
208
+REG32(MODE_SELECT_REGISTER, 0x4)
246
+ void (*handler)(int, siginfo_t *, ucontext_t *);
209
+ FIELD(MODE_SELECT_REGISTER, SNOOP, 2, 1)
247
+ unsigned long flags;
210
+ FIELD(MODE_SELECT_REGISTER, LBACK, 1, 1)
248
+ unsigned long restorer;
211
+ FIELD(MODE_SELECT_REGISTER, SLEEP, 0, 1)
249
+ unsigned long mask;
212
+REG32(ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER, 0x8)
250
+ } sa = { fn, SA_SIGINFO, 0, 0 };
213
+ FIELD(ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER, BRP, 0, 8)
251
+
214
+REG32(ARBITRATION_PHASE_BIT_TIMING_REGISTER, 0xc)
252
+ register int x0 __asm__("x0") = sig;
215
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, SJW, 7, 2)
253
+ register void *x1 __asm__("x1") = &sa;
216
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, TS2, 4, 3)
254
+ register void *x2 __asm__("x2") = 0;
217
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, TS1, 0, 4)
255
+ register int x3 __asm__("x3") = sizeof(unsigned long);
218
+REG32(ERROR_COUNTER_REGISTER, 0x10)
256
+ register int x8 __asm__("x8") = __NR_rt_sigaction;
219
+ FIELD(ERROR_COUNTER_REGISTER, REC, 8, 8)
257
+
220
+ FIELD(ERROR_COUNTER_REGISTER, TEC, 0, 8)
258
+ asm volatile("svc #0"
221
+REG32(ERROR_STATUS_REGISTER, 0x14)
259
+ : : "r"(x0), "r"(x1), "r"(x2), "r"(x3), "r"(x8) : "memory");
222
+ FIELD(ERROR_STATUS_REGISTER, ACKER, 4, 1)
260
+}
223
+ FIELD(ERROR_STATUS_REGISTER, BERR, 3, 1)
261
diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
224
+ FIELD(ERROR_STATUS_REGISTER, STER, 2, 1)
225
+ FIELD(ERROR_STATUS_REGISTER, FMER, 1, 1)
226
+ FIELD(ERROR_STATUS_REGISTER, CRCER, 0, 1)
227
+REG32(STATUS_REGISTER, 0x18)
228
+ FIELD(STATUS_REGISTER, SNOOP, 12, 1)
229
+ FIELD(STATUS_REGISTER, ACFBSY, 11, 1)
230
+ FIELD(STATUS_REGISTER, TXFLL, 10, 1)
231
+ FIELD(STATUS_REGISTER, TXBFLL, 9, 1)
232
+ FIELD(STATUS_REGISTER, ESTAT, 7, 2)
233
+ FIELD(STATUS_REGISTER, ERRWRN, 6, 1)
234
+ FIELD(STATUS_REGISTER, BBSY, 5, 1)
235
+ FIELD(STATUS_REGISTER, BIDLE, 4, 1)
236
+ FIELD(STATUS_REGISTER, NORMAL, 3, 1)
237
+ FIELD(STATUS_REGISTER, SLEEP, 2, 1)
238
+ FIELD(STATUS_REGISTER, LBACK, 1, 1)
239
+ FIELD(STATUS_REGISTER, CONFIG, 0, 1)
240
+REG32(INTERRUPT_STATUS_REGISTER, 0x1c)
241
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFEMP, 14, 1)
242
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFWMEMP, 13, 1)
243
+ FIELD(INTERRUPT_STATUS_REGISTER, RXFWMFLL, 12, 1)
244
+ FIELD(INTERRUPT_STATUS_REGISTER, WKUP, 11, 1)
245
+ FIELD(INTERRUPT_STATUS_REGISTER, SLP, 10, 1)
246
+ FIELD(INTERRUPT_STATUS_REGISTER, BSOFF, 9, 1)
247
+ FIELD(INTERRUPT_STATUS_REGISTER, ERROR, 8, 1)
248
+ FIELD(INTERRUPT_STATUS_REGISTER, RXNEMP, 7, 1)
249
+ FIELD(INTERRUPT_STATUS_REGISTER, RXOFLW, 6, 1)
250
+ FIELD(INTERRUPT_STATUS_REGISTER, RXUFLW, 5, 1)
251
+ FIELD(INTERRUPT_STATUS_REGISTER, RXOK, 4, 1)
252
+ FIELD(INTERRUPT_STATUS_REGISTER, TXBFLL, 3, 1)
253
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFLL, 2, 1)
254
+ FIELD(INTERRUPT_STATUS_REGISTER, TXOK, 1, 1)
255
+ FIELD(INTERRUPT_STATUS_REGISTER, ARBLST, 0, 1)
256
+REG32(INTERRUPT_ENABLE_REGISTER, 0x20)
257
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFEMP, 14, 1)
258
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFWMEMP, 13, 1)
259
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXFWMFLL, 12, 1)
260
+ FIELD(INTERRUPT_ENABLE_REGISTER, EWKUP, 11, 1)
261
+ FIELD(INTERRUPT_ENABLE_REGISTER, ESLP, 10, 1)
262
+ FIELD(INTERRUPT_ENABLE_REGISTER, EBSOFF, 9, 1)
263
+ FIELD(INTERRUPT_ENABLE_REGISTER, EERROR, 8, 1)
264
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXNEMP, 7, 1)
265
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXOFLW, 6, 1)
266
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXUFLW, 5, 1)
267
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXOK, 4, 1)
268
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXBFLL, 3, 1)
269
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFLL, 2, 1)
270
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXOK, 1, 1)
271
+ FIELD(INTERRUPT_ENABLE_REGISTER, EARBLST, 0, 1)
272
+REG32(INTERRUPT_CLEAR_REGISTER, 0x24)
273
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFEMP, 14, 1)
274
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFWMEMP, 13, 1)
275
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXFWMFLL, 12, 1)
276
+ FIELD(INTERRUPT_CLEAR_REGISTER, CWKUP, 11, 1)
277
+ FIELD(INTERRUPT_CLEAR_REGISTER, CSLP, 10, 1)
278
+ FIELD(INTERRUPT_CLEAR_REGISTER, CBSOFF, 9, 1)
279
+ FIELD(INTERRUPT_CLEAR_REGISTER, CERROR, 8, 1)
280
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXNEMP, 7, 1)
281
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXOFLW, 6, 1)
282
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXUFLW, 5, 1)
283
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXOK, 4, 1)
284
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXBFLL, 3, 1)
285
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFLL, 2, 1)
286
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXOK, 1, 1)
287
+ FIELD(INTERRUPT_CLEAR_REGISTER, CARBLST, 0, 1)
288
+REG32(TIMESTAMP_REGISTER, 0x28)
289
+ FIELD(TIMESTAMP_REGISTER, CTS, 0, 1)
290
+REG32(WIR, 0x2c)
291
+ FIELD(WIR, EW, 8, 8)
292
+ FIELD(WIR, FW, 0, 8)
293
+REG32(TXFIFO_ID, 0x30)
294
+ FIELD(TXFIFO_ID, IDH, 21, 11)
295
+ FIELD(TXFIFO_ID, SRRRTR, 20, 1)
296
+ FIELD(TXFIFO_ID, IDE, 19, 1)
297
+ FIELD(TXFIFO_ID, IDL, 1, 18)
298
+ FIELD(TXFIFO_ID, RTR, 0, 1)
299
+REG32(TXFIFO_DLC, 0x34)
300
+ FIELD(TXFIFO_DLC, DLC, 28, 4)
301
+REG32(TXFIFO_DATA1, 0x38)
302
+ FIELD(TXFIFO_DATA1, DB0, 24, 8)
303
+ FIELD(TXFIFO_DATA1, DB1, 16, 8)
304
+ FIELD(TXFIFO_DATA1, DB2, 8, 8)
305
+ FIELD(TXFIFO_DATA1, DB3, 0, 8)
306
+REG32(TXFIFO_DATA2, 0x3c)
307
+ FIELD(TXFIFO_DATA2, DB4, 24, 8)
308
+ FIELD(TXFIFO_DATA2, DB5, 16, 8)
309
+ FIELD(TXFIFO_DATA2, DB6, 8, 8)
310
+ FIELD(TXFIFO_DATA2, DB7, 0, 8)
311
+REG32(TXHPB_ID, 0x40)
312
+ FIELD(TXHPB_ID, IDH, 21, 11)
313
+ FIELD(TXHPB_ID, SRRRTR, 20, 1)
314
+ FIELD(TXHPB_ID, IDE, 19, 1)
315
+ FIELD(TXHPB_ID, IDL, 1, 18)
316
+ FIELD(TXHPB_ID, RTR, 0, 1)
317
+REG32(TXHPB_DLC, 0x44)
318
+ FIELD(TXHPB_DLC, DLC, 28, 4)
319
+REG32(TXHPB_DATA1, 0x48)
320
+ FIELD(TXHPB_DATA1, DB0, 24, 8)
321
+ FIELD(TXHPB_DATA1, DB1, 16, 8)
322
+ FIELD(TXHPB_DATA1, DB2, 8, 8)
323
+ FIELD(TXHPB_DATA1, DB3, 0, 8)
324
+REG32(TXHPB_DATA2, 0x4c)
325
+ FIELD(TXHPB_DATA2, DB4, 24, 8)
326
+ FIELD(TXHPB_DATA2, DB5, 16, 8)
327
+ FIELD(TXHPB_DATA2, DB6, 8, 8)
328
+ FIELD(TXHPB_DATA2, DB7, 0, 8)
329
+REG32(RXFIFO_ID, 0x50)
330
+ FIELD(RXFIFO_ID, IDH, 21, 11)
331
+ FIELD(RXFIFO_ID, SRRRTR, 20, 1)
332
+ FIELD(RXFIFO_ID, IDE, 19, 1)
333
+ FIELD(RXFIFO_ID, IDL, 1, 18)
334
+ FIELD(RXFIFO_ID, RTR, 0, 1)
335
+REG32(RXFIFO_DLC, 0x54)
336
+ FIELD(RXFIFO_DLC, DLC, 28, 4)
337
+ FIELD(RXFIFO_DLC, RXT, 0, 16)
338
+REG32(RXFIFO_DATA1, 0x58)
339
+ FIELD(RXFIFO_DATA1, DB0, 24, 8)
340
+ FIELD(RXFIFO_DATA1, DB1, 16, 8)
341
+ FIELD(RXFIFO_DATA1, DB2, 8, 8)
342
+ FIELD(RXFIFO_DATA1, DB3, 0, 8)
343
+REG32(RXFIFO_DATA2, 0x5c)
344
+ FIELD(RXFIFO_DATA2, DB4, 24, 8)
345
+ FIELD(RXFIFO_DATA2, DB5, 16, 8)
346
+ FIELD(RXFIFO_DATA2, DB6, 8, 8)
347
+ FIELD(RXFIFO_DATA2, DB7, 0, 8)
348
+REG32(AFR, 0x60)
349
+ FIELD(AFR, UAF4, 3, 1)
350
+ FIELD(AFR, UAF3, 2, 1)
351
+ FIELD(AFR, UAF2, 1, 1)
352
+ FIELD(AFR, UAF1, 0, 1)
353
+REG32(AFMR1, 0x64)
354
+ FIELD(AFMR1, AMIDH, 21, 11)
355
+ FIELD(AFMR1, AMSRR, 20, 1)
356
+ FIELD(AFMR1, AMIDE, 19, 1)
357
+ FIELD(AFMR1, AMIDL, 1, 18)
358
+ FIELD(AFMR1, AMRTR, 0, 1)
359
+REG32(AFIR1, 0x68)
360
+ FIELD(AFIR1, AIIDH, 21, 11)
361
+ FIELD(AFIR1, AISRR, 20, 1)
362
+ FIELD(AFIR1, AIIDE, 19, 1)
363
+ FIELD(AFIR1, AIIDL, 1, 18)
364
+ FIELD(AFIR1, AIRTR, 0, 1)
365
+REG32(AFMR2, 0x6c)
366
+ FIELD(AFMR2, AMIDH, 21, 11)
367
+ FIELD(AFMR2, AMSRR, 20, 1)
368
+ FIELD(AFMR2, AMIDE, 19, 1)
369
+ FIELD(AFMR2, AMIDL, 1, 18)
370
+ FIELD(AFMR2, AMRTR, 0, 1)
371
+REG32(AFIR2, 0x70)
372
+ FIELD(AFIR2, AIIDH, 21, 11)
373
+ FIELD(AFIR2, AISRR, 20, 1)
374
+ FIELD(AFIR2, AIIDE, 19, 1)
375
+ FIELD(AFIR2, AIIDL, 1, 18)
376
+ FIELD(AFIR2, AIRTR, 0, 1)
377
+REG32(AFMR3, 0x74)
378
+ FIELD(AFMR3, AMIDH, 21, 11)
379
+ FIELD(AFMR3, AMSRR, 20, 1)
380
+ FIELD(AFMR3, AMIDE, 19, 1)
381
+ FIELD(AFMR3, AMIDL, 1, 18)
382
+ FIELD(AFMR3, AMRTR, 0, 1)
383
+REG32(AFIR3, 0x78)
384
+ FIELD(AFIR3, AIIDH, 21, 11)
385
+ FIELD(AFIR3, AISRR, 20, 1)
386
+ FIELD(AFIR3, AIIDE, 19, 1)
387
+ FIELD(AFIR3, AIIDL, 1, 18)
388
+ FIELD(AFIR3, AIRTR, 0, 1)
389
+REG32(AFMR4, 0x7c)
390
+ FIELD(AFMR4, AMIDH, 21, 11)
391
+ FIELD(AFMR4, AMSRR, 20, 1)
392
+ FIELD(AFMR4, AMIDE, 19, 1)
393
+ FIELD(AFMR4, AMIDL, 1, 18)
394
+ FIELD(AFMR4, AMRTR, 0, 1)
395
+REG32(AFIR4, 0x80)
396
+ FIELD(AFIR4, AIIDH, 21, 11)
397
+ FIELD(AFIR4, AISRR, 20, 1)
398
+ FIELD(AFIR4, AIIDE, 19, 1)
399
+ FIELD(AFIR4, AIIDL, 1, 18)
400
+ FIELD(AFIR4, AIRTR, 0, 1)
401
+
402
+static void can_update_irq(XlnxZynqMPCANState *s)
403
+{
404
+ uint32_t irq;
405
+
406
+ /* Watermark register interrupts. */
407
+ if ((fifo32_num_free(&s->tx_fifo) / CAN_FRAME_SIZE) >
408
+ ARRAY_FIELD_EX32(s->regs, WIR, EW)) {
409
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXFWMEMP, 1);
410
+ }
411
+
412
+ if ((fifo32_num_used(&s->rx_fifo) / CAN_FRAME_SIZE) >
413
+ ARRAY_FIELD_EX32(s->regs, WIR, FW)) {
414
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXFWMFLL, 1);
415
+ }
416
+
417
+ /* RX Interrupts. */
418
+ if (fifo32_num_used(&s->rx_fifo) >= CAN_FRAME_SIZE) {
419
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXNEMP, 1);
420
+ }
421
+
422
+ /* TX interrupts. */
423
+ if (fifo32_is_empty(&s->tx_fifo)) {
424
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXFEMP, 1);
425
+ }
426
+
427
+ if (fifo32_is_full(&s->tx_fifo)) {
428
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXFLL, 1);
429
+ }
430
+
431
+ if (fifo32_is_full(&s->txhpb_fifo)) {
432
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXBFLL, 1);
433
+ }
434
+
435
+ irq = s->regs[R_INTERRUPT_STATUS_REGISTER];
436
+ irq &= s->regs[R_INTERRUPT_ENABLE_REGISTER];
437
+
438
+ trace_xlnx_can_update_irq(s->regs[R_INTERRUPT_STATUS_REGISTER],
439
+ s->regs[R_INTERRUPT_ENABLE_REGISTER], irq);
440
+ qemu_set_irq(s->irq, irq);
441
+}
442
+
443
+static void can_ier_post_write(RegisterInfo *reg, uint64_t val)
444
+{
445
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
446
+
447
+ can_update_irq(s);
448
+}
449
+
450
+static uint64_t can_icr_pre_write(RegisterInfo *reg, uint64_t val)
451
+{
452
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
453
+
454
+ s->regs[R_INTERRUPT_STATUS_REGISTER] &= ~val;
455
+ can_update_irq(s);
456
+
457
+ return 0;
458
+}
459
+
460
+static void can_config_reset(XlnxZynqMPCANState *s)
461
+{
462
+ /* Reset all the configuration registers. */
463
+ register_reset(&s->reg_info[R_SOFTWARE_RESET_REGISTER]);
464
+ register_reset(&s->reg_info[R_MODE_SELECT_REGISTER]);
465
+ register_reset(
466
+ &s->reg_info[R_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER]);
467
+ register_reset(&s->reg_info[R_ARBITRATION_PHASE_BIT_TIMING_REGISTER]);
468
+ register_reset(&s->reg_info[R_STATUS_REGISTER]);
469
+ register_reset(&s->reg_info[R_INTERRUPT_STATUS_REGISTER]);
470
+ register_reset(&s->reg_info[R_INTERRUPT_ENABLE_REGISTER]);
471
+ register_reset(&s->reg_info[R_INTERRUPT_CLEAR_REGISTER]);
472
+ register_reset(&s->reg_info[R_WIR]);
473
+}
474
+
475
+static void can_config_mode(XlnxZynqMPCANState *s)
476
+{
477
+ register_reset(&s->reg_info[R_ERROR_COUNTER_REGISTER]);
478
+ register_reset(&s->reg_info[R_ERROR_STATUS_REGISTER]);
479
+
480
+ /* Put XlnxZynqMPCAN in configuration mode. */
481
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, CONFIG, 1);
482
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, WKUP, 0);
483
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, SLP, 0);
484
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, BSOFF, 0);
485
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, ERROR, 0);
486
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOFLW, 0);
487
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 0);
488
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXOK, 0);
489
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, ARBLST, 0);
490
+
491
+ can_update_irq(s);
492
+}
493
+
494
+static void update_status_register_mode_bits(XlnxZynqMPCANState *s)
495
+{
496
+ bool sleep_status = ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP);
497
+ bool sleep_mode = ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SLEEP);
498
+ /* Wake up interrupt bit. */
499
+ bool wakeup_irq_val = sleep_status && (sleep_mode == 0);
500
+ /* Sleep interrupt bit. */
501
+ bool sleep_irq_val = sleep_mode && (sleep_status == 0);
502
+
503
+ /* Clear previous core mode status bits. */
504
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, LBACK, 0);
505
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SLEEP, 0);
506
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SNOOP, 0);
507
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, NORMAL, 0);
508
+
509
+ /* set current mode bit and generate irqs accordingly. */
510
+ if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, LBACK)) {
511
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, LBACK, 1);
512
+ } else if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SLEEP)) {
513
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SLEEP, 1);
514
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, SLP,
515
+ sleep_irq_val);
516
+ } else if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SNOOP)) {
517
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SNOOP, 1);
518
+ } else {
519
+ /*
520
+ * If all bits are zero then XlnxZynqMPCAN is set in normal mode.
521
+ */
522
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, NORMAL, 1);
523
+ /* Set wakeup interrupt bit. */
524
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, WKUP,
525
+ wakeup_irq_val);
526
+ }
527
+
528
+ can_update_irq(s);
529
+}
530
+
531
+static void can_exit_sleep_mode(XlnxZynqMPCANState *s)
532
+{
533
+ ARRAY_FIELD_DP32(s->regs, MODE_SELECT_REGISTER, SLEEP, 0);
534
+ update_status_register_mode_bits(s);
535
+}
536
+
537
+static void generate_frame(qemu_can_frame *frame, uint32_t *data)
538
+{
539
+ frame->can_id = data[0];
540
+ frame->can_dlc = FIELD_EX32(data[1], TXFIFO_DLC, DLC);
541
+
542
+ frame->data[0] = FIELD_EX32(data[2], TXFIFO_DATA1, DB3);
543
+ frame->data[1] = FIELD_EX32(data[2], TXFIFO_DATA1, DB2);
544
+ frame->data[2] = FIELD_EX32(data[2], TXFIFO_DATA1, DB1);
545
+ frame->data[3] = FIELD_EX32(data[2], TXFIFO_DATA1, DB0);
546
+
547
+ frame->data[4] = FIELD_EX32(data[3], TXFIFO_DATA2, DB7);
548
+ frame->data[5] = FIELD_EX32(data[3], TXFIFO_DATA2, DB6);
549
+ frame->data[6] = FIELD_EX32(data[3], TXFIFO_DATA2, DB5);
550
+ frame->data[7] = FIELD_EX32(data[3], TXFIFO_DATA2, DB4);
551
+}
552
+
553
+static bool tx_ready_check(XlnxZynqMPCANState *s)
554
+{
555
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, SRST)) {
556
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
557
+
558
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer data while"
559
+ " data while controller is in reset mode.\n",
560
+ path);
561
+ return false;
562
+ }
563
+
564
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
565
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
566
+
567
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer"
568
+ " data while controller is in configuration mode. Reset"
569
+ " the core so operations can start fresh.\n",
570
+ path);
571
+ return false;
572
+ }
573
+
574
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SNOOP)) {
575
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
576
+
577
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer"
578
+ " data while controller is in SNOOP MODE.\n",
579
+ path);
580
+ return false;
581
+ }
582
+
583
+ return true;
584
+}
585
+
586
+static void transfer_fifo(XlnxZynqMPCANState *s, Fifo32 *fifo)
587
+{
588
+ qemu_can_frame frame;
589
+ uint32_t data[CAN_FRAME_SIZE];
590
+ int i;
591
+ bool can_tx = tx_ready_check(s);
592
+
593
+ if (!can_tx) {
594
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
595
+
596
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Controller is not enabled for data"
597
+ " transfer.\n", path);
598
+ can_update_irq(s);
599
+ return;
600
+ }
601
+
602
+ while (!fifo32_is_empty(fifo)) {
603
+ for (i = 0; i < CAN_FRAME_SIZE; i++) {
604
+ data[i] = fifo32_pop(fifo);
605
+ }
606
+
607
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, LBACK)) {
608
+ /*
609
+ * Controller is in loopback. In Loopback mode, the CAN core
610
+ * transmits a recessive bitstream on to the XlnxZynqMPCAN Bus.
611
+ * Any message transmitted is looped back to the RX line and
612
+ * acknowledged. The XlnxZynqMPCAN core receives any message
613
+ * that it transmits.
614
+ */
615
+ if (fifo32_is_full(&s->rx_fifo)) {
616
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOFLW, 1);
617
+ } else {
618
+ for (i = 0; i < CAN_FRAME_SIZE; i++) {
619
+ fifo32_push(&s->rx_fifo, data[i]);
620
+ }
621
+
622
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 1);
623
+ }
624
+ } else {
625
+ /* Normal mode Tx. */
626
+ generate_frame(&frame, data);
627
+
628
+ trace_xlnx_can_tx_data(frame.can_id, frame.can_dlc,
629
+ frame.data[0], frame.data[1],
630
+ frame.data[2], frame.data[3],
631
+ frame.data[4], frame.data[5],
632
+ frame.data[6], frame.data[7]);
633
+ can_bus_client_send(&s->bus_client, &frame, 1);
634
+ }
635
+ }
636
+
637
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXOK, 1);
638
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, TXBFLL, 0);
639
+
640
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP)) {
641
+ can_exit_sleep_mode(s);
642
+ }
643
+
644
+ can_update_irq(s);
645
+}
646
+
647
+static uint64_t can_srr_pre_write(RegisterInfo *reg, uint64_t val)
648
+{
649
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
650
+
651
+ ARRAY_FIELD_DP32(s->regs, SOFTWARE_RESET_REGISTER, CEN,
652
+ FIELD_EX32(val, SOFTWARE_RESET_REGISTER, CEN));
653
+
654
+ if (FIELD_EX32(val, SOFTWARE_RESET_REGISTER, SRST)) {
655
+ trace_xlnx_can_reset(val);
656
+
657
+ /* First, core will do software reset then will enter in config mode. */
658
+ can_config_reset(s);
659
+ }
660
+
661
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
662
+ can_config_mode(s);
663
+ } else {
664
+ /*
665
+ * Leave config mode. Now XlnxZynqMPCAN core will enter normal,
666
+ * sleep, snoop or loopback mode depending upon LBACK, SLEEP, SNOOP
667
+ * register states.
668
+ */
669
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, CONFIG, 0);
670
+
671
+ ptimer_transaction_begin(s->can_timer);
672
+ ptimer_set_count(s->can_timer, 0);
673
+ ptimer_transaction_commit(s->can_timer);
674
+
675
+ /* XlnxZynqMPCAN is out of config mode. It will send pending data. */
676
+ transfer_fifo(s, &s->txhpb_fifo);
677
+ transfer_fifo(s, &s->tx_fifo);
678
+ }
679
+
680
+ update_status_register_mode_bits(s);
681
+
682
+ return s->regs[R_SOFTWARE_RESET_REGISTER];
683
+}
684
+
685
+static uint64_t can_msr_pre_write(RegisterInfo *reg, uint64_t val)
686
+{
687
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
688
+ uint8_t multi_mode;
689
+
690
+ /*
691
+ * Multiple mode set check. This is done to make sure user doesn't set
692
+ * multiple modes.
693
+ */
694
+ multi_mode = FIELD_EX32(val, MODE_SELECT_REGISTER, LBACK) +
695
+ FIELD_EX32(val, MODE_SELECT_REGISTER, SLEEP) +
696
+ FIELD_EX32(val, MODE_SELECT_REGISTER, SNOOP);
697
+
698
+ if (multi_mode > 1) {
699
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
700
+
701
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to config"
702
+ " several modes simultaneously. One mode will be selected"
703
+ " according to their priority: LBACK > SLEEP > SNOOP.\n",
704
+ path);
705
+ }
706
+
707
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
708
+ /* We are in configuration mode, any mode can be selected. */
709
+ s->regs[R_MODE_SELECT_REGISTER] = val;
710
+ } else {
711
+ bool sleep_mode_bit = FIELD_EX32(val, MODE_SELECT_REGISTER, SLEEP);
712
+
713
+ ARRAY_FIELD_DP32(s->regs, MODE_SELECT_REGISTER, SLEEP, sleep_mode_bit);
714
+
715
+ if (FIELD_EX32(val, MODE_SELECT_REGISTER, LBACK)) {
716
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
717
+
718
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to set"
719
+ " LBACK mode without setting CEN bit as 0.\n",
720
+ path);
721
+ } else if (FIELD_EX32(val, MODE_SELECT_REGISTER, SNOOP)) {
722
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
723
+
724
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to set"
725
+ " SNOOP mode without setting CEN bit as 0.\n",
726
+ path);
727
+ }
728
+
729
+ update_status_register_mode_bits(s);
730
+ }
731
+
732
+ return s->regs[R_MODE_SELECT_REGISTER];
733
+}
734
+
735
+static uint64_t can_brpr_pre_write(RegisterInfo *reg, uint64_t val)
736
+{
737
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
738
+
739
+ /* Only allow writes when in config mode. */
740
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) {
741
+ return s->regs[R_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER];
742
+ }
743
+
744
+ return val;
745
+}
746
+
747
+static uint64_t can_btr_pre_write(RegisterInfo *reg, uint64_t val)
748
+{
749
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
750
+
751
+ /* Only allow writes when in config mode. */
752
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) {
753
+ return s->regs[R_ARBITRATION_PHASE_BIT_TIMING_REGISTER];
754
+ }
755
+
756
+ return val;
757
+}
758
+
759
+static uint64_t can_tcr_pre_write(RegisterInfo *reg, uint64_t val)
760
+{
761
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
762
+
763
+ if (FIELD_EX32(val, TIMESTAMP_REGISTER, CTS)) {
764
+ ptimer_transaction_begin(s->can_timer);
765
+ ptimer_set_count(s->can_timer, 0);
766
+ ptimer_transaction_commit(s->can_timer);
767
+ }
768
+
769
+ return 0;
770
+}
771
+
772
+static void update_rx_fifo(XlnxZynqMPCANState *s, const qemu_can_frame *frame)
773
+{
774
+ bool filter_pass = false;
775
+ uint16_t timestamp = 0;
776
+
777
+ /* If no filter is enabled. Message will be stored in FIFO. */
778
+ if (!((ARRAY_FIELD_EX32(s->regs, AFR, UAF1)) |
779
+ (ARRAY_FIELD_EX32(s->regs, AFR, UAF2)) |
780
+ (ARRAY_FIELD_EX32(s->regs, AFR, UAF3)) |
781
+ (ARRAY_FIELD_EX32(s->regs, AFR, UAF4)))) {
782
+ filter_pass = true;
783
+ }
784
+
785
+ /*
786
+ * Messages that pass any of the acceptance filters will be stored in
787
+ * the RX FIFO.
788
+ */
789
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF1)) {
790
+ uint32_t id_masked = s->regs[R_AFMR1] & frame->can_id;
791
+ uint32_t filter_id_masked = s->regs[R_AFMR1] & s->regs[R_AFIR1];
792
+
793
+ if (filter_id_masked == id_masked) {
794
+ filter_pass = true;
795
+ }
796
+ }
797
+
798
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF2)) {
799
+ uint32_t id_masked = s->regs[R_AFMR2] & frame->can_id;
800
+ uint32_t filter_id_masked = s->regs[R_AFMR2] & s->regs[R_AFIR2];
801
+
802
+ if (filter_id_masked == id_masked) {
803
+ filter_pass = true;
804
+ }
805
+ }
806
+
807
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF3)) {
808
+ uint32_t id_masked = s->regs[R_AFMR3] & frame->can_id;
809
+ uint32_t filter_id_masked = s->regs[R_AFMR3] & s->regs[R_AFIR3];
810
+
811
+ if (filter_id_masked == id_masked) {
812
+ filter_pass = true;
813
+ }
814
+ }
815
+
816
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF4)) {
817
+ uint32_t id_masked = s->regs[R_AFMR4] & frame->can_id;
818
+ uint32_t filter_id_masked = s->regs[R_AFMR4] & s->regs[R_AFIR4];
819
+
820
+ if (filter_id_masked == id_masked) {
821
+ filter_pass = true;
822
+ }
823
+ }
824
+
825
+ if (!filter_pass) {
826
+ trace_xlnx_can_rx_fifo_filter_reject(frame->can_id, frame->can_dlc);
827
+ return;
828
+ }
829
+
830
+ /* Store the message in fifo if it passed through any of the filters. */
831
+ if (filter_pass && frame->can_dlc <= MAX_DLC) {
832
+
833
+ if (fifo32_is_full(&s->rx_fifo)) {
834
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOFLW, 1);
835
+ } else {
836
+ timestamp = CAN_TIMER_MAX - ptimer_get_count(s->can_timer);
837
+
838
+ fifo32_push(&s->rx_fifo, frame->can_id);
839
+
840
+ fifo32_push(&s->rx_fifo, deposit32(0, R_RXFIFO_DLC_DLC_SHIFT,
841
+ R_RXFIFO_DLC_DLC_LENGTH,
842
+ frame->can_dlc) |
843
+ deposit32(0, R_RXFIFO_DLC_RXT_SHIFT,
844
+ R_RXFIFO_DLC_RXT_LENGTH,
845
+ timestamp));
846
+
847
+ /* First 32 bit of the data. */
848
+ fifo32_push(&s->rx_fifo, deposit32(0, R_TXFIFO_DATA1_DB3_SHIFT,
849
+ R_TXFIFO_DATA1_DB3_LENGTH,
850
+ frame->data[0]) |
851
+ deposit32(0, R_TXFIFO_DATA1_DB2_SHIFT,
852
+ R_TXFIFO_DATA1_DB2_LENGTH,
853
+ frame->data[1]) |
854
+ deposit32(0, R_TXFIFO_DATA1_DB1_SHIFT,
855
+ R_TXFIFO_DATA1_DB1_LENGTH,
856
+ frame->data[2]) |
857
+ deposit32(0, R_TXFIFO_DATA1_DB0_SHIFT,
858
+ R_TXFIFO_DATA1_DB0_LENGTH,
859
+ frame->data[3]));
860
+ /* Last 32 bit of the data. */
861
+ fifo32_push(&s->rx_fifo, deposit32(0, R_TXFIFO_DATA2_DB7_SHIFT,
862
+ R_TXFIFO_DATA2_DB7_LENGTH,
863
+ frame->data[4]) |
864
+ deposit32(0, R_TXFIFO_DATA2_DB6_SHIFT,
865
+ R_TXFIFO_DATA2_DB6_LENGTH,
866
+ frame->data[5]) |
867
+ deposit32(0, R_TXFIFO_DATA2_DB5_SHIFT,
868
+ R_TXFIFO_DATA2_DB5_LENGTH,
869
+ frame->data[6]) |
870
+ deposit32(0, R_TXFIFO_DATA2_DB4_SHIFT,
871
+ R_TXFIFO_DATA2_DB4_LENGTH,
872
+ frame->data[7]));
873
+
874
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 1);
875
+ trace_xlnx_can_rx_data(frame->can_id, frame->can_dlc,
876
+ frame->data[0], frame->data[1],
877
+ frame->data[2], frame->data[3],
878
+ frame->data[4], frame->data[5],
879
+ frame->data[6], frame->data[7]);
880
+ }
881
+
882
+ can_update_irq(s);
883
+ }
884
+}
885
+
886
+static uint64_t can_rxfifo_pre_read(RegisterInfo *reg, uint64_t val)
887
+{
888
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
889
+
890
+ if (!fifo32_is_empty(&s->rx_fifo)) {
891
+ val = fifo32_pop(&s->rx_fifo);
892
+ } else {
893
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXUFLW, 1);
894
+ }
895
+
896
+ can_update_irq(s);
897
+ return val;
898
+}
899
+
900
+static void can_filter_enable_post_write(RegisterInfo *reg, uint64_t val)
901
+{
902
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
903
+
904
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF1) &&
905
+ ARRAY_FIELD_EX32(s->regs, AFR, UAF2) &&
906
+ ARRAY_FIELD_EX32(s->regs, AFR, UAF3) &&
907
+ ARRAY_FIELD_EX32(s->regs, AFR, UAF4)) {
908
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, ACFBSY, 1);
909
+ } else {
910
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, ACFBSY, 0);
911
+ }
912
+}
913
+
914
+static uint64_t can_filter_mask_pre_write(RegisterInfo *reg, uint64_t val)
915
+{
916
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
917
+ uint32_t reg_idx = (reg->access->addr) / 4;
918
+ uint32_t filter_number = (reg_idx - R_AFMR1) / 2;
919
+
920
+ /* modify an acceptance filter, the corresponding UAF bit should be '0'. */
921
+ if (!(s->regs[R_AFR] & (1 << filter_number))) {
922
+ s->regs[reg_idx] = val;
923
+
924
+ trace_xlnx_can_filter_mask_pre_write(filter_number, s->regs[reg_idx]);
925
+ } else {
926
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
927
+
928
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter %d"
929
+ " mask is not set as corresponding UAF bit is not 0.\n",
930
+ path, filter_number + 1);
931
+ }
932
+
933
+ return s->regs[reg_idx];
934
+}
935
+
936
+static uint64_t can_filter_id_pre_write(RegisterInfo *reg, uint64_t val)
937
+{
938
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
939
+ uint32_t reg_idx = (reg->access->addr) / 4;
940
+ uint32_t filter_number = (reg_idx - R_AFIR1) / 2;
941
+
942
+ if (!(s->regs[R_AFR] & (1 << filter_number))) {
943
+ s->regs[reg_idx] = val;
944
+
945
+ trace_xlnx_can_filter_id_pre_write(filter_number, s->regs[reg_idx]);
946
+ } else {
947
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
948
+
949
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter %d"
950
+ " id is not set as corresponding UAF bit is not 0.\n",
951
+ path, filter_number + 1);
952
+ }
953
+
954
+ return s->regs[reg_idx];
955
+}
956
+
957
+static void can_tx_post_write(RegisterInfo *reg, uint64_t val)
958
+{
959
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
960
+
961
+ bool is_txhpb = reg->access->addr > A_TXFIFO_DATA2;
962
+
963
+ bool initiate_transfer = (reg->access->addr == A_TXFIFO_DATA2) ||
964
+ (reg->access->addr == A_TXHPB_DATA2);
965
+
966
+ Fifo32 *f = is_txhpb ? &s->txhpb_fifo : &s->tx_fifo;
967
+
968
+ if (!fifo32_is_full(f)) {
969
+ fifo32_push(f, val);
970
+ } else {
971
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
972
+
973
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: TX FIFO is full.\n", path);
974
+ }
975
+
976
+ /* Initiate the message send if TX register is written. */
977
+ if (initiate_transfer &&
978
+ ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) {
979
+ transfer_fifo(s, f);
980
+ }
981
+
982
+ can_update_irq(s);
983
+}
984
+
985
+static const RegisterAccessInfo can_regs_info[] = {
986
+ { .name = "SOFTWARE_RESET_REGISTER",
987
+ .addr = A_SOFTWARE_RESET_REGISTER,
988
+ .rsvd = 0xfffffffc,
989
+ .pre_write = can_srr_pre_write,
990
+ },{ .name = "MODE_SELECT_REGISTER",
991
+ .addr = A_MODE_SELECT_REGISTER,
992
+ .rsvd = 0xfffffff8,
993
+ .pre_write = can_msr_pre_write,
994
+ },{ .name = "ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER",
995
+ .addr = A_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER,
996
+ .rsvd = 0xffffff00,
997
+ .pre_write = can_brpr_pre_write,
998
+ },{ .name = "ARBITRATION_PHASE_BIT_TIMING_REGISTER",
999
+ .addr = A_ARBITRATION_PHASE_BIT_TIMING_REGISTER,
1000
+ .rsvd = 0xfffffe00,
1001
+ .pre_write = can_btr_pre_write,
1002
+ },{ .name = "ERROR_COUNTER_REGISTER",
1003
+ .addr = A_ERROR_COUNTER_REGISTER,
1004
+ .rsvd = 0xffff0000,
1005
+ .ro = 0xffffffff,
1006
+ },{ .name = "ERROR_STATUS_REGISTER",
1007
+ .addr = A_ERROR_STATUS_REGISTER,
1008
+ .rsvd = 0xffffffe0,
1009
+ .w1c = 0x1f,
1010
+ },{ .name = "STATUS_REGISTER", .addr = A_STATUS_REGISTER,
1011
+ .reset = 0x1,
1012
+ .rsvd = 0xffffe000,
1013
+ .ro = 0x1fff,
1014
+ },{ .name = "INTERRUPT_STATUS_REGISTER",
1015
+ .addr = A_INTERRUPT_STATUS_REGISTER,
1016
+ .reset = 0x6000,
1017
+ .rsvd = 0xffff8000,
1018
+ .ro = 0x7fff,
1019
+ },{ .name = "INTERRUPT_ENABLE_REGISTER",
1020
+ .addr = A_INTERRUPT_ENABLE_REGISTER,
1021
+ .rsvd = 0xffff8000,
1022
+ .post_write = can_ier_post_write,
1023
+ },{ .name = "INTERRUPT_CLEAR_REGISTER",
1024
+ .addr = A_INTERRUPT_CLEAR_REGISTER,
1025
+ .rsvd = 0xffff8000,
1026
+ .pre_write = can_icr_pre_write,
1027
+ },{ .name = "TIMESTAMP_REGISTER",
1028
+ .addr = A_TIMESTAMP_REGISTER,
1029
+ .rsvd = 0xfffffffe,
1030
+ .pre_write = can_tcr_pre_write,
1031
+ },{ .name = "WIR", .addr = A_WIR,
1032
+ .reset = 0x3f3f,
1033
+ .rsvd = 0xffff0000,
1034
+ },{ .name = "TXFIFO_ID", .addr = A_TXFIFO_ID,
1035
+ .post_write = can_tx_post_write,
1036
+ },{ .name = "TXFIFO_DLC", .addr = A_TXFIFO_DLC,
1037
+ .rsvd = 0xfffffff,
1038
+ .post_write = can_tx_post_write,
1039
+ },{ .name = "TXFIFO_DATA1", .addr = A_TXFIFO_DATA1,
1040
+ .post_write = can_tx_post_write,
1041
+ },{ .name = "TXFIFO_DATA2", .addr = A_TXFIFO_DATA2,
1042
+ .post_write = can_tx_post_write,
1043
+ },{ .name = "TXHPB_ID", .addr = A_TXHPB_ID,
1044
+ .post_write = can_tx_post_write,
1045
+ },{ .name = "TXHPB_DLC", .addr = A_TXHPB_DLC,
1046
+ .rsvd = 0xfffffff,
1047
+ .post_write = can_tx_post_write,
1048
+ },{ .name = "TXHPB_DATA1", .addr = A_TXHPB_DATA1,
1049
+ .post_write = can_tx_post_write,
1050
+ },{ .name = "TXHPB_DATA2", .addr = A_TXHPB_DATA2,
1051
+ .post_write = can_tx_post_write,
1052
+ },{ .name = "RXFIFO_ID", .addr = A_RXFIFO_ID,
1053
+ .ro = 0xffffffff,
1054
+ .post_read = can_rxfifo_pre_read,
1055
+ },{ .name = "RXFIFO_DLC", .addr = A_RXFIFO_DLC,
1056
+ .rsvd = 0xfff0000,
1057
+ .post_read = can_rxfifo_pre_read,
1058
+ },{ .name = "RXFIFO_DATA1", .addr = A_RXFIFO_DATA1,
1059
+ .post_read = can_rxfifo_pre_read,
1060
+ },{ .name = "RXFIFO_DATA2", .addr = A_RXFIFO_DATA2,
1061
+ .post_read = can_rxfifo_pre_read,
1062
+ },{ .name = "AFR", .addr = A_AFR,
1063
+ .rsvd = 0xfffffff0,
1064
+ .post_write = can_filter_enable_post_write,
1065
+ },{ .name = "AFMR1", .addr = A_AFMR1,
1066
+ .pre_write = can_filter_mask_pre_write,
1067
+ },{ .name = "AFIR1", .addr = A_AFIR1,
1068
+ .pre_write = can_filter_id_pre_write,
1069
+ },{ .name = "AFMR2", .addr = A_AFMR2,
1070
+ .pre_write = can_filter_mask_pre_write,
1071
+ },{ .name = "AFIR2", .addr = A_AFIR2,
1072
+ .pre_write = can_filter_id_pre_write,
1073
+ },{ .name = "AFMR3", .addr = A_AFMR3,
1074
+ .pre_write = can_filter_mask_pre_write,
1075
+ },{ .name = "AFIR3", .addr = A_AFIR3,
1076
+ .pre_write = can_filter_id_pre_write,
1077
+ },{ .name = "AFMR4", .addr = A_AFMR4,
1078
+ .pre_write = can_filter_mask_pre_write,
1079
+ },{ .name = "AFIR4", .addr = A_AFIR4,
1080
+ .pre_write = can_filter_id_pre_write,
1081
+ }
1082
+};
1083
+
1084
+static void xlnx_zynqmp_can_ptimer_cb(void *opaque)
1085
+{
1086
+ /* No action required on the timer rollover. */
1087
+}
1088
+
1089
+static const MemoryRegionOps can_ops = {
1090
+ .read = register_read_memory,
1091
+ .write = register_write_memory,
1092
+ .endianness = DEVICE_LITTLE_ENDIAN,
1093
+ .valid = {
1094
+ .min_access_size = 4,
1095
+ .max_access_size = 4,
1096
+ },
1097
+};
1098
+
1099
+static void xlnx_zynqmp_can_reset_init(Object *obj, ResetType type)
1100
+{
1101
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(obj);
1102
+ unsigned int i;
1103
+
1104
+ for (i = R_RXFIFO_ID; i < ARRAY_SIZE(s->reg_info); ++i) {
1105
+ register_reset(&s->reg_info[i]);
1106
+ }
1107
+
1108
+ ptimer_transaction_begin(s->can_timer);
1109
+ ptimer_set_count(s->can_timer, 0);
1110
+ ptimer_transaction_commit(s->can_timer);
1111
+}
1112
+
1113
+static void xlnx_zynqmp_can_reset_hold(Object *obj)
1114
+{
1115
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(obj);
1116
+ unsigned int i;
1117
+
1118
+ for (i = 0; i < R_RXFIFO_ID; ++i) {
1119
+ register_reset(&s->reg_info[i]);
1120
+ }
1121
+
1122
+ /*
1123
+ * Reset FIFOs when CAN model is reset. This will clear the fifo writes
1124
+ * done by post_write which gets called from register_reset function,
1125
+ * post_write handle will not be able to trigger tx because CAN will be
1126
+ * disabled when software_reset_register is cleared first.
1127
+ */
1128
+ fifo32_reset(&s->rx_fifo);
1129
+ fifo32_reset(&s->tx_fifo);
1130
+ fifo32_reset(&s->txhpb_fifo);
1131
+}
1132
+
1133
+static bool xlnx_zynqmp_can_can_receive(CanBusClientState *client)
1134
+{
1135
+ XlnxZynqMPCANState *s = container_of(client, XlnxZynqMPCANState,
1136
+ bus_client);
1137
+
1138
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, SRST)) {
1139
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1140
+
1141
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Controller is in reset state.\n",
1142
+ path);
1143
+ return false;
1144
+ }
1145
+
1146
+ if ((ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) == 0) {
1147
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1148
+
1149
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Controller is disabled. Incoming"
1150
+ " messages will be discarded.\n", path);
1151
+ return false;
1152
+ }
1153
+
1154
+ return true;
1155
+}
1156
+
1157
+static ssize_t xlnx_zynqmp_can_receive(CanBusClientState *client,
1158
+ const qemu_can_frame *buf, size_t buf_size) {
1159
+ XlnxZynqMPCANState *s = container_of(client, XlnxZynqMPCANState,
1160
+ bus_client);
1161
+ const qemu_can_frame *frame = buf;
1162
+
1163
+ if (buf_size <= 0) {
1164
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1165
+
1166
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Error in the data received.\n",
1167
+ path);
1168
+ return 0;
1169
+ }
1170
+
1171
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SNOOP)) {
1172
+ /* Snoop Mode: Just keep the data. no response back. */
1173
+ update_rx_fifo(s, frame);
1174
+ } else if ((ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP))) {
1175
+ /*
1176
+ * XlnxZynqMPCAN is in sleep mode. Any data on bus will bring it to wake
1177
+ * up state.
1178
+ */
1179
+ can_exit_sleep_mode(s);
1180
+ update_rx_fifo(s, frame);
1181
+ } else if ((ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP)) == 0) {
1182
+ update_rx_fifo(s, frame);
1183
+ } else {
1184
+ /*
1185
+ * XlnxZynqMPCAN will not participate in normal bus communication
1186
+ * and will not receive any messages transmitted by other CAN nodes.
1187
+ */
1188
+ trace_xlnx_can_rx_discard(s->regs[R_STATUS_REGISTER]);
1189
+ }
1190
+
1191
+ return 1;
1192
+}
1193
+
1194
+static CanBusClientInfo can_xilinx_bus_client_info = {
1195
+ .can_receive = xlnx_zynqmp_can_can_receive,
1196
+ .receive = xlnx_zynqmp_can_receive,
1197
+};
1198
+
1199
+static int xlnx_zynqmp_can_connect_to_bus(XlnxZynqMPCANState *s,
1200
+ CanBusState *bus)
1201
+{
1202
+ s->bus_client.info = &can_xilinx_bus_client_info;
1203
+
1204
+ if (can_bus_insert_client(bus, &s->bus_client) < 0) {
1205
+ return -1;
1206
+ }
1207
+ return 0;
1208
+}
1209
+
1210
+static void xlnx_zynqmp_can_realize(DeviceState *dev, Error **errp)
1211
+{
1212
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(dev);
1213
+
1214
+ if (s->canbus) {
1215
+ if (xlnx_zynqmp_can_connect_to_bus(s, s->canbus) < 0) {
1216
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1217
+
1218
+ error_setg(errp, "%s: xlnx_zynqmp_can_connect_to_bus"
1219
+ " failed.", path);
1220
+ return;
1221
+ }
1222
+ }
1223
+
1224
+ /* Create RX FIFO, TXFIFO, TXHPB storage. */
1225
+ fifo32_create(&s->rx_fifo, RXFIFO_SIZE);
1226
+ fifo32_create(&s->tx_fifo, RXFIFO_SIZE);
1227
+ fifo32_create(&s->txhpb_fifo, CAN_FRAME_SIZE);
1228
+
1229
+ /* Allocate a new timer. */
1230
+ s->can_timer = ptimer_init(xlnx_zynqmp_can_ptimer_cb, s,
1231
+ PTIMER_POLICY_DEFAULT);
1232
+
1233
+ ptimer_transaction_begin(s->can_timer);
1234
+
1235
+ ptimer_set_freq(s->can_timer, s->cfg.ext_clk_freq);
1236
+ ptimer_set_limit(s->can_timer, CAN_TIMER_MAX, 1);
1237
+ ptimer_run(s->can_timer, 0);
1238
+ ptimer_transaction_commit(s->can_timer);
1239
+}
1240
+
1241
+static void xlnx_zynqmp_can_init(Object *obj)
1242
+{
1243
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(obj);
1244
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
1245
+
1246
+ RegisterInfoArray *reg_array;
1247
+
1248
+ memory_region_init(&s->iomem, obj, TYPE_XLNX_ZYNQMP_CAN,
1249
+ XLNX_ZYNQMP_CAN_R_MAX * 4);
1250
+ reg_array = register_init_block32(DEVICE(obj), can_regs_info,
1251
+ ARRAY_SIZE(can_regs_info),
1252
+ s->reg_info, s->regs,
1253
+ &can_ops,
1254
+ XLNX_ZYNQMP_CAN_ERR_DEBUG,
1255
+ XLNX_ZYNQMP_CAN_R_MAX * 4);
1256
+
1257
+ memory_region_add_subregion(&s->iomem, 0x00, &reg_array->mem);
1258
+ sysbus_init_mmio(sbd, &s->iomem);
1259
+ sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
1260
+}
1261
+
1262
+static const VMStateDescription vmstate_can = {
1263
+ .name = TYPE_XLNX_ZYNQMP_CAN,
1264
+ .version_id = 1,
1265
+ .minimum_version_id = 1,
1266
+ .fields = (VMStateField[]) {
1267
+ VMSTATE_FIFO32(rx_fifo, XlnxZynqMPCANState),
1268
+ VMSTATE_FIFO32(tx_fifo, XlnxZynqMPCANState),
1269
+ VMSTATE_FIFO32(txhpb_fifo, XlnxZynqMPCANState),
1270
+ VMSTATE_UINT32_ARRAY(regs, XlnxZynqMPCANState, XLNX_ZYNQMP_CAN_R_MAX),
1271
+ VMSTATE_PTIMER(can_timer, XlnxZynqMPCANState),
1272
+ VMSTATE_END_OF_LIST(),
1273
+ }
1274
+};
1275
+
1276
+static Property xlnx_zynqmp_can_properties[] = {
1277
+ DEFINE_PROP_UINT32("ext_clk_freq", XlnxZynqMPCANState, cfg.ext_clk_freq,
1278
+ CAN_DEFAULT_CLOCK),
1279
+ DEFINE_PROP_LINK("canbus", XlnxZynqMPCANState, canbus, TYPE_CAN_BUS,
1280
+ CanBusState *),
1281
+ DEFINE_PROP_END_OF_LIST(),
1282
+};
1283
+
1284
+static void xlnx_zynqmp_can_class_init(ObjectClass *klass, void *data)
1285
+{
1286
+ DeviceClass *dc = DEVICE_CLASS(klass);
1287
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
1288
+
1289
+ rc->phases.enter = xlnx_zynqmp_can_reset_init;
1290
+ rc->phases.hold = xlnx_zynqmp_can_reset_hold;
1291
+ dc->realize = xlnx_zynqmp_can_realize;
1292
+ device_class_set_props(dc, xlnx_zynqmp_can_properties);
1293
+ dc->vmsd = &vmstate_can;
1294
+}
1295
+
1296
+static const TypeInfo can_info = {
1297
+ .name = TYPE_XLNX_ZYNQMP_CAN,
1298
+ .parent = TYPE_SYS_BUS_DEVICE,
1299
+ .instance_size = sizeof(XlnxZynqMPCANState),
1300
+ .class_init = xlnx_zynqmp_can_class_init,
1301
+ .instance_init = xlnx_zynqmp_can_init,
1302
+};
1303
+
1304
+static void can_register_types(void)
1305
+{
1306
+ type_register_static(&can_info);
1307
+}
1308
+
1309
+type_init(can_register_types)
1310
diff --git a/hw/Kconfig b/hw/Kconfig
262
index XXXXXXX..XXXXXXX 100644
1311
index XXXXXXX..XXXXXXX 100644
263
--- a/tests/tcg/aarch64/Makefile.target
1312
--- a/hw/Kconfig
264
+++ b/tests/tcg/aarch64/Makefile.target
1313
+++ b/hw/Kconfig
265
@@ -XXX,XX +XXX,XX @@ run-pauth-%: QEMU_OPTS += -cpu max
1314
@@ -XXX,XX +XXX,XX @@ config XILINX_AXI
266
run-plugin-pauth-%: QEMU_OPTS += -cpu max
1315
config XLNX_ZYNQMP
267
endif
1316
bool
268
1317
select REGISTER
269
+# BTI Tests
1318
+ select CAN_BUS
270
+# bti-1 tests the elf notes, so we require special compiler support.
1319
diff --git a/hw/net/can/meson.build b/hw/net/can/meson.build
271
+ifneq ($(DOCKER_IMAGE)$(CROSS_CC_HAS_ARMV8_BTI),)
1320
index XXXXXXX..XXXXXXX 100644
272
+AARCH64_TESTS += bti-1
1321
--- a/hw/net/can/meson.build
273
+bti-1: CFLAGS += -mbranch-protection=standard
1322
+++ b/hw/net/can/meson.build
274
+bti-1: LDFLAGS += -nostdlib
1323
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_CAN_PCI', if_true: files('can_pcm3680_pci.c'))
275
+endif
1324
softmmu_ss.add(when: 'CONFIG_CAN_PCI', if_true: files('can_mioe3680_pci.c'))
276
+# bti-2 tests PROT_BTI, so no special compiler support required.
1325
softmmu_ss.add(when: 'CONFIG_CAN_CTUCANFD', if_true: files('ctucan_core.c'))
277
+AARCH64_TESTS += bti-2
1326
softmmu_ss.add(when: 'CONFIG_CAN_CTUCANFD_PCI', if_true: files('ctucan_pci.c'))
278
+
1327
+softmmu_ss.add(when: 'CONFIG_XLNX_ZYNQMP', if_true: files('xlnx-zynqmp-can.c'))
279
# Semihosting smoke test for linux-user
1328
diff --git a/hw/net/can/trace-events b/hw/net/can/trace-events
280
AARCH64_TESTS += semihosting
1329
new file mode 100644
281
run-semihosting: semihosting
1330
index XXXXXXX..XXXXXXX
282
diff --git a/tests/tcg/configure.sh b/tests/tcg/configure.sh
1331
--- /dev/null
283
index XXXXXXX..XXXXXXX 100755
1332
+++ b/hw/net/can/trace-events
284
--- a/tests/tcg/configure.sh
1333
@@ -XXX,XX +XXX,XX @@
285
+++ b/tests/tcg/configure.sh
1334
+# xlnx-zynqmp-can.c
286
@@ -XXX,XX +XXX,XX @@ for target in $target_list; do
1335
+xlnx_can_update_irq(uint32_t isr, uint32_t ier, uint32_t irq) "ISR: 0x%08x IER: 0x%08x IRQ: 0x%08x"
287
-march=armv8.3-a -o $TMPE $TMPC; then
1336
+xlnx_can_reset(uint32_t val) "Resetting controller with value = 0x%08x"
288
echo "CROSS_CC_HAS_ARMV8_3=y" >> $config_target_mak
1337
+xlnx_can_rx_fifo_filter_reject(uint32_t id, uint8_t dlc) "Frame: ID: 0x%08x DLC: 0x%02x"
289
fi
1338
+xlnx_can_filter_id_pre_write(uint8_t filter_num, uint32_t value) "Filter%d ID: 0x%08x"
290
+ if do_compiler "$target_compiler" $target_compiler_cflags \
1339
+xlnx_can_filter_mask_pre_write(uint8_t filter_num, uint32_t value) "Filter%d MASK: 0x%08x"
291
+ -mbranch-protection=standard -o $TMPE $TMPC; then
1340
+xlnx_can_tx_data(uint32_t id, uint8_t dlc, uint8_t db0, uint8_t db1, uint8_t db2, uint8_t db3, uint8_t db4, uint8_t db5, uint8_t db6, uint8_t db7) "Frame: ID: 0x%08x DLC: 0x%02x DATA: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x"
292
+ echo "CROSS_CC_HAS_ARMV8_BTI=y" >> $config_target_mak
1341
+xlnx_can_rx_data(uint32_t id, uint32_t dlc, uint8_t db0, uint8_t db1, uint8_t db2, uint8_t db3, uint8_t db4, uint8_t db5, uint8_t db6, uint8_t db7) "Frame: ID: 0x%08x DLC: 0x%02x DATA: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x"
293
+ fi
1342
+xlnx_can_rx_discard(uint32_t status) "Controller is not enabled for bus communication. Status Register: 0x%08x"
294
;;
295
esac
296
297
--
1343
--
298
2.20.1
1344
2.20.1
299
1345
300
1346
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
2
2
3
This peripheral has 1 free-running timer and 4 compare registers.
3
Connect CAN0 and CAN1 on the ZynqMP.
4
4
5
Only the free-running timer is implemented. Add support the
5
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
6
COMPARE registers (each register is wired to an IRQ).
6
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
7
7
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
8
Reference: "BCM2835 ARM Peripherals" datasheet [*]
8
Message-id: 1605728926-352690-3-git-send-email-fnu.vikram@xilinx.com
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
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
28
---
10
---
29
include/hw/timer/bcm2835_systmr.h | 11 +++++--
11
include/hw/arm/xlnx-zynqmp.h | 8 ++++++++
30
hw/timer/bcm2835_systmr.c | 48 ++++++++++++++++++++-----------
12
hw/arm/xlnx-zcu102.c | 20 ++++++++++++++++++++
31
hw/timer/trace-events | 6 ++--
13
hw/arm/xlnx-zynqmp.c | 34 ++++++++++++++++++++++++++++++++++
32
3 files changed, 44 insertions(+), 21 deletions(-)
14
3 files changed, 62 insertions(+)
33
15
34
diff --git a/include/hw/timer/bcm2835_systmr.h b/include/hw/timer/bcm2835_systmr.h
16
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
35
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
36
--- a/include/hw/timer/bcm2835_systmr.h
18
--- a/include/hw/arm/xlnx-zynqmp.h
37
+++ b/include/hw/timer/bcm2835_systmr.h
19
+++ b/include/hw/arm/xlnx-zynqmp.h
38
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@
39
21
#include "hw/intc/arm_gic.h"
40
#include "hw/sysbus.h"
22
#include "hw/net/cadence_gem.h"
41
#include "hw/irq.h"
23
#include "hw/char/cadence_uart.h"
42
+#include "qemu/timer.h"
24
+#include "hw/net/xlnx-zynqmp-can.h"
25
#include "hw/ide/ahci.h"
26
#include "hw/sd/sdhci.h"
27
#include "hw/ssi/xilinx_spips.h"
28
@@ -XXX,XX +XXX,XX @@
29
#include "hw/cpu/cluster.h"
30
#include "target/arm/cpu.h"
43
#include "qom/object.h"
31
#include "qom/object.h"
44
32
+#include "net/can_emu.h"
45
#define TYPE_BCM2835_SYSTIMER "bcm2835-sys-timer"
33
46
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(BCM2835SystemTimerState, BCM2835_SYSTIMER)
34
#define TYPE_XLNX_ZYNQMP "xlnx,zynqmp"
47
35
OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
48
#define BCM2835_SYSTIMER_COUNT 4
36
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
49
37
#define XLNX_ZYNQMP_NUM_RPU_CPUS 2
50
+typedef struct {
38
#define XLNX_ZYNQMP_NUM_GEMS 4
51
+ unsigned id;
39
#define XLNX_ZYNQMP_NUM_UARTS 2
52
+ QEMUTimer timer;
40
+#define XLNX_ZYNQMP_NUM_CAN 2
53
+ qemu_irq irq;
41
+#define XLNX_ZYNQMP_CAN_REF_CLK (24 * 1000 * 1000)
54
+ BCM2835SystemTimerState *state;
42
#define XLNX_ZYNQMP_NUM_SDHCI 2
55
+} BCM2835SystemTimerCompare;
43
#define XLNX_ZYNQMP_NUM_SPIS 2
44
#define XLNX_ZYNQMP_NUM_GDMA_CH 8
45
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
46
47
CadenceGEMState gem[XLNX_ZYNQMP_NUM_GEMS];
48
CadenceUARTState uart[XLNX_ZYNQMP_NUM_UARTS];
49
+ XlnxZynqMPCANState can[XLNX_ZYNQMP_NUM_CAN];
50
SysbusAHCIState sata;
51
SDHCIState sdhci[XLNX_ZYNQMP_NUM_SDHCI];
52
XilinxSPIPS spi[XLNX_ZYNQMP_NUM_SPIS];
53
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
54
bool virt;
55
/* Has the RPU subsystem? */
56
bool has_rpu;
56
+
57
+
57
struct BCM2835SystemTimerState {
58
+ /* CAN bus. */
58
/*< private >*/
59
+ CanBusState *canbus[XLNX_ZYNQMP_NUM_CAN];
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
};
60
};
71
61
72
#endif
62
#endif
73
diff --git a/hw/timer/bcm2835_systmr.c b/hw/timer/bcm2835_systmr.c
63
diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c
74
index XXXXXXX..XXXXXXX 100644
64
index XXXXXXX..XXXXXXX 100644
75
--- a/hw/timer/bcm2835_systmr.c
65
--- a/hw/arm/xlnx-zcu102.c
76
+++ b/hw/timer/bcm2835_systmr.c
66
+++ b/hw/arm/xlnx-zcu102.c
77
@@ -XXX,XX +XXX,XX @@ REG32(COMPARE1, 0x10)
67
@@ -XXX,XX +XXX,XX @@
78
REG32(COMPARE2, 0x14)
68
#include "sysemu/qtest.h"
79
REG32(COMPARE3, 0x18)
69
#include "sysemu/device_tree.h"
80
70
#include "qom/object.h"
81
-static void bcm2835_systmr_update_irq(BCM2835SystemTimerState *s)
71
+#include "net/can_emu.h"
82
+static void bcm2835_systmr_timer_expire(void *opaque)
72
83
{
73
struct XlnxZCU102 {
84
- bool enable = !!s->reg.ctrl_status;
74
MachineState parent_obj;
85
+ BCM2835SystemTimerCompare *tmr = opaque;
75
@@ -XXX,XX +XXX,XX @@ struct XlnxZCU102 {
86
76
bool secure;
87
- trace_bcm2835_systmr_irq(enable);
77
bool virt;
88
- qemu_set_irq(s->irq, enable);
78
89
-}
79
+ CanBusState *canbus[XLNX_ZYNQMP_NUM_CAN];
90
-
80
+
91
-static void bcm2835_systmr_update_compare(BCM2835SystemTimerState *s,
81
struct arm_boot_info binfo;
92
- unsigned timer_index)
82
};
93
-{
83
94
- /* TODO fow now, since neither Linux nor U-boot use these timers. */
84
@@ -XXX,XX +XXX,XX @@ static void xlnx_zcu102_init(MachineState *machine)
95
- qemu_log_mask(LOG_UNIMP, "COMPARE register %u not implemented\n",
85
object_property_set_bool(OBJECT(&s->soc), "virtualization", s->virt,
96
- timer_index);
86
&error_fatal);
97
+ trace_bcm2835_systmr_timer_expired(tmr->id);
87
98
+ tmr->state->reg.ctrl_status |= 1 << tmr->id;
88
+ for (i = 0; i < XLNX_ZYNQMP_NUM_CAN; i++) {
99
+ qemu_set_irq(tmr->irq, 1);
89
+ gchar *bus_name = g_strdup_printf("canbus%d", i);
90
+
91
+ object_property_set_link(OBJECT(&s->soc), bus_name,
92
+ OBJECT(s->canbus[i]), &error_fatal);
93
+ g_free(bus_name);
94
+ }
95
+
96
qdev_realize(DEVICE(&s->soc), NULL, &error_fatal);
97
98
/* Create and plug in the SD cards */
99
@@ -XXX,XX +XXX,XX @@ static void xlnx_zcu102_machine_instance_init(Object *obj)
100
s->secure = false;
101
/* Default to virt (EL2) being disabled */
102
s->virt = false;
103
+ object_property_add_link(obj, "xlnx-zcu102.canbus0", TYPE_CAN_BUS,
104
+ (Object **)&s->canbus[0],
105
+ object_property_allow_set_link,
106
+ 0);
107
+
108
+ object_property_add_link(obj, "xlnx-zcu102.canbus1", TYPE_CAN_BUS,
109
+ (Object **)&s->canbus[1],
110
+ object_property_allow_set_link,
111
+ 0);
100
}
112
}
101
113
102
static uint64_t bcm2835_systmr_read(void *opaque, hwaddr offset,
114
static void xlnx_zcu102_machine_class_init(ObjectClass *oc, void *data)
103
@@ -XXX,XX +XXX,XX @@ static uint64_t bcm2835_systmr_read(void *opaque, hwaddr offset,
115
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
104
}
116
index XXXXXXX..XXXXXXX 100644
105
117
--- a/hw/arm/xlnx-zynqmp.c
106
static void bcm2835_systmr_write(void *opaque, hwaddr offset,
118
+++ b/hw/arm/xlnx-zynqmp.c
107
- uint64_t value, unsigned size)
119
@@ -XXX,XX +XXX,XX @@ static const int uart_intr[XLNX_ZYNQMP_NUM_UARTS] = {
108
+ uint64_t value64, unsigned size)
120
21, 22,
109
{
121
};
110
BCM2835SystemTimerState *s = BCM2835_SYSTIMER(opaque);
122
111
+ int index;
123
+static const uint64_t can_addr[XLNX_ZYNQMP_NUM_CAN] = {
112
+ uint32_t value = value64;
124
+ 0xFF060000, 0xFF070000,
113
+ uint32_t triggers_delay_us;
125
+};
114
+ uint64_t now;
126
+
115
127
+static const int can_intr[XLNX_ZYNQMP_NUM_CAN] = {
116
trace_bcm2835_systmr_write(offset, value);
128
+ 23, 24,
117
switch (offset) {
129
+};
118
case A_CTRL_STATUS:
130
+
119
s->reg.ctrl_status &= ~value; /* Ack */
131
static const uint64_t sdhci_addr[XLNX_ZYNQMP_NUM_SDHCI] = {
120
- bcm2835_systmr_update_irq(s);
132
0xFF160000, 0xFF170000,
121
+ for (index = 0; index < ARRAY_SIZE(s->tmr); index++) {
133
};
122
+ if (extract32(value, index, 1)) {
134
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_init(Object *obj)
123
+ trace_bcm2835_systmr_irq_ack(index);
135
TYPE_CADENCE_UART);
124
+ qemu_set_irq(s->tmr[index].irq, 0);
136
}
125
+ }
137
138
+ for (i = 0; i < XLNX_ZYNQMP_NUM_CAN; i++) {
139
+ object_initialize_child(obj, "can[*]", &s->can[i],
140
+ TYPE_XLNX_ZYNQMP_CAN);
141
+ }
142
+
143
object_initialize_child(obj, "sata", &s->sata, TYPE_SYSBUS_AHCI);
144
145
for (i = 0; i < XLNX_ZYNQMP_NUM_SDHCI; i++) {
146
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
147
gic_spi[uart_intr[i]]);
148
}
149
150
+ for (i = 0; i < XLNX_ZYNQMP_NUM_CAN; i++) {
151
+ object_property_set_int(OBJECT(&s->can[i]), "ext_clk_freq",
152
+ XLNX_ZYNQMP_CAN_REF_CLK, &error_abort);
153
+
154
+ object_property_set_link(OBJECT(&s->can[i]), "canbus",
155
+ OBJECT(s->canbus[i]), &error_fatal);
156
+
157
+ sysbus_realize(SYS_BUS_DEVICE(&s->can[i]), &err);
158
+ if (err) {
159
+ error_propagate(errp, err);
160
+ return;
126
+ }
161
+ }
127
break;
162
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->can[i]), 0, can_addr[i]);
128
case A_COMPARE0 ... A_COMPARE3:
163
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->can[i]), 0,
129
- s->reg.compare[(offset - A_COMPARE0) >> 2] = value;
164
+ gic_spi[can_intr[i]]);
130
- bcm2835_systmr_update_compare(s, (offset - A_COMPARE0) >> 2);
165
+ }
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);
146
+
166
+
147
+ for (size_t i = 0; i < ARRAY_SIZE(s->tmr); i++) {
167
object_property_set_int(OBJECT(&s->sata), "num-ports", SATA_NUM_PORTS,
148
+ s->tmr[i].id = i;
168
&error_abort);
149
+ s->tmr[i].state = s;
169
if (!sysbus_realize(SYS_BUS_DEVICE(&s->sata), errp)) {
150
+ sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->tmr[i].irq);
170
@@ -XXX,XX +XXX,XX @@ static Property xlnx_zynqmp_props[] = {
151
+ timer_init_us(&s->tmr[i].timer, QEMU_CLOCK_VIRTUAL,
171
DEFINE_PROP_BOOL("has_rpu", XlnxZynqMPState, has_rpu, false),
152
+ bcm2835_systmr_timer_expire, &s->tmr[i]);
172
DEFINE_PROP_LINK("ddr-ram", XlnxZynqMPState, ddr_ram, TYPE_MEMORY_REGION,
153
+ }
173
MemoryRegion *),
154
}
174
+ DEFINE_PROP_LINK("canbus0", XlnxZynqMPState, canbus[0], TYPE_CAN_BUS,
155
175
+ CanBusState *),
156
static const VMStateDescription bcm2835_systmr_vmstate = {
176
+ DEFINE_PROP_LINK("canbus1", XlnxZynqMPState, canbus[1], TYPE_CAN_BUS,
157
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
177
+ CanBusState *),
158
index XXXXXXX..XXXXXXX 100644
178
DEFINE_PROP_END_OF_LIST()
159
--- a/hw/timer/trace-events
179
};
160
+++ b/hw/timer/trace-events
180
161
@@ -XXX,XX +XXX,XX @@ nrf51_timer_write(uint8_t timer_id, uint64_t addr, uint32_t value, unsigned size
162
nrf51_timer_set_count(uint8_t timer_id, uint8_t counter_id, uint32_t value) "timer %u counter %u count 0x%" PRIx32
163
164
# bcm2835_systmr.c
165
-bcm2835_systmr_irq(bool enable) "timer irq state %u"
166
+bcm2835_systmr_timer_expired(unsigned id) "timer #%u expired"
167
+bcm2835_systmr_irq_ack(unsigned id) "timer #%u acked"
168
bcm2835_systmr_read(uint64_t offset, uint64_t data) "timer read: offset 0x%" PRIx64 " data 0x%" PRIx64
169
-bcm2835_systmr_write(uint64_t offset, uint64_t data) "timer write: offset 0x%" PRIx64 " data 0x%" PRIx64
170
+bcm2835_systmr_write(uint64_t offset, uint32_t data) "timer write: offset 0x%" PRIx64 " data 0x%" PRIx32
171
+bcm2835_systmr_run(unsigned id, uint64_t delay_us) "timer #%u expiring in %"PRIu64" us"
172
173
# avr_timer16.c
174
avr_timer16_read(uint8_t addr, uint8_t value) "timer16 read addr:%u value:%u"
175
--
181
--
176
2.20.1
182
2.20.1
177
183
178
184
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
2
2
3
This test exercises the various modes of the npcm7xx timer. In
3
The QTests perform five tests on the Xilinx ZynqMP CAN controller:
4
particular, it triggers the bug found by the fuzzer, as reported here:
4
Tests the CAN controller in loopback, sleep and snoop mode.
5
5
Tests filtering of incoming CAN messages.
6
https://lists.gnu.org/archive/html/qemu-devel/2020-09/msg02992.html
6
7
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
It also found several other bugs, especially related to interrupt
8
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
9
handling.
9
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
10
10
Message-id: 1605728926-352690-4-git-send-email-fnu.vikram@xilinx.com
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>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
12
---
19
tests/qtest/npcm7xx_timer-test.c | 562 +++++++++++++++++++++++++++++++
13
tests/qtest/xlnx-can-test.c | 360 ++++++++++++++++++++++++++++++++++++
20
tests/qtest/meson.build | 1 +
14
tests/qtest/meson.build | 1 +
21
2 files changed, 563 insertions(+)
15
2 files changed, 361 insertions(+)
22
create mode 100644 tests/qtest/npcm7xx_timer-test.c
16
create mode 100644 tests/qtest/xlnx-can-test.c
23
17
24
diff --git a/tests/qtest/npcm7xx_timer-test.c b/tests/qtest/npcm7xx_timer-test.c
18
diff --git a/tests/qtest/xlnx-can-test.c b/tests/qtest/xlnx-can-test.c
25
new file mode 100644
19
new file mode 100644
26
index XXXXXXX..XXXXXXX
20
index XXXXXXX..XXXXXXX
27
--- /dev/null
21
--- /dev/null
28
+++ b/tests/qtest/npcm7xx_timer-test.c
22
+++ b/tests/qtest/xlnx-can-test.c
29
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@
30
+/*
24
+/*
31
+ * QTest testcase for the Nuvoton NPCM7xx Timer
25
+ * QTests for the Xilinx ZynqMP CAN controller.
32
+ *
26
+ *
33
+ * Copyright 2020 Google LLC
27
+ * Copyright (c) 2020 Xilinx Inc.
34
+ *
28
+ *
35
+ * This program is free software; you can redistribute it and/or modify it
29
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
36
+ * under the terms of the GNU General Public License as published by the
30
+ *
37
+ * Free Software Foundation; either version 2 of the License, or
31
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
38
+ * (at your option) any later version.
32
+ * of this software and associated documentation files (the "Software"), to deal
39
+ *
33
+ * in the Software without restriction, including without limitation the rights
40
+ * This program is distributed in the hope that it will be useful, but WITHOUT
34
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
41
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
35
+ * copies of the Software, and to permit persons to whom the Software is
42
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
36
+ * furnished to do so, subject to the following conditions:
43
+ * for more details.
37
+ *
38
+ * The above copyright notice and this permission notice shall be included in
39
+ * all copies or substantial portions of the Software.
40
+ *
41
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
42
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
43
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
44
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
45
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
46
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
47
+ * THE SOFTWARE.
44
+ */
48
+ */
45
+
49
+
46
+#include "qemu/osdep.h"
50
+#include "qemu/osdep.h"
47
+#include "qemu/timer.h"
51
+#include "libqos/libqtest.h"
48
+#include "libqtest-single.h"
52
+
49
+
53
+/* Base address. */
50
+#define TIM_REF_HZ (25000000)
54
+#define CAN0_BASE_ADDR 0xFF060000
51
+
55
+#define CAN1_BASE_ADDR 0xFF070000
52
+/* Bits in TCSRx */
56
+
53
+#define CEN BIT(30)
57
+/* Register addresses. */
54
+#define IE BIT(29)
58
+#define R_SRR_OFFSET 0x00
55
+#define MODE_ONESHOT (0 << 27)
59
+#define R_MSR_OFFSET 0x04
56
+#define MODE_PERIODIC (1 << 27)
60
+#define R_SR_OFFSET 0x18
57
+#define CRST BIT(26)
61
+#define R_ISR_OFFSET 0x1C
58
+#define CACT BIT(25)
62
+#define R_ICR_OFFSET 0x24
59
+#define PRESCALE(x) (x)
63
+#define R_TXID_OFFSET 0x30
60
+
64
+#define R_TXDLC_OFFSET 0x34
61
+/* Registers shared between all timers in a module. */
65
+#define R_TXDATA1_OFFSET 0x38
62
+#define TISR 0x18
66
+#define R_TXDATA2_OFFSET 0x3C
63
+#define WTCR 0x1c
67
+#define R_RXID_OFFSET 0x50
64
+# define WTCLK(x) ((x) << 10)
68
+#define R_RXDLC_OFFSET 0x54
65
+
69
+#define R_RXDATA1_OFFSET 0x58
66
+/* Power-on default; used to re-initialize timers before each test. */
70
+#define R_RXDATA2_OFFSET 0x5C
67
+#define TCSR_DEFAULT PRESCALE(5)
71
+#define R_AFR 0x60
68
+
72
+#define R_AFMR1 0x64
69
+/* Register offsets for a timer within a timer block. */
73
+#define R_AFIR1 0x68
70
+typedef struct Timer {
74
+#define R_AFMR2 0x6C
71
+ unsigned int tcsr_offset;
75
+#define R_AFIR2 0x70
72
+ unsigned int ticr_offset;
76
+#define R_AFMR3 0x74
73
+ unsigned int tdr_offset;
77
+#define R_AFIR3 0x78
74
+} Timer;
78
+#define R_AFMR4 0x7C
75
+
79
+#define R_AFIR4 0x80
76
+/* A timer block containing 5 timers. */
80
+
77
+typedef struct TimerBlock {
81
+/* CAN modes. */
78
+ int irq_base;
82
+#define CONFIG_MODE 0x00
79
+ uint64_t base_addr;
83
+#define NORMAL_MODE 0x00
80
+} TimerBlock;
84
+#define LOOPBACK_MODE 0x02
81
+
85
+#define SNOOP_MODE 0x04
82
+/* Testdata for testing a particular timer within a timer block. */
86
+#define SLEEP_MODE 0x01
83
+typedef struct TestData {
87
+#define ENABLE_CAN (1 << 1)
84
+ const TimerBlock *tim;
88
+#define STATUS_NORMAL_MODE (1 << 3)
85
+ const Timer *timer;
89
+#define STATUS_LOOPBACK_MODE (1 << 1)
86
+} TestData;
90
+#define STATUS_SNOOP_MODE (1 << 12)
87
+
91
+#define STATUS_SLEEP_MODE (1 << 2)
88
+const TimerBlock timer_block[] = {
92
+#define ISR_TXOK (1 << 1)
89
+ {
93
+#define ISR_RXOK (1 << 4)
90
+ .irq_base = 32,
94
+
91
+ .base_addr = 0xf0008000,
95
+static void match_rx_tx_data(const uint32_t *buf_tx, const uint32_t *buf_rx,
92
+ },
96
+ uint8_t can_timestamp)
93
+ {
97
+{
94
+ .irq_base = 37,
98
+ uint16_t size = 0;
95
+ .base_addr = 0xf0009000,
99
+ uint8_t len = 4;
96
+ },
100
+
97
+ {
101
+ while (size < len) {
98
+ .irq_base = 42,
102
+ if (R_RXID_OFFSET + 4 * size == R_RXDLC_OFFSET) {
99
+ .base_addr = 0xf000a000,
103
+ g_assert_cmpint(buf_rx[size], ==, buf_tx[size] + can_timestamp);
100
+ },
104
+ } else {
101
+};
105
+ g_assert_cmpint(buf_rx[size], ==, buf_tx[size]);
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
+ }
106
+ }
214
+ writel(timer_block[i].base_addr + TISR, -1);
107
+
108
+ size++;
215
+ }
109
+ }
216
+}
110
+}
217
+
111
+
218
+/* Verifies the reset state of a timer. */
112
+static void read_data(QTestState *qts, uint64_t can_base_addr, uint32_t *buf_rx)
219
+static void test_reset(gconstpointer test_data)
113
+{
220
+{
114
+ uint32_t int_status;
221
+ const TestData *td = test_data;
115
+
222
+
116
+ /* Read the interrupt on CAN rx. */
223
+ tim_reset(td);
117
+ int_status = qtest_readl(qts, can_base_addr + R_ISR_OFFSET) & ISR_RXOK;
224
+
118
+
225
+ g_assert_cmphex(tim_read_tcsr(td), ==, TCSR_DEFAULT);
119
+ g_assert_cmpint(int_status, ==, ISR_RXOK);
226
+ g_assert_cmphex(tim_read_ticr(td), ==, 0);
120
+
227
+ g_assert_cmphex(tim_read_tdr(td), ==, 0);
121
+ /* Read the RX register data for CAN. */
228
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
122
+ buf_rx[0] = qtest_readl(qts, can_base_addr + R_RXID_OFFSET);
229
+ g_assert_cmphex(tim_read(td, WTCR), ==, WTCLK(1));
123
+ buf_rx[1] = qtest_readl(qts, can_base_addr + R_RXDLC_OFFSET);
230
+}
124
+ buf_rx[2] = qtest_readl(qts, can_base_addr + R_RXDATA1_OFFSET);
231
+
125
+ buf_rx[3] = qtest_readl(qts, can_base_addr + R_RXDATA2_OFFSET);
232
+/* Verifies that CRST wins if both CEN and CRST are set. */
126
+
233
+static void test_reset_overrides_enable(gconstpointer test_data)
127
+ /* Clear the RX interrupt. */
234
+{
128
+ qtest_writel(qts, CAN1_BASE_ADDR + R_ICR_OFFSET, ISR_RXOK);
235
+ const TestData *td = test_data;
129
+}
236
+
130
+
237
+ tim_reset(td);
131
+static void send_data(QTestState *qts, uint64_t can_base_addr,
238
+
132
+ const uint32_t *buf_tx)
239
+ /* CRST should force CEN to 0 */
133
+{
240
+ tim_write_tcsr(td, CEN | CRST | TCSR_DEFAULT);
134
+ uint32_t int_status;
241
+
135
+
242
+ g_assert_cmphex(tim_read_tcsr(td), ==, TCSR_DEFAULT);
136
+ /* Write the TX register data for CAN. */
243
+ g_assert_cmphex(tim_read_tdr(td), ==, 0);
137
+ qtest_writel(qts, can_base_addr + R_TXID_OFFSET, buf_tx[0]);
244
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
138
+ qtest_writel(qts, can_base_addr + R_TXDLC_OFFSET, buf_tx[1]);
245
+}
139
+ qtest_writel(qts, can_base_addr + R_TXDATA1_OFFSET, buf_tx[2]);
246
+
140
+ qtest_writel(qts, can_base_addr + R_TXDATA2_OFFSET, buf_tx[3]);
247
+/* Verifies the behavior when CEN is set and then cleared. */
141
+
248
+static void test_oneshot_enable_then_disable(gconstpointer test_data)
142
+ /* Read the interrupt on CAN for tx. */
249
+{
143
+ int_status = qtest_readl(qts, can_base_addr + R_ISR_OFFSET) & ISR_TXOK;
250
+ const TestData *td = test_data;
144
+
251
+
145
+ g_assert_cmpint(int_status, ==, ISR_TXOK);
252
+ tim_reset(td);
146
+
253
+
147
+ /* Clear the interrupt for tx. */
254
+ /* Enable the timer with zero initial count, then disable it again. */
148
+ qtest_writel(qts, CAN0_BASE_ADDR + R_ICR_OFFSET, ISR_TXOK);
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
+}
149
+}
376
+
150
+
377
+/*
151
+/*
378
+ * Verifies that the timer can be paused and later resumed, and it still fires
152
+ * This test will be transferring data from CAN0 and CAN1 through canbus. CAN0
379
+ * at the right moment.
153
+ * initiate the data transfer to can-bus, CAN1 receives the data. Test compares
154
+ * the data sent from CAN0 with received on CAN1.
380
+ */
155
+ */
381
+static void test_pause_resume(gconstpointer test_data)
156
+static void test_can_bus(void)
382
+{
157
+{
383
+ const TestData *td = test_data;
158
+ const uint32_t buf_tx[4] = { 0xFF, 0x80000000, 0x12345678, 0x87654321 };
384
+ unsigned int count = 256;
159
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
385
+ unsigned int ps = 1;
160
+ uint32_t status = 0;
386
+
161
+ uint8_t can_timestamp = 1;
387
+ tim_reset(td);
162
+
388
+
163
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
389
+ tim_write_ticr(td, count);
164
+ " -object can-bus,id=canbus0"
390
+ tim_write_tcsr(td, IE | CEN | MODE_ONESHOT | PRESCALE(ps));
165
+ " -machine xlnx-zcu102.canbus0=canbus0"
391
+
166
+ " -machine xlnx-zcu102.canbus1=canbus0"
392
+ /* Pause the timer halfway to expiration. */
167
+ );
393
+ clock_step(tim_calculate_step(count / 2, ps));
168
+
394
+ tim_write_tcsr(td, IE | MODE_ONESHOT | PRESCALE(ps));
169
+ /* Configure the CAN0 and CAN1. */
395
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 2);
170
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
396
+
171
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
397
+ /* Counter should not advance during the following step. */
172
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
398
+ clock_step(2 * tim_calculate_step(count, ps));
173
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
399
+ g_assert_cmpuint(tim_read_tdr(td), ==, count / 2);
174
+
400
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
175
+ /* Check here if CAN0 and CAN1 are in normal mode. */
401
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
176
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
402
+
177
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
403
+ /* Resume the timer and run _almost_ to expiration. */
178
+
404
+ tim_write_tcsr(td, IE | CEN | MODE_ONESHOT | PRESCALE(ps));
179
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
405
+ clock_step(tim_calculate_step(count / 2, ps) - 1);
180
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
406
+ g_assert_cmpuint(tim_read_tdr(td), <, count);
181
+
407
+ g_assert_cmphex(tim_read(td, TISR), ==, 0);
182
+ send_data(qts, CAN0_BASE_ADDR, buf_tx);
408
+ g_assert_false(qtest_get_irq(global_qtest, tim_timer_irq(td)));
183
+
409
+
184
+ read_data(qts, CAN1_BASE_ADDR, buf_rx);
410
+ /* Now, run the rest of the way and verify that the interrupt fires. */
185
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
411
+ clock_step(1);
186
+
412
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
187
+ qtest_quit(qts);
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
+}
188
+}
513
+
189
+
514
+/*
190
+/*
515
+ * Verifies that the timer behaves correctly when disabled right before and
191
+ * This test is performing loopback mode on CAN0 and CAN1. Data sent from TX of
516
+ * exactly when it's supposed to expire.
192
+ * each CAN0 and CAN1 are compared with RX register data for respective CAN.
517
+ */
193
+ */
518
+static void test_disable_on_expiration(gconstpointer test_data)
194
+static void test_can_loopback(void)
519
+{
195
+{
520
+ const TestData *td = test_data;
196
+ uint32_t buf_tx[4] = { 0xFF, 0x80000000, 0x12345678, 0x87654321 };
521
+ unsigned int count = 8;
197
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
522
+ unsigned int ps = 255;
198
+ uint32_t status = 0;
523
+
199
+
524
+ tim_reset(td);
200
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
525
+
201
+ " -object can-bus,id=canbus0"
526
+ tim_write_ticr(td, count);
202
+ " -machine xlnx-zcu102.canbus0=canbus0"
527
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
203
+ " -machine xlnx-zcu102.canbus1=canbus0"
528
+
204
+ );
529
+ clock_step(tim_calculate_step(count, ps) - 1);
205
+
530
+
206
+ /* Configure the CAN0 in loopback mode. */
531
+ tim_write_tcsr(td, MODE_ONESHOT | PRESCALE(ps));
207
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
532
+ tim_write_tcsr(td, CEN | MODE_ONESHOT | PRESCALE(ps));
208
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, LOOPBACK_MODE);
533
+ clock_step(1);
209
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
534
+ tim_write_tcsr(td, MODE_ONESHOT | PRESCALE(ps));
210
+
535
+ g_assert_cmphex(tim_read(td, TISR), ==, tim_timer_bit(td));
211
+ /* Check here if CAN0 is set in loopback mode. */
212
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
213
+
214
+ g_assert_cmpint(status, ==, STATUS_LOOPBACK_MODE);
215
+
216
+ send_data(qts, CAN0_BASE_ADDR, buf_tx);
217
+ read_data(qts, CAN0_BASE_ADDR, buf_rx);
218
+ match_rx_tx_data(buf_tx, buf_rx, 0);
219
+
220
+ /* Configure the CAN1 in loopback mode. */
221
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
222
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, LOOPBACK_MODE);
223
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
224
+
225
+ /* Check here if CAN1 is set in loopback mode. */
226
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
227
+
228
+ g_assert_cmpint(status, ==, STATUS_LOOPBACK_MODE);
229
+
230
+ send_data(qts, CAN1_BASE_ADDR, buf_tx);
231
+ read_data(qts, CAN1_BASE_ADDR, buf_rx);
232
+ match_rx_tx_data(buf_tx, buf_rx, 0);
233
+
234
+ qtest_quit(qts);
536
+}
235
+}
537
+
236
+
538
+/*
237
+/*
539
+ * Constructs a name that includes the timer block, timer and testcase name,
238
+ * Enable filters for CAN1. This will filter incoming messages with ID. In this
540
+ * and adds the test to the test suite.
239
+ * test message will pass through filter 2.
541
+ */
240
+ */
542
+static void tim_add_test(const char *name, const TestData *td, GTestDataFunc fn)
241
+static void test_can_filter(void)
543
+{
242
+{
544
+ g_autofree char *full_name;
243
+ uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
545
+
244
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
546
+ full_name = g_strdup_printf("npcm7xx_timer/tim[%d]/timer[%d]/%s",
245
+ uint32_t status = 0;
547
+ tim_index(td->tim), timer_index(td->timer),
246
+ uint8_t can_timestamp = 1;
548
+ name);
247
+
549
+ qtest_add_data_func(full_name, td, fn);
248
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
550
+}
249
+ " -object can-bus,id=canbus0"
551
+
250
+ " -machine xlnx-zcu102.canbus0=canbus0"
552
+/* Convenience macro for adding a test with a predictable function name. */
251
+ " -machine xlnx-zcu102.canbus1=canbus0"
553
+#define add_test(name, td) tim_add_test(#name, td, test_##name)
252
+ );
253
+
254
+ /* Configure the CAN0 and CAN1. */
255
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
256
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
257
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
258
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
259
+
260
+ /* Check here if CAN0 and CAN1 are in normal mode. */
261
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
262
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
263
+
264
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
265
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
266
+
267
+ /* Set filter for CAN1 for incoming messages. */
268
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFR, 0x0);
269
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR1, 0xF7);
270
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR1, 0x121F);
271
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR2, 0x5431);
272
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR2, 0x14);
273
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR3, 0x1234);
274
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR3, 0x5431);
275
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR4, 0xFFF);
276
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR4, 0x1234);
277
+
278
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFR, 0xF);
279
+
280
+ send_data(qts, CAN0_BASE_ADDR, buf_tx);
281
+
282
+ read_data(qts, CAN1_BASE_ADDR, buf_rx);
283
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
284
+
285
+ qtest_quit(qts);
286
+}
287
+
288
+/* Testing sleep mode on CAN0 while CAN1 is in normal mode. */
289
+static void test_can_sleepmode(void)
290
+{
291
+ uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
292
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
293
+ uint32_t status = 0;
294
+ uint8_t can_timestamp = 1;
295
+
296
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
297
+ " -object can-bus,id=canbus0"
298
+ " -machine xlnx-zcu102.canbus0=canbus0"
299
+ " -machine xlnx-zcu102.canbus1=canbus0"
300
+ );
301
+
302
+ /* Configure the CAN0. */
303
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
304
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, SLEEP_MODE);
305
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
306
+
307
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
308
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
309
+
310
+ /* Check here if CAN0 is in SLEEP mode and CAN1 in normal mode. */
311
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
312
+ g_assert_cmpint(status, ==, STATUS_SLEEP_MODE);
313
+
314
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
315
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
316
+
317
+ send_data(qts, CAN1_BASE_ADDR, buf_tx);
318
+
319
+ /*
320
+ * Once CAN1 sends data on can-bus. CAN0 should exit sleep mode.
321
+ * Check the CAN0 status now. It should exit the sleep mode and receive the
322
+ * incoming data.
323
+ */
324
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
325
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
326
+
327
+ read_data(qts, CAN0_BASE_ADDR, buf_rx);
328
+
329
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
330
+
331
+ qtest_quit(qts);
332
+}
333
+
334
+/* Testing Snoop mode on CAN0 while CAN1 is in normal mode. */
335
+static void test_can_snoopmode(void)
336
+{
337
+ uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
338
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
339
+ uint32_t status = 0;
340
+ uint8_t can_timestamp = 1;
341
+
342
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
343
+ " -object can-bus,id=canbus0"
344
+ " -machine xlnx-zcu102.canbus0=canbus0"
345
+ " -machine xlnx-zcu102.canbus1=canbus0"
346
+ );
347
+
348
+ /* Configure the CAN0. */
349
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
350
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, SNOOP_MODE);
351
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
352
+
353
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
354
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
355
+
356
+ /* Check here if CAN0 is in SNOOP mode and CAN1 in normal mode. */
357
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
358
+ g_assert_cmpint(status, ==, STATUS_SNOOP_MODE);
359
+
360
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
361
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
362
+
363
+ send_data(qts, CAN1_BASE_ADDR, buf_tx);
364
+
365
+ read_data(qts, CAN0_BASE_ADDR, buf_rx);
366
+
367
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
368
+
369
+ qtest_quit(qts);
370
+}
554
+
371
+
555
+int main(int argc, char **argv)
372
+int main(int argc, char **argv)
556
+{
373
+{
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);
374
+ g_test_init(&argc, &argv, NULL);
562
+ g_test_set_nonfatal_assertions();
375
+
563
+
376
+ qtest_add_func("/net/can/can_bus", test_can_bus);
564
+ for (i = 0; i < ARRAY_SIZE(timer_block); i++) {
377
+ qtest_add_func("/net/can/can_loopback", test_can_loopback);
565
+ for (j = 0; j < ARRAY_SIZE(timer); j++) {
378
+ qtest_add_func("/net/can/can_filter", test_can_filter);
566
+ TestData *td = &testdata[i * ARRAY_SIZE(timer) + j];
379
+ qtest_add_func("/net/can/can_test_snoopmode", test_can_snoopmode);
567
+ td->tim = &timer_block[i];
380
+ qtest_add_func("/net/can/can_test_sleepmode", test_can_sleepmode);
568
+ td->timer = &timer[j];
381
+
569
+
382
+ return g_test_run();
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
+}
383
+}
592
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
384
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
593
index XXXXXXX..XXXXXXX 100644
385
index XXXXXXX..XXXXXXX 100644
594
--- a/tests/qtest/meson.build
386
--- a/tests/qtest/meson.build
595
+++ b/tests/qtest/meson.build
387
+++ b/tests/qtest/meson.build
596
@@ -XXX,XX +XXX,XX @@ qtests_arm = \
388
@@ -XXX,XX +XXX,XX @@ qtests_aarch64 = \
597
['arm-cpu-features',
389
['arm-cpu-features',
598
'microbit-test',
390
'numa-test',
599
'm25p80-test',
600
+ 'npcm7xx_timer-test',
601
'test-arm-mptimer',
602
'boot-serial-test',
391
'boot-serial-test',
603
'hexloader-test']
392
+ 'xlnx-can-test',
393
'migration-test']
394
395
qtests_s390x = \
604
--
396
--
605
2.20.1
397
2.20.1
606
398
607
399
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
2
2
3
Fixing this now will clarify following patches.
3
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
4
4
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Message-id: 1605728926-352690-5-git-send-email-fnu.vikram@xilinx.com
7
Message-id: 20201016184207.786698-6-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
8
---
10
linux-user/elfload.c | 12 +++++++++---
9
MAINTAINERS | 8 ++++++++
11
1 file changed, 9 insertions(+), 3 deletions(-)
10
1 file changed, 8 insertions(+)
12
11
13
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
12
diff --git a/MAINTAINERS b/MAINTAINERS
14
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
15
--- a/linux-user/elfload.c
14
--- a/MAINTAINERS
16
+++ b/linux-user/elfload.c
15
+++ b/MAINTAINERS
17
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
16
@@ -XXX,XX +XXX,XX @@ F: hw/net/opencores_eth.c
18
abi_ulong vaddr, vaddr_po, vaddr_ps, vaddr_ef, vaddr_em, vaddr_len;
17
19
int elf_prot = 0;
18
Devices
20
19
-------
21
- if (eppnt->p_flags & PF_R) elf_prot = PROT_READ;
20
+Xilinx CAN
22
- if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
21
+M: Vikram Garhwal <fnu.vikram@xilinx.com>
23
- if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
22
+M: Francisco Iglesias <francisco.iglesias@xilinx.com>
24
+ if (eppnt->p_flags & PF_R) {
23
+S: Maintained
25
+ elf_prot |= PROT_READ;
24
+F: hw/net/can/xlnx-*
26
+ }
25
+F: include/hw/net/xlnx-*
27
+ if (eppnt->p_flags & PF_W) {
26
+F: tests/qtest/xlnx-can-test*
28
+ elf_prot |= PROT_WRITE;
27
+
29
+ }
28
EDU
30
+ if (eppnt->p_flags & PF_X) {
29
M: Jiri Slaby <jslaby@suse.cz>
31
+ elf_prot |= PROT_EXEC;
30
S: Maintained
32
+ }
33
34
vaddr = load_bias + eppnt->p_vaddr;
35
vaddr_po = TARGET_ELF_PAGEOFFSET(vaddr);
36
--
31
--
37
2.20.1
32
2.20.1
38
33
39
34
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
2
2
3
This is generic support, with the code disabled for all targets.
3
Trusted Firmware now supports A72 on sbsa-ref by default [1] so enable
4
it for QEMU as well. A53 was already enabled there.
4
5
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
1. https://review.trustedfirmware.org/c/TF-A/trusted-firmware-a/+/7117
6
Message-id: 20201016184207.786698-11-richard.henderson@linaro.org
7
8
Signed-off-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20201120141705.246690-1-marcin.juszkiewicz@linaro.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
13
---
10
linux-user/qemu.h | 4 ++
14
hw/arm/sbsa-ref.c | 23 ++++++++++++++++++++---
11
linux-user/elfload.c | 157 +++++++++++++++++++++++++++++++++++++++++++
15
1 file changed, 20 insertions(+), 3 deletions(-)
12
2 files changed, 161 insertions(+)
13
16
14
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
17
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
15
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
16
--- a/linux-user/qemu.h
19
--- a/hw/arm/sbsa-ref.c
17
+++ b/linux-user/qemu.h
20
+++ b/hw/arm/sbsa-ref.c
18
@@ -XXX,XX +XXX,XX @@ struct image_info {
21
@@ -XXX,XX +XXX,XX @@ static const int sbsa_ref_irqmap[] = {
19
abi_ulong interpreter_loadmap_addr;
22
[SBSA_GWDT] = 16,
20
abi_ulong interpreter_pt_dynamic_addr;
23
};
21
struct image_info *other_info;
24
22
+
25
+static const char * const valid_cpus[] = {
23
+ /* For target-specific processing of NT_GNU_PROPERTY_TYPE_0. */
26
+ ARM_CPU_TYPE_NAME("cortex-a53"),
24
+ uint32_t note_flags;
27
+ ARM_CPU_TYPE_NAME("cortex-a57"),
25
+
28
+ ARM_CPU_TYPE_NAME("cortex-a72"),
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
+};
29
+};
60
+
30
+
61
+/*
31
+static bool cpu_type_valid(const char *cpu)
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
+{
32
+{
69
+ uint32_t pr_type, pr_datasz, step;
33
+ int i;
70
+
34
+
71
+ if (*off > datasz || !QEMU_IS_ALIGNED(*off, ELF_GNU_PROPERTY_ALIGN)) {
35
+ for (i = 0; i < ARRAY_SIZE(valid_cpus); i++) {
72
+ goto error_data;
36
+ if (strcmp(cpu, valid_cpus[i]) == 0) {
37
+ return true;
38
+ }
73
+ }
39
+ }
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;
40
+ return false;
110
+}
41
+}
111
+
42
+
112
+/* Process NT_GNU_PROPERTY_TYPE_0. */
43
static uint64_t sbsa_ref_cpu_mp_affinity(SBSAMachineState *sms, int idx)
113
+static bool parse_elf_properties(int image_fd,
44
{
114
+ struct image_info *info,
45
uint8_t clustersz = ARM_DEFAULT_CPUS_PER_CLUSTER;
115
+ const struct elf_phdr *phdr,
46
@@ -XXX,XX +XXX,XX @@ static void sbsa_ref_init(MachineState *machine)
116
+ char bprm_buf[BPRM_BUF_SIZE],
47
const CPUArchIdList *possible_cpus;
117
+ Error **errp)
48
int n, sbsa_max_cpus;
118
+{
49
119
+ union {
50
- if (strcmp(machine->cpu_type, ARM_CPU_TYPE_NAME("cortex-a57"))) {
120
+ struct elf_note nhdr;
51
- error_report("sbsa-ref: CPU type other than the built-in "
121
+ uint32_t data[NOTE_DATA_SZ / sizeof(uint32_t)];
52
- "cortex-a57 not supported");
122
+ } note;
53
+ if (!cpu_type_valid(machine->cpu_type)) {
123
+
54
+ error_report("mach-virt: CPU type %s not supported", machine->cpu_type);
124
+ int n, off, datasz;
55
exit(1);
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
}
56
}
210
57
211
--
58
--
212
2.20.1
59
2.20.1
213
60
214
61
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
2
3
The IRQ values are defined few lines earlier, use them instead of
3
Dump the collected random data after a randomness test failure.
4
the magic numbers.
5
4
6
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Note that this relies on the test having called
7
Message-id: 20201017180731.1165871-3-f4bug@amsat.org
6
g_test_set_nonfatal_assertions() so we don't abort immediately on the
7
assertion failure.
8
9
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
[PMM: minor commit message tweak]
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
13
---
11
hw/intc/bcm2836_control.c | 8 ++++----
14
tests/qtest/npcm7xx_rng-test.c | 12 ++++++++++++
12
1 file changed, 4 insertions(+), 4 deletions(-)
15
1 file changed, 12 insertions(+)
13
16
14
diff --git a/hw/intc/bcm2836_control.c b/hw/intc/bcm2836_control.c
17
diff --git a/tests/qtest/npcm7xx_rng-test.c b/tests/qtest/npcm7xx_rng-test.c
15
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/intc/bcm2836_control.c
19
--- a/tests/qtest/npcm7xx_rng-test.c
17
+++ b/hw/intc/bcm2836_control.c
20
+++ b/tests/qtest/npcm7xx_rng-test.c
18
@@ -XXX,XX +XXX,XX @@ static void bcm2836_control_set_local_irq(void *opaque, int core, int local_irq,
21
@@ -XXX,XX +XXX,XX @@
19
22
20
static void bcm2836_control_set_local_irq0(void *opaque, int core, int level)
23
#include "libqtest-single.h"
24
#include "qemu/bitops.h"
25
+#include "qemu-common.h"
26
27
#define RNG_BASE_ADDR 0xf000b000
28
29
@@ -XXX,XX +XXX,XX @@
30
/* Number of bits to collect for randomness tests. */
31
#define TEST_INPUT_BITS (128)
32
33
+static void dump_buf_if_failed(const uint8_t *buf, size_t size)
34
+{
35
+ if (g_test_failed()) {
36
+ qemu_hexdump(stderr, "", buf, size);
37
+ }
38
+}
39
+
40
static void rng_writeb(unsigned int offset, uint8_t value)
21
{
41
{
22
- bcm2836_control_set_local_irq(opaque, core, 0, level);
42
writeb(RNG_BASE_ADDR + offset, value);
23
+ bcm2836_control_set_local_irq(opaque, core, IRQ_CNTPSIRQ, level);
43
@@ -XXX,XX +XXX,XX @@ static void test_continuous_monobit(void)
44
}
45
46
g_assert_cmpfloat(calc_monobit_p(buf, sizeof(buf)), >, 0.01);
47
+ dump_buf_if_failed(buf, sizeof(buf));
24
}
48
}
25
49
26
static void bcm2836_control_set_local_irq1(void *opaque, int core, int level)
50
/*
27
{
51
@@ -XXX,XX +XXX,XX @@ static void test_continuous_runs(void)
28
- bcm2836_control_set_local_irq(opaque, core, 1, level);
52
}
29
+ bcm2836_control_set_local_irq(opaque, core, IRQ_CNTPNSIRQ, level);
53
54
g_assert_cmpfloat(calc_runs_p(buf.l, sizeof(buf) * BITS_PER_BYTE), >, 0.01);
55
+ dump_buf_if_failed(buf.c, sizeof(buf));
30
}
56
}
31
57
32
static void bcm2836_control_set_local_irq2(void *opaque, int core, int level)
58
/*
33
{
59
@@ -XXX,XX +XXX,XX @@ static void test_first_byte_monobit(void)
34
- bcm2836_control_set_local_irq(opaque, core, 2, level);
60
}
35
+ bcm2836_control_set_local_irq(opaque, core, IRQ_CNTHPIRQ, level);
61
62
g_assert_cmpfloat(calc_monobit_p(buf, sizeof(buf)), >, 0.01);
63
+ dump_buf_if_failed(buf, sizeof(buf));
36
}
64
}
37
65
38
static void bcm2836_control_set_local_irq3(void *opaque, int core, int level)
66
/*
39
{
67
@@ -XXX,XX +XXX,XX @@ static void test_first_byte_runs(void)
40
- bcm2836_control_set_local_irq(opaque, core, 3, level);
68
}
41
+ bcm2836_control_set_local_irq(opaque, core, IRQ_CNTVIRQ, level);
69
70
g_assert_cmpfloat(calc_runs_p(buf.l, sizeof(buf) * BITS_PER_BYTE), >, 0.01);
71
+ dump_buf_if_failed(buf.c, sizeof(buf));
42
}
72
}
43
73
44
static void bcm2836_control_set_gpu_irq(void *opaque, int irq, int level)
74
int main(int argc, char **argv)
45
--
75
--
46
2.20.1
76
2.20.1
47
77
48
78
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Alex Chen <alex.chen@huawei.com>
2
2
3
This is slightly clearer than just using strerror, though
3
We should use printf format specifier "%u" instead of "%d" for
4
the different forms produced by error_setg_file_open and
4
argument of type "unsigned int".
5
error_setg_errno isn't entirely convenient.
6
5
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Reported-by: Euler Robot <euler.robot@huawei.com>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Signed-off-by: Alex Chen <alex.chen@huawei.com>
9
Message-id: 20201016184207.786698-10-richard.henderson@linaro.org
8
Message-id: 20201126111109.112238-2-alex.chen@huawei.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
11
---
12
linux-user/elfload.c | 15 ++++++++-------
12
hw/misc/imx25_ccm.c | 12 ++++++------
13
1 file changed, 8 insertions(+), 7 deletions(-)
13
1 file changed, 6 insertions(+), 6 deletions(-)
14
14
15
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
15
diff --git a/hw/misc/imx25_ccm.c b/hw/misc/imx25_ccm.c
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
17
--- a/linux-user/elfload.c
17
--- a/hw/misc/imx25_ccm.c
18
+++ b/linux-user/elfload.c
18
+++ b/hw/misc/imx25_ccm.c
19
@@ -XXX,XX +XXX,XX @@ static void load_elf_interp(const char *filename, struct image_info *info,
19
@@ -XXX,XX +XXX,XX @@ static const char *imx25_ccm_reg_name(uint32_t reg)
20
char bprm_buf[BPRM_BUF_SIZE])
20
case IMX25_CCM_LPIMR1_REG:
21
{
21
return "lpimr1";
22
int fd, retval;
22
default:
23
+ Error *err = NULL;
23
- sprintf(unknown, "[%d ?]", reg);
24
24
+ sprintf(unknown, "[%u ?]", reg);
25
fd = open(path(filename), O_RDONLY);
25
return unknown;
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
}
26
}
32
27
}
33
retval = read(fd, bprm_buf, BPRM_BUF_SIZE);
28
@@ -XXX,XX +XXX,XX @@ static uint32_t imx25_ccm_get_mpll_clk(IMXCCMState *dev)
34
if (retval < 0) {
29
freq = imx_ccm_calc_pll(s->reg[IMX25_CCM_MPCTL_REG], CKIH_FREQ);
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
}
30
}
40
+
31
41
if (retval < BPRM_BUF_SIZE) {
32
- DPRINTF("freq = %d\n", freq);
42
memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval);
33
+ DPRINTF("freq = %u\n", freq);
34
35
return freq;
36
}
37
@@ -XXX,XX +XXX,XX @@ static uint32_t imx25_ccm_get_mcu_clk(IMXCCMState *dev)
38
39
freq = freq / (1 + EXTRACT(s->reg[IMX25_CCM_CCTL_REG], ARM_CLK_DIV));
40
41
- DPRINTF("freq = %d\n", freq);
42
+ DPRINTF("freq = %u\n", freq);
43
44
return freq;
45
}
46
@@ -XXX,XX +XXX,XX @@ static uint32_t imx25_ccm_get_ahb_clk(IMXCCMState *dev)
47
freq = imx25_ccm_get_mcu_clk(dev)
48
/ (1 + EXTRACT(s->reg[IMX25_CCM_CCTL_REG], AHB_CLK_DIV));
49
50
- DPRINTF("freq = %d\n", freq);
51
+ DPRINTF("freq = %u\n", freq);
52
53
return freq;
54
}
55
@@ -XXX,XX +XXX,XX @@ static uint32_t imx25_ccm_get_ipg_clk(IMXCCMState *dev)
56
57
freq = imx25_ccm_get_ahb_clk(dev) / 2;
58
59
- DPRINTF("freq = %d\n", freq);
60
+ DPRINTF("freq = %u\n", freq);
61
62
return freq;
63
}
64
@@ -XXX,XX +XXX,XX @@ static uint32_t imx25_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
65
break;
43
}
66
}
44
67
45
load_elf_image(filename, fd, info, NULL, bprm_buf);
68
- DPRINTF("Clock = %d) = %d\n", clock, freq);
46
- return;
69
+ DPRINTF("Clock = %d) = %u\n", clock, freq);
47
-
70
48
- exit_perror:
71
return freq;
49
- fprintf(stderr, "%s: %s\n", filename, strerror(errno));
50
- exit(-1);
51
}
72
}
52
53
static int symfind(const void *s0, const void *s1)
54
--
73
--
55
2.20.1
74
2.20.1
56
75
57
76
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Alex Chen <alex.chen@huawei.com>
2
2
3
Fix an unlikely memory leak in load_elf_image().
3
We should use printf format specifier "%u" instead of "%d" for
4
argument of type "unsigned int".
4
5
5
Fixes: bf858897b7 ("linux-user: Re-use load_elf_image for the main binary.")
6
Reported-by: Euler Robot <euler.robot@huawei.com>
6
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Signed-off-by: Alex Chen <alex.chen@huawei.com>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20201126111109.112238-3-alex.chen@huawei.com
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>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
11
---
14
linux-user/elfload.c | 8 ++++----
12
hw/misc/imx31_ccm.c | 14 +++++++-------
15
1 file changed, 4 insertions(+), 4 deletions(-)
13
hw/misc/imx_ccm.c | 4 ++--
14
2 files changed, 9 insertions(+), 9 deletions(-)
16
15
17
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
16
diff --git a/hw/misc/imx31_ccm.c b/hw/misc/imx31_ccm.c
18
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
19
--- a/linux-user/elfload.c
18
--- a/hw/misc/imx31_ccm.c
20
+++ b/linux-user/elfload.c
19
+++ b/hw/misc/imx31_ccm.c
21
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
20
@@ -XXX,XX +XXX,XX @@ static const char *imx31_ccm_reg_name(uint32_t reg)
22
info->brk = vaddr_em;
21
case IMX31_CCM_PDR2_REG:
23
}
22
return "PDR2";
24
} else if (eppnt->p_type == PT_INTERP && pinterp_name) {
23
default:
25
- char *interp_name;
24
- sprintf(unknown, "[%d ?]", reg);
26
+ g_autofree char *interp_name = NULL;
25
+ sprintf(unknown, "[%u ?]", reg);
27
26
return unknown;
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
}
27
}
53
28
}
54
#ifdef USE_ELF_CORE_DUMP
29
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_pll_ref_clk(IMXCCMState *dev)
30
freq = CKIH_FREQ;
31
}
32
33
- DPRINTF("freq = %d\n", freq);
34
+ DPRINTF("freq = %u\n", freq);
35
36
return freq;
37
}
38
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_mpll_clk(IMXCCMState *dev)
39
freq = imx_ccm_calc_pll(s->reg[IMX31_CCM_MPCTL_REG],
40
imx31_ccm_get_pll_ref_clk(dev));
41
42
- DPRINTF("freq = %d\n", freq);
43
+ DPRINTF("freq = %u\n", freq);
44
45
return freq;
46
}
47
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_mcu_main_clk(IMXCCMState *dev)
48
freq = imx31_ccm_get_mpll_clk(dev);
49
}
50
51
- DPRINTF("freq = %d\n", freq);
52
+ DPRINTF("freq = %u\n", freq);
53
54
return freq;
55
}
56
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_hclk_clk(IMXCCMState *dev)
57
freq = imx31_ccm_get_mcu_main_clk(dev)
58
/ (1 + EXTRACT(s->reg[IMX31_CCM_PDR0_REG], MAX));
59
60
- DPRINTF("freq = %d\n", freq);
61
+ DPRINTF("freq = %u\n", freq);
62
63
return freq;
64
}
65
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_ipg_clk(IMXCCMState *dev)
66
freq = imx31_ccm_get_hclk_clk(dev)
67
/ (1 + EXTRACT(s->reg[IMX31_CCM_PDR0_REG], IPG));
68
69
- DPRINTF("freq = %d\n", freq);
70
+ DPRINTF("freq = %u\n", freq);
71
72
return freq;
73
}
74
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
75
break;
76
}
77
78
- DPRINTF("Clock = %d) = %d\n", clock, freq);
79
+ DPRINTF("Clock = %d) = %u\n", clock, freq);
80
81
return freq;
82
}
83
diff --git a/hw/misc/imx_ccm.c b/hw/misc/imx_ccm.c
84
index XXXXXXX..XXXXXXX 100644
85
--- a/hw/misc/imx_ccm.c
86
+++ b/hw/misc/imx_ccm.c
87
@@ -XXX,XX +XXX,XX @@ uint32_t imx_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
88
freq = klass->get_clock_frequency(dev, clock);
89
}
90
91
- DPRINTF("(clock = %d) = %d\n", clock, freq);
92
+ DPRINTF("(clock = %d) = %u\n", clock, freq);
93
94
return freq;
95
}
96
@@ -XXX,XX +XXX,XX @@ uint32_t imx_ccm_calc_pll(uint32_t pllreg, uint32_t base_freq)
97
freq = ((2 * (base_freq >> 10) * (mfi * mfd + mfn)) /
98
(mfd * pd)) << 10;
99
100
- DPRINTF("(pllreg = 0x%08x, base_freq = %d) = %d\n", pllreg, base_freq,
101
+ DPRINTF("(pllreg = 0x%08x, base_freq = %u) = %d\n", pllreg, base_freq,
102
freq);
103
104
return freq;
55
--
105
--
56
2.20.1
106
2.20.1
57
107
58
108
diff view generated by jsdifflib
1
From: Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com>
1
From: Alex Chen <alex.chen@huawei.com>
2
2
3
Current documentation is not too clear on the GETPC usage.
3
We should use printf format specifier "%u" instead of "%d" for
4
In particular, when used outside the top level helper function
4
argument of type "unsigned int".
5
it causes unexpected behavior.
6
5
7
Signed-off-by: Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com>
6
Reported-by: Euler Robot <euler.robot@huawei.com>
8
Message-id: 20201015095147.1691-1-e.emanuelegiuseppe@gmail.com
7
Signed-off-by: Alex Chen <alex.chen@huawei.com>
8
Message-id: 20201126111109.112238-4-alex.chen@huawei.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
11
---
12
docs/devel/loads-stores.rst | 8 +++++++-
12
hw/misc/imx6_ccm.c | 20 ++++++++++----------
13
1 file changed, 7 insertions(+), 1 deletion(-)
13
hw/misc/imx6_src.c | 2 +-
14
2 files changed, 11 insertions(+), 11 deletions(-)
14
15
15
diff --git a/docs/devel/loads-stores.rst b/docs/devel/loads-stores.rst
16
diff --git a/hw/misc/imx6_ccm.c b/hw/misc/imx6_ccm.c
16
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
17
--- a/docs/devel/loads-stores.rst
18
--- a/hw/misc/imx6_ccm.c
18
+++ b/docs/devel/loads-stores.rst
19
+++ b/hw/misc/imx6_ccm.c
19
@@ -XXX,XX +XXX,XX @@ guest CPU state in case of a guest CPU exception. This is passed
20
@@ -XXX,XX +XXX,XX @@ static const char *imx6_ccm_reg_name(uint32_t reg)
20
to ``cpu_restore_state()``. Therefore the value should either be 0,
21
case CCM_CMEOR:
21
to indicate that the guest CPU state is already synchronized, or
22
return "CMEOR";
22
the result of ``GETPC()`` from the top level ``HELPER(foo)``
23
default:
23
-function, which is a return address into the generated code.
24
- sprintf(unknown, "%d ?", reg);
24
+function, which is a return address into the generated code [#gpc]_.
25
+ sprintf(unknown, "%u ?", reg);
25
+
26
return unknown;
26
+.. [#gpc] Note that ``GETPC()`` should be used with great care: calling
27
}
27
+ it in other functions that are *not* the top level
28
}
28
+ ``HELPER(foo)`` will cause unexpected behavior. Instead, the
29
@@ -XXX,XX +XXX,XX @@ static const char *imx6_analog_reg_name(uint32_t reg)
29
+ value of ``GETPC()`` should be read from the helper and passed
30
case USB_ANALOG_DIGPROG:
30
+ if needed to the functions that the helper calls.
31
return "USB_ANALOG_DIGPROG";
31
32
default:
32
Function names follow the pattern:
33
- sprintf(unknown, "%d ?", reg);
33
34
+ sprintf(unknown, "%u ?", reg);
35
return unknown;
36
}
37
}
38
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_analog_get_pll2_clk(IMX6CCMState *dev)
39
freq *= 20;
40
}
41
42
- DPRINTF("freq = %d\n", (uint32_t)freq);
43
+ DPRINTF("freq = %u\n", (uint32_t)freq);
44
45
return freq;
46
}
47
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_analog_get_pll2_pfd0_clk(IMX6CCMState *dev)
48
freq = imx6_analog_get_pll2_clk(dev) * 18
49
/ EXTRACT(dev->analog[CCM_ANALOG_PFD_528], PFD0_FRAC);
50
51
- DPRINTF("freq = %d\n", (uint32_t)freq);
52
+ DPRINTF("freq = %u\n", (uint32_t)freq);
53
54
return freq;
55
}
56
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_analog_get_pll2_pfd2_clk(IMX6CCMState *dev)
57
freq = imx6_analog_get_pll2_clk(dev) * 18
58
/ EXTRACT(dev->analog[CCM_ANALOG_PFD_528], PFD2_FRAC);
59
60
- DPRINTF("freq = %d\n", (uint32_t)freq);
61
+ DPRINTF("freq = %u\n", (uint32_t)freq);
62
63
return freq;
64
}
65
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_analog_get_periph_clk(IMX6CCMState *dev)
66
break;
67
}
68
69
- DPRINTF("freq = %d\n", (uint32_t)freq);
70
+ DPRINTF("freq = %u\n", (uint32_t)freq);
71
72
return freq;
73
}
74
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_ccm_get_ahb_clk(IMX6CCMState *dev)
75
freq = imx6_analog_get_periph_clk(dev)
76
/ (1 + EXTRACT(dev->ccm[CCM_CBCDR], AHB_PODF));
77
78
- DPRINTF("freq = %d\n", (uint32_t)freq);
79
+ DPRINTF("freq = %u\n", (uint32_t)freq);
80
81
return freq;
82
}
83
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_ccm_get_ipg_clk(IMX6CCMState *dev)
84
freq = imx6_ccm_get_ahb_clk(dev)
85
/ (1 + EXTRACT(dev->ccm[CCM_CBCDR], IPG_PODF));
86
87
- DPRINTF("freq = %d\n", (uint32_t)freq);
88
+ DPRINTF("freq = %u\n", (uint32_t)freq);
89
90
return freq;
91
}
92
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_ccm_get_per_clk(IMX6CCMState *dev)
93
freq = imx6_ccm_get_ipg_clk(dev)
94
/ (1 + EXTRACT(dev->ccm[CCM_CSCMR1], PERCLK_PODF));
95
96
- DPRINTF("freq = %d\n", (uint32_t)freq);
97
+ DPRINTF("freq = %u\n", (uint32_t)freq);
98
99
return freq;
100
}
101
@@ -XXX,XX +XXX,XX @@ static uint32_t imx6_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
102
break;
103
}
104
105
- DPRINTF("Clock = %d) = %d\n", clock, freq);
106
+ DPRINTF("Clock = %d) = %u\n", clock, freq);
107
108
return freq;
109
}
110
diff --git a/hw/misc/imx6_src.c b/hw/misc/imx6_src.c
111
index XXXXXXX..XXXXXXX 100644
112
--- a/hw/misc/imx6_src.c
113
+++ b/hw/misc/imx6_src.c
114
@@ -XXX,XX +XXX,XX @@ static const char *imx6_src_reg_name(uint32_t reg)
115
case SRC_GPR10:
116
return "SRC_GPR10";
117
default:
118
- sprintf(unknown, "%d ?", reg);
119
+ sprintf(unknown, "%u ?", reg);
120
return unknown;
121
}
122
}
34
--
123
--
35
2.20.1
124
2.20.1
36
125
37
126
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Alex Chen <alex.chen@huawei.com>
2
2
3
The time to transmit a char is expressed in nanoseconds, not in ticks.
3
We should use printf format specifier "%u" instead of "%d" for
4
argument of type "unsigned int".
4
5
5
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reported-by: Euler Robot <euler.robot@huawei.com>
6
Message-id: 20201014213601.205222-1-f4bug@amsat.org
7
Signed-off-by: Alex Chen <alex.chen@huawei.com>
8
Message-id: 20201126111109.112238-5-alex.chen@huawei.com
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
11
---
10
hw/arm/strongarm.c | 2 +-
12
hw/misc/imx6ul_ccm.c | 4 ++--
11
1 file changed, 1 insertion(+), 1 deletion(-)
13
1 file changed, 2 insertions(+), 2 deletions(-)
12
14
13
diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c
15
diff --git a/hw/misc/imx6ul_ccm.c b/hw/misc/imx6ul_ccm.c
14
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/strongarm.c
17
--- a/hw/misc/imx6ul_ccm.c
16
+++ b/hw/arm/strongarm.c
18
+++ b/hw/misc/imx6ul_ccm.c
17
@@ -XXX,XX +XXX,XX @@ struct StrongARMUARTState {
19
@@ -XXX,XX +XXX,XX @@ static const char *imx6ul_ccm_reg_name(uint32_t reg)
18
uint8_t rx_start;
20
case CCM_CMEOR:
19
uint8_t rx_len;
21
return "CMEOR";
20
22
default:
21
- uint64_t char_transmit_time; /* time to transmit a char in ticks*/
23
- sprintf(unknown, "%d ?", reg);
22
+ uint64_t char_transmit_time; /* time to transmit a char in nanoseconds */
24
+ sprintf(unknown, "%u ?", reg);
23
bool wait_break_end;
25
return unknown;
24
QEMUTimer *rx_timeout_timer;
26
}
25
QEMUTimer *tx_timer;
27
}
28
@@ -XXX,XX +XXX,XX @@ static const char *imx6ul_analog_reg_name(uint32_t reg)
29
case USB_ANALOG_DIGPROG:
30
return "USB_ANALOG_DIGPROG";
31
default:
32
- sprintf(unknown, "%d ?", reg);
33
+ sprintf(unknown, "%u ?", reg);
34
return unknown;
35
}
36
}
26
--
37
--
27
2.20.1
38
2.20.1
28
39
29
40
diff view generated by jsdifflib
1
From: Peng Liang <liangpeng10@huawei.com>
1
For M-profile CPUs, the range from 0xe0000000 to 0xe00fffff is the
2
Private Peripheral Bus range, which includes all of the memory mapped
3
devices and registers that are part of the CPU itself, including the
4
NVIC, systick timer, and debug and trace components like the Data
5
Watchpoint and Trace unit (DWT). Within this large region, the range
6
0xe000e000 to 0xe000efff is the System Control Space (NVIC, system
7
registers, systick) and 0xe002e000 to 0exe002efff is its Non-secure
8
alias.
2
9
3
VMStateDescription.fields should be end with VMSTATE_END_OF_LIST().
10
The architecture is clear that within the SCS unimplemented registers
4
However, microbit_i2c_vmstate doesn't follow it. Let's change it.
11
should be RES0 for privileged accesses and generate BusFault for
12
unprivileged accesses, and we currently implement this.
5
13
6
Fixes: 9d68bf564e ("arm: Stub out NRF51 TWI magnetometer/accelerometer detection")
14
It is less clear about how to handle accesses to unimplemented
7
Reported-by: Euler Robot <euler.robot@huawei.com>
15
regions of the wider PPB. Unprivileged accesses should definitely
8
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
16
cause BusFaults (R_DQQS), but the behaviour of privileged accesses is
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
17
not given as a general rule. However, the register definitions of
10
Message-id: 20201019093401.2993833-1-liangpeng10@huawei.com
18
individual registers for components like the DWT all state that they
19
are RES0 if the relevant component is not implemented, so the
20
simplest way to provide that is to provide RAZ/WI for the whole range
21
for privileged accesses. (The v7M Arm ARM does say that reserved
22
registers should be UNK/SBZP.)
23
24
Expand the container MemoryRegion that the NVIC exposes so that
25
it covers the whole PPB space. This means:
26
* moving the address that the ARMV7M device maps it to down by
27
0xe000 bytes
28
* moving the off and the offsets within the container of all the
29
subregions forward by 0xe000 bytes
30
* adding a new default MemoryRegion that covers the whole container
31
at a lower priority than anything else and which provides the
32
RAZWI/BusFault behaviour
33
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
34
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
35
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
36
Message-id: 20201119215617.29887-2-peter.maydell@linaro.org
12
---
37
---
13
hw/i2c/microbit_i2c.c | 1 +
38
include/hw/intc/armv7m_nvic.h | 1 +
14
1 file changed, 1 insertion(+)
39
hw/arm/armv7m.c | 2 +-
40
hw/intc/armv7m_nvic.c | 78 ++++++++++++++++++++++++++++++-----
41
3 files changed, 69 insertions(+), 12 deletions(-)
15
42
16
diff --git a/hw/i2c/microbit_i2c.c b/hw/i2c/microbit_i2c.c
43
diff --git a/include/hw/intc/armv7m_nvic.h b/include/hw/intc/armv7m_nvic.h
17
index XXXXXXX..XXXXXXX 100644
44
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/i2c/microbit_i2c.c
45
--- a/include/hw/intc/armv7m_nvic.h
19
+++ b/hw/i2c/microbit_i2c.c
46
+++ b/include/hw/intc/armv7m_nvic.h
20
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription microbit_i2c_vmstate = {
47
@@ -XXX,XX +XXX,XX @@ struct NVICState {
21
.fields = (VMStateField[]) {
48
MemoryRegion systickmem;
22
VMSTATE_UINT32_ARRAY(regs, MicrobitI2CState, MICROBIT_I2C_NREGS),
49
MemoryRegion systick_ns_mem;
23
VMSTATE_UINT32(read_idx, MicrobitI2CState),
50
MemoryRegion container;
24
+ VMSTATE_END_OF_LIST()
51
+ MemoryRegion defaultmem;
25
},
52
53
uint32_t num_irq;
54
qemu_irq excpout;
55
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/hw/arm/armv7m.c
58
+++ b/hw/arm/armv7m.c
59
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
60
sysbus_connect_irq(sbd, 0,
61
qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ));
62
63
- memory_region_add_subregion(&s->container, 0xe000e000,
64
+ memory_region_add_subregion(&s->container, 0xe0000000,
65
sysbus_mmio_get_region(sbd, 0));
66
67
for (i = 0; i < ARRAY_SIZE(s->bitband); i++) {
68
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
69
index XXXXXXX..XXXXXXX 100644
70
--- a/hw/intc/armv7m_nvic.c
71
+++ b/hw/intc/armv7m_nvic.c
72
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps nvic_systick_ops = {
73
.endianness = DEVICE_NATIVE_ENDIAN,
26
};
74
};
75
76
+/*
77
+ * Unassigned portions of the PPB space are RAZ/WI for privileged
78
+ * accesses, and fault for non-privileged accesses.
79
+ */
80
+static MemTxResult ppb_default_read(void *opaque, hwaddr addr,
81
+ uint64_t *data, unsigned size,
82
+ MemTxAttrs attrs)
83
+{
84
+ qemu_log_mask(LOG_UNIMP, "Read of unassigned area of PPB: offset 0x%x\n",
85
+ (uint32_t)addr);
86
+ if (attrs.user) {
87
+ return MEMTX_ERROR;
88
+ }
89
+ *data = 0;
90
+ return MEMTX_OK;
91
+}
92
+
93
+static MemTxResult ppb_default_write(void *opaque, hwaddr addr,
94
+ uint64_t value, unsigned size,
95
+ MemTxAttrs attrs)
96
+{
97
+ qemu_log_mask(LOG_UNIMP, "Write of unassigned area of PPB: offset 0x%x\n",
98
+ (uint32_t)addr);
99
+ if (attrs.user) {
100
+ return MEMTX_ERROR;
101
+ }
102
+ return MEMTX_OK;
103
+}
104
+
105
+static const MemoryRegionOps ppb_default_ops = {
106
+ .read_with_attrs = ppb_default_read,
107
+ .write_with_attrs = ppb_default_write,
108
+ .endianness = DEVICE_NATIVE_ENDIAN,
109
+ .valid.min_access_size = 1,
110
+ .valid.max_access_size = 8,
111
+};
112
+
113
static int nvic_post_load(void *opaque, int version_id)
114
{
115
NVICState *s = opaque;
116
@@ -XXX,XX +XXX,XX @@ static void nvic_systick_trigger(void *opaque, int n, int level)
117
static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
118
{
119
NVICState *s = NVIC(dev);
120
- int regionlen;
121
122
/* The armv7m container object will have set our CPU pointer */
123
if (!s->cpu || !arm_feature(&s->cpu->env, ARM_FEATURE_M)) {
124
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
125
M_REG_S));
126
}
127
128
- /* The NVIC and System Control Space (SCS) starts at 0xe000e000
129
+ /*
130
+ * This device provides a single sysbus memory region which
131
+ * represents the whole of the "System PPB" space. This is the
132
+ * range from 0xe0000000 to 0xe00fffff and includes the NVIC,
133
+ * the System Control Space (system registers), the systick timer,
134
+ * and for CPUs with the Security extension an NS banked version
135
+ * of all of these.
136
+ *
137
+ * The default behaviour for unimplemented registers/ranges
138
+ * (for instance the Data Watchpoint and Trace unit at 0xe0001000)
139
+ * is to RAZ/WI for privileged access and BusFault for non-privileged
140
+ * access.
141
+ *
142
+ * The NVIC and System Control Space (SCS) starts at 0xe000e000
143
* and looks like this:
144
* 0x004 - ICTR
145
* 0x010 - 0xff - systick
146
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
147
* generally code determining which banked register to use should
148
* use attrs.secure; code determining actual behaviour of the system
149
* should use env->v7m.secure.
150
+ *
151
+ * The container covers the whole PPB space. Within it the priority
152
+ * of overlapping regions is:
153
+ * - default region (for RAZ/WI and BusFault) : -1
154
+ * - system register regions : 0
155
+ * - systick : 1
156
+ * This is because the systick device is a small block of registers
157
+ * in the middle of the other system control registers.
158
*/
159
- regionlen = arm_feature(&s->cpu->env, ARM_FEATURE_V8) ? 0x21000 : 0x1000;
160
- memory_region_init(&s->container, OBJECT(s), "nvic", regionlen);
161
- /* The system register region goes at the bottom of the priority
162
- * stack as it covers the whole page.
163
- */
164
+ memory_region_init(&s->container, OBJECT(s), "nvic", 0x100000);
165
+ memory_region_init_io(&s->defaultmem, OBJECT(s), &ppb_default_ops, s,
166
+ "nvic-default", 0x100000);
167
+ memory_region_add_subregion_overlap(&s->container, 0, &s->defaultmem, -1);
168
memory_region_init_io(&s->sysregmem, OBJECT(s), &nvic_sysreg_ops, s,
169
"nvic_sysregs", 0x1000);
170
- memory_region_add_subregion(&s->container, 0, &s->sysregmem);
171
+ memory_region_add_subregion(&s->container, 0xe000, &s->sysregmem);
172
173
memory_region_init_io(&s->systickmem, OBJECT(s),
174
&nvic_systick_ops, s,
175
"nvic_systick", 0xe0);
176
177
- memory_region_add_subregion_overlap(&s->container, 0x10,
178
+ memory_region_add_subregion_overlap(&s->container, 0xe010,
179
&s->systickmem, 1);
180
181
if (arm_feature(&s->cpu->env, ARM_FEATURE_V8)) {
182
memory_region_init_io(&s->sysreg_ns_mem, OBJECT(s),
183
&nvic_sysreg_ns_ops, &s->sysregmem,
184
"nvic_sysregs_ns", 0x1000);
185
- memory_region_add_subregion(&s->container, 0x20000, &s->sysreg_ns_mem);
186
+ memory_region_add_subregion(&s->container, 0x2e000, &s->sysreg_ns_mem);
187
memory_region_init_io(&s->systick_ns_mem, OBJECT(s),
188
&nvic_sysreg_ns_ops, &s->systickmem,
189
"nvic_systick_ns", 0xe0);
190
- memory_region_add_subregion_overlap(&s->container, 0x20010,
191
+ memory_region_add_subregion_overlap(&s->container, 0x2e010,
192
&s->systick_ns_mem, 1);
193
}
27
194
28
--
195
--
29
2.20.1
196
2.20.1
30
197
31
198
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
In v8.1M the PXN architecture extension adds a new PXN bit to the
2
MPU_RLAR registers, which forbids execution of code in the region
3
from a privileged mode.
2
4
3
When TBI is enabled in a given regime, 56 bits of the address
5
This is another feature which is just in the generic "in v8.1M" set
4
are significant and we need to clear out any other matching
6
and has no ID register field indicating its presence.
5
virtual addresses with differing tags.
6
7
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>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20201119215617.29887-3-peter.maydell@linaro.org
17
---
11
---
18
target/arm/helper.c | 46 ++++++++++++++++++++++++++++++++++++++-------
12
target/arm/helper.c | 7 ++++++-
19
1 file changed, 39 insertions(+), 7 deletions(-)
13
1 file changed, 6 insertions(+), 1 deletion(-)
20
14
21
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
22
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/helper.c
17
--- a/target/arm/helper.c
24
+++ b/target/arm/helper.c
18
+++ b/target/arm/helper.c
25
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
19
@@ -XXX,XX +XXX,XX @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
26
#endif
20
} else {
27
21
uint32_t ap = extract32(env->pmsav8.rbar[secure][matchregion], 1, 2);
28
static void switch_mode(CPUARMState *env, int mode);
22
uint32_t xn = extract32(env->pmsav8.rbar[secure][matchregion], 0, 1);
29
+static int aa64_va_parameter_tbi(uint64_t tcr, ARMMMUIdx mmu_idx);
23
+ bool pxn = false;
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
+
24
+
45
+ return (tbi >> select) & 1 ? 56 : 64;
25
+ if (arm_feature(env, ARM_FEATURE_V8_1M)) {
46
+}
26
+ pxn = extract32(env->pmsav8.rlar[secure][matchregion], 4, 1);
47
+
27
+ }
48
+static int vae1_tlbbits(CPUARMState *env, uint64_t addr)
28
49
+{
29
if (m_is_system_region(env, address)) {
50
+ ARMMMUIdx mmu_idx;
30
/* System space is always execute never */
51
+
31
@@ -XXX,XX +XXX,XX @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
52
+ /* Only the regime of the mmu_idx below is significant. */
32
}
53
+ if (arm_is_secure_below_el3(env)) {
33
54
+ mmu_idx = ARMMMUIdx_SE10_0;
34
*prot = simple_ap_to_rw_prot(env, mmu_idx, ap);
55
+ } else if ((env->cp15.hcr_el2 & (HCR_E2H | HCR_TGE))
35
- if (*prot && !xn) {
56
+ == (HCR_E2H | HCR_TGE)) {
36
+ if (*prot && !xn && !(pxn && !is_user)) {
57
+ mmu_idx = ARMMMUIdx_E20_0;
37
*prot |= PAGE_EXEC;
58
+ } else {
38
}
59
+ mmu_idx = ARMMMUIdx_E10_0;
39
/* We don't need to look the attribute up in the MAIR0/MAIR1
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
--
40
--
120
2.20.1
41
2.20.1
121
42
122
43
diff view generated by jsdifflib
1
In arm_cpu_realizefn(), if the CPU has VFP or Neon disabled then we
1
In arm_cpu_realizefn() we check whether the board code disabled EL3
2
squash the ID register fields so that we don't advertise it to the
2
via the has_el3 CPU object property, which we create if the CPU
3
guest. This code was written for A-profile and needs some tweaks to
3
starts with the ARM_FEATURE_EL3 feature bit. If it is disabled, then
4
work correctly on M-profile:
4
we turn off ARM_FEATURE_EL3 and also zero out the relevant fields in
5
the ID_PFR1 and ID_AA64PFR0 registers.
5
6
6
* A-profile only fields should not be zeroed on M-profile:
7
This codepath was incorrectly being taken for M-profile CPUs, which
7
- MVFR0.FPSHVEC,FPTRAP
8
do not have an EL3 and don't set ARM_FEATURE_EL3, but which may have
8
- MVFR1.SIMDLS,SIMDINT,SIMDSP,SIMDHP
9
the M-profile Security extension and so should have non-zero values
9
- MVFR2.SIMDMISC
10
in the ID_PFR1.Security field.
10
* M-profile only fields should be zeroed on M-profile:
11
- MVFR1.FP16
12
11
13
In particular, because MVFR1.SIMDHP on A-profile is the same field as
12
Restrict the handling of the feature flag to A/R-profile cores.
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
13
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Message-id: 20201119215617.29887-4-peter.maydell@linaro.org
21
Message-id: 20201019151301.2046-9-peter.maydell@linaro.org
22
---
17
---
23
target/arm/cpu.c | 29 ++++++++++++++++++-----------
18
target/arm/cpu.c | 2 +-
24
1 file changed, 18 insertions(+), 11 deletions(-)
19
1 file changed, 1 insertion(+), 1 deletion(-)
25
20
26
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
21
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
27
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/cpu.c
23
--- a/target/arm/cpu.c
29
+++ b/target/arm/cpu.c
24
+++ b/target/arm/cpu.c
30
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
25
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
31
u = cpu->isar.mvfr0;
26
}
32
u = FIELD_DP32(u, MVFR0, FPSP, 0);
33
u = FIELD_DP32(u, MVFR0, FPDP, 0);
34
- u = FIELD_DP32(u, MVFR0, FPTRAP, 0);
35
u = FIELD_DP32(u, MVFR0, FPDIVIDE, 0);
36
u = FIELD_DP32(u, MVFR0, FPSQRT, 0);
37
- u = FIELD_DP32(u, MVFR0, FPSHVEC, 0);
38
u = FIELD_DP32(u, MVFR0, FPROUND, 0);
39
+ if (!arm_feature(env, ARM_FEATURE_M)) {
40
+ u = FIELD_DP32(u, MVFR0, FPTRAP, 0);
41
+ u = FIELD_DP32(u, MVFR0, FPSHVEC, 0);
42
+ }
43
cpu->isar.mvfr0 = u;
44
45
u = cpu->isar.mvfr1;
46
u = FIELD_DP32(u, MVFR1, FPFTZ, 0);
47
u = FIELD_DP32(u, MVFR1, FPDNAN, 0);
48
u = FIELD_DP32(u, MVFR1, FPHP, 0);
49
+ if (arm_feature(env, ARM_FEATURE_M)) {
50
+ u = FIELD_DP32(u, MVFR1, FP16, 0);
51
+ }
52
cpu->isar.mvfr1 = u;
53
54
u = cpu->isar.mvfr2;
55
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
56
u = FIELD_DP32(u, ID_ISAR6, FHM, 0);
57
cpu->isar.id_isar6 = u;
58
59
- u = cpu->isar.mvfr1;
60
- u = FIELD_DP32(u, MVFR1, SIMDLS, 0);
61
- u = FIELD_DP32(u, MVFR1, SIMDINT, 0);
62
- u = FIELD_DP32(u, MVFR1, SIMDSP, 0);
63
- u = FIELD_DP32(u, MVFR1, SIMDHP, 0);
64
- cpu->isar.mvfr1 = u;
65
+ if (!arm_feature(env, ARM_FEATURE_M)) {
66
+ u = cpu->isar.mvfr1;
67
+ u = FIELD_DP32(u, MVFR1, SIMDLS, 0);
68
+ u = FIELD_DP32(u, MVFR1, SIMDINT, 0);
69
+ u = FIELD_DP32(u, MVFR1, SIMDSP, 0);
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
}
27
}
81
28
82
if (!cpu->has_neon && !cpu->has_vfp) {
29
- if (!cpu->has_el3) {
30
+ if (!arm_feature(env, ARM_FEATURE_M) && !cpu->has_el3) {
31
/* If the has_el3 CPU property is disabled then we need to disable the
32
* feature.
33
*/
83
--
34
--
84
2.20.1
35
2.20.1
85
36
86
37
diff view generated by jsdifflib
1
From v8.1M, disabled-coprocessor handling changes slightly:
1
Implement the v8.1M VSCCLRM insn, which zeros floating point
2
* coprocessors 8, 9, 14 and 15 are also governed by the
2
registers if there is an active floating point context.
3
cp10 enable bit, like cp11
3
This requires support in write_neon_element32() for the MO_32
4
* an extra range of instruction patterns is considered
4
element size, so add it.
5
to be inside the coprocessor space
5
6
6
Because we want to use arm_gen_condlabel(), we need to move
7
We previously marked these up with TODO comments; implement the
7
the definition of that function up in translate.c so it is
8
correct behaviour.
8
before the #include of translate-vfp.c.inc.
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.
16
9
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
Message-id: 20201019151301.2046-3-peter.maydell@linaro.org
12
Message-id: 20201119215617.29887-5-peter.maydell@linaro.org
20
---
13
---
21
target/arm/cpu.h | 1 +
14
target/arm/cpu.h | 9 ++++
22
target/arm/m-nocp.decode | 10 ++++++----
15
target/arm/m-nocp.decode | 8 +++-
23
target/arm/translate-vfp.c.inc | 17 +++++++++++++++--
16
target/arm/translate.c | 21 +++++----
24
3 files changed, 22 insertions(+), 6 deletions(-)
17
target/arm/translate-vfp.c.inc | 84 ++++++++++++++++++++++++++++++++++
18
4 files changed, 111 insertions(+), 11 deletions(-)
25
19
26
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
20
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
27
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/cpu.h
22
--- a/target/arm/cpu.h
29
+++ b/target/arm/cpu.h
23
+++ b/target/arm/cpu.h
30
@@ -XXX,XX +XXX,XX @@ enum arm_features {
24
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_mprofile(const ARMISARegisters *id)
31
ARM_FEATURE_VBAR, /* has cp15 VBAR */
25
return FIELD_EX32(id->id_pfr1, ID_PFR1, MPROGMOD) != 0;
32
ARM_FEATURE_M_SECURITY, /* M profile Security Extension */
26
}
33
ARM_FEATURE_M_MAIN, /* M profile Main Extension */
27
34
+ ARM_FEATURE_V8_1M, /* M profile extras only in v8.1M and later */
28
+static inline bool isar_feature_aa32_m_sec_state(const ARMISARegisters *id)
35
};
29
+{
36
30
+ /*
37
static inline int arm_feature(CPUARMState *env, int feature)
31
+ * Return true if M-profile state handling insns
32
+ * (VSCCLRM, CLRM, FPCTX access insns) are implemented
33
+ */
34
+ return FIELD_EX32(id->id_pfr1, ID_PFR1, SECURITY) >= 3;
35
+}
36
+
37
static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id)
38
{
39
/* Sadly this is encoded differently for A-profile and M-profile */
38
diff --git a/target/arm/m-nocp.decode b/target/arm/m-nocp.decode
40
diff --git a/target/arm/m-nocp.decode b/target/arm/m-nocp.decode
39
index XXXXXXX..XXXXXXX 100644
41
index XXXXXXX..XXXXXXX 100644
40
--- a/target/arm/m-nocp.decode
42
--- a/target/arm/m-nocp.decode
41
+++ b/target/arm/m-nocp.decode
43
+++ b/target/arm/m-nocp.decode
42
@@ -XXX,XX +XXX,XX @@
44
@@ -XXX,XX +XXX,XX @@
43
# If the coprocessor is not present or disabled then we will generate
45
# If the coprocessor is not present or disabled then we will generate
44
# the NOCP exception; otherwise we let the insn through to the main decode.
46
# the NOCP exception; otherwise we let the insn through to the main decode.
45
47
46
+&nocp cp
48
+%vd_dp 22:1 12:4
47
+
49
+%vd_sp 12:4 22:1
50
+
51
&nocp cp
52
48
{
53
{
49
# Special cases which do not take an early NOCP: VLLDM and VLSTM
54
# Special cases which do not take an early NOCP: VLLDM and VLSTM
50
VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 0000 0000
55
VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 0000 0000
51
# TODO: VSCCLRM (new in v8.1M) is similar:
56
- # TODO: VSCCLRM (new in v8.1M) is similar:
52
#VSCCLRM 1110 1100 1-01 1111 ---- 1011 ---- ---0
57
- #VSCCLRM 1110 1100 1-01 1111 ---- 1011 ---- ---0
53
58
+ # VSCCLRM (new in v8.1M) is similar:
54
- NOCP 111- 1110 ---- ---- ---- cp:4 ---- ----
59
+ VSCCLRM 1110 1100 1.01 1111 .... 1011 imm:7 0 vd=%vd_dp size=3
55
- NOCP 111- 110- ---- ---- ---- cp:4 ---- ----
60
+ VSCCLRM 1110 1100 1.01 1111 .... 1010 imm:8 vd=%vd_sp size=2
56
- # TODO: From v8.1M onwards we will also want this range to NOCP
61
57
- #NOCP_8_1 111- 1111 ---- ---- ---- ---- ---- ---- cp=10
62
NOCP 111- 1110 ---- ---- ---- cp:4 ---- ---- &nocp
58
+ NOCP 111- 1110 ---- ---- ---- cp:4 ---- ---- &nocp
63
NOCP 111- 110- ---- ---- ---- cp:4 ---- ---- &nocp
59
+ NOCP 111- 110- ---- ---- ---- cp:4 ---- ---- &nocp
64
diff --git a/target/arm/translate.c b/target/arm/translate.c
60
+ # From v8.1M onwards this range will also NOCP:
65
index XXXXXXX..XXXXXXX 100644
61
+ NOCP_8_1 111- 1111 ---- ---- ---- ---- ---- ---- &nocp cp=10
66
--- a/target/arm/translate.c
62
}
67
+++ b/target/arm/translate.c
68
@@ -XXX,XX +XXX,XX @@ void arm_translate_init(void)
69
a64_translate_init();
70
}
71
72
+/* Generate a label used for skipping this instruction */
73
+static void arm_gen_condlabel(DisasContext *s)
74
+{
75
+ if (!s->condjmp) {
76
+ s->condlabel = gen_new_label();
77
+ s->condjmp = 1;
78
+ }
79
+}
80
+
81
/* Flags for the disas_set_da_iss info argument:
82
* lower bits hold the Rt register number, higher bits are flags.
83
*/
84
@@ -XXX,XX +XXX,XX @@ static void write_neon_element64(TCGv_i64 src, int reg, int ele, MemOp memop)
85
long off = neon_element_offset(reg, ele, memop);
86
87
switch (memop) {
88
+ case MO_32:
89
+ tcg_gen_st32_i64(src, cpu_env, off);
90
+ break;
91
case MO_64:
92
tcg_gen_st_i64(src, cpu_env, off);
93
break;
94
@@ -XXX,XX +XXX,XX @@ static void gen_srs(DisasContext *s,
95
s->base.is_jmp = DISAS_UPDATE_EXIT;
96
}
97
98
-/* Generate a label used for skipping this instruction */
99
-static void arm_gen_condlabel(DisasContext *s)
100
-{
101
- if (!s->condjmp) {
102
- s->condlabel = gen_new_label();
103
- s->condjmp = 1;
104
- }
105
-}
106
-
107
/* Skip this instruction if the ARM condition is false */
108
static void arm_skip_unless(DisasContext *s, uint32_t cond)
109
{
63
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
110
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
64
index XXXXXXX..XXXXXXX 100644
111
index XXXXXXX..XXXXXXX 100644
65
--- a/target/arm/translate-vfp.c.inc
112
--- a/target/arm/translate-vfp.c.inc
66
+++ b/target/arm/translate-vfp.c.inc
113
+++ b/target/arm/translate-vfp.c.inc
67
@@ -XXX,XX +XXX,XX @@ static bool trans_VLLDM_VLSTM(DisasContext *s, arg_VLLDM_VLSTM *a)
114
@@ -XXX,XX +XXX,XX @@ static bool trans_VLLDM_VLSTM(DisasContext *s, arg_VLLDM_VLSTM *a)
68
return true;
115
return true;
69
}
116
}
70
117
71
-static bool trans_NOCP(DisasContext *s, arg_NOCP *a)
118
+static bool trans_VSCCLRM(DisasContext *s, arg_VSCCLRM *a)
72
+static bool trans_NOCP(DisasContext *s, arg_nocp *a)
119
+{
120
+ int btmreg, topreg;
121
+ TCGv_i64 zero;
122
+ TCGv_i32 aspen, sfpa;
123
+
124
+ if (!dc_isar_feature(aa32_m_sec_state, s)) {
125
+ /* Before v8.1M, fall through in decode to NOCP check */
126
+ return false;
127
+ }
128
+
129
+ /* Explicitly UNDEF because this takes precedence over NOCP */
130
+ if (!arm_dc_feature(s, ARM_FEATURE_M_MAIN) || !s->v8m_secure) {
131
+ unallocated_encoding(s);
132
+ return true;
133
+ }
134
+
135
+ if (!dc_isar_feature(aa32_vfp_simd, s)) {
136
+ /* NOP if we have neither FP nor MVE */
137
+ return true;
138
+ }
139
+
140
+ /*
141
+ * If FPCCR.ASPEN != 0 && CONTROL_S.SFPA == 0 then there is no
142
+ * active floating point context so we must NOP (without doing
143
+ * any lazy state preservation or the NOCP check).
144
+ */
145
+ aspen = load_cpu_field(v7m.fpccr[M_REG_S]);
146
+ sfpa = load_cpu_field(v7m.control[M_REG_S]);
147
+ tcg_gen_andi_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);
148
+ tcg_gen_xori_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);
149
+ tcg_gen_andi_i32(sfpa, sfpa, R_V7M_CONTROL_SFPA_MASK);
150
+ tcg_gen_or_i32(sfpa, sfpa, aspen);
151
+ arm_gen_condlabel(s);
152
+ tcg_gen_brcondi_i32(TCG_COND_EQ, sfpa, 0, s->condlabel);
153
+
154
+ if (s->fp_excp_el != 0) {
155
+ gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
156
+ syn_uncategorized(), s->fp_excp_el);
157
+ return true;
158
+ }
159
+
160
+ topreg = a->vd + a->imm - 1;
161
+ btmreg = a->vd;
162
+
163
+ /* Convert to Sreg numbers if the insn specified in Dregs */
164
+ if (a->size == 3) {
165
+ topreg = topreg * 2 + 1;
166
+ btmreg *= 2;
167
+ }
168
+
169
+ if (topreg > 63 || (topreg > 31 && !(topreg & 1))) {
170
+ /* UNPREDICTABLE: we choose to undef */
171
+ unallocated_encoding(s);
172
+ return true;
173
+ }
174
+
175
+ /* Silently ignore requests to clear D16-D31 if they don't exist */
176
+ if (topreg > 31 && !dc_isar_feature(aa32_simd_r32, s)) {
177
+ topreg = 31;
178
+ }
179
+
180
+ if (!vfp_access_check(s)) {
181
+ return true;
182
+ }
183
+
184
+ /* Zero the Sregs from btmreg to topreg inclusive. */
185
+ zero = tcg_const_i64(0);
186
+ if (btmreg & 1) {
187
+ write_neon_element64(zero, btmreg >> 1, 1, MO_32);
188
+ btmreg++;
189
+ }
190
+ for (; btmreg + 1 <= topreg; btmreg += 2) {
191
+ write_neon_element64(zero, btmreg >> 1, 0, MO_64);
192
+ }
193
+ if (btmreg == topreg) {
194
+ write_neon_element64(zero, btmreg >> 1, 0, MO_32);
195
+ btmreg++;
196
+ }
197
+ assert(btmreg == topreg + 1);
198
+ /* TODO: when MVE is implemented, zero VPR here */
199
+ return true;
200
+}
201
+
202
static bool trans_NOCP(DisasContext *s, arg_nocp *a)
73
{
203
{
74
/*
204
/*
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;
105
--
205
--
106
2.20.1
206
2.20.1
107
207
108
208
diff view generated by jsdifflib
1
v8.1M brings four new insns to M-profile:
1
In v8.1M the new CLRM instruction allows zeroing an arbitrary set of
2
* CSEL : Rd = cond ? Rn : Rm
2
the general-purpose registers and APSR. Implement this.
3
* CSINC : Rd = cond ? Rn : Rm+1
4
* CSINV : Rd = cond ? Rn : ~Rm
5
* CSNEG : Rd = cond ? Rn : -Rm
6
3
7
Implement these.
4
The encoding is a subset of the LDMIA T2 encoding, using what would
5
be Rn=0b1111 (which UNDEFs for LDMIA).
8
6
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20201119215617.29887-6-peter.maydell@linaro.org
11
Message-id: 20201019151301.2046-4-peter.maydell@linaro.org
12
---
10
---
13
target/arm/t32.decode | 3 +++
11
target/arm/t32.decode | 6 +++++-
14
target/arm/translate.c | 60 ++++++++++++++++++++++++++++++++++++++++++
12
target/arm/translate.c | 38 ++++++++++++++++++++++++++++++++++++++
15
2 files changed, 63 insertions(+)
13
2 files changed, 43 insertions(+), 1 deletion(-)
16
14
17
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
15
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
18
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/t32.decode
17
--- a/target/arm/t32.decode
20
+++ b/target/arm/t32.decode
18
+++ b/target/arm/t32.decode
21
@@ -XXX,XX +XXX,XX @@ SBC_rrri 1110101 1011 . .... 0 ... .... .... .... @s_rrr_shi
19
@@ -XXX,XX +XXX,XX @@ UXTAB 1111 1010 0101 .... 1111 .... 10.. .... @rrr_rot
22
}
20
23
RSB_rrri 1110101 1110 . .... 0 ... .... .... .... @s_rrr_shi
21
STM_t32 1110 1000 10.0 .... ................ @ldstm i=1 b=0
24
22
STM_t32 1110 1001 00.0 .... ................ @ldstm i=0 b=1
25
+# v8.1M CSEL and friends
23
-LDM_t32 1110 1000 10.1 .... ................ @ldstm i=1 b=0
26
+CSEL 1110101 0010 1 rn:4 10 op:2 rd:4 fcond:4 rm:4
24
+{
27
+
25
+ # Rn=15 UNDEFs for LDM; M-profile CLRM uses that encoding
28
# Data-processing (register-shifted register)
26
+ CLRM 1110 1000 1001 1111 list:16
29
27
+ LDM_t32 1110 1000 10.1 .... ................ @ldstm i=1 b=0
30
MOV_rxrr 1111 1010 0 shty:2 s:1 rm:4 1111 rd:4 0000 rs:4 \
28
+}
29
LDM_t32 1110 1001 00.1 .... ................ @ldstm i=0 b=1
30
31
&rfe !extern rn w pu
31
diff --git a/target/arm/translate.c b/target/arm/translate.c
32
diff --git a/target/arm/translate.c b/target/arm/translate.c
32
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/translate.c
34
--- a/target/arm/translate.c
34
+++ b/target/arm/translate.c
35
+++ b/target/arm/translate.c
35
@@ -XXX,XX +XXX,XX @@ static bool trans_IT(DisasContext *s, arg_IT *a)
36
@@ -XXX,XX +XXX,XX @@ static bool trans_LDM_t16(DisasContext *s, arg_ldst_block *a)
36
return true;
37
return do_ldm(s, a, 1);
37
}
38
}
38
39
39
+/* v8.1M CSEL/CSINC/CSNEG/CSINV */
40
+static bool trans_CLRM(DisasContext *s, arg_CLRM *a)
40
+static bool trans_CSEL(DisasContext *s, arg_CSEL *a)
41
+{
41
+{
42
+ TCGv_i32 rn, rm, zero;
42
+ int i;
43
+ DisasCompare c;
43
+ TCGv_i32 zero;
44
+
44
+
45
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
45
+ if (!dc_isar_feature(aa32_m_sec_state, s)) {
46
+ return false;
46
+ return false;
47
+ }
47
+ }
48
+
48
+
49
+ if (a->rm == 13) {
49
+ if (extract32(a->list, 13, 1)) {
50
+ /* SEE "Related encodings" (MVE shifts) */
51
+ return false;
50
+ return false;
52
+ }
51
+ }
53
+
52
+
54
+ if (a->rd == 13 || a->rd == 15 || a->rn == 13 || a->fcond >= 14) {
53
+ if (!a->list) {
55
+ /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */
54
+ /* UNPREDICTABLE; we choose to UNDEF */
56
+ return false;
55
+ return false;
57
+ }
56
+ }
58
+
57
+
59
+ /* In this insn input reg fields of 0b1111 mean "zero", not "PC" */
58
+ zero = tcg_const_i32(0);
60
+ if (a->rn == 15) {
59
+ for (i = 0; i < 15; i++) {
61
+ rn = tcg_const_i32(0);
60
+ if (extract32(a->list, i, 1)) {
62
+ } else {
61
+ /* Clear R[i] */
63
+ rn = load_reg(s, a->rn);
62
+ tcg_gen_mov_i32(cpu_R[i], zero);
63
+ }
64
+ }
64
+ }
65
+ if (a->rm == 15) {
65
+ if (extract32(a->list, 15, 1)) {
66
+ rm = tcg_const_i32(0);
66
+ /*
67
+ } else {
67
+ * Clear APSR (by calling the MSR helper with the same argument
68
+ rm = load_reg(s, a->rm);
68
+ * as for "MSR APSR_nzcvqg, Rn": mask = 0b1100, SYSM=0)
69
+ */
70
+ TCGv_i32 maskreg = tcg_const_i32(0xc << 8);
71
+ gen_helper_v7m_msr(cpu_env, maskreg, zero);
72
+ tcg_temp_free_i32(maskreg);
69
+ }
73
+ }
70
+
71
+ switch (a->op) {
72
+ case 0: /* CSEL */
73
+ break;
74
+ case 1: /* CSINC */
75
+ tcg_gen_addi_i32(rm, rm, 1);
76
+ break;
77
+ case 2: /* CSINV */
78
+ tcg_gen_not_i32(rm, rm);
79
+ break;
80
+ case 3: /* CSNEG */
81
+ tcg_gen_neg_i32(rm, rm);
82
+ break;
83
+ default:
84
+ g_assert_not_reached();
85
+ }
86
+
87
+ arm_test_cc(&c, a->fcond);
88
+ zero = tcg_const_i32(0);
89
+ tcg_gen_movcond_i32(c.cond, rn, c.value, zero, rn, rm);
90
+ arm_free_cc(&c);
91
+ tcg_temp_free_i32(zero);
74
+ tcg_temp_free_i32(zero);
92
+
93
+ store_reg(s, a->rd, rn);
94
+ tcg_temp_free_i32(rm);
95
+
96
+ return true;
75
+ return true;
97
+}
76
+}
98
+
77
+
99
/*
78
/*
100
* Legacy decoder.
79
* Branch, branch with link
101
*/
80
*/
102
--
81
--
103
2.20.1
82
2.20.1
104
83
105
84
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
For M-profile before v8.1M, the only valid register for VMSR/VMRS is
2
the FPSCR. We have a comment that states this, but the actual logic
3
to forbid accesses for any other register value is missing, so we
4
would end up with A-profile style behaviour. Add the missing check.
2
5
3
The second loop uses a loop induction variable, and the first
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
does not. Transform the first to match the second, to simplify
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
a following patch moving code between them.
8
Message-id: 20201119215617.29887-7-peter.maydell@linaro.org
9
---
10
target/arm/translate-vfp.c.inc | 5 ++++-
11
1 file changed, 4 insertions(+), 1 deletion(-)
6
12
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
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
14
index XXXXXXX..XXXXXXX 100644
17
--- a/linux-user/elfload.c
15
--- a/target/arm/translate-vfp.c.inc
18
+++ b/linux-user/elfload.c
16
+++ b/target/arm/translate-vfp.c.inc
19
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
17
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
20
loaddr = -1, hiaddr = 0;
18
* Accesses to R15 are UNPREDICTABLE; we choose to undef.
21
info->alignment = 0;
19
* (FPSCR -> r15 is a special case which writes to the PSR flags.)
22
for (i = 0; i < ehdr->e_phnum; ++i) {
20
*/
23
- if (phdr[i].p_type == PT_LOAD) {
21
- if (a->rt == 15 && (!a->l || a->reg != ARM_VFP_FPSCR)) {
24
- abi_ulong a = phdr[i].p_vaddr - phdr[i].p_offset;
22
+ if (a->reg != ARM_VFP_FPSCR) {
25
+ struct elf_phdr *eppnt = phdr + i;
23
+ return false;
26
+ if (eppnt->p_type == PT_LOAD) {
24
+ }
27
+ abi_ulong a = eppnt->p_vaddr - eppnt->p_offset;
25
+ if (a->rt == 15 && !a->l) {
28
if (a < loaddr) {
26
return false;
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
}
27
}
40
}
28
}
41
42
--
29
--
43
2.20.1
30
2.20.1
44
31
45
32
diff view generated by jsdifflib
1
v8.1M implements a new 'branch future' feature, which is a
1
Currently M-profile borrows the A-profile code for VMSR and VMRS
2
set of instructions that request the CPU to perform a branch
2
(access to the FP system registers), because all it needs to support
3
"in the future", when it reaches a particular execution address.
3
is the FPSCR. In v8.1M things become significantly more complicated
4
In hardware, the expected implementation is that the information
4
in two ways:
5
about the branch location and destination is cached and then
5
6
acted upon when execution reaches the specified address.
6
* there are several new FP system registers; some have side effects
7
However the architecture permits an implementation to discard
7
on read, and one (FPCXT_NS) needs to avoid the usual
8
this cached information at any point, and so guest code must
8
vfp_access_check() and the "only if FPU implemented" check
9
always include a normal branch insn at the branch point as
9
10
a fallback. In particular, an implementation is specifically
10
* all sysregs are now accessible both by VMRS/VMSR (which
11
permitted to treat all BF insns as NOPs (which is equivalent
11
reads/writes a general purpose register) and also by VLDR/VSTR
12
to discarding the cached information immediately).
12
(which reads/writes them directly to memory)
13
13
14
For QEMU, implementing this caching of branch information
14
Refactor the structure of how we handle VMSR/VMRS to cope with this:
15
would be complicated and would not improve the speed of
15
16
execution at all, so we make the IMPDEF choice to implement
16
* keep the M-profile code entirely separate from the A-profile code
17
all BF insns as NOPs.
17
18
18
* abstract out the "read or write the general purpose register" part
19
of the code into a loadfn or storefn function pointer, so we can
20
reuse it for VLDR/VSTR.
21
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
23
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Message-id: 20201119215617.29887-8-peter.maydell@linaro.org
21
Message-id: 20201019151301.2046-7-peter.maydell@linaro.org
22
---
25
---
23
target/arm/cpu.h | 6 ++++++
26
target/arm/cpu.h | 3 +
24
target/arm/t32.decode | 13 ++++++++++++-
27
target/arm/translate-vfp.c.inc | 182 ++++++++++++++++++++++++++++++---
25
target/arm/translate.c | 20 ++++++++++++++++++++
28
2 files changed, 171 insertions(+), 14 deletions(-)
26
3 files changed, 38 insertions(+), 1 deletion(-)
27
29
28
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
30
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
29
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/cpu.h
32
--- a/target/arm/cpu.h
31
+++ b/target/arm/cpu.h
33
+++ b/target/arm/cpu.h
32
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_arm_div(const ARMISARegisters *id)
34
@@ -XXX,XX +XXX,XX @@ enum arm_cpu_mode {
33
return FIELD_EX32(id->id_isar0, ID_ISAR0, DIVIDE) > 1;
35
#define ARM_VFP_FPINST 9
34
}
36
#define ARM_VFP_FPINST2 10
35
37
36
+static inline bool isar_feature_aa32_lob(const ARMISARegisters *id)
38
+/* QEMU-internal value meaning "FPSCR, but we care only about NZCV" */
37
+{
39
+#define QEMU_VFP_FPSCR_NZCV 0xffff
38
+ /* (M-profile) low-overhead loops and branch future */
40
+
39
+ return FIELD_EX32(id->id_isar0, ID_ISAR0, CMPBRANCH) >= 3;
41
/* iwMMXt coprocessor control registers. */
40
+}
42
#define ARM_IWMMXT_wCID 0
41
+
43
#define ARM_IWMMXT_wCon 1
42
static inline bool isar_feature_aa32_jazelle(const ARMISARegisters *id)
44
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
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
45
index XXXXXXX..XXXXXXX 100644
47
--- a/target/arm/t32.decode
46
--- a/target/arm/translate-vfp.c.inc
48
+++ b/target/arm/t32.decode
47
+++ b/target/arm/translate-vfp.c.inc
49
@@ -XXX,XX +XXX,XX @@ MRC 1110 1110 ... 1 .... .... .... ... 1 .... @mcr
48
@@ -XXX,XX +XXX,XX @@ static bool trans_VDUP(DisasContext *s, arg_VDUP *a)
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
+}
66
diff --git a/target/arm/translate.c b/target/arm/translate.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/target/arm/translate.c
69
+++ b/target/arm/translate.c
70
@@ -XXX,XX +XXX,XX @@ static bool trans_BLX_suffix(DisasContext *s, arg_BLX_suffix *a)
71
return true;
49
return true;
72
}
50
}
73
51
74
+static bool trans_BF(DisasContext *s, arg_BF *a)
52
+/*
53
+ * M-profile provides two different sets of instructions that can
54
+ * access floating point system registers: VMSR/VMRS (which move
55
+ * to/from a general purpose register) and VLDR/VSTR sysreg (which
56
+ * move directly to/from memory). In some cases there are also side
57
+ * effects which must happen after any write to memory (which could
58
+ * cause an exception). So we implement the common logic for the
59
+ * sysreg access in gen_M_fp_sysreg_write() and gen_M_fp_sysreg_read(),
60
+ * which take pointers to callback functions which will perform the
61
+ * actual "read/write general purpose register" and "read/write
62
+ * memory" operations.
63
+ */
64
+
65
+/*
66
+ * Emit code to store the sysreg to its final destination; frees the
67
+ * TCG temp 'value' it is passed.
68
+ */
69
+typedef void fp_sysreg_storefn(DisasContext *s, void *opaque, TCGv_i32 value);
70
+/*
71
+ * Emit code to load the value to be copied to the sysreg; returns
72
+ * a new TCG temporary
73
+ */
74
+typedef TCGv_i32 fp_sysreg_loadfn(DisasContext *s, void *opaque);
75
+
76
+/* Common decode/access checks for fp sysreg read/write */
77
+typedef enum FPSysRegCheckResult {
78
+ FPSysRegCheckFailed, /* caller should return false */
79
+ FPSysRegCheckDone, /* caller should return true */
80
+ FPSysRegCheckContinue, /* caller should continue generating code */
81
+} FPSysRegCheckResult;
82
+
83
+static FPSysRegCheckResult fp_sysreg_checks(DisasContext *s, int regno)
84
+{
85
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
86
+ return FPSysRegCheckFailed;
87
+ }
88
+
89
+ switch (regno) {
90
+ case ARM_VFP_FPSCR:
91
+ case QEMU_VFP_FPSCR_NZCV:
92
+ break;
93
+ default:
94
+ return FPSysRegCheckFailed;
95
+ }
96
+
97
+ if (!vfp_access_check(s)) {
98
+ return FPSysRegCheckDone;
99
+ }
100
+
101
+ return FPSysRegCheckContinue;
102
+}
103
+
104
+static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
105
+
106
+ fp_sysreg_loadfn *loadfn,
107
+ void *opaque)
108
+{
109
+ /* Do a write to an M-profile floating point system register */
110
+ TCGv_i32 tmp;
111
+
112
+ switch (fp_sysreg_checks(s, regno)) {
113
+ case FPSysRegCheckFailed:
114
+ return false;
115
+ case FPSysRegCheckDone:
116
+ return true;
117
+ case FPSysRegCheckContinue:
118
+ break;
119
+ }
120
+
121
+ switch (regno) {
122
+ case ARM_VFP_FPSCR:
123
+ tmp = loadfn(s, opaque);
124
+ gen_helper_vfp_set_fpscr(cpu_env, tmp);
125
+ tcg_temp_free_i32(tmp);
126
+ gen_lookup_tb(s);
127
+ break;
128
+ default:
129
+ g_assert_not_reached();
130
+ }
131
+ return true;
132
+}
133
+
134
+static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
135
+ fp_sysreg_storefn *storefn,
136
+ void *opaque)
137
+{
138
+ /* Do a read from an M-profile floating point system register */
139
+ TCGv_i32 tmp;
140
+
141
+ switch (fp_sysreg_checks(s, regno)) {
142
+ case FPSysRegCheckFailed:
143
+ return false;
144
+ case FPSysRegCheckDone:
145
+ return true;
146
+ case FPSysRegCheckContinue:
147
+ break;
148
+ }
149
+
150
+ switch (regno) {
151
+ case ARM_VFP_FPSCR:
152
+ tmp = tcg_temp_new_i32();
153
+ gen_helper_vfp_get_fpscr(tmp, cpu_env);
154
+ storefn(s, opaque, tmp);
155
+ break;
156
+ case QEMU_VFP_FPSCR_NZCV:
157
+ /*
158
+ * Read just NZCV; this is a special case to avoid the
159
+ * helper call for the "VMRS to CPSR.NZCV" insn.
160
+ */
161
+ tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
162
+ tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
163
+ storefn(s, opaque, tmp);
164
+ break;
165
+ default:
166
+ g_assert_not_reached();
167
+ }
168
+ return true;
169
+}
170
+
171
+static void fp_sysreg_to_gpr(DisasContext *s, void *opaque, TCGv_i32 value)
172
+{
173
+ arg_VMSR_VMRS *a = opaque;
174
+
175
+ if (a->rt == 15) {
176
+ /* Set the 4 flag bits in the CPSR */
177
+ gen_set_nzcv(value);
178
+ tcg_temp_free_i32(value);
179
+ } else {
180
+ store_reg(s, a->rt, value);
181
+ }
182
+}
183
+
184
+static TCGv_i32 gpr_to_fp_sysreg(DisasContext *s, void *opaque)
185
+{
186
+ arg_VMSR_VMRS *a = opaque;
187
+
188
+ return load_reg(s, a->rt);
189
+}
190
+
191
+static bool gen_M_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
75
+{
192
+{
76
+ /*
193
+ /*
77
+ * M-profile branch future insns. The architecture permits an
194
+ * Accesses to R15 are UNPREDICTABLE; we choose to undef.
78
+ * implementation to implement these as NOPs (equivalent to
195
+ * FPSCR -> r15 is a special case which writes to the PSR flags;
79
+ * discarding the LO_BRANCH_INFO cache immediately), and we
196
+ * set a->reg to a special value to tell gen_M_fp_sysreg_read()
80
+ * take that IMPDEF option because for QEMU a "real" implementation
197
+ * we only care about the top 4 bits of FPSCR there.
81
+ * would be complicated and wouldn't execute any faster.
82
+ */
198
+ */
83
+ if (!dc_isar_feature(aa32_lob, s)) {
199
+ if (a->rt == 15) {
200
+ if (a->l && a->reg == ARM_VFP_FPSCR) {
201
+ a->reg = QEMU_VFP_FPSCR_NZCV;
202
+ } else {
203
+ return false;
204
+ }
205
+ }
206
+
207
+ if (a->l) {
208
+ /* VMRS, move FP system register to gp register */
209
+ return gen_M_fp_sysreg_read(s, a->reg, fp_sysreg_to_gpr, a);
210
+ } else {
211
+ /* VMSR, move gp register to FP system register */
212
+ return gen_M_fp_sysreg_write(s, a->reg, gpr_to_fp_sysreg, a);
213
+ }
214
+}
215
+
216
static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
217
{
218
TCGv_i32 tmp;
219
bool ignore_vfp_enabled = false;
220
221
- if (!dc_isar_feature(aa32_fpsp_v2, s)) {
222
- return false;
223
+ if (arm_dc_feature(s, ARM_FEATURE_M)) {
224
+ return gen_M_VMSR_VMRS(s, a);
225
}
226
227
- if (arm_dc_feature(s, ARM_FEATURE_M)) {
228
- /*
229
- * The only M-profile VFP vmrs/vmsr sysreg is FPSCR.
230
- * Accesses to R15 are UNPREDICTABLE; we choose to undef.
231
- * (FPSCR -> r15 is a special case which writes to the PSR flags.)
232
- */
233
- if (a->reg != ARM_VFP_FPSCR) {
234
- return false;
235
- }
236
- if (a->rt == 15 && !a->l) {
237
- return false;
238
- }
239
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
84
+ return false;
240
+ return false;
85
+ }
241
}
86
+ if (a->boff == 0) {
242
87
+ /* SEE "Related encodings" (loop insns) */
243
switch (a->reg) {
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;
97
--
244
--
98
2.20.1
245
2.20.1
99
246
100
247
diff view generated by jsdifflib
1
The BLX immediate insn in the Thumb encoding always performs
1
The constant-expander functions like negate, plus_2, etc, are
2
a switch from Thumb to Arm state. This would be totally useless
2
generally useful; move them up in translate.c so we can use them in
3
in M-profile which has no Arm decoder, and so the instruction
3
the VFP/Neon decoders as well as in the A32/T32/T16 decoders.
4
does not exist at all there. Make the encoding UNDEF for M-profile.
5
4
6
(This part of the encoding space is used for the branch-future
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
and low-overhead-loop insns in v8.1M.)
8
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20201119215617.29887-9-peter.maydell@linaro.org
11
Message-id: 20201019151301.2046-6-peter.maydell@linaro.org
12
---
8
---
13
target/arm/translate.c | 8 ++++++++
9
target/arm/translate.c | 46 +++++++++++++++++++++++-------------------
14
1 file changed, 8 insertions(+)
10
1 file changed, 25 insertions(+), 21 deletions(-)
15
11
16
diff --git a/target/arm/translate.c b/target/arm/translate.c
12
diff --git a/target/arm/translate.c b/target/arm/translate.c
17
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/translate.c
14
--- a/target/arm/translate.c
19
+++ b/target/arm/translate.c
15
+++ b/target/arm/translate.c
20
@@ -XXX,XX +XXX,XX @@ static bool trans_BLX_i(DisasContext *s, arg_BLX_i *a)
16
@@ -XXX,XX +XXX,XX @@ static void arm_gen_condlabel(DisasContext *s)
17
}
18
}
19
20
+/*
21
+ * Constant expanders for the decoders.
22
+ */
23
+
24
+static int negate(DisasContext *s, int x)
25
+{
26
+ return -x;
27
+}
28
+
29
+static int plus_2(DisasContext *s, int x)
30
+{
31
+ return x + 2;
32
+}
33
+
34
+static int times_2(DisasContext *s, int x)
35
+{
36
+ return x * 2;
37
+}
38
+
39
+static int times_4(DisasContext *s, int x)
40
+{
41
+ return x * 4;
42
+}
43
+
44
/* Flags for the disas_set_da_iss info argument:
45
* lower bits hold the Rt register number, higher bits are flags.
46
*/
47
@@ -XXX,XX +XXX,XX @@ static void arm_skip_unless(DisasContext *s, uint32_t cond)
48
49
50
/*
51
- * Constant expanders for the decoders.
52
+ * Constant expanders used by T16/T32 decode
53
*/
54
55
-static int negate(DisasContext *s, int x)
56
-{
57
- return -x;
58
-}
59
-
60
-static int plus_2(DisasContext *s, int x)
61
-{
62
- return x + 2;
63
-}
64
-
65
-static int times_2(DisasContext *s, int x)
66
-{
67
- return x * 2;
68
-}
69
-
70
-static int times_4(DisasContext *s, int x)
71
-{
72
- return x * 4;
73
-}
74
-
75
/* Return only the rotation part of T32ExpandImm. */
76
static int t32_expandimm_rot(DisasContext *s, int x)
21
{
77
{
22
TCGv_i32 tmp;
23
24
+ /*
25
+ * BLX <imm> would be useless on M-profile; the encoding space
26
+ * is used for other insns from v8.1M onward, and UNDEFs before that.
27
+ */
28
+ if (arm_dc_feature(s, ARM_FEATURE_M)) {
29
+ return false;
30
+ }
31
+
32
/* For A32, ARM_FEATURE_V5 is checked near the start of the uncond block. */
33
if (s->thumb && (a->imm & 2)) {
34
return false;
35
--
78
--
36
2.20.1
79
2.20.1
37
80
38
81
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Implement the new-in-v8.1M VLDR/VSTR variants which directly
2
read or write FP system registers to memory.
2
3
3
On ARM, the Top Byte Ignore feature means that only 56 bits of
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
the address are significant in the virtual address. We are
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
required to give the entire 64-bit address to FAR_ELx on fault,
6
Message-id: 20201119215617.29887-10-peter.maydell@linaro.org
6
which means that we do not "clean" the top byte early in TCG.
7
---
8
target/arm/vfp.decode | 14 ++++++
9
target/arm/translate-vfp.c.inc | 91 ++++++++++++++++++++++++++++++++++
10
2 files changed, 105 insertions(+)
7
11
8
This new interface allows us to flush all 256 possible aliases
12
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
9
for a given page, currently missed by tlb_flush_page*.
10
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
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
17
include/exec/exec-all.h | 36 ++++++
18
accel/tcg/cputlb.c | 275 ++++++++++++++++++++++++++++++++++++++--
19
2 files changed, 302 insertions(+), 9 deletions(-)
20
21
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
22
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
23
--- a/include/exec/exec-all.h
14
--- a/target/arm/vfp.decode
24
+++ b/include/exec/exec-all.h
15
+++ b/target/arm/vfp.decode
25
@@ -XXX,XX +XXX,XX @@ void tlb_flush_by_mmuidx_all_cpus(CPUState *cpu, uint16_t idxmap);
16
@@ -XXX,XX +XXX,XX @@ VLDR_VSTR_hp ---- 1101 u:1 .0 l:1 rn:4 .... 1001 imm:8 vd=%vd_sp
26
* depend on when the guests translation ends the TB.
17
VLDR_VSTR_sp ---- 1101 u:1 .0 l:1 rn:4 .... 1010 imm:8 vd=%vd_sp
27
*/
18
VLDR_VSTR_dp ---- 1101 u:1 .0 l:1 rn:4 .... 1011 imm:8 vd=%vd_dp
28
void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *cpu, uint16_t idxmap);
19
20
+# M-profile VLDR/VSTR to sysreg
21
+%vldr_sysreg 22:1 13:3
22
+%imm7_0x4 0:7 !function=times_4
29
+
23
+
30
+/**
24
+&vldr_sysreg rn reg imm a w p
31
+ * tlb_flush_page_bits_by_mmuidx
25
+@vldr_sysreg .... ... . a:1 . . . rn:4 ... . ... .. ....... \
32
+ * @cpu: CPU whose TLB should be flushed
26
+ reg=%vldr_sysreg imm=%imm7_0x4 &vldr_sysreg
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
+
27
+
42
+/* Similarly, with broadcast and syncing. */
28
+# P=0 W=0 is SEE "Related encodings", so split into two patterns
43
+void tlb_flush_page_bits_by_mmuidx_all_cpus(CPUState *cpu, target_ulong addr,
29
+VLDR_sysreg ---- 110 1 . . w:1 1 .... ... 0 111 11 ....... @vldr_sysreg p=1
44
+ uint16_t idxmap, unsigned bits);
30
+VLDR_sysreg ---- 110 0 . . 1 1 .... ... 0 111 11 ....... @vldr_sysreg p=0 w=1
45
+void tlb_flush_page_bits_by_mmuidx_all_cpus_synced
31
+VSTR_sysreg ---- 110 1 . . w:1 0 .... ... 0 111 11 ....... @vldr_sysreg p=1
46
+ (CPUState *cpu, target_ulong addr, uint16_t idxmap, unsigned bits);
32
+VSTR_sysreg ---- 110 0 . . 1 0 .... ... 0 111 11 ....... @vldr_sysreg p=0 w=1
47
+
33
+
48
/**
34
# We split the load/store multiple up into two patterns to avoid
49
* tlb_set_page_with_attrs:
35
# overlap with other insns in the "Advanced SIMD load/store and 64-bit move"
50
* @cpu: CPU to add this TLB entry for
36
# grouping:
51
@@ -XXX,XX +XXX,XX @@ static inline void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *cpu,
37
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
52
uint16_t idxmap)
38
index XXXXXXX..XXXXXXX 100644
53
{
39
--- a/target/arm/translate-vfp.c.inc
40
+++ b/target/arm/translate-vfp.c.inc
41
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
42
return true;
54
}
43
}
55
+static inline void tlb_flush_page_bits_by_mmuidx(CPUState *cpu,
44
56
+ target_ulong addr,
45
+static void fp_sysreg_to_memory(DisasContext *s, void *opaque, TCGv_i32 value)
57
+ uint16_t idxmap,
58
+ unsigned bits)
59
+{
46
+{
60
+}
47
+ arg_vldr_sysreg *a = opaque;
61
+static inline void tlb_flush_page_bits_by_mmuidx_all_cpus(CPUState *cpu,
48
+ uint32_t offset = a->imm;
62
+ target_ulong addr,
49
+ TCGv_i32 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
+}
72
#endif
73
/**
74
* probe_access:
75
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
76
index XXXXXXX..XXXXXXX 100644
77
--- a/accel/tcg/cputlb.c
78
+++ b/accel/tcg/cputlb.c
79
@@ -XXX,XX +XXX,XX @@ void tlb_flush_all_cpus_synced(CPUState *src_cpu)
80
tlb_flush_by_mmuidx_all_cpus_synced(src_cpu, ALL_MMUIDX_BITS);
81
}
82
83
+static bool tlb_hit_page_mask_anyprot(CPUTLBEntry *tlb_entry,
84
+ target_ulong page, target_ulong mask)
85
+{
86
+ page &= mask;
87
+ mask &= TARGET_PAGE_MASK | TLB_INVALID_MASK;
88
+
50
+
89
+ return (page == (tlb_entry->addr_read & mask) ||
51
+ if (!a->a) {
90
+ page == (tlb_addr_write(tlb_entry) & mask) ||
52
+ offset = - offset;
91
+ page == (tlb_entry->addr_code & mask));
92
+}
93
+
94
static inline bool tlb_hit_page_anyprot(CPUTLBEntry *tlb_entry,
95
target_ulong page)
96
{
97
- return tlb_hit_page(tlb_entry->addr_read, page) ||
98
- tlb_hit_page(tlb_addr_write(tlb_entry), page) ||
99
- tlb_hit_page(tlb_entry->addr_code, page);
100
+ return tlb_hit_page_mask_anyprot(tlb_entry, page, -1);
101
}
102
103
/**
104
@@ -XXX,XX +XXX,XX @@ static inline bool tlb_entry_is_empty(const CPUTLBEntry *te)
105
}
106
107
/* Called with tlb_c.lock held */
108
-static inline bool tlb_flush_entry_locked(CPUTLBEntry *tlb_entry,
109
- target_ulong page)
110
+static bool tlb_flush_entry_mask_locked(CPUTLBEntry *tlb_entry,
111
+ target_ulong page,
112
+ target_ulong mask)
113
{
114
- if (tlb_hit_page_anyprot(tlb_entry, page)) {
115
+ if (tlb_hit_page_mask_anyprot(tlb_entry, page, mask)) {
116
memset(tlb_entry, -1, sizeof(*tlb_entry));
117
return true;
118
}
119
return false;
120
}
121
122
+static inline bool tlb_flush_entry_locked(CPUTLBEntry *tlb_entry,
123
+ target_ulong page)
124
+{
125
+ return tlb_flush_entry_mask_locked(tlb_entry, page, -1);
126
+}
127
+
128
/* Called with tlb_c.lock held */
129
-static inline void tlb_flush_vtlb_page_locked(CPUArchState *env, int mmu_idx,
130
- target_ulong page)
131
+static void tlb_flush_vtlb_page_mask_locked(CPUArchState *env, int mmu_idx,
132
+ target_ulong page,
133
+ target_ulong mask)
134
{
135
CPUTLBDesc *d = &env_tlb(env)->d[mmu_idx];
136
int k;
137
138
assert_cpu_is_self(env_cpu(env));
139
for (k = 0; k < CPU_VTLB_SIZE; k++) {
140
- if (tlb_flush_entry_locked(&d->vtable[k], page)) {
141
+ if (tlb_flush_entry_mask_locked(&d->vtable[k], page, mask)) {
142
tlb_n_used_entries_dec(env, mmu_idx);
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
+ }
53
+ }
182
+
54
+
183
+ /* Check if we need to flush due to large pages. */
55
+ addr = load_reg(s, a->rn);
184
+ if ((page & d->large_page_mask) == d->large_page_addr) {
56
+ if (a->p) {
185
+ tlb_debug("forcing full flush midx %d ("
57
+ tcg_gen_addi_i32(addr, addr, offset);
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
+ }
58
+ }
191
+
59
+
192
+ if (tlb_flush_entry_mask_locked(tlb_entry(env, midx, page), page, mask)) {
60
+ if (s->v8m_stackcheck && a->rn == 13 && a->w) {
193
+ tlb_n_used_entries_dec(env, midx);
61
+ gen_helper_v8m_stackcheck(cpu_env, addr);
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
+ }
62
+ }
279
+
63
+
280
+ /* This should already be page aligned */
64
+ gen_aa32_st_i32(s, value, addr, get_mem_index(s),
281
+ d.addr = addr & TARGET_PAGE_MASK;
65
+ MO_UL | MO_ALIGN | s->be_data);
282
+ d.idxmap = idxmap;
66
+ tcg_temp_free_i32(value);
283
+ d.bits = bits;
284
+
67
+
285
+ if (qemu_cpu_is_self(cpu)) {
68
+ if (a->w) {
286
+ tlb_flush_page_bits_by_mmuidx_async_0(cpu, d);
69
+ /* writeback */
287
+ } else if (encode_pbm_to_runon(&runon, d)) {
70
+ if (!a->p) {
288
+ async_run_on_cpu(cpu, tlb_flush_page_bits_by_mmuidx_async_1, runon);
71
+ tcg_gen_addi_i32(addr, addr, offset);
72
+ }
73
+ store_reg(s, a->rn, addr);
289
+ } else {
74
+ } else {
290
+ TLBFlushPageBitsByMMUIdxData *p
75
+ tcg_temp_free_i32(addr);
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
+ }
76
+ }
298
+}
77
+}
299
+
78
+
300
+void tlb_flush_page_bits_by_mmuidx_all_cpus(CPUState *src_cpu,
79
+static TCGv_i32 memory_to_fp_sysreg(DisasContext *s, void *opaque)
301
+ target_ulong addr,
302
+ uint16_t idxmap,
303
+ unsigned bits)
304
+{
80
+{
305
+ TLBFlushPageBitsByMMUIdxData d;
81
+ arg_vldr_sysreg *a = opaque;
306
+ run_on_cpu_data runon;
82
+ uint32_t offset = a->imm;
83
+ TCGv_i32 addr;
84
+ TCGv_i32 value = tcg_temp_new_i32();
307
+
85
+
308
+ /* If all bits are significant, this devolves to tlb_flush_page. */
86
+ if (!a->a) {
309
+ if (bits >= TARGET_LONG_BITS) {
87
+ offset = - offset;
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
+ }
88
+ }
318
+
89
+
319
+ /* This should already be page aligned */
90
+ addr = load_reg(s, a->rn);
320
+ d.addr = addr & TARGET_PAGE_MASK;
91
+ if (a->p) {
321
+ d.idxmap = idxmap;
92
+ tcg_gen_addi_i32(addr, addr, offset);
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
+ }
93
+ }
341
+
94
+
342
+ tlb_flush_page_bits_by_mmuidx_async_0(src_cpu, d);
95
+ if (s->v8m_stackcheck && a->rn == 13 && a->w) {
96
+ gen_helper_v8m_stackcheck(cpu_env, addr);
97
+ }
98
+
99
+ gen_aa32_ld_i32(s, value, addr, get_mem_index(s),
100
+ MO_UL | MO_ALIGN | s->be_data);
101
+
102
+ if (a->w) {
103
+ /* writeback */
104
+ if (!a->p) {
105
+ tcg_gen_addi_i32(addr, addr, offset);
106
+ }
107
+ store_reg(s, a->rn, addr);
108
+ } else {
109
+ tcg_temp_free_i32(addr);
110
+ }
111
+ return value;
343
+}
112
+}
344
+
113
+
345
+void tlb_flush_page_bits_by_mmuidx_all_cpus_synced(CPUState *src_cpu,
114
+static bool trans_VLDR_sysreg(DisasContext *s, arg_vldr_sysreg *a)
346
+ target_ulong addr,
347
+ uint16_t idxmap,
348
+ unsigned bits)
349
+{
115
+{
350
+ TLBFlushPageBitsByMMUIdxData d;
116
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
351
+ run_on_cpu_data runon;
117
+ return false;
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
+ }
118
+ }
358
+ /* If no page bits are significant, this devolves to tlb_flush. */
119
+ if (a->rn == 15) {
359
+ if (bits < TARGET_PAGE_BITS) {
120
+ return false;
360
+ tlb_flush_by_mmuidx_all_cpus_synced(src_cpu, idxmap);
361
+ return;
362
+ }
121
+ }
363
+
122
+ return gen_M_fp_sysreg_write(s, a->reg, memory_to_fp_sysreg, a);
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
+}
123
+}
393
+
124
+
394
/* update the TLBs so that writes to code in the virtual page 'addr'
125
+static bool trans_VSTR_sysreg(DisasContext *s, arg_vldr_sysreg *a)
395
can be detected */
126
+{
396
void tlb_protect_code(ram_addr_t ram_addr)
127
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
128
+ return false;
129
+ }
130
+ if (a->rn == 15) {
131
+ return false;
132
+ }
133
+ return gen_M_fp_sysreg_read(s, a->reg, fp_sysreg_to_memory, a);
134
+}
135
+
136
static bool trans_VMOV_half(DisasContext *s, arg_VMOV_single *a)
137
{
138
TCGv_i32 tmp;
397
--
139
--
398
2.20.1
140
2.20.1
399
141
400
142
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
v8.1M defines a new FP system register FPSCR_nzcvqc; this behaves
2
like the existing FPSCR, except that it reads and writes only bits
3
[31:27] of the FPSCR (the N, Z, C, V and QC flag bits). (Unlike the
4
FPSCR, the special case for Rt=15 of writing the CPSR.NZCV is not
5
permitted.)
2
6
3
The kernel sets btype for the signal handler as if for a call.
7
Implement the register. Since we don't yet implement MVE, we handle
8
the QC bit as RES0, with todo comments for where we will need to add
9
support later.
4
10
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>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20201119215617.29887-11-peter.maydell@linaro.org
9
---
14
---
10
linux-user/aarch64/signal.c | 10 ++++++++--
15
target/arm/cpu.h | 13 +++++++++++++
11
1 file changed, 8 insertions(+), 2 deletions(-)
16
target/arm/translate-vfp.c.inc | 27 +++++++++++++++++++++++++++
17
2 files changed, 40 insertions(+)
12
18
13
diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
19
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
15
--- a/linux-user/aarch64/signal.c
21
--- a/target/arm/cpu.h
16
+++ b/linux-user/aarch64/signal.c
22
+++ b/target/arm/cpu.h
17
@@ -XXX,XX +XXX,XX @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
23
@@ -XXX,XX +XXX,XX @@ void vfp_set_fpscr(CPUARMState *env, uint32_t val);
18
+ offsetof(struct target_rt_frame_record, tramp);
24
#define FPCR_FZ (1 << 24) /* Flush-to-zero enable bit */
25
#define FPCR_DN (1 << 25) /* Default NaN enable bit */
26
#define FPCR_QC (1 << 27) /* Cumulative saturation bit */
27
+#define FPCR_V (1 << 28) /* FP overflow flag */
28
+#define FPCR_C (1 << 29) /* FP carry flag */
29
+#define FPCR_Z (1 << 30) /* FP zero flag */
30
+#define FPCR_N (1 << 31) /* FP negative flag */
31
+
32
+#define FPCR_NZCV_MASK (FPCR_N | FPCR_Z | FPCR_C | FPCR_V)
33
+#define FPCR_NZCVQC_MASK (FPCR_NZCV_MASK | FPCR_QC)
34
35
static inline uint32_t vfp_get_fpsr(CPUARMState *env)
36
{
37
@@ -XXX,XX +XXX,XX @@ enum arm_cpu_mode {
38
#define ARM_VFP_FPEXC 8
39
#define ARM_VFP_FPINST 9
40
#define ARM_VFP_FPINST2 10
41
+/* These ones are M-profile only */
42
+#define ARM_VFP_FPSCR_NZCVQC 2
43
+#define ARM_VFP_VPR 12
44
+#define ARM_VFP_P0 13
45
+#define ARM_VFP_FPCXT_NS 14
46
+#define ARM_VFP_FPCXT_S 15
47
48
/* QEMU-internal value meaning "FPSCR, but we care only about NZCV" */
49
#define QEMU_VFP_FPSCR_NZCV 0xffff
50
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
51
index XXXXXXX..XXXXXXX 100644
52
--- a/target/arm/translate-vfp.c.inc
53
+++ b/target/arm/translate-vfp.c.inc
54
@@ -XXX,XX +XXX,XX @@ static FPSysRegCheckResult fp_sysreg_checks(DisasContext *s, int regno)
55
case ARM_VFP_FPSCR:
56
case QEMU_VFP_FPSCR_NZCV:
57
break;
58
+ case ARM_VFP_FPSCR_NZCVQC:
59
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
60
+ return false;
61
+ }
62
+ break;
63
default:
64
return FPSysRegCheckFailed;
19
}
65
}
20
env->xregs[0] = usig;
66
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
21
- env->xregs[31] = frame_addr;
67
tcg_temp_free_i32(tmp);
22
env->xregs[29] = frame_addr + fr_ofs;
68
gen_lookup_tb(s);
23
- env->pc = ka->_sa_handler;
69
break;
24
env->xregs[30] = return_addr;
70
+ case ARM_VFP_FPSCR_NZCVQC:
25
+ env->xregs[31] = frame_addr;
71
+ {
26
+ env->pc = ka->_sa_handler;
72
+ TCGv_i32 fpscr;
27
+
73
+ tmp = loadfn(s, opaque);
28
+ /* Invoke the signal handler as if by indirect call. */
74
+ /*
29
+ if (cpu_isar_feature(aa64_bti, env_archcpu(env))) {
75
+ * TODO: when we implement MVE, write the QC bit.
30
+ env->btype = 2;
76
+ * For non-MVE, QC is RES0.
77
+ */
78
+ tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
79
+ fpscr = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
80
+ tcg_gen_andi_i32(fpscr, fpscr, ~FPCR_NZCV_MASK);
81
+ tcg_gen_or_i32(fpscr, fpscr, tmp);
82
+ store_cpu_field(fpscr, vfp.xregs[ARM_VFP_FPSCR]);
83
+ tcg_temp_free_i32(tmp);
84
+ break;
31
+ }
85
+ }
32
+
86
default:
33
if (info) {
87
g_assert_not_reached();
34
tswap_siginfo(&frame->info, info);
88
}
35
env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info);
89
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
90
gen_helper_vfp_get_fpscr(tmp, cpu_env);
91
storefn(s, opaque, tmp);
92
break;
93
+ case ARM_VFP_FPSCR_NZCVQC:
94
+ /*
95
+ * TODO: MVE has a QC bit, which we probably won't store
96
+ * in the xregs[] field. For non-MVE, where QC is RES0,
97
+ * we can just fall through to the FPSCR_NZCV case.
98
+ */
99
case QEMU_VFP_FPSCR_NZCV:
100
/*
101
* Read just NZCV; this is a special case to avoid the
36
--
102
--
37
2.20.1
103
2.20.1
38
104
39
105
diff view generated by jsdifflib
1
For AArch32, unlike the VCVT of integer to float, which honours the
1
We defined a constant name for the mask of NZCV bits in the FPCR/FPSCR
2
rounding mode specified by the FPSCR, VCVT of fixed-point to float is
2
in the previous commit; use it in a couple of places in existing code,
3
always round-to-nearest. (AArch64 fixed-point-to-float conversions
3
where we're masking out everything except NZCV for the "load to Rt=15
4
always honour the FPCR rounding mode.)
4
sets CPSR.NZCV" special case.
5
6
Implement this by providing _round_to_nearest versions of the
7
relevant helpers which set the rounding mode temporarily when making
8
the call to the underlying softfloat function.
9
10
We only need to change the VFP VCVT instructions, because the
11
standard- FPSCR value used by the Neon VCVT is always set to
12
round-to-nearest, so we don't need to do the extra work of saving
13
and restoring the rounding mode.
14
5
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20201013103532.13391-1-peter.maydell@linaro.org
8
Message-id: 20201119215617.29887-12-peter.maydell@linaro.org
18
---
9
---
19
target/arm/helper.h | 13 +++++++++++++
10
target/arm/translate-vfp.c.inc | 4 ++--
20
target/arm/vfp_helper.c | 23 ++++++++++++++++++++++-
11
1 file changed, 2 insertions(+), 2 deletions(-)
21
target/arm/translate-vfp.c.inc | 24 ++++++++++++------------
22
3 files changed, 47 insertions(+), 13 deletions(-)
23
12
24
diff --git a/target/arm/helper.h b/target/arm/helper.h
25
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/helper.h
27
+++ b/target/arm/helper.h
28
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(vfp_ultoh, f16, i32, i32, ptr)
29
DEF_HELPER_3(vfp_sqtoh, f16, i64, i32, ptr)
30
DEF_HELPER_3(vfp_uqtoh, f16, i64, i32, ptr)
31
32
+DEF_HELPER_3(vfp_shtos_round_to_nearest, f32, i32, i32, ptr)
33
+DEF_HELPER_3(vfp_sltos_round_to_nearest, f32, i32, i32, ptr)
34
+DEF_HELPER_3(vfp_uhtos_round_to_nearest, f32, i32, i32, ptr)
35
+DEF_HELPER_3(vfp_ultos_round_to_nearest, f32, i32, i32, ptr)
36
+DEF_HELPER_3(vfp_shtod_round_to_nearest, f64, i64, i32, ptr)
37
+DEF_HELPER_3(vfp_sltod_round_to_nearest, f64, i64, i32, ptr)
38
+DEF_HELPER_3(vfp_uhtod_round_to_nearest, f64, i64, i32, ptr)
39
+DEF_HELPER_3(vfp_ultod_round_to_nearest, f64, i64, i32, ptr)
40
+DEF_HELPER_3(vfp_shtoh_round_to_nearest, f16, i32, i32, ptr)
41
+DEF_HELPER_3(vfp_uhtoh_round_to_nearest, f16, i32, i32, ptr)
42
+DEF_HELPER_3(vfp_sltoh_round_to_nearest, f16, i32, i32, ptr)
43
+DEF_HELPER_3(vfp_ultoh_round_to_nearest, f16, i32, i32, ptr)
44
+
45
DEF_HELPER_FLAGS_2(set_rmode, TCG_CALL_NO_RWG, i32, i32, ptr)
46
47
DEF_HELPER_FLAGS_3(vfp_fcvt_f16_to_f32, TCG_CALL_NO_RWG, f32, f16, ptr, i32)
48
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/target/arm/vfp_helper.c
51
+++ b/target/arm/vfp_helper.c
52
@@ -XXX,XX +XXX,XX @@ float32 VFP_HELPER(fcvts, d)(float64 x, CPUARMState *env)
53
return float64_to_float32(x, &env->vfp.fp_status);
54
}
55
56
-/* VFP3 fixed point conversion. */
57
+/*
58
+ * VFP3 fixed point conversion. The AArch32 versions of fix-to-float
59
+ * must always round-to-nearest; the AArch64 ones honour the FPSCR
60
+ * rounding mode. (For AArch32 Neon the standard-FPSCR is set to
61
+ * round-to-nearest so either helper will work.) AArch32 float-to-fix
62
+ * must round-to-zero.
63
+ */
64
#define VFP_CONV_FIX_FLOAT(name, p, fsz, ftype, isz, itype) \
65
ftype HELPER(vfp_##name##to##p)(uint##isz##_t x, uint32_t shift, \
66
void *fpstp) \
67
{ return itype##_to_##float##fsz##_scalbn(x, -shift, fpstp); }
68
69
+#define VFP_CONV_FIX_FLOAT_ROUND(name, p, fsz, ftype, isz, itype) \
70
+ ftype HELPER(vfp_##name##to##p##_round_to_nearest)(uint##isz##_t x, \
71
+ uint32_t shift, \
72
+ void *fpstp) \
73
+ { \
74
+ ftype ret; \
75
+ float_status *fpst = fpstp; \
76
+ FloatRoundMode oldmode = fpst->float_rounding_mode; \
77
+ fpst->float_rounding_mode = float_round_nearest_even; \
78
+ ret = itype##_to_##float##fsz##_scalbn(x, -shift, fpstp); \
79
+ fpst->float_rounding_mode = oldmode; \
80
+ return ret; \
81
+ }
82
+
83
#define VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, ftype, isz, itype, ROUND, suff) \
84
uint##isz##_t HELPER(vfp_to##name##p##suff)(ftype x, uint32_t shift, \
85
void *fpst) \
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
13
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
95
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
96
--- a/target/arm/translate-vfp.c.inc
15
--- a/target/arm/translate-vfp.c.inc
97
+++ b/target/arm/translate-vfp.c.inc
16
+++ b/target/arm/translate-vfp.c.inc
98
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_hp(DisasContext *s, arg_VCVT_fix_sp *a)
17
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
99
/* Switch on op:U:sx bits */
18
* helper call for the "VMRS to CPSR.NZCV" insn.
100
switch (a->opc) {
19
*/
101
case 0:
20
tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
102
- gen_helper_vfp_shtoh(vd, vd, shift, fpst);
21
- tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
103
+ gen_helper_vfp_shtoh_round_to_nearest(vd, vd, shift, fpst);
22
+ tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
23
storefn(s, opaque, tmp);
104
break;
24
break;
105
case 1:
25
default:
106
- gen_helper_vfp_sltoh(vd, vd, shift, fpst);
26
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
107
+ gen_helper_vfp_sltoh_round_to_nearest(vd, vd, shift, fpst);
27
case ARM_VFP_FPSCR:
108
break;
28
if (a->rt == 15) {
109
case 2:
29
tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
110
- gen_helper_vfp_uhtoh(vd, vd, shift, fpst);
30
- tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
111
+ gen_helper_vfp_uhtoh_round_to_nearest(vd, vd, shift, fpst);
31
+ tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
112
break;
32
} else {
113
case 3:
33
tmp = tcg_temp_new_i32();
114
- gen_helper_vfp_ultoh(vd, vd, shift, fpst);
34
gen_helper_vfp_get_fpscr(tmp, cpu_env);
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);
161
--
35
--
162
2.20.1
36
2.20.1
163
37
164
38
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Factor out the code which handles M-profile lazy FP state preservation
2
from full_vfp_access_check(); accesses to the FPCXT_NS register are
3
a special case which need to do just this part (corresponding in the
4
pseudocode to the PreserveFPState() function), and not the full
5
set of actions matching the pseudocode ExecuteFPCheck() which
6
normal FP instructions need to do.
2
7
3
These are all of the defines required to parse
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
GNU_PROPERTY_AARCH64_FEATURE_1_AND, copied from binutils.
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Other missing defines related to other GNU program headers
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
and notes are elided for now.
11
Message-id: 20201119215617.29887-13-peter.maydell@linaro.org
12
---
13
target/arm/translate-vfp.c.inc | 45 ++++++++++++++++++++--------------
14
1 file changed, 27 insertions(+), 18 deletions(-)
7
15
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
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
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/elf.h
18
--- a/target/arm/translate-vfp.c.inc
19
+++ b/include/elf.h
19
+++ b/target/arm/translate-vfp.c.inc
20
@@ -XXX,XX +XXX,XX @@ typedef int64_t Elf64_Sxword;
20
@@ -XXX,XX +XXX,XX @@ static inline long vfp_f16_offset(unsigned reg, bool top)
21
#define PT_NOTE 4
21
return offs;
22
#define PT_SHLIB 5
22
}
23
#define PT_PHDR 6
23
24
+#define PT_LOOS 0x60000000
24
+/*
25
+#define PT_HIOS 0x6fffffff
25
+ * Generate code for M-profile lazy FP state preservation if needed;
26
#define PT_LOPROC 0x70000000
26
+ * this corresponds to the pseudocode PreserveFPState() function.
27
#define PT_HIPROC 0x7fffffff
27
+ */
28
28
+static void gen_preserve_fp_state(DisasContext *s)
29
+#define PT_GNU_PROPERTY (PT_LOOS + 0x474e553)
29
+{
30
+
30
+ if (s->v7m_lspact) {
31
#define PT_MIPS_REGINFO 0x70000000
31
+ /*
32
#define PT_MIPS_RTPROC 0x70000001
32
+ * Lazy state saving affects external memory and also the NVIC,
33
#define PT_MIPS_OPTIONS 0x70000002
33
+ * so we must mark it as an IO operation for icount (and cause
34
@@ -XXX,XX +XXX,XX @@ typedef struct elf64_shdr {
34
+ * this to be the last insn in the TB).
35
#define NT_ARM_SYSTEM_CALL 0x404 /* ARM system call number */
35
+ */
36
#define NT_ARM_SVE 0x405 /* ARM Scalable Vector Extension regs */
36
+ if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
37
37
+ s->base.is_jmp = DISAS_UPDATE_EXIT;
38
+/* Defined note types for GNU systems. */
38
+ gen_io_start();
39
+
39
+ }
40
+#define NT_GNU_PROPERTY_TYPE_0 5 /* Program property */
40
+ gen_helper_v7m_preserve_fp_state(cpu_env);
41
+
41
+ /*
42
+/* Values used in GNU .note.gnu.property notes (NT_GNU_PROPERTY_TYPE_0). */
42
+ * If the preserve_fp_state helper doesn't throw an exception
43
+
43
+ * then it will clear LSPACT; we don't need to repeat this for
44
+#define GNU_PROPERTY_STACK_SIZE 1
44
+ * any further FP insns in this TB.
45
+#define GNU_PROPERTY_NO_COPY_ON_PROTECTED 2
45
+ */
46
+
46
+ s->v7m_lspact = false;
47
+#define GNU_PROPERTY_LOPROC 0xc0000000
47
+ }
48
+#define GNU_PROPERTY_HIPROC 0xdfffffff
48
+}
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
+
49
+
56
/*
50
/*
57
* Physical entry point into the kernel.
51
* Check that VFP access is enabled. If it is, do the necessary
58
*
52
* M-profile lazy-FP handling and then return true.
53
@@ -XXX,XX +XXX,XX @@ static bool full_vfp_access_check(DisasContext *s, bool ignore_vfp_enabled)
54
/* Handle M-profile lazy FP state mechanics */
55
56
/* Trigger lazy-state preservation if necessary */
57
- if (s->v7m_lspact) {
58
- /*
59
- * Lazy state saving affects external memory and also the NVIC,
60
- * so we must mark it as an IO operation for icount (and cause
61
- * this to be the last insn in the TB).
62
- */
63
- if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
64
- s->base.is_jmp = DISAS_UPDATE_EXIT;
65
- gen_io_start();
66
- }
67
- gen_helper_v7m_preserve_fp_state(cpu_env);
68
- /*
69
- * If the preserve_fp_state helper doesn't throw an exception
70
- * then it will clear LSPACT; we don't need to repeat this for
71
- * any further FP insns in this TB.
72
- */
73
- s->v7m_lspact = false;
74
- }
75
+ gen_preserve_fp_state(s);
76
77
/* Update ownership of FP context: set FPCCR.S to match current state */
78
if (s->v8m_fpccr_s_wrong) {
59
--
79
--
60
2.20.1
80
2.20.1
61
81
62
82
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Implement the new-in-v8.1M FPCXT_S floating point system register.
2
This is for saving and restoring the secure floating point context,
3
and it reads and writes bits [27:0] from the FPSCR and the
4
CONTROL.SFPA bit in bit [31].
2
5
3
Use the new generic support for NT_GNU_PROPERTY_TYPE_0.
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20201119215617.29887-14-peter.maydell@linaro.org
9
---
10
target/arm/translate-vfp.c.inc | 58 ++++++++++++++++++++++++++++++++++
11
1 file changed, 58 insertions(+)
4
12
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
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
14
index XXXXXXX..XXXXXXX 100644
15
--- a/linux-user/elfload.c
15
--- a/target/arm/translate-vfp.c.inc
16
+++ b/linux-user/elfload.c
16
+++ b/target/arm/translate-vfp.c.inc
17
@@ -XXX,XX +XXX,XX @@ static void elf_core_copy_regs(target_elf_gregset_t *regs,
17
@@ -XXX,XX +XXX,XX @@ static FPSysRegCheckResult fp_sysreg_checks(DisasContext *s, int regno)
18
18
return false;
19
#include "elf.h"
19
}
20
20
break;
21
+/* We must delay the following stanzas until after "elf.h". */
21
+ case ARM_VFP_FPCXT_S:
22
+#if defined(TARGET_AARCH64)
22
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
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;
23
+ return false;
33
+ }
24
+ }
34
+ /* We will extract GNU_PROPERTY_AARCH64_FEATURE_1_BTI later. */
25
+ if (!s->v8m_secure) {
35
+ info->note_flags = *data;
26
+ return false;
27
+ }
28
+ break;
29
default:
30
return FPSysRegCheckFailed;
31
}
32
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
33
tcg_temp_free_i32(tmp);
34
break;
35
}
36
+ case ARM_VFP_FPCXT_S:
37
+ {
38
+ TCGv_i32 sfpa, control, fpscr;
39
+ /* Set FPSCR[27:0] and CONTROL.SFPA from value */
40
+ tmp = loadfn(s, opaque);
41
+ sfpa = tcg_temp_new_i32();
42
+ tcg_gen_shri_i32(sfpa, tmp, 31);
43
+ control = load_cpu_field(v7m.control[M_REG_S]);
44
+ tcg_gen_deposit_i32(control, control, sfpa,
45
+ R_V7M_CONTROL_SFPA_SHIFT, 1);
46
+ store_cpu_field(control, v7m.control[M_REG_S]);
47
+ fpscr = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
48
+ tcg_gen_andi_i32(fpscr, fpscr, FPCR_NZCV_MASK);
49
+ tcg_gen_andi_i32(tmp, tmp, ~FPCR_NZCV_MASK);
50
+ tcg_gen_or_i32(fpscr, fpscr, tmp);
51
+ store_cpu_field(fpscr, vfp.xregs[ARM_VFP_FPSCR]);
52
+ tcg_temp_free_i32(tmp);
53
+ tcg_temp_free_i32(sfpa);
54
+ break;
36
+ }
55
+ }
37
+ return true;
56
default:
38
+}
57
g_assert_not_reached();
39
+#define ARCH_USE_GNU_PROPERTY 1
58
}
40
+
59
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
41
+#else
60
tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
42
+
61
storefn(s, opaque, tmp);
43
static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
62
break;
44
const uint32_t *data,
63
+ case ARM_VFP_FPCXT_S:
45
struct image_info *info,
64
+ {
46
@@ -XXX,XX +XXX,XX @@ static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
65
+ TCGv_i32 control, sfpa, fpscr;
47
}
66
+ /* Bits [27:0] from FPSCR, bit [31] from CONTROL.SFPA */
48
#define ARCH_USE_GNU_PROPERTY 0
67
+ tmp = tcg_temp_new_i32();
49
68
+ sfpa = tcg_temp_new_i32();
50
+#endif
69
+ gen_helper_vfp_get_fpscr(tmp, cpu_env);
51
+
70
+ tcg_gen_andi_i32(tmp, tmp, ~FPCR_NZCV_MASK);
52
struct exec
71
+ control = load_cpu_field(v7m.control[M_REG_S]);
53
{
72
+ tcg_gen_andi_i32(sfpa, control, R_V7M_CONTROL_SFPA_MASK);
54
unsigned int a_info; /* Use macros N_MAGIC, etc for access */
73
+ tcg_gen_shli_i32(sfpa, sfpa, 31 - R_V7M_CONTROL_SFPA_SHIFT);
55
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
74
+ tcg_gen_or_i32(tmp, tmp, sfpa);
56
struct elfhdr *ehdr = (struct elfhdr *)bprm_buf;
75
+ tcg_temp_free_i32(sfpa);
57
struct elf_phdr *phdr;
76
+ /*
58
abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
77
+ * Store result before updating FPSCR etc, in case
59
- int i, retval;
78
+ * it is a memory write which causes an exception.
60
+ int i, retval, prot_exec;
79
+ */
61
Error *err = NULL;
80
+ storefn(s, opaque, tmp);
62
81
+ /*
63
/* First of all, some simple consistency checks */
82
+ * Now we must reset FPSCR from FPDSCR_NS, and clear
64
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
83
+ * CONTROL.SFPA; so we'll end the TB here.
65
info->brk = 0;
84
+ */
66
info->elf_flags = ehdr->e_flags;
85
+ tcg_gen_andi_i32(control, control, ~R_V7M_CONTROL_SFPA_MASK);
67
86
+ store_cpu_field(control, v7m.control[M_REG_S]);
68
+ prot_exec = PROT_EXEC;
87
+ fpscr = load_cpu_field(v7m.fpdscr[M_REG_NS]);
69
+#ifdef TARGET_AARCH64
88
+ gen_helper_vfp_set_fpscr(cpu_env, fpscr);
70
+ /*
89
+ tcg_temp_free_i32(fpscr);
71
+ * If the BTI feature is present, this indicates that the executable
90
+ gen_lookup_tb(s);
72
+ * pages of the startup binary should be mapped with PROT_BTI, so that
91
+ break;
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
+ }
92
+ }
86
+#endif
93
default:
87
+
94
g_assert_not_reached();
88
for (i = 0; i < ehdr->e_phnum; i++) {
95
}
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
--
96
--
101
2.20.1
97
2.20.1
102
98
103
99
diff view generated by jsdifflib
1
If the M-profile low-overhead-branch extension is implemented, FPSCR
1
The FPDSCR register has a similar layout to the FPSCR. In v8.1M it
2
bits [18:16] are a new field LTPSIZE. If MVE is not implemented
2
gains new fields FZ16 (if half-precision floating point is supported)
3
(currently always true for us) then this field always reads as 4 and
3
and LTPSIZE (always reads as 4). Update the reset value and the code
4
ignores writes.
4
that handles writes to this register accordingly.
5
6
These bits used to be the vector-length field for the old
7
short-vector extension, so we need to take care that they are not
8
misinterpreted as setting vec_len. We do this with a rearrangement
9
of the vfp_set_fpscr() code that deals with vec_len, vec_stride
10
and also the QC bit; this obviates the need for the M-profile
11
only masking step that we used to have at the start of the function.
12
13
We provide a new field in CPUState for LTPSIZE, even though this
14
will always be 4, in preparation for MVE, so we don't have to
15
come back later and split it out of the vfp.xregs[FPSCR] value.
16
(This state struct field will be saved and restored as part of
17
the FPSCR value via the vmstate_fpscr in machine.c.)
18
5
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Message-id: 20201019151301.2046-11-peter.maydell@linaro.org
8
Message-id: 20201119215617.29887-16-peter.maydell@linaro.org
22
---
9
---
23
target/arm/cpu.h | 1 +
10
target/arm/cpu.h | 5 +++++
24
target/arm/cpu.c | 9 +++++++++
11
hw/intc/armv7m_nvic.c | 9 ++++++++-
25
target/arm/vfp_helper.c | 6 ++++++
12
target/arm/cpu.c | 3 +++
26
3 files changed, 16 insertions(+)
13
3 files changed, 16 insertions(+), 1 deletion(-)
27
14
28
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
29
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/cpu.h
17
--- a/target/arm/cpu.h
31
+++ b/target/arm/cpu.h
18
+++ b/target/arm/cpu.h
32
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
19
@@ -XXX,XX +XXX,XX @@ void vfp_set_fpscr(CPUARMState *env, uint32_t val);
33
uint32_t fpdscr[M_REG_NUM_BANKS];
20
#define FPCR_IXE (1 << 12) /* Inexact exception trap enable */
34
uint32_t cpacr[M_REG_NUM_BANKS];
21
#define FPCR_IDE (1 << 15) /* Input Denormal exception trap enable */
35
uint32_t nsacr;
22
#define FPCR_FZ16 (1 << 19) /* ARMv8.2+, FP16 flush-to-zero */
36
+ int ltpsize;
23
+#define FPCR_RMODE_MASK (3 << 22) /* Rounding mode */
37
} v7m;
24
#define FPCR_FZ (1 << 24) /* Flush-to-zero enable bit */
38
25
#define FPCR_DN (1 << 25) /* Default NaN enable bit */
39
/* Information associated with an exception about to be taken:
26
+#define FPCR_AHP (1 << 26) /* Alternative half-precision */
27
#define FPCR_QC (1 << 27) /* Cumulative saturation bit */
28
#define FPCR_V (1 << 28) /* FP overflow flag */
29
#define FPCR_C (1 << 29) /* FP carry flag */
30
#define FPCR_Z (1 << 30) /* FP zero flag */
31
#define FPCR_N (1 << 31) /* FP negative flag */
32
33
+#define FPCR_LTPSIZE_SHIFT 16 /* LTPSIZE, M-profile only */
34
+#define FPCR_LTPSIZE_MASK (7 << FPCR_LTPSIZE_SHIFT)
35
+
36
#define FPCR_NZCV_MASK (FPCR_N | FPCR_Z | FPCR_C | FPCR_V)
37
#define FPCR_NZCVQC_MASK (FPCR_NZCV_MASK | FPCR_QC)
38
39
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/hw/intc/armv7m_nvic.c
42
+++ b/hw/intc/armv7m_nvic.c
43
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
44
break;
45
case 0xf3c: /* FPDSCR */
46
if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
47
- value &= 0x07c00000;
48
+ uint32_t mask = FPCR_AHP | FPCR_DN | FPCR_FZ | FPCR_RMODE_MASK;
49
+ if (cpu_isar_feature(any_fp16, cpu)) {
50
+ mask |= FPCR_FZ16;
51
+ }
52
+ value &= mask;
53
+ if (cpu_isar_feature(aa32_lob, cpu)) {
54
+ value |= 4 << FPCR_LTPSIZE_SHIFT;
55
+ }
56
cpu->env.v7m.fpdscr[attrs.secure] = value;
57
}
58
break;
40
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
59
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
41
index XXXXXXX..XXXXXXX 100644
60
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/cpu.c
61
--- a/target/arm/cpu.c
43
+++ b/target/arm/cpu.c
62
+++ b/target/arm/cpu.c
44
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
63
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
45
uint8_t *rom;
64
* always reset to 4.
46
uint32_t vecbase;
65
*/
47
66
env->v7m.ltpsize = 4;
48
+ if (cpu_isar_feature(aa32_lob, cpu)) {
67
+ /* The LTPSIZE field in FPDSCR is constant and reads as 4. */
49
+ /*
68
+ env->v7m.fpdscr[M_REG_NS] = 4 << FPCR_LTPSIZE_SHIFT;
50
+ * LTPSIZE is constant 4 if MVE not implemented, and resets
69
+ env->v7m.fpdscr[M_REG_S] = 4 << FPCR_LTPSIZE_SHIFT;
51
+ * to an UNKNOWN value if MVE is implemented. We choose to
70
}
52
+ * always reset to 4.
71
53
+ */
54
+ env->v7m.ltpsize = 4;
55
+ }
56
+
57
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
72
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
58
env->v7m.secure = true;
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];
77
--
73
--
78
2.20.1
74
2.20.1
79
75
80
76
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
In v8.0M, on exception entry the registers R0-R3, R12, APSR and EPSR
2
are zeroed for an exception taken to Non-secure state; for an
3
exception taken to Secure state they become UNKNOWN, and we chose to
4
leave them at their previous values.
2
5
3
Commit 7998beb9c2e removed the ram_size initialization in the
6
In v8.1M the behaviour is specified more tightly and these registers
4
arm_boot_info structure, however it is used by arm_load_kernel().
7
are always zeroed regardless of the security state that the exception
8
targets (see rule R_KPZV). Implement this.
5
9
6
Initialize the field to fix:
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20201119215617.29887-17-peter.maydell@linaro.org
13
---
14
target/arm/m_helper.c | 16 ++++++++++++----
15
1 file changed, 12 insertions(+), 4 deletions(-)
7
16
8
$ qemu-system-arm -M n800 -append 'console=ttyS1' \
17
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
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
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
---
22
hw/arm/nseries.c | 1 +
23
1 file changed, 1 insertion(+)
24
25
diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
26
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/arm/nseries.c
19
--- a/target/arm/m_helper.c
28
+++ b/hw/arm/nseries.c
20
+++ b/target/arm/m_helper.c
29
@@ -XXX,XX +XXX,XX @@ static void n8x0_init(MachineState *machine,
21
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
30
g_free(sz);
22
* Clear registers if necessary to prevent non-secure exception
31
exit(EXIT_FAILURE);
23
* code being able to see register values from secure code.
32
}
24
* Where register values become architecturally UNKNOWN we leave
33
+ binfo->ram_size = machine->ram_size;
25
- * them with their previous values.
34
26
+ * them with their previous values. v8.1M is tighter than v8.0M
35
memory_region_add_subregion(get_system_memory(), OMAP2_Q2_BASE,
27
+ * here and always zeroes the caller-saved registers regardless
36
machine->ram);
28
+ * of the security state the exception is targeting.
29
*/
30
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
31
- if (!targets_secure) {
32
+ if (!targets_secure || arm_feature(env, ARM_FEATURE_V8_1M)) {
33
/*
34
* Always clear the caller-saved registers (they have been
35
* pushed to the stack earlier in v7m_push_stack()).
36
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
37
* v7m_push_callee_stack()).
38
*/
39
int i;
40
+ /*
41
+ * r4..r11 are callee-saves, zero only if background
42
+ * state was Secure (EXCRET.S == 1) and exception
43
+ * targets Non-secure state
44
+ */
45
+ bool zero_callee_saves = !targets_secure &&
46
+ (lr & R_V7M_EXCRET_S_MASK);
47
48
for (i = 0; i < 13; i++) {
49
- /* r4..r11 are callee-saves, zero only if EXCRET.S == 1 */
50
- if (i < 4 || i > 11 || (lr & R_V7M_EXCRET_S_MASK)) {
51
+ if (i < 4 || i > 11 || zero_callee_saves) {
52
env->regs[i] = 0;
53
}
54
}
37
--
55
--
38
2.20.1
56
2.20.1
39
57
40
58
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
In v8.1M, vector table fetch failures don't set HFSR.FORCED (see rule
2
R_LLRP). (In previous versions of the architecture this was either
3
required or IMPDEF.)
2
4
3
The reporting in AArch64.TagCheckFail only depends on PSTATE.EL,
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
and not the AccType of the operation. There are two guest
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
visible problems that affect LDTR and STTR because of this:
7
Message-id: 20201119215617.29887-18-peter.maydell@linaro.org
8
---
9
target/arm/m_helper.c | 6 +++++-
10
1 file changed, 5 insertions(+), 1 deletion(-)
6
11
7
(1) Selecting TCF0 vs TCF1 to decide on reporting,
12
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
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
13
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/mte_helper.c
14
--- a/target/arm/m_helper.c
23
+++ b/target/arm/mte_helper.c
15
+++ b/target/arm/m_helper.c
24
@@ -XXX,XX +XXX,XX @@ static void mte_check_fail(CPUARMState *env, uint32_t desc,
16
@@ -XXX,XX +XXX,XX @@ load_fail:
25
reg_el = regime_el(env, arm_mmu_idx);
17
* The HardFault is Secure if BFHFNMINS is 0 (meaning that all HFs are
26
sctlr = env->cp15.sctlr_el[reg_el];
18
* secure); otherwise it targets the same security state as the
27
19
* underlying exception.
28
- switch (arm_mmu_idx) {
20
+ * In v8.1M HardFaults from vector table fetch fails don't set FORCED.
29
- case ARMMMUIdx_E10_0:
21
*/
30
- case ARMMMUIdx_E20_0:
22
if (!(cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK)) {
31
- el = 0;
23
exc_secure = true;
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
}
24
}
41
25
- env->v7m.hfsr |= R_V7M_HFSR_VECTTBL_MASK | R_V7M_HFSR_FORCED_MASK;
26
+ env->v7m.hfsr |= R_V7M_HFSR_VECTTBL_MASK;
27
+ if (!arm_feature(env, ARM_FEATURE_V8_1M)) {
28
+ env->v7m.hfsr |= R_V7M_HFSR_FORCED_MASK;
29
+ }
30
armv7m_nvic_set_pending_derived(env->nvic, ARMV7M_EXCP_HARD, exc_secure);
31
return false;
32
}
42
--
33
--
43
2.20.1
34
2.20.1
44
35
45
36
diff view generated by jsdifflib
1
The SMLAD instruction is supposed to:
1
In v8.1M a REVIDR register is defined, which is at address 0xe00ecfc
2
* signed multiply Rn[15:0] * Rm[15:0]
2
and is a read-only IMPDEF register providing implementation specific
3
* signed multiply Rn[31:16] * Rm[31:16]
3
minor revision information, like the v8A REVIDR_EL1. Implement this.
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)
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
4
29
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
30
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
31
Message-id: 20201009144712.11187-1-peter.maydell@linaro.org
7
Message-id: 20201119215617.29887-19-peter.maydell@linaro.org
32
---
8
---
33
target/arm/translate.c | 58 ++++++++++++++++++++++++++++++++++--------
9
hw/intc/armv7m_nvic.c | 5 +++++
34
1 file changed, 48 insertions(+), 10 deletions(-)
10
1 file changed, 5 insertions(+)
35
11
36
diff --git a/target/arm/translate.c b/target/arm/translate.c
12
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
37
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/translate.c
14
--- a/hw/intc/armv7m_nvic.c
39
+++ b/target/arm/translate.c
15
+++ b/hw/intc/armv7m_nvic.c
40
@@ -XXX,XX +XXX,XX @@ static bool op_smlad(DisasContext *s, arg_rrrr *a, bool m_swap, bool sub)
16
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
41
gen_smul_dual(t1, t2);
17
}
42
18
return val;
43
if (sub) {
19
}
44
- /* This subtraction cannot overflow. */
20
+ case 0xcfc:
45
+ /*
21
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8_1M)) {
46
+ * This subtraction cannot overflow, so we can do a simple
22
+ goto bad_offset;
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
+ }
23
+ }
58
+ } else if (a->ra == 15) {
24
+ return cpu->revidr;
59
+ /* Single saturation-checking addition */
25
case 0xd00: /* CPUID Base. */
60
+ gen_helper_add_setq(t1, cpu_env, t1, t2);
26
return cpu->midr;
61
+ tcg_temp_free_i32(t2);
27
case 0xd04: /* Interrupt Control State (ICSR) */
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
--
28
--
111
2.20.1
29
2.20.1
112
30
113
31
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
1
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
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
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
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
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
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
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
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
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
1
From: Richard Henderson <richard.henderson@linaro.org>
1
In v8.1M a new exception return check is added which may cause a NOCP
2
UsageFault (see rule R_XLTP): before we clear s0..s15 and the FPSCR
3
we must check whether access to CP10 from the Security state of the
4
returning exception is disabled; if it is then we must take a fault.
2
5
3
For BTI, we need to know if the executable is static or dynamic,
6
(Note that for our implementation CPPWR is always RAZ/WI and so can
4
which means looking for PT_INTERP earlier.
7
never cause CP10 accesses to fail.)
5
8
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
The other v8.1M change to this register-clearing code is that if MVE
7
Message-id: 20201016184207.786698-8-richard.henderson@linaro.org
10
is implemented VPR must also be cleared, so add a TODO comment to
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
that effect.
12
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20201119215617.29887-20-peter.maydell@linaro.org
10
---
16
---
11
linux-user/elfload.c | 60 +++++++++++++++++++++++---------------------
17
target/arm/m_helper.c | 22 +++++++++++++++++++++-
12
1 file changed, 31 insertions(+), 29 deletions(-)
18
1 file changed, 21 insertions(+), 1 deletion(-)
13
19
14
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
20
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
15
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
16
--- a/linux-user/elfload.c
22
--- a/target/arm/m_helper.c
17
+++ b/linux-user/elfload.c
23
+++ b/target/arm/m_helper.c
18
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
24
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
19
25
v7m_exception_taken(cpu, excret, true, false);
20
mmap_lock();
26
return;
21
27
} else {
22
- /* Find the maximum size of the image and allocate an appropriate
28
- /* Clear s0..s15 and FPSCR */
23
- amount of memory to handle that. */
29
+ if (arm_feature(env, ARM_FEATURE_V8_1M)) {
24
+ /*
30
+ /* v8.1M adds this NOCP check */
25
+ * Find the maximum size of the image and allocate an appropriate
31
+ bool nsacr_pass = exc_secure ||
26
+ * amount of memory to handle that. Locate the interpreter, if any.
32
+ extract32(env->v7m.nsacr, 10, 1);
27
+ */
33
+ bool cpacr_pass = v7m_cpacr_pass(env, exc_secure, true);
28
loaddr = -1, hiaddr = 0;
34
+ if (!nsacr_pass) {
29
info->alignment = 0;
35
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, true);
30
for (i = 0; i < ehdr->e_phnum; ++i) {
36
+ env->v7m.cfsr[M_REG_S] |= R_V7M_CFSR_NOCP_MASK;
31
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
37
+ qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on existing "
32
}
38
+ "stackframe: NSACR prevents clearing FPU registers\n");
33
++info->nsegs;
39
+ v7m_exception_taken(cpu, excret, true, false);
34
info->alignment |= eppnt->p_align;
40
+ } else if (!cpacr_pass) {
35
+ } else if (eppnt->p_type == PT_INTERP && pinterp_name) {
41
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE,
36
+ g_autofree char *interp_name = NULL;
42
+ exc_secure);
37
+
43
+ env->v7m.cfsr[exc_secure] |= R_V7M_CFSR_NOCP_MASK;
38
+ if (*pinterp_name) {
44
+ qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on existing "
39
+ errmsg = "Multiple PT_INTERP entries";
45
+ "stackframe: CPACR prevents clearing FPU registers\n");
40
+ goto exit_errmsg;
46
+ v7m_exception_taken(cpu, excret, true, false);
41
+ }
42
+ interp_name = g_malloc(eppnt->p_filesz);
43
+ if (!interp_name) {
44
+ goto exit_perror;
45
+ }
46
+
47
+ if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
48
+ memcpy(interp_name, bprm_buf + eppnt->p_offset,
49
+ eppnt->p_filesz);
50
+ } else {
51
+ retval = pread(image_fd, interp_name, eppnt->p_filesz,
52
+ eppnt->p_offset);
53
+ if (retval != eppnt->p_filesz) {
54
+ goto exit_perror;
55
+ }
47
+ }
56
+ }
48
+ }
57
+ if (interp_name[eppnt->p_filesz - 1] != 0) {
49
+ /* Clear s0..s15 and FPSCR; TODO also VPR when MVE is implemented */
58
+ errmsg = "Invalid PT_INTERP entry";
50
int i;
59
+ goto exit_errmsg;
51
60
+ }
52
for (i = 0; i < 16; i += 2) {
61
+ *pinterp_name = g_steal_pointer(&interp_name);
62
}
63
}
64
65
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
66
if (vaddr_em > info->brk) {
67
info->brk = vaddr_em;
68
}
69
- } else if (eppnt->p_type == PT_INTERP && pinterp_name) {
70
- g_autofree char *interp_name = NULL;
71
-
72
- if (*pinterp_name) {
73
- errmsg = "Multiple PT_INTERP entries";
74
- goto exit_errmsg;
75
- }
76
- interp_name = g_malloc(eppnt->p_filesz);
77
- if (!interp_name) {
78
- goto exit_perror;
79
- }
80
-
81
- if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
82
- memcpy(interp_name, bprm_buf + eppnt->p_offset,
83
- eppnt->p_filesz);
84
- } else {
85
- retval = pread(image_fd, interp_name, eppnt->p_filesz,
86
- eppnt->p_offset);
87
- if (retval != eppnt->p_filesz) {
88
- goto exit_perror;
89
- }
90
- }
91
- if (interp_name[eppnt->p_filesz - 1] != 0) {
92
- errmsg = "Invalid PT_INTERP entry";
93
- goto exit_errmsg;
94
- }
95
- *pinterp_name = g_steal_pointer(&interp_name);
96
#ifdef TARGET_MIPS
97
} else if (eppnt->p_type == PT_MIPS_ABIFLAGS) {
98
Mips_elf_abiflags_v0 abiflags;
99
--
53
--
100
2.20.1
54
2.20.1
101
55
102
56
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
v8.1M adds new encodings of VLLDM and VLSTM (where bit 7 is set).
2
The only difference is that:
3
* the old T1 encodings UNDEF if the implementation implements 32
4
Dregs (this is currently architecturally impossible for M-profile)
5
* the new T2 encodings have the implementation-defined option to
6
read from memory (discarding the data) or write UNKNOWN values to
7
memory for the stack slots that would be D16-D31
2
8
3
Unlike many other bits in HCR_EL2, the description for this
9
We choose not to make those accesses, so for us the two
4
bit does not contain the phrase "if ... this field behaves
10
instructions behave identically assuming they don't UNDEF.
5
as 0 for all purposes other than", so do not squash the bit
6
in arm_hcr_el2_eff.
7
11
8
Instead, replicate the E2H+TGE test in the two places that
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
require it.
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20201119215617.29887-21-peter.maydell@linaro.org
15
---
16
target/arm/m-nocp.decode | 2 +-
17
target/arm/translate-vfp.c.inc | 25 +++++++++++++++++++++++++
18
2 files changed, 26 insertions(+), 1 deletion(-)
10
19
11
Reported-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
20
diff --git a/target/arm/m-nocp.decode b/target/arm/m-nocp.decode
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
21
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/internals.h
22
--- a/target/arm/m-nocp.decode
25
+++ b/target/arm/internals.h
23
+++ b/target/arm/m-nocp.decode
26
@@ -XXX,XX +XXX,XX @@ static inline bool allocation_tag_access_enabled(CPUARMState *env, int el,
24
@@ -XXX,XX +XXX,XX @@
27
&& !(env->cp15.scr_el3 & SCR_ATA)) {
25
26
{
27
# Special cases which do not take an early NOCP: VLLDM and VLSTM
28
- VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 0000 0000
29
+ VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 op:1 000 0000
30
# VSCCLRM (new in v8.1M) is similar:
31
VSCCLRM 1110 1100 1.01 1111 .... 1011 imm:7 0 vd=%vd_dp size=3
32
VSCCLRM 1110 1100 1.01 1111 .... 1010 imm:8 vd=%vd_sp size=2
33
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/translate-vfp.c.inc
36
+++ b/target/arm/translate-vfp.c.inc
37
@@ -XXX,XX +XXX,XX @@ static bool trans_VLLDM_VLSTM(DisasContext *s, arg_VLLDM_VLSTM *a)
38
!arm_dc_feature(s, ARM_FEATURE_V8)) {
28
return false;
39
return false;
29
}
40
}
30
- if (el < 2
41
+
31
- && arm_feature(env, ARM_FEATURE_EL2)
42
+ if (a->op) {
32
- && !(arm_hcr_el2_eff(env) & HCR_ATA)) {
43
+ /*
33
- return false;
44
+ * T2 encoding ({D0-D31} reglist): v8.1M and up. We choose not
34
+ if (el < 2 && arm_feature(env, ARM_FEATURE_EL2)) {
45
+ * to take the IMPDEF option to make memory accesses to the stack
35
+ uint64_t hcr = arm_hcr_el2_eff(env);
46
+ * slots that correspond to the D16-D31 registers (discarding
36
+ if (!(hcr & HCR_ATA) && (!(hcr & HCR_E2H) || !(hcr & HCR_TGE))) {
47
+ * read data and writing UNKNOWN values), so for us the T2
48
+ * encoding behaves identically to the T1 encoding.
49
+ */
50
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
37
+ return false;
51
+ return false;
38
+ }
52
+ }
39
}
53
+ } else {
40
sctlr &= (el == 0 ? SCTLR_ATA0 : SCTLR_ATA);
54
+ /*
41
return sctlr != 0;
55
+ * T1 encoding ({D0-D15} reglist); undef if we have 32 Dregs.
42
diff --git a/target/arm/helper.c b/target/arm/helper.c
56
+ * This is currently architecturally impossible, but we add the
43
index XXXXXXX..XXXXXXX 100644
57
+ * check to stay in line with the pseudocode. Note that we must
44
--- a/target/arm/helper.c
58
+ * emit code for the UNDEF so it takes precedence over the NOCP.
45
+++ b/target/arm/helper.c
59
+ */
46
@@ -XXX,XX +XXX,XX @@ static CPAccessResult access_mte(CPUARMState *env, const ARMCPRegInfo *ri,
60
+ if (dc_isar_feature(aa32_simd_r32, s)) {
47
{
61
+ unallocated_encoding(s);
48
int el = arm_current_el(env);
62
+ return true;
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
+ }
63
+ }
59
}
64
+ }
60
if (el < 3 &&
65
+
61
arm_feature(env, ARM_FEATURE_EL3) &&
66
/*
67
* If not secure, UNDEF. We must emit code for this
68
* rather than returning false so that this takes
62
--
69
--
63
2.20.1
70
2.20.1
64
71
65
72
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
v8.1M introduces a new TRD flag in the CCR register, which enables
2
checking for stack frame integrity signatures on SG instructions.
3
This bit is not banked, and is always RAZ/WI to Non-secure code.
4
Adjust the code for handling CCR reads and writes to handle this.
2
5
3
Transform the prot bit to a qemu internal page bit, and save
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
it in the page tables.
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20201119215617.29887-23-peter.maydell@linaro.org
9
---
10
target/arm/cpu.h | 2 ++
11
hw/intc/armv7m_nvic.c | 26 ++++++++++++++++++--------
12
2 files changed, 20 insertions(+), 8 deletions(-)
5
13
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20201016184207.786698-3-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
include/exec/cpu-all.h | 2 ++
12
linux-user/syscall_defs.h | 4 ++++
13
target/arm/cpu.h | 5 +++++
14
linux-user/mmap.c | 16 ++++++++++++++++
15
target/arm/translate-a64.c | 6 +++---
16
5 files changed, 30 insertions(+), 3 deletions(-)
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
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
47
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/cpu.h
16
--- a/target/arm/cpu.h
49
+++ b/target/arm/cpu.h
17
+++ b/target/arm/cpu.h
50
@@ -XXX,XX +XXX,XX @@ static inline MemTxAttrs *typecheck_memtxattrs(MemTxAttrs *x)
18
@@ -XXX,XX +XXX,XX @@ FIELD(V7M_CCR, STKOFHFNMIGN, 10, 1)
51
#define arm_tlb_bti_gp(x) (typecheck_memtxattrs(x)->target_tlb_bit0)
19
FIELD(V7M_CCR, DC, 16, 1)
52
#define arm_tlb_mte_tagged(x) (typecheck_memtxattrs(x)->target_tlb_bit1)
20
FIELD(V7M_CCR, IC, 17, 1)
53
21
FIELD(V7M_CCR, BP, 18, 1)
54
+/*
22
+FIELD(V7M_CCR, LOB, 19, 1)
55
+ * AArch64 usage of the PAGE_TARGET_* bits for linux-user.
23
+FIELD(V7M_CCR, TRD, 20, 1)
56
+ */
24
57
+#define PAGE_BTI PAGE_TARGET_1
25
/* V7M SCR bits */
26
FIELD(V7M_SCR, SLEEPONEXIT, 1, 1)
27
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/intc/armv7m_nvic.c
30
+++ b/hw/intc/armv7m_nvic.c
31
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
32
}
33
return cpu->env.v7m.scr[attrs.secure];
34
case 0xd14: /* Configuration Control. */
35
- /* The BFHFNMIGN bit is the only non-banked bit; we
36
- * keep it in the non-secure copy of the register.
37
+ /*
38
+ * Non-banked bits: BFHFNMIGN (stored in the NS copy of the register)
39
+ * and TRD (stored in the S copy of the register)
40
*/
41
val = cpu->env.v7m.ccr[attrs.secure];
42
val |= cpu->env.v7m.ccr[M_REG_NS] & R_V7M_CCR_BFHFNMIGN_MASK;
43
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
44
cpu->env.v7m.scr[attrs.secure] = value;
45
break;
46
case 0xd14: /* Configuration Control. */
47
+ {
48
+ uint32_t mask;
58
+
49
+
59
/*
50
if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
60
* Naming convention for isar_feature functions:
51
goto bad_offset;
61
* Functions which test 32-bit ID registers should have _aa32_ in
52
}
62
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
53
63
index XXXXXXX..XXXXXXX 100644
54
/* Enforce RAZ/WI on reserved and must-RAZ/WI bits */
64
--- a/linux-user/mmap.c
55
- value &= (R_V7M_CCR_STKALIGN_MASK |
65
+++ b/linux-user/mmap.c
56
- R_V7M_CCR_BFHFNMIGN_MASK |
66
@@ -XXX,XX +XXX,XX @@ static int validate_prot_to_pageflags(int *host_prot, int prot)
57
- R_V7M_CCR_DIV_0_TRP_MASK |
67
*host_prot = (prot & (PROT_READ | PROT_WRITE))
58
- R_V7M_CCR_UNALIGN_TRP_MASK |
68
| (prot & PROT_EXEC ? PROT_READ : 0);
59
- R_V7M_CCR_USERSETMPEND_MASK |
69
60
- R_V7M_CCR_NONBASETHRDENA_MASK);
70
+#ifdef TARGET_AARCH64
61
+ mask = R_V7M_CCR_STKALIGN_MASK |
71
+ /*
62
+ R_V7M_CCR_BFHFNMIGN_MASK |
72
+ * The PROT_BTI bit is only accepted if the cpu supports the feature.
63
+ R_V7M_CCR_DIV_0_TRP_MASK |
73
+ * Since this is the unusual case, don't bother checking unless
64
+ R_V7M_CCR_UNALIGN_TRP_MASK |
74
+ * the bit has been requested. If set and valid, record the bit
65
+ R_V7M_CCR_USERSETMPEND_MASK |
75
+ * within QEMU's page_flags.
66
+ R_V7M_CCR_NONBASETHRDENA_MASK;
76
+ */
67
+ if (arm_feature(&cpu->env, ARM_FEATURE_V8_1M) && attrs.secure) {
77
+ if (prot & TARGET_PROT_BTI) {
68
+ /* TRD is always RAZ/WI from NS */
78
+ ARMCPU *cpu = ARM_CPU(thread_cpu);
69
+ mask |= R_V7M_CCR_TRD_MASK;
79
+ if (cpu_isar_feature(aa64_bti, cpu)) {
80
+ valid |= TARGET_PROT_BTI;
81
+ page_flags |= PAGE_BTI;
82
+ }
70
+ }
71
+ value &= mask;
72
73
if (arm_feature(&cpu->env, ARM_FEATURE_V8)) {
74
/* v8M makes NONBASETHRDENA and STKALIGN be RES1 */
75
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
76
77
cpu->env.v7m.ccr[attrs.secure] = value;
78
break;
83
+ }
79
+ }
84
+#endif
80
case 0xd24: /* System Handler Control and State (SHCSR) */
85
+
81
if (!arm_feature(&cpu->env, ARM_FEATURE_V7)) {
86
return prot & ~valid ? 0 : page_flags;
82
goto bad_offset;
87
}
88
89
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
90
index XXXXXXX..XXXXXXX 100644
91
--- a/target/arm/translate-a64.c
92
+++ b/target/arm/translate-a64.c
93
@@ -XXX,XX +XXX,XX @@ static void disas_data_proc_simd_fp(DisasContext *s, uint32_t insn)
94
*/
95
static bool is_guarded_page(CPUARMState *env, DisasContext *s)
96
{
97
-#ifdef CONFIG_USER_ONLY
98
- return false; /* FIXME */
99
-#else
100
uint64_t addr = s->base.pc_first;
101
+#ifdef CONFIG_USER_ONLY
102
+ return page_get_flags(addr) & PAGE_BTI;
103
+#else
104
int mmu_idx = arm_to_core_mmu_idx(s->mmu_idx);
105
unsigned int index = tlb_index(env, mmu_idx, addr);
106
CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
107
--
83
--
108
2.20.1
84
2.20.1
109
85
110
86
diff view generated by jsdifflib
1
v8.1M's "low-overhead-loop" extension has three instructions
1
v8.1M introduces a new TRD flag in the CCR register, which enables
2
for looping:
2
checking for stack frame integrity signatures on SG instructions.
3
* DLS (start of a do-loop)
3
Add the code in the SG insn implementation for the new behaviour.
4
* WLS (start of a while-loop)
5
* LE (end of a loop)
6
7
The loop-start instructions are both simple operations to start a
8
loop whose iteration count (if any) is in LR. The loop-end
9
instruction handles "decrement iteration count and jump back to loop
10
start"; it also caches the information about the branch back to the
11
start of the loop to improve performance of the branch on subsequent
12
iterations.
13
14
As with the branch-future instructions, the architecture permits an
15
implementation to discard the LO_BRANCH_INFO cache at any time, and
16
QEMU takes the IMPDEF option to never set it in the first place
17
(equivalent to discarding it immediately), because for us a "real"
18
implementation would be unnecessary complexity.
19
20
(This implementation only provides the simple looping constructs; the
21
vector extension MVE (Helium) adds some extra variants to handle
22
looping across vectors. We'll add those later when we implement
23
MVE.)
24
4
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
27
Message-id: 20201019151301.2046-8-peter.maydell@linaro.org
7
Message-id: 20201119215617.29887-24-peter.maydell@linaro.org
28
---
8
---
29
target/arm/t32.decode | 8 ++++
9
target/arm/m_helper.c | 86 +++++++++++++++++++++++++++++++++++++++++++
30
target/arm/translate.c | 93 +++++++++++++++++++++++++++++++++++++++++-
10
1 file changed, 86 insertions(+)
31
2 files changed, 99 insertions(+), 2 deletions(-)
32
11
33
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
12
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
34
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/t32.decode
14
--- a/target/arm/m_helper.c
36
+++ b/target/arm/t32.decode
15
+++ b/target/arm/m_helper.c
37
@@ -XXX,XX +XXX,XX @@ BL 1111 0. .......... 11.1 ............ @branch24
16
@@ -XXX,XX +XXX,XX @@ static bool v7m_read_half_insn(ARMCPU *cpu, ARMMMUIdx mmu_idx,
38
BF 1111 0 boff:4 10 ----- 1110 - ---------- 1 # BF
39
BF 1111 0 boff:4 11 ----- 1110 0 0000000000 1 # BFX, BFLX
40
]
41
+ [
42
+ # LE and WLS immediate
43
+ %lob_imm 1:10 11:1 !function=times_2
44
+
45
+ DLS 1111 0 0000 100 rn:4 1110 0000 0000 0001
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
+}
76
+
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;
17
return true;
82
}
18
}
83
19
84
+static bool trans_DLS(DisasContext *s, arg_DLS *a)
20
+static bool v7m_read_sg_stack_word(ARMCPU *cpu, ARMMMUIdx mmu_idx,
21
+ uint32_t addr, uint32_t *spdata)
85
+{
22
+{
86
+ /* M-profile low-overhead loop start */
23
+ /*
87
+ TCGv_i32 tmp;
24
+ * Read a word of data from the stack for the SG instruction,
25
+ * writing the value into *spdata. If the load succeeds, return
26
+ * true; otherwise pend an appropriate exception and return false.
27
+ * (We can't use data load helpers here that throw an exception
28
+ * because of the context we're called in, which is halfway through
29
+ * arm_v7m_cpu_do_interrupt().)
30
+ */
31
+ CPUState *cs = CPU(cpu);
32
+ CPUARMState *env = &cpu->env;
33
+ MemTxAttrs attrs = {};
34
+ MemTxResult txres;
35
+ target_ulong page_size;
36
+ hwaddr physaddr;
37
+ int prot;
38
+ ARMMMUFaultInfo fi = {};
39
+ ARMCacheAttrs cacheattrs = {};
40
+ uint32_t value;
88
+
41
+
89
+ if (!dc_isar_feature(aa32_lob, s)) {
42
+ if (get_phys_addr(env, addr, MMU_DATA_LOAD, mmu_idx, &physaddr,
43
+ &attrs, &prot, &page_size, &fi, &cacheattrs)) {
44
+ /* MPU/SAU lookup failed */
45
+ if (fi.type == ARMFault_QEMU_SFault) {
46
+ qemu_log_mask(CPU_LOG_INT,
47
+ "...SecureFault during stack word read\n");
48
+ env->v7m.sfsr |= R_V7M_SFSR_AUVIOL_MASK | R_V7M_SFSR_SFARVALID_MASK;
49
+ env->v7m.sfar = addr;
50
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SECURE, false);
51
+ } else {
52
+ qemu_log_mask(CPU_LOG_INT,
53
+ "...MemManageFault during stack word read\n");
54
+ env->v7m.cfsr[M_REG_S] |= R_V7M_CFSR_DACCVIOL_MASK |
55
+ R_V7M_CFSR_MMARVALID_MASK;
56
+ env->v7m.mmfar[M_REG_S] = addr;
57
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_MEM, false);
58
+ }
90
+ return false;
59
+ return false;
91
+ }
60
+ }
92
+ if (a->rn == 13 || a->rn == 15) {
61
+ value = address_space_ldl(arm_addressspace(cs, attrs), physaddr,
93
+ /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */
62
+ attrs, &txres);
63
+ if (txres != MEMTX_OK) {
64
+ /* BusFault trying to read the data */
65
+ qemu_log_mask(CPU_LOG_INT,
66
+ "...BusFault during stack word read\n");
67
+ env->v7m.cfsr[M_REG_NS] |=
68
+ (R_V7M_CFSR_PRECISERR_MASK | R_V7M_CFSR_BFARVALID_MASK);
69
+ env->v7m.bfar = addr;
70
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_BUS, false);
94
+ return false;
71
+ return false;
95
+ }
72
+ }
96
+
73
+
97
+ /* Not a while loop, no tail predication: just set LR to the count */
74
+ *spdata = value;
98
+ tmp = load_reg(s, a->rn);
99
+ store_reg(s, 14, tmp);
100
+ return true;
75
+ return true;
101
+}
76
+}
102
+
77
+
103
+static bool trans_WLS(DisasContext *s, arg_WLS *a)
78
static bool v7m_handle_execute_nsc(ARMCPU *cpu)
104
+{
79
{
105
+ /* M-profile low-overhead while-loop start */
80
/*
106
+ TCGv_i32 tmp;
81
@@ -XXX,XX +XXX,XX @@ static bool v7m_handle_execute_nsc(ARMCPU *cpu)
107
+ TCGLabel *nextlabel;
82
*/
83
qemu_log_mask(CPU_LOG_INT, "...really an SG instruction at 0x%08" PRIx32
84
", executing it\n", env->regs[15]);
108
+
85
+
109
+ if (!dc_isar_feature(aa32_lob, s)) {
86
+ if (cpu_isar_feature(aa32_m_sec_state, cpu) &&
110
+ return false;
87
+ !arm_v7m_is_handler_mode(env)) {
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
+ /*
88
+ /*
118
+ * WLS in an IT block is CONSTRAINED UNPREDICTABLE;
89
+ * v8.1M exception stack frame integrity check. Note that we
119
+ * we choose to UNDEF, because otherwise our use of
90
+ * must perform the memory access even if CCR_S.TRD is zero
120
+ * gen_goto_tb(1) would clash with the use of TB exit 1
91
+ * and we aren't going to check what the data loaded is.
121
+ * in the dc->condjmp condition-failed codepath in
122
+ * arm_tr_tb_stop() and we'd get an assertion.
123
+ */
92
+ */
124
+ return false;
93
+ uint32_t spdata, sp;
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
+
94
+
132
+ gen_set_label(nextlabel);
95
+ /*
133
+ gen_jmp(s, read_pc(s) + a->imm);
96
+ * We know we are currently NS, so the S stack pointers must be
134
+ return true;
97
+ * in other_ss_{psp,msp}, not in regs[13]/other_sp.
135
+}
98
+ */
99
+ sp = v7m_using_psp(env) ? env->v7m.other_ss_psp : env->v7m.other_ss_msp;
100
+ if (!v7m_read_sg_stack_word(cpu, mmu_idx, sp, &spdata)) {
101
+ /* Stack access failed and an exception has been pended */
102
+ return false;
103
+ }
136
+
104
+
137
+static bool trans_LE(DisasContext *s, arg_LE *a)
105
+ if (env->v7m.ccr[M_REG_S] & R_V7M_CCR_TRD_MASK) {
138
+{
106
+ if (((spdata & ~1) == 0xfefa125a) ||
139
+ /*
107
+ !(env->v7m.control[M_REG_S] & 1)) {
140
+ * M-profile low-overhead loop end. The architecture permits an
108
+ goto gen_invep;
141
+ * implementation to discard the LO_BRANCH_INFO cache at any time,
109
+ }
142
+ * and we take the IMPDEF option to never set it in the first place
110
+ }
143
+ * (equivalent to always discarding it immediately), because for QEMU
144
+ * a "real" implementation would be complicated and wouldn't execute
145
+ * any faster.
146
+ */
147
+ TCGv_i32 tmp;
148
+
149
+ if (!dc_isar_feature(aa32_lob, s)) {
150
+ return false;
151
+ }
111
+ }
152
+
112
+
153
+ if (!a->f) {
113
env->regs[14] &= ~1;
154
+ /* Not loop-forever. If LR <= 1 this is the last loop: do nothing. */
114
env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_SFPA_MASK;
155
+ arm_gen_condlabel(s);
115
switch_v7m_security_state(env, true);
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);
164
+ return true;
165
+}
166
+
167
static bool op_tbranch(DisasContext *s, arg_tbranch *a, bool half)
168
{
169
TCGv_i32 addr, tmp;
170
--
116
--
171
2.20.1
117
2.20.1
172
118
173
119
diff view generated by jsdifflib
1
M-profile CPUs with half-precision floating point support should
1
In commit 077d7449100d824a4 we added code to handle the v8M
2
be able to write to FPSCR.FZ16, but an M-profile specific masking
2
requirement that returns from NMI or HardFault forcibly deactivate
3
of the value at the top of vfp_set_fpscr() currently prevents that.
3
those exceptions regardless of what interrupt the guest is trying to
4
This is not yet an active bug because we have no M-profile
4
deactivate. Unfortunately this broke the handling of the "illegal
5
FP16 CPUs, but needs to be fixed before we can add any.
5
exception return because the returning exception number is not
6
active" check for those cases. In the pseudocode this test is done
7
on the exception the guest asks to return from, but because our
8
implementation was doing this in armv7m_nvic_complete_irq() after the
9
new "deactivate NMI/HardFault regardless" code we ended up doing the
10
test on the VecInfo for that exception instead, which usually meant
11
failing to raise the illegal exception return fault.
6
12
7
The bits that the masking is effectively preventing from being
13
In the case for "configurable exception targeting the opposite
8
set are the A-profile only short-vector Len and Stride fields,
14
security state" we detected the illegal-return case but went ahead
9
plus the Neon QC bit. Rearrange the order of the function so
15
and deactivated the VecInfo anyway, which is wrong because that is
10
that those fields are handled earlier and only under a suitable
16
the VecInfo for the other security state.
11
guard; this allows us to drop the M-profile specific masking,
12
making FZ16 writeable.
13
17
14
This change also makes the QC bit correctly RAZ/WI for older
18
Rearrange the code so that we first identify the illegal return
15
no-Neon A-profile cores.
19
cases, then see if we really need to deactivate NMI or HardFault
16
20
instead, and finally do the deactivation.
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.
20
21
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
23
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
23
Message-id: 20201019151301.2046-10-peter.maydell@linaro.org
24
Message-id: 20201119215617.29887-25-peter.maydell@linaro.org
24
---
25
---
25
target/arm/vfp_helper.c | 47 ++++++++++++++++++++++++-----------------
26
hw/intc/armv7m_nvic.c | 59 +++++++++++++++++++++++--------------------
26
1 file changed, 28 insertions(+), 19 deletions(-)
27
1 file changed, 32 insertions(+), 27 deletions(-)
27
28
28
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
29
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
29
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/vfp_helper.c
31
--- a/hw/intc/armv7m_nvic.c
31
+++ b/target/arm/vfp_helper.c
32
+++ b/hw/intc/armv7m_nvic.c
32
@@ -XXX,XX +XXX,XX @@ void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
33
@@ -XXX,XX +XXX,XX @@ int armv7m_nvic_complete_irq(void *opaque, int irq, bool secure)
33
val &= ~FPCR_FZ16;
34
{
35
NVICState *s = (NVICState *)opaque;
36
VecInfo *vec = NULL;
37
- int ret;
38
+ int ret = 0;
39
40
assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
41
42
+ trace_nvic_complete_irq(irq, secure);
43
+
44
+ if (secure && exc_is_banked(irq)) {
45
+ vec = &s->sec_vectors[irq];
46
+ } else {
47
+ vec = &s->vectors[irq];
48
+ }
49
+
50
+ /*
51
+ * Identify illegal exception return cases. We can't immediately
52
+ * return at this point because we still need to deactivate
53
+ * (either this exception or NMI/HardFault) first.
54
+ */
55
+ if (!exc_is_banked(irq) && exc_targets_secure(s, irq) != secure) {
56
+ /*
57
+ * Return from a configurable exception targeting the opposite
58
+ * security state from the one we're trying to complete it for.
59
+ * Clear vec because it's not really the VecInfo for this
60
+ * (irq, secstate) so we mustn't deactivate it.
61
+ */
62
+ ret = -1;
63
+ vec = NULL;
64
+ } else if (!vec->active) {
65
+ /* Return from an inactive interrupt */
66
+ ret = -1;
67
+ } else {
68
+ /* Legal return, we will return the RETTOBASE bit value to the caller */
69
+ ret = nvic_rettobase(s);
70
+ }
71
+
72
/*
73
* For negative priorities, v8M will forcibly deactivate the appropriate
74
* NMI or HardFault regardless of what interrupt we're being asked to
75
@@ -XXX,XX +XXX,XX @@ int armv7m_nvic_complete_irq(void *opaque, int irq, bool secure)
34
}
76
}
35
77
36
- if (arm_feature(env, ARM_FEATURE_M)) {
78
if (!vec) {
37
+ vfp_set_fpscr_to_host(env, val);
79
- if (secure && exc_is_banked(irq)) {
38
+
80
- vec = &s->sec_vectors[irq];
39
+ if (!arm_feature(env, ARM_FEATURE_M)) {
81
- } else {
40
/*
82
- vec = &s->vectors[irq];
41
- * M profile FPSCR is RES0 for the QC, STRIDE, FZ16, LEN bits
83
- }
42
- * and also for the trapped-exception-handling bits IxE.
84
- }
43
+ * Short-vector length and stride; on M-profile these bits
85
-
44
+ * are used for different purposes.
86
- trace_nvic_complete_irq(irq, secure);
45
+ * We can't make this conditional be "if MVFR0.FPShVec != 0",
87
-
46
+ * because in v7A no-short-vector-support cores still had to
88
- if (!vec->active) {
47
+ * allow Stride/Len to be written with the only effect that
89
- /* Tell the caller this was an illegal exception return */
48
+ * some insns are required to UNDEF if the guest sets them.
90
- return -1;
49
+ *
91
- }
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
-
92
-
86
- /*
93
- /*
87
- * The bit we set within fpscr_q is arbitrary; the register as a
94
- * If this is a configurable exception and it is currently
88
- * whole being zero/non-zero is what counts.
95
- * targeting the opposite security state from the one we're trying
96
- * to complete it for, this counts as an illegal exception return.
97
- * We still need to deactivate whatever vector the logic above has
98
- * selected, though, as it might not be the same as the one for the
99
- * requested exception number.
89
- */
100
- */
90
- env->vfp.qc[0] = val & FPCR_QC;
101
- if (!exc_is_banked(irq) && exc_targets_secure(s, irq) != secure) {
91
- env->vfp.qc[1] = 0;
102
- ret = -1;
92
- env->vfp.qc[2] = 0;
103
- } else {
93
- env->vfp.qc[3] = 0;
104
- ret = nvic_rettobase(s);
94
}
105
+ return ret;
95
106
}
96
void vfp_set_fpscr(CPUARMState *env, uint32_t val)
107
108
vec->active = 0;
97
--
109
--
98
2.20.1
110
2.20.1
99
111
100
112
diff view generated by jsdifflib
1
The t32 decode has a group which represents a set of insns
1
For v8.1M the architecture mandates that CPUs must provide at
2
which overlap with B_cond_thumb because they have [25:23]=111
2
least the "minimal RAS implementation" from the Reliability,
3
(which is an invalid condition code field for the branch insn).
3
Availability and Serviceability extension. This consists of:
4
This group is currently defined using the {} overlap-OK syntax,
4
* an ESB instruction which is a NOP
5
but it is almost entirely non-overlapping patterns. Switch
5
-- since it is in the HINT space we need only add a comment
6
it over to use a non-overlapping group.
6
* an RFSR register which will RAZ/WI
7
* a RAZ/WI AIRCR.IESB bit
8
-- the code which handles writes to AIRCR does not allow setting
9
of RES0 bits, so we already treat this as RAZ/WI; add a comment
10
noting that this is deliberate
11
* minimal implementation of the RAS register block at 0xe0005000
12
-- this will be in a subsequent commit
13
* setting the ID_PFR0.RAS field to 0b0010
14
-- we will do this when we add the Cortex-M55 CPU model
7
15
8
For this to be valid syntactically, CPS must move into the same
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
overlapping-group as the hint insns (CPS vs hints was the
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
only actual use of the overlap facility for the group).
18
Message-id: 20201119215617.29887-26-peter.maydell@linaro.org
19
---
20
target/arm/cpu.h | 14 ++++++++++++++
21
target/arm/t32.decode | 4 ++++
22
hw/intc/armv7m_nvic.c | 13 +++++++++++++
23
3 files changed, 31 insertions(+)
11
24
12
The non-overlapping subgroup for CLREX/DSB/DMB/ISB/SB is no longer
25
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
13
necessary and so we can remove it (promoting those insns to
26
index XXXXXXX..XXXXXXX 100644
14
be members of the parent group).
27
--- a/target/arm/cpu.h
15
28
+++ b/target/arm/cpu.h
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
29
@@ -XXX,XX +XXX,XX @@ FIELD(ID_MMFR4, LSM, 20, 4)
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
30
FIELD(ID_MMFR4, CCIDX, 24, 4)
18
Message-id: 20201019151301.2046-5-peter.maydell@linaro.org
31
FIELD(ID_MMFR4, EVT, 28, 4)
19
---
32
20
target/arm/t32.decode | 26 ++++++++++++--------------
33
+FIELD(ID_PFR0, STATE0, 0, 4)
21
1 file changed, 12 insertions(+), 14 deletions(-)
34
+FIELD(ID_PFR0, STATE1, 4, 4)
22
35
+FIELD(ID_PFR0, STATE2, 8, 4)
36
+FIELD(ID_PFR0, STATE3, 12, 4)
37
+FIELD(ID_PFR0, CSV2, 16, 4)
38
+FIELD(ID_PFR0, AMU, 20, 4)
39
+FIELD(ID_PFR0, DIT, 24, 4)
40
+FIELD(ID_PFR0, RAS, 28, 4)
41
+
42
FIELD(ID_PFR1, PROGMOD, 0, 4)
43
FIELD(ID_PFR1, SECURITY, 4, 4)
44
FIELD(ID_PFR1, MPROGMOD, 8, 4)
45
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_predinv(const ARMISARegisters *id)
46
return FIELD_EX32(id->id_isar6, ID_ISAR6, SPECRES) != 0;
47
}
48
49
+static inline bool isar_feature_aa32_ras(const ARMISARegisters *id)
50
+{
51
+ return FIELD_EX32(id->id_pfr0, ID_PFR0, RAS) != 0;
52
+}
53
+
54
static inline bool isar_feature_aa32_mprofile(const ARMISARegisters *id)
55
{
56
return FIELD_EX32(id->id_pfr1, ID_PFR1, MPROGMOD) != 0;
23
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
57
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
24
index XXXXXXX..XXXXXXX 100644
58
index XXXXXXX..XXXXXXX 100644
25
--- a/target/arm/t32.decode
59
--- a/target/arm/t32.decode
26
+++ b/target/arm/t32.decode
60
+++ b/target/arm/t32.decode
27
@@ -XXX,XX +XXX,XX @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm
61
@@ -XXX,XX +XXX,XX @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm
28
{
62
# SEV 1111 0011 1010 1111 1000 0000 0000 0100
29
# Group insn[25:23] = 111, which is cond=111x for the branch below,
63
# SEVL 1111 0011 1010 1111 1000 0000 0000 0101
30
# or unconditional, which would be illegal for the branch.
64
31
- {
65
+ # For M-profile minimal-RAS ESB can be a NOP, which is the
32
- # Hints
66
+ # default behaviour since it is in the hint space.
33
+ [
67
+ # ESB 1111 0011 1010 1111 1000 0000 0001 0000
34
+ # Hints, and CPS
68
+
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
69
# The canonical nop ends in 0000 0000, but the whole rest
40
# of the space is "reserved hint, behaves as nop".
70
# of the space is "reserved hint, behaves as nop".
41
NOP 1111 0011 1010 1111 1000 0000 ---- ----
71
NOP 1111 0011 1010 1111 1000 0000 ---- ----
42
+
72
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
43
+ # If imod == '00' && M == '0' then SEE "Hint instructions", above.
73
index XXXXXXX..XXXXXXX 100644
44
+ CPS 1111 0011 1010 1111 1000 0 imod:2 M:1 A:1 I:1 F:1 mode:5 \
74
--- a/hw/intc/armv7m_nvic.c
45
+ &cps
75
+++ b/hw/intc/armv7m_nvic.c
76
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
77
return 0;
78
}
79
return cpu->env.v7m.sfar;
80
+ case 0xf04: /* RFSR */
81
+ if (!cpu_isar_feature(aa32_ras, cpu)) {
82
+ goto bad_offset;
83
+ }
84
+ /* We provide minimal-RAS only: RFSR is RAZ/WI */
85
+ return 0;
86
case 0xf34: /* FPCCR */
87
if (!cpu_isar_feature(aa32_vfp_simd, cpu)) {
88
return 0;
89
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
90
R_V7M_AIRCR_PRIGROUP_SHIFT,
91
R_V7M_AIRCR_PRIGROUP_LENGTH);
92
}
93
+ /* AIRCR.IESB is RAZ/WI because we implement only minimal RAS */
94
if (attrs.secure) {
95
/* These bits are only writable by secure */
96
cpu->env.v7m.aircr = value &
97
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
98
}
99
break;
46
}
100
}
47
101
+ case 0xf04: /* RFSR */
48
- # If imod == '00' && M == '0' then SEE "Hint instructions", above.
102
+ if (!cpu_isar_feature(aa32_ras, cpu)) {
49
- CPS 1111 0011 1010 1111 1000 0 imod:2 M:1 A:1 I:1 F:1 mode:5 \
103
+ goto bad_offset;
50
- &cps
104
+ }
51
-
105
+ /* We provide minimal-RAS only: RFSR is RAZ/WI */
52
# Miscellaneous control
106
+ break;
53
- [
107
case 0xf34: /* FPCCR */
54
- CLREX 1111 0011 1011 1111 1000 1111 0010 1111
108
if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
55
- DSB 1111 0011 1011 1111 1000 1111 0100 ----
109
/* Not all bits here are banked. */
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
--
110
--
78
2.20.1
111
2.20.1
79
112
80
113
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
The RAS feature has a block of memory-mapped registers at offset
2
0x5000 within the PPB. For a "minimal RAS" implementation we provide
3
no error records and so the only registers that exist in the block
4
are ERRIIDR and ERRDEVID.
2
5
3
This is a bit clearer than open-coding some of this
6
The "RAZ/WI for privileged, BusFault for nonprivileged" behaviour
4
with a bare c string.
7
of the "nvic-default" region is actually valid for minimal-RAS,
8
so the main benefit of providing an explicit implementation of
9
the register block is more accurate LOG_UNIMP messages, and a
10
framework for where we could add a real RAS implementation later
11
if necessary.
5
12
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20201016184207.786698-9-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20201119215617.29887-27-peter.maydell@linaro.org
10
---
16
---
11
linux-user/elfload.c | 37 ++++++++++++++++++++-----------------
17
include/hw/intc/armv7m_nvic.h | 1 +
12
1 file changed, 20 insertions(+), 17 deletions(-)
18
hw/intc/armv7m_nvic.c | 56 +++++++++++++++++++++++++++++++++++
19
2 files changed, 57 insertions(+)
13
20
14
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
21
diff --git a/include/hw/intc/armv7m_nvic.h b/include/hw/intc/armv7m_nvic.h
15
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
16
--- a/linux-user/elfload.c
23
--- a/include/hw/intc/armv7m_nvic.h
17
+++ b/linux-user/elfload.c
24
+++ b/include/hw/intc/armv7m_nvic.h
18
@@ -XXX,XX +XXX,XX @@
25
@@ -XXX,XX +XXX,XX @@ struct NVICState {
19
#include "qemu/guest-random.h"
26
MemoryRegion sysreg_ns_mem;
20
#include "qemu/units.h"
27
MemoryRegion systickmem;
21
#include "qemu/selfmap.h"
28
MemoryRegion systick_ns_mem;
22
+#include "qapi/error.h"
29
+ MemoryRegion ras_mem;
23
30
MemoryRegion container;
24
#ifdef _ARCH_PPC64
31
MemoryRegion defaultmem;
25
#undef ARCH_DLINFO
32
26
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
33
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
27
struct elf_phdr *phdr;
34
index XXXXXXX..XXXXXXX 100644
28
abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
35
--- a/hw/intc/armv7m_nvic.c
29
int i, retval;
36
+++ b/hw/intc/armv7m_nvic.c
30
- const char *errmsg;
37
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps nvic_systick_ops = {
31
+ Error *err = NULL;
38
.endianness = DEVICE_NATIVE_ENDIAN,
32
39
};
33
/* First of all, some simple consistency checks */
40
34
- errmsg = "Invalid ELF image for this architecture";
41
+
35
if (!elf_check_ident(ehdr)) {
42
+static MemTxResult ras_read(void *opaque, hwaddr addr,
36
+ error_setg(&err, "Invalid ELF image for this architecture");
43
+ uint64_t *data, unsigned size,
37
goto exit_errmsg;
44
+ MemTxAttrs attrs)
45
+{
46
+ if (attrs.user) {
47
+ return MEMTX_ERROR;
48
+ }
49
+
50
+ switch (addr) {
51
+ case 0xe10: /* ERRIIDR */
52
+ /* architect field = Arm; product/variant/revision 0 */
53
+ *data = 0x43b;
54
+ break;
55
+ case 0xfc8: /* ERRDEVID */
56
+ /* Minimal RAS: we implement 0 error record indexes */
57
+ *data = 0;
58
+ break;
59
+ default:
60
+ qemu_log_mask(LOG_UNIMP, "Read RAS register offset 0x%x\n",
61
+ (uint32_t)addr);
62
+ *data = 0;
63
+ break;
64
+ }
65
+ return MEMTX_OK;
66
+}
67
+
68
+static MemTxResult ras_write(void *opaque, hwaddr addr,
69
+ uint64_t value, unsigned size,
70
+ MemTxAttrs attrs)
71
+{
72
+ if (attrs.user) {
73
+ return MEMTX_ERROR;
74
+ }
75
+
76
+ switch (addr) {
77
+ default:
78
+ qemu_log_mask(LOG_UNIMP, "Write to RAS register offset 0x%x\n",
79
+ (uint32_t)addr);
80
+ break;
81
+ }
82
+ return MEMTX_OK;
83
+}
84
+
85
+static const MemoryRegionOps ras_ops = {
86
+ .read_with_attrs = ras_read,
87
+ .write_with_attrs = ras_write,
88
+ .endianness = DEVICE_NATIVE_ENDIAN,
89
+};
90
+
91
/*
92
* Unassigned portions of the PPB space are RAZ/WI for privileged
93
* accesses, and fault for non-privileged accesses.
94
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
95
&s->systick_ns_mem, 1);
38
}
96
}
39
bswap_ehdr(ehdr);
97
40
if (!elf_check_ehdr(ehdr)) {
98
+ if (cpu_isar_feature(aa32_ras, s->cpu)) {
41
+ error_setg(&err, "Invalid ELF image for this architecture");
99
+ memory_region_init_io(&s->ras_mem, OBJECT(s),
42
goto exit_errmsg;
100
+ &ras_ops, s, "nvic_ras", 0x1000);
43
}
101
+ memory_region_add_subregion(&s->container, 0x5000, &s->ras_mem);
44
102
+ }
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
+
103
+
54
interp_name = g_malloc(eppnt->p_filesz);
104
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->container);
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
}
105
}
132
106
133
--
107
--
134
2.20.1
108
2.20.1
135
109
136
110
diff view generated by jsdifflib
1
For nested groups like:
1
Correct a typo in the name we give the NVIC object.
2
2
3
{
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
[
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
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>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Message-id: 20201119215617.29887-28-peter.maydell@linaro.org
28
Message-id: 20201019151301.2046-2-peter.maydell@linaro.org
29
---
7
---
30
scripts/decodetree.py | 2 +-
8
hw/arm/armv7m.c | 2 +-
31
1 file changed, 1 insertion(+), 1 deletion(-)
9
1 file changed, 1 insertion(+), 1 deletion(-)
32
10
33
diff --git a/scripts/decodetree.py b/scripts/decodetree.py
11
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
34
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
35
--- a/scripts/decodetree.py
13
--- a/hw/arm/armv7m.c
36
+++ b/scripts/decodetree.py
14
+++ b/hw/arm/armv7m.c
37
@@ -XXX,XX +XXX,XX @@ class Tree:
15
@@ -XXX,XX +XXX,XX @@ static void armv7m_instance_init(Object *obj)
38
output(ind, ' /* ',
16
39
str_match_bits(innerbits, innermask), ' */\n')
17
memory_region_init(&s->container, obj, "armv7m-container", UINT64_MAX);
40
s.output_code(i + 4, extracted, innerbits, innermask)
18
41
- output(ind, ' return false;\n')
19
- object_initialize_child(obj, "nvnic", &s->nvic, TYPE_NVIC);
42
+ output(ind, ' break;\n')
20
+ object_initialize_child(obj, "nvic", &s->nvic, TYPE_NVIC);
43
output(ind, '}\n')
21
object_property_add_alias(obj, "num-irq",
44
# end Tree
22
OBJECT(&s->nvic), "num-irq");
45
23
46
--
24
--
47
2.20.1
25
2.20.1
48
26
49
27
diff view generated by jsdifflib