1
Second pull request of the week; mostly RTH's support for some
1
The big thing in here is RTH's caching-of-tb-flags patchset
2
new-in-v8.1/v8.3 instructions, and my v8M board model.
2
which should improve TCG performance.
3
3
4
thanks
4
thanks
5
-- PMM
5
-- PMM
6
6
7
The following changes since commit 427cbc7e4136a061628cb4315cc8182ea36d772f:
7
The following changes since commit 2152e740a8938b3bad73bfe1a01f8b94dab02d41:
8
8
9
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging (2018-03-01 18:46:41 +0000)
9
Merge remote-tracking branch 'remotes/vivier2/tags/trivial-branch-pull-request' into staging (2019-10-22 12:03:03 +0100)
10
10
11
are available in the Git repository at:
11
are available in the Git repository at:
12
12
13
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20180302
13
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20191022
14
14
15
for you to fetch changes up to e66a67bf28e1b4fce2e3d72a2610dbd48d9d3078:
15
for you to fetch changes up to 833043a060f7d0e95ded88e61e992466305c0345:
16
16
17
target/arm: Enable ARM_FEATURE_V8_FCMA (2018-03-02 11:03:45 +0000)
17
hw/arm/digic4: Inline digic4_board_setup_ram() function (2019-10-22 14:21:57 +0100)
18
18
19
----------------------------------------------------------------
19
----------------------------------------------------------------
20
target-arm queue:
20
target-arm queue:
21
* implement FCMA and RDM v8.1 and v8.3 instructions
21
* Fix sign-extension for SMLAL* instructions
22
* enable Cortex-M33 v8M core, and provide new mps2-an505 board model
22
* aspeed: Add an AST2600 eval board
23
that uses it
23
* Various ptimer device conversions to new transaction API
24
* decodetree: Propagate return value from translate subroutines
24
* Cache TB flags to avoid expensively recomputing them every time
25
* xlnx-zynqmp: Implement the RTC device
25
* Add a dummy Samsung SDHCI controller model to exynos4 boards
26
* Minor refactorings of RAM creation for some arm boards
26
27
27
----------------------------------------------------------------
28
----------------------------------------------------------------
28
Alistair Francis (3):
29
Cédric Le Goater (1):
29
xlnx-zynqmp-rtc: Initial commit
30
aspeed: Add an AST2600 eval board
30
xlnx-zynqmp-rtc: Add basic time support
31
xlnx-zynqmp: Connect the RTC device
32
31
33
Peter Maydell (19):
32
Guenter Roeck (1):
34
loader: Add new load_ramdisk_as()
33
hw/timer/exynos4210_mct: Initialize ptimer before starting it
35
hw/arm/boot: Honour CPU's address space for image loads
36
hw/arm/armv7m: Honour CPU's address space for image loads
37
target/arm: Define an IDAU interface
38
armv7m: Forward idau property to CPU object
39
target/arm: Define init-svtor property for the reset secure VTOR value
40
armv7m: Forward init-svtor property to CPU object
41
target/arm: Add Cortex-M33
42
hw/misc/unimp: Move struct to header file
43
include/hw/or-irq.h: Add missing include guard
44
qdev: Add new qdev_init_gpio_in_named_with_opaque()
45
hw/core/split-irq: Device that splits IRQ lines
46
hw/misc/mps2-fpgaio: FPGA control block for MPS2 AN505
47
hw/misc/tz-ppc: Model TrustZone peripheral protection controller
48
hw/misc/iotkit-secctl: Arm IoT Kit security controller initial skeleton
49
hw/misc/iotkit-secctl: Add handling for PPCs
50
hw/misc/iotkit-secctl: Add remaining simple registers
51
hw/arm/iotkit: Model Arm IOT Kit
52
mps2-an505: New board model: MPS2 with AN505 Cortex-M33 FPGA image
53
34
54
Richard Henderson (17):
35
Peter Maydell (7):
55
decodetree: Propagate return value from translate subroutines
36
hw/timer/arm_mptimer.c: Undo accidental rename of arm_mptimer_init()
56
target/arm: Add ARM_FEATURE_V8_RDM
37
hw/timer/puv3_ost.c: Switch to transaction-based ptimer API
57
target/arm: Refactor disas_simd_indexed decode
38
hw/timer/sh_timer: Switch to transaction-based ptimer API
58
target/arm: Refactor disas_simd_indexed size checks
39
hw/timer/lm32_timer: Switch to transaction-based ptimer API
59
target/arm: Decode aa64 armv8.1 scalar three same extra
40
hw/timer/altera_timer.c: Switch to transaction-based ptimer API
60
target/arm: Decode aa64 armv8.1 three same extra
41
hw/watchdog/etraxfs_timer.c: Switch to transaction-based ptimer API
61
target/arm: Decode aa64 armv8.1 scalar/vector x indexed element
42
hw/m68k/mcf5208.c: Switch to transaction-based ptimer API
62
target/arm: Decode aa32 armv8.1 three same
63
target/arm: Decode aa32 armv8.1 two reg and a scalar
64
target/arm: Enable ARM_FEATURE_V8_RDM
65
target/arm: Add ARM_FEATURE_V8_FCMA
66
target/arm: Decode aa64 armv8.3 fcadd
67
target/arm: Decode aa64 armv8.3 fcmla
68
target/arm: Decode aa32 armv8.3 3-same
69
target/arm: Decode aa32 armv8.3 2-reg-index
70
target/arm: Decode t32 simd 3reg and 2reg_scalar extension
71
target/arm: Enable ARM_FEATURE_V8_FCMA
72
43
73
hw/arm/Makefile.objs | 2 +
44
Philippe Mathieu-Daudé (9):
74
hw/core/Makefile.objs | 1 +
45
hw/sd/sdhci: Add a comment to distinct the i.MX eSDHC functions
75
hw/misc/Makefile.objs | 4 +
46
hw/sd/sdhci: Add dummy Samsung SDHCI controller
76
hw/timer/Makefile.objs | 1 +
47
hw/arm/exynos4210: Use the Samsung s3c SDHCI controller
77
target/arm/Makefile.objs | 2 +-
48
hw/arm/xilinx_zynq: Use the IEC binary prefix definitions
78
include/hw/arm/armv7m.h | 5 +
49
hw/arm/mps2: Use the IEC binary prefix definitions
79
include/hw/arm/iotkit.h | 109 ++++++
50
hw/arm/collie: Create the RAM in the board
80
include/hw/arm/xlnx-zynqmp.h | 2 +
51
hw/arm/omap2: Create the RAM in the board
81
include/hw/core/split-irq.h | 57 +++
52
hw/arm/omap1: Create the RAM in the board
82
include/hw/irq.h | 4 +-
53
hw/arm/digic4: Inline digic4_board_setup_ram() function
83
include/hw/loader.h | 12 +-
84
include/hw/misc/iotkit-secctl.h | 103 ++++++
85
include/hw/misc/mps2-fpgaio.h | 43 +++
86
include/hw/misc/tz-ppc.h | 101 ++++++
87
include/hw/misc/unimp.h | 10 +
88
include/hw/or-irq.h | 5 +
89
include/hw/qdev-core.h | 30 +-
90
include/hw/timer/xlnx-zynqmp-rtc.h | 86 +++++
91
target/arm/cpu.h | 8 +
92
target/arm/helper.h | 31 ++
93
target/arm/idau.h | 61 ++++
94
hw/arm/armv7m.c | 35 +-
95
hw/arm/boot.c | 119 ++++---
96
hw/arm/iotkit.c | 598 +++++++++++++++++++++++++++++++
97
hw/arm/mps2-tz.c | 503 ++++++++++++++++++++++++++
98
hw/arm/xlnx-zynqmp.c | 14 +
99
hw/core/loader.c | 8 +-
100
hw/core/qdev.c | 8 +-
101
hw/core/split-irq.c | 89 +++++
102
hw/misc/iotkit-secctl.c | 704 +++++++++++++++++++++++++++++++++++++
103
hw/misc/mps2-fpgaio.c | 176 ++++++++++
104
hw/misc/tz-ppc.c | 302 ++++++++++++++++
105
hw/misc/unimp.c | 10 -
106
hw/timer/xlnx-zynqmp-rtc.c | 272 ++++++++++++++
107
linux-user/elfload.c | 2 +
108
target/arm/cpu.c | 66 +++-
109
target/arm/cpu64.c | 2 +
110
target/arm/helper.c | 28 +-
111
target/arm/translate-a64.c | 514 +++++++++++++++++++++------
112
target/arm/translate.c | 275 +++++++++++++--
113
target/arm/vec_helper.c | 429 ++++++++++++++++++++++
114
default-configs/arm-softmmu.mak | 5 +
115
hw/misc/trace-events | 24 ++
116
hw/timer/trace-events | 3 +
117
scripts/decodetree.py | 5 +-
118
45 files changed, 4668 insertions(+), 200 deletions(-)
119
create mode 100644 include/hw/arm/iotkit.h
120
create mode 100644 include/hw/core/split-irq.h
121
create mode 100644 include/hw/misc/iotkit-secctl.h
122
create mode 100644 include/hw/misc/mps2-fpgaio.h
123
create mode 100644 include/hw/misc/tz-ppc.h
124
create mode 100644 include/hw/timer/xlnx-zynqmp-rtc.h
125
create mode 100644 target/arm/idau.h
126
create mode 100644 hw/arm/iotkit.c
127
create mode 100644 hw/arm/mps2-tz.c
128
create mode 100644 hw/core/split-irq.c
129
create mode 100644 hw/misc/iotkit-secctl.c
130
create mode 100644 hw/misc/mps2-fpgaio.c
131
create mode 100644 hw/misc/tz-ppc.c
132
create mode 100644 hw/timer/xlnx-zynqmp-rtc.c
133
create mode 100644 target/arm/vec_helper.c
134
54
55
Richard Henderson (23):
56
target/arm: Fix sign-extension for SMLAL*
57
target/arm: Split out rebuild_hflags_common
58
target/arm: Split out rebuild_hflags_a64
59
target/arm: Split out rebuild_hflags_common_32
60
target/arm: Split arm_cpu_data_is_big_endian
61
target/arm: Split out rebuild_hflags_m32
62
target/arm: Reduce tests vs M-profile in cpu_get_tb_cpu_state
63
target/arm: Split out rebuild_hflags_a32
64
target/arm: Split out rebuild_hflags_aprofile
65
target/arm: Hoist XSCALE_CPAR, VECLEN, VECSTRIDE in cpu_get_tb_cpu_state
66
target/arm: Simplify set of PSTATE_SS in cpu_get_tb_cpu_state
67
target/arm: Hoist computation of TBFLAG_A32.VFPEN
68
target/arm: Add arm_rebuild_hflags
69
target/arm: Split out arm_mmu_idx_el
70
target/arm: Hoist store to cs_base in cpu_get_tb_cpu_state
71
target/arm: Add HELPER(rebuild_hflags_{a32, a64, m32})
72
target/arm: Rebuild hflags at EL changes
73
target/arm: Rebuild hflags at MSR writes
74
target/arm: Rebuild hflags at CPSR writes
75
target/arm: Rebuild hflags at Xscale SCTLR writes
76
target/arm: Rebuild hflags for M-profile
77
target/arm: Rebuild hflags for M-profile NVIC
78
target/arm: Rely on hflags correct in cpu_get_tb_cpu_state
79
80
hw/arm/strongarm.h | 4 +-
81
include/hw/arm/aspeed.h | 1 +
82
include/hw/arm/omap.h | 10 +-
83
include/hw/sd/sdhci.h | 2 +
84
target/arm/cpu.h | 84 ++++++----
85
target/arm/helper.h | 4 +
86
target/arm/internals.h | 9 ++
87
hw/arm/aspeed.c | 23 +++
88
hw/arm/collie.c | 8 +-
89
hw/arm/digic_boards.c | 9 +-
90
hw/arm/exynos4210.c | 2 +-
91
hw/arm/mps2-tz.c | 3 +-
92
hw/arm/mps2.c | 3 +-
93
hw/arm/nseries.c | 10 +-
94
hw/arm/omap1.c | 12 +-
95
hw/arm/omap2.c | 13 +-
96
hw/arm/omap_sx1.c | 8 +-
97
hw/arm/palm.c | 8 +-
98
hw/arm/strongarm.c | 7 +-
99
hw/arm/xilinx_zynq.c | 3 +-
100
hw/intc/armv7m_nvic.c | 22 +--
101
hw/m68k/mcf5208.c | 9 +-
102
hw/sd/sdhci.c | 68 +++++++-
103
hw/timer/altera_timer.c | 13 +-
104
hw/timer/arm_mptimer.c | 4 +-
105
hw/timer/etraxfs_timer.c | 23 +--
106
hw/timer/exynos4210_mct.c | 2 +-
107
hw/timer/lm32_timer.c | 13 +-
108
hw/timer/puv3_ost.c | 9 +-
109
hw/timer/sh_timer.c | 13 +-
110
linux-user/syscall.c | 1 +
111
target/arm/cpu.c | 1 +
112
target/arm/helper-a64.c | 3 +
113
target/arm/helper.c | 393 +++++++++++++++++++++++++++++----------------
114
target/arm/m_helper.c | 6 +
115
target/arm/machine.c | 1 +
116
target/arm/op_helper.c | 4 +
117
target/arm/translate-a64.c | 13 +-
118
target/arm/translate.c | 37 ++++-
119
39 files changed, 588 insertions(+), 270 deletions(-)
120
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
3
The 32-bit product should be sign-extended, not zero-extended.
4
5
Fixes: ea96b374641b
6
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180228193125.20577-9-richard.henderson@linaro.org
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com>
10
Message-id: 20190912183058.17947-1-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
12
---
8
target/arm/translate.c | 46 ++++++++++++++++++++++++++++++++++++++++++----
13
target/arm/translate.c | 4 +++-
9
1 file changed, 42 insertions(+), 4 deletions(-)
14
1 file changed, 3 insertions(+), 1 deletion(-)
10
15
11
diff --git a/target/arm/translate.c b/target/arm/translate.c
16
diff --git a/target/arm/translate.c b/target/arm/translate.c
12
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate.c
18
--- a/target/arm/translate.c
14
+++ b/target/arm/translate.c
19
+++ b/target/arm/translate.c
15
@@ -XXX,XX +XXX,XX @@ static const char *regnames[] =
20
@@ -XXX,XX +XXX,XX @@ static bool op_smlaxxx(DisasContext *s, arg_rrrr *a,
16
{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
21
case 2:
17
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
22
tl = load_reg(s, a->ra);
18
23
th = load_reg(s, a->rd);
19
+/* Function prototypes for gen_ functions calling Neon helpers. */
24
- t1 = tcg_const_i32(0);
20
+typedef void NeonGenThreeOpEnvFn(TCGv_i32, TCGv_env, TCGv_i32,
25
+ /* Sign-extend the 32-bit product to 64 bits. */
21
+ TCGv_i32, TCGv_i32);
26
+ t1 = tcg_temp_new_i32();
22
+
27
+ tcg_gen_sari_i32(t1, t0, 31);
23
/* initialize TCG globals. */
28
tcg_gen_add2_i32(tl, th, tl, th, t0, t1);
24
void arm_translate_init(void)
29
tcg_temp_free_i32(t0);
25
{
30
tcg_temp_free_i32(t1);
26
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
27
}
28
neon_store_reg64(cpu_V0, rd + pass);
29
}
30
-
31
-
32
break;
33
- default: /* 14 and 15 are RESERVED */
34
- return 1;
35
+ case 14: /* VQRDMLAH scalar */
36
+ case 15: /* VQRDMLSH scalar */
37
+ {
38
+ NeonGenThreeOpEnvFn *fn;
39
+
40
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_RDM)) {
41
+ return 1;
42
+ }
43
+ if (u && ((rd | rn) & 1)) {
44
+ return 1;
45
+ }
46
+ if (op == 14) {
47
+ if (size == 1) {
48
+ fn = gen_helper_neon_qrdmlah_s16;
49
+ } else {
50
+ fn = gen_helper_neon_qrdmlah_s32;
51
+ }
52
+ } else {
53
+ if (size == 1) {
54
+ fn = gen_helper_neon_qrdmlsh_s16;
55
+ } else {
56
+ fn = gen_helper_neon_qrdmlsh_s32;
57
+ }
58
+ }
59
+
60
+ tmp2 = neon_get_scalar(size, rm);
61
+ for (pass = 0; pass < (u ? 4 : 2); pass++) {
62
+ tmp = neon_load_reg(rn, pass);
63
+ tmp3 = neon_load_reg(rd, pass);
64
+ fn(tmp, cpu_env, tmp, tmp2, tmp3);
65
+ tcg_temp_free_i32(tmp3);
66
+ neon_store_reg(rd, pass, tmp);
67
+ }
68
+ tcg_temp_free_i32(tmp2);
69
+ }
70
+ break;
71
+ default:
72
+ g_assert_not_reached();
73
}
74
}
75
} else { /* size == 3 */
76
--
31
--
77
2.16.2
32
2.20.1
78
33
79
34
diff view generated by jsdifflib
1
From: Alistair Francis <alistair.francis@xilinx.com>
1
From: Cédric Le Goater <clg@kaod.org>
2
2
3
Allow the guest to determine the time set from the QEMU command line.
3
Define the board with 1 GiB of RAM but some boards can have up to 2
4
GiB.
4
5
5
This includes adding a trace event to debug the new time.
6
Signed-off-by: Cédric Le Goater <clg@kaod.org>
6
7
Reviewed-by: Joel Stanley <joel@jms.id.au>
7
Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
8
Message-id: 20191016090745.15334-1-clg@kaod.org
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
10
---
12
include/hw/timer/xlnx-zynqmp-rtc.h | 2 ++
11
include/hw/arm/aspeed.h | 1 +
13
hw/timer/xlnx-zynqmp-rtc.c | 58 ++++++++++++++++++++++++++++++++++++++
12
hw/arm/aspeed.c | 23 +++++++++++++++++++++++
14
hw/timer/trace-events | 3 ++
13
2 files changed, 24 insertions(+)
15
3 files changed, 63 insertions(+)
16
14
17
diff --git a/include/hw/timer/xlnx-zynqmp-rtc.h b/include/hw/timer/xlnx-zynqmp-rtc.h
15
diff --git a/include/hw/arm/aspeed.h b/include/hw/arm/aspeed.h
18
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/timer/xlnx-zynqmp-rtc.h
17
--- a/include/hw/arm/aspeed.h
20
+++ b/include/hw/timer/xlnx-zynqmp-rtc.h
18
+++ b/include/hw/arm/aspeed.h
21
@@ -XXX,XX +XXX,XX @@ typedef struct XlnxZynqMPRTC {
19
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedBoardConfig {
22
qemu_irq irq_rtc_int;
20
const char *desc;
23
qemu_irq irq_addr_error_int;
21
const char *soc_name;
24
22
uint32_t hw_strap1;
25
+ uint32_t tick_offset;
23
+ uint32_t hw_strap2;
24
const char *fmc_model;
25
const char *spi_model;
26
uint32_t num_cs;
27
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/arm/aspeed.c
30
+++ b/hw/arm/aspeed.c
31
@@ -XXX,XX +XXX,XX @@ struct AspeedBoardState {
32
/* Witherspoon hardware value: 0xF10AD216 (but use romulus definition) */
33
#define WITHERSPOON_BMC_HW_STRAP1 ROMULUS_BMC_HW_STRAP1
34
35
+/* AST2600 evb hardware value */
36
+#define AST2600_EVB_HW_STRAP1 0x000000C0
37
+#define AST2600_EVB_HW_STRAP2 0x00000003
26
+
38
+
27
uint32_t regs[XLNX_ZYNQMP_RTC_R_MAX];
39
/*
28
RegisterInfo regs_info[XLNX_ZYNQMP_RTC_R_MAX];
40
* The max ram region is for firmwares that scan the address space
29
} XlnxZynqMPRTC;
41
* with load/store to guess how much RAM the SoC has.
30
diff --git a/hw/timer/xlnx-zynqmp-rtc.c b/hw/timer/xlnx-zynqmp-rtc.c
42
@@ -XXX,XX +XXX,XX @@ static void aspeed_board_init(MachineState *machine,
31
index XXXXXXX..XXXXXXX 100644
43
&error_abort);
32
--- a/hw/timer/xlnx-zynqmp-rtc.c
44
object_property_set_int(OBJECT(&bmc->soc), cfg->hw_strap1, "hw-strap1",
33
+++ b/hw/timer/xlnx-zynqmp-rtc.c
45
&error_abort);
34
@@ -XXX,XX +XXX,XX @@
46
+ object_property_set_int(OBJECT(&bmc->soc), cfg->hw_strap2, "hw-strap2",
35
#include "hw/register.h"
47
+ &error_abort);
36
#include "qemu/bitops.h"
48
object_property_set_int(OBJECT(&bmc->soc), cfg->num_cs, "num-cs",
37
#include "qemu/log.h"
49
&error_abort);
38
+#include "hw/ptimer.h"
50
object_property_set_int(OBJECT(&bmc->soc), machine->smp.cpus, "num-cpus",
39
+#include "qemu/cutils.h"
51
@@ -XXX,XX +XXX,XX @@ static void ast2500_evb_i2c_init(AspeedBoardState *bmc)
40
+#include "sysemu/sysemu.h"
52
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 11), "ds1338", 0x32);
41
+#include "trace.h"
42
#include "hw/timer/xlnx-zynqmp-rtc.h"
43
44
#ifndef XLNX_ZYNQMP_RTC_ERR_DEBUG
45
@@ -XXX,XX +XXX,XX @@ static void addr_error_int_update_irq(XlnxZynqMPRTC *s)
46
qemu_set_irq(s->irq_addr_error_int, pending);
47
}
53
}
48
54
49
+static uint32_t rtc_get_count(XlnxZynqMPRTC *s)
55
+static void ast2600_evb_i2c_init(AspeedBoardState *bmc)
50
+{
56
+{
51
+ int64_t now = qemu_clock_get_ns(rtc_clock);
57
+ /* Start with some devices on our I2C busses */
52
+ return s->tick_offset + now / NANOSECONDS_PER_SECOND;
58
+ ast2500_evb_i2c_init(bmc);
53
+}
59
+}
54
+
60
+
55
+static uint64_t current_time_postr(RegisterInfo *reg, uint64_t val64)
61
static void romulus_bmc_i2c_init(AspeedBoardState *bmc)
56
+{
57
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
58
+
59
+ return rtc_get_count(s);
60
+}
61
+
62
static void rtc_int_status_postw(RegisterInfo *reg, uint64_t val64)
63
{
62
{
64
XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
63
AspeedSoCState *soc = &bmc->soc;
65
@@ -XXX,XX +XXX,XX @@ static uint64_t addr_error_int_dis_prew(RegisterInfo *reg, uint64_t val64)
64
@@ -XXX,XX +XXX,XX @@ static const AspeedBoardConfig aspeed_boards[] = {
66
65
.num_cs = 2,
67
static const RegisterAccessInfo rtc_regs_info[] = {
66
.i2c_init = witherspoon_bmc_i2c_init,
68
{ .name = "SET_TIME_WRITE", .addr = A_SET_TIME_WRITE,
67
.ram = 512 * MiB,
69
+ .unimp = MAKE_64BIT_MASK(0, 32),
68
+ }, {
70
},{ .name = "SET_TIME_READ", .addr = A_SET_TIME_READ,
69
+ .name = MACHINE_TYPE_NAME("ast2600-evb"),
71
.ro = 0xffffffff,
70
+ .desc = "Aspeed AST2600 EVB (Cortex A7)",
72
+ .post_read = current_time_postr,
71
+ .soc_name = "ast2600-a0",
73
},{ .name = "CALIB_WRITE", .addr = A_CALIB_WRITE,
72
+ .hw_strap1 = AST2600_EVB_HW_STRAP1,
74
+ .unimp = MAKE_64BIT_MASK(0, 32),
73
+ .hw_strap2 = AST2600_EVB_HW_STRAP2,
75
},{ .name = "CALIB_READ", .addr = A_CALIB_READ,
74
+ .fmc_model = "w25q512jv",
76
.ro = 0x1fffff,
75
+ .spi_model = "mx66u51235f",
77
},{ .name = "CURRENT_TIME", .addr = A_CURRENT_TIME,
76
+ .num_cs = 1,
78
.ro = 0xffffffff,
77
+ .i2c_init = ast2600_evb_i2c_init,
79
+ .post_read = current_time_postr,
78
+ .ram = 1 * GiB,
80
},{ .name = "CURRENT_TICK", .addr = A_CURRENT_TICK,
79
},
81
.ro = 0xffff,
82
},{ .name = "ALARM", .addr = A_ALARM,
83
@@ -XXX,XX +XXX,XX @@ static void rtc_init(Object *obj)
84
XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(obj);
85
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
86
RegisterInfoArray *reg_array;
87
+ struct tm current_tm;
88
89
memory_region_init(&s->iomem, obj, TYPE_XLNX_ZYNQMP_RTC,
90
XLNX_ZYNQMP_RTC_R_MAX * 4);
91
@@ -XXX,XX +XXX,XX @@ static void rtc_init(Object *obj)
92
sysbus_init_mmio(sbd, &s->iomem);
93
sysbus_init_irq(sbd, &s->irq_rtc_int);
94
sysbus_init_irq(sbd, &s->irq_addr_error_int);
95
+
96
+ qemu_get_timedate(&current_tm, 0);
97
+ s->tick_offset = mktimegm(&current_tm) -
98
+ qemu_clock_get_ns(rtc_clock) / NANOSECONDS_PER_SECOND;
99
+
100
+ trace_xlnx_zynqmp_rtc_gettime(current_tm.tm_year, current_tm.tm_mon,
101
+ current_tm.tm_mday, current_tm.tm_hour,
102
+ current_tm.tm_min, current_tm.tm_sec);
103
+}
104
+
105
+static int rtc_pre_save(void *opaque)
106
+{
107
+ XlnxZynqMPRTC *s = opaque;
108
+ int64_t now = qemu_clock_get_ns(rtc_clock) / NANOSECONDS_PER_SECOND;
109
+
110
+ /* Add the time at migration */
111
+ s->tick_offset = s->tick_offset + now;
112
+
113
+ return 0;
114
+}
115
+
116
+static int rtc_post_load(void *opaque, int version_id)
117
+{
118
+ XlnxZynqMPRTC *s = opaque;
119
+ int64_t now = qemu_clock_get_ns(rtc_clock) / NANOSECONDS_PER_SECOND;
120
+
121
+ /* Subtract the time after migration. This combined with the pre_save
122
+ * action results in us having subtracted the time that the guest was
123
+ * stopped to the offset.
124
+ */
125
+ s->tick_offset = s->tick_offset - now;
126
+
127
+ return 0;
128
}
129
130
static const VMStateDescription vmstate_rtc = {
131
.name = TYPE_XLNX_ZYNQMP_RTC,
132
.version_id = 1,
133
.minimum_version_id = 1,
134
+ .pre_save = rtc_pre_save,
135
+ .post_load = rtc_post_load,
136
.fields = (VMStateField[]) {
137
VMSTATE_UINT32_ARRAY(regs, XlnxZynqMPRTC, XLNX_ZYNQMP_RTC_R_MAX),
138
+ VMSTATE_UINT32(tick_offset, XlnxZynqMPRTC),
139
VMSTATE_END_OF_LIST(),
140
}
141
};
80
};
142
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
81
143
index XXXXXXX..XXXXXXX 100644
144
--- a/hw/timer/trace-events
145
+++ b/hw/timer/trace-events
146
@@ -XXX,XX +XXX,XX @@ systick_write(uint64_t addr, uint32_t value, unsigned size) "systick write addr
147
cmsdk_apb_timer_read(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB timer read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
148
cmsdk_apb_timer_write(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB timer write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
149
cmsdk_apb_timer_reset(void) "CMSDK APB timer: reset"
150
+
151
+# hw/timer/xlnx-zynqmp-rtc.c
152
+xlnx_zynqmp_rtc_gettime(int year, int month, int day, int hour, int min, int sec) "Get time from host: %d-%d-%d %2d:%02d:%02d"
153
--
82
--
154
2.16.2
83
2.20.1
155
84
156
85
diff view generated by jsdifflib
New patch
1
From: Guenter Roeck <linux@roeck-us.net>
1
2
3
When booting a recent Linux kernel, the qemu message "Timer with delta
4
zero, disabling" is seen, apparently because a ptimer is started before
5
being initialized. Fix the problem by initializing the offending ptimer
6
before starting it.
7
8
The bug is effectively harmless in the old QEMUBH setup
9
because the sequence of events is:
10
* the delta zero means the timer expires immediately
11
* ptimer_reload() arranges for exynos4210_gfrc_event() to be called
12
* ptimer_reload() notices the zero delta and disables the timer
13
* later, the QEMUBH runs, and exynos4210_gfrc_event() correctly
14
configures the timer and restarts it
15
16
In the new transaction based API the bug is still harmless,
17
but differences of when the callback function runs mean the
18
message is not printed any more:
19
* ptimer_run() does nothing as it's inside a transaction block
20
* ptimer_transaction_commit() sees it has work to do and
21
calls ptimer_reload()
22
* the zero delta means the timer expires immediately
23
* ptimer_reload() calls exynos4210_gfrc_event() directly
24
* exynos4210_gfrc_event() configures the timer
25
* the delta is no longer zero so ptimer_reload() doesn't complain
26
(the zero-delta test is after the trigger-callback in
27
the ptimer_reload() function)
28
29
Regardless, the behaviour here was not intentional, and we should
30
just program the ptimer correctly to start with.
31
32
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
33
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
34
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
35
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
36
Message-id: 20191018143149.9216-1-peter.maydell@linaro.org
37
[PMM: Expansion/clarification of the commit message:
38
the message is about a zero delta, not a zero period;
39
added detail to the commit message of the analysis of what
40
is happening and why the kernel boots even with the message;
41
added note that the message goes away with the new ptimer API]
42
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
43
---
44
hw/timer/exynos4210_mct.c | 2 +-
45
1 file changed, 1 insertion(+), 1 deletion(-)
46
47
diff --git a/hw/timer/exynos4210_mct.c b/hw/timer/exynos4210_mct.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/hw/timer/exynos4210_mct.c
50
+++ b/hw/timer/exynos4210_mct.c
51
@@ -XXX,XX +XXX,XX @@ static void exynos4210_mct_write(void *opaque, hwaddr offset,
52
/* Start FRC if transition from disabled to enabled */
53
if ((value & G_TCON_TIMER_ENABLE) > (old_val &
54
G_TCON_TIMER_ENABLE)) {
55
- exynos4210_gfrc_start(&s->g_timer);
56
+ exynos4210_gfrc_restart(s);
57
}
58
if ((value & G_TCON_TIMER_ENABLE) < (old_val &
59
G_TCON_TIMER_ENABLE)) {
60
--
61
2.20.1
62
63
diff view generated by jsdifflib
1
Create an "init-svtor" property on the armv7m container
1
In commit b01422622b we did an automated rename of the ptimer_init()
2
object which we can forward to the CPU object.
2
function to ptimer_init_with_bh(). Unfortunately this caught the
3
unrelated arm_mptimer_init() function. Undo that accidental
4
renaming.
3
5
6
Fixes: b01422622b7c7293196fdaf1dbb4f495af44ecf9
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20180220180325.29818-8-peter.maydell@linaro.org
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Message-id: 20191017133331.5901-1-peter.maydell@linaro.org
7
---
11
---
8
include/hw/arm/armv7m.h | 2 ++
12
hw/timer/arm_mptimer.c | 4 ++--
9
hw/arm/armv7m.c | 9 +++++++++
13
1 file changed, 2 insertions(+), 2 deletions(-)
10
2 files changed, 11 insertions(+)
11
14
12
diff --git a/include/hw/arm/armv7m.h b/include/hw/arm/armv7m.h
15
diff --git a/hw/timer/arm_mptimer.c b/hw/timer/arm_mptimer.c
13
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
14
--- a/include/hw/arm/armv7m.h
17
--- a/hw/timer/arm_mptimer.c
15
+++ b/include/hw/arm/armv7m.h
18
+++ b/hw/timer/arm_mptimer.c
16
@@ -XXX,XX +XXX,XX @@ typedef struct {
19
@@ -XXX,XX +XXX,XX @@ static void arm_mptimer_reset(DeviceState *dev)
17
* that CPU accesses see. (The NVIC, bitbanding and other CPU-internal
18
* devices will be automatically layered on top of this view.)
19
* + Property "idau": IDAU interface (forwarded to CPU object)
20
+ * + Property "init-svtor": secure VTOR reset value (forwarded to CPU object)
21
*/
22
typedef struct ARMv7MState {
23
/*< private >*/
24
@@ -XXX,XX +XXX,XX @@ typedef struct ARMv7MState {
25
/* MemoryRegion the board provides to us (with its devices, RAM, etc) */
26
MemoryRegion *board_memory;
27
Object *idau;
28
+ uint32_t init_svtor;
29
} ARMv7MState;
30
31
#endif
32
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/hw/arm/armv7m.c
35
+++ b/hw/arm/armv7m.c
36
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
37
return;
38
}
39
}
20
}
40
+ if (object_property_find(OBJECT(s->cpu), "init-svtor", NULL)) {
21
}
41
+ object_property_set_uint(OBJECT(s->cpu), s->init_svtor,
22
42
+ "init-svtor", &err);
23
-static void arm_mptimer_init_with_bh(Object *obj)
43
+ if (err != NULL) {
24
+static void arm_mptimer_init(Object *obj)
44
+ error_propagate(errp, err);
25
{
45
+ return;
26
ARMMPTimerState *s = ARM_MPTIMER(obj);
46
+ }
27
47
+ }
28
@@ -XXX,XX +XXX,XX @@ static const TypeInfo arm_mptimer_info = {
48
object_property_set_bool(OBJECT(s->cpu), true, "realized", &err);
29
.name = TYPE_ARM_MPTIMER,
49
if (err != NULL) {
30
.parent = TYPE_SYS_BUS_DEVICE,
50
error_propagate(errp, err);
31
.instance_size = sizeof(ARMMPTimerState),
51
@@ -XXX,XX +XXX,XX @@ static Property armv7m_properties[] = {
32
- .instance_init = arm_mptimer_init_with_bh,
52
DEFINE_PROP_LINK("memory", ARMv7MState, board_memory, TYPE_MEMORY_REGION,
33
+ .instance_init = arm_mptimer_init,
53
MemoryRegion *),
34
.class_init = arm_mptimer_class_init,
54
DEFINE_PROP_LINK("idau", ARMv7MState, idau, TYPE_IDAU_INTERFACE, Object *),
55
+ DEFINE_PROP_UINT32("init-svtor", ARMv7MState, init_svtor, 0),
56
DEFINE_PROP_END_OF_LIST(),
57
};
35
};
58
36
59
--
37
--
60
2.16.2
38
2.20.1
61
39
62
40
diff view generated by jsdifflib
1
The IoTKit Security Controller includes various registers
1
Switch the puv3_ost code away from bottom-half based ptimers to the
2
that expose to software the controls for the Peripheral
2
new transaction-based ptimer API. This just requires adding
3
Protection Controllers in the system. Implement these.
3
begin/commit calls around the various places that modify the ptimer
4
state, and using the new ptimer_init() function to create the timer.
4
5
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180220180325.29818-17-peter.maydell@linaro.org
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Message-id: 20191017132905.5604-2-peter.maydell@linaro.org
8
---
10
---
9
include/hw/misc/iotkit-secctl.h | 64 +++++++++-
11
hw/timer/puv3_ost.c | 9 +++++----
10
hw/misc/iotkit-secctl.c | 270 +++++++++++++++++++++++++++++++++++++---
12
1 file changed, 5 insertions(+), 4 deletions(-)
11
2 files changed, 315 insertions(+), 19 deletions(-)
12
13
13
diff --git a/include/hw/misc/iotkit-secctl.h b/include/hw/misc/iotkit-secctl.h
14
diff --git a/hw/timer/puv3_ost.c b/hw/timer/puv3_ost.c
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/misc/iotkit-secctl.h
16
--- a/hw/timer/puv3_ost.c
16
+++ b/include/hw/misc/iotkit-secctl.h
17
+++ b/hw/timer/puv3_ost.c
17
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@
18
* QEMU interface:
19
#include "hw/sysbus.h"
19
* + sysbus MMIO region 0 is the "secure privilege control block" registers
20
#include "hw/irq.h"
20
* + sysbus MMIO region 1 is the "non-secure privilege control block" registers
21
#include "hw/ptimer.h"
21
+ * + named GPIO output "sec_resp_cfg" indicating whether blocked accesses
22
-#include "qemu/main-loop.h"
22
+ * should RAZ/WI or bus error
23
#include "qemu/module.h"
23
+ * Controlling the 2 APB PPCs in the IoTKit:
24
24
+ * + named GPIO outputs apb_ppc0_nonsec[0..2] and apb_ppc1_nonsec
25
#undef DEBUG_PUV3
25
+ * + named GPIO outputs apb_ppc0_ap[0..2] and apb_ppc1_ap
26
@@ -XXX,XX +XXX,XX @@ typedef struct PUV3OSTState {
26
+ * + named GPIO outputs apb_ppc{0,1}_irq_enable
27
+ * + named GPIO outputs apb_ppc{0,1}_irq_clear
28
+ * + named GPIO inputs apb_ppc{0,1}_irq_status
29
+ * Controlling each of the 4 expansion APB PPCs which a system using the IoTKit
30
+ * might provide:
31
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_nonsec[0..15]
32
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_ap[0..15]
33
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_irq_enable
34
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_irq_clear
35
+ * + named GPIO inputs apb_ppcexp{0,1,2,3}_irq_status
36
+ * Controlling each of the 4 expansion AHB PPCs which a system using the IoTKit
37
+ * might provide:
38
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_nonsec[0..15]
39
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_ap[0..15]
40
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_enable
41
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_clear
42
+ * + named GPIO inputs ahb_ppcexp{0,1,2,3}_irq_status
43
*/
44
45
#ifndef IOTKIT_SECCTL_H
46
@@ -XXX,XX +XXX,XX @@
47
#define TYPE_IOTKIT_SECCTL "iotkit-secctl"
48
#define IOTKIT_SECCTL(obj) OBJECT_CHECK(IoTKitSecCtl, (obj), TYPE_IOTKIT_SECCTL)
49
50
-typedef struct IoTKitSecCtl {
51
+#define IOTS_APB_PPC0_NUM_PORTS 3
52
+#define IOTS_APB_PPC1_NUM_PORTS 1
53
+#define IOTS_PPC_NUM_PORTS 16
54
+#define IOTS_NUM_APB_PPC 2
55
+#define IOTS_NUM_APB_EXP_PPC 4
56
+#define IOTS_NUM_AHB_EXP_PPC 4
57
+
58
+typedef struct IoTKitSecCtl IoTKitSecCtl;
59
+
60
+/* State and IRQ lines relating to a PPC. For the
61
+ * PPCs in the IoTKit not all the IRQ lines are used.
62
+ */
63
+typedef struct IoTKitSecCtlPPC {
64
+ qemu_irq nonsec[IOTS_PPC_NUM_PORTS];
65
+ qemu_irq ap[IOTS_PPC_NUM_PORTS];
66
+ qemu_irq irq_enable;
67
+ qemu_irq irq_clear;
68
+
69
+ uint32_t ns;
70
+ uint32_t sp;
71
+ uint32_t nsp;
72
+
73
+ /* Number of ports actually present */
74
+ int numports;
75
+ /* Offset of this PPC's interrupt bits in SECPPCINTSTAT */
76
+ int irq_bit_offset;
77
+ IoTKitSecCtl *parent;
78
+} IoTKitSecCtlPPC;
79
+
80
+struct IoTKitSecCtl {
81
/*< private >*/
82
SysBusDevice parent_obj;
27
SysBusDevice parent_obj;
83
28
84
/*< public >*/
29
MemoryRegion iomem;
85
+ qemu_irq sec_resp_cfg;
30
- QEMUBH *bh;
86
31
qemu_irq irq;
87
MemoryRegion s_regs;
32
ptimer_state *ptimer;
88
MemoryRegion ns_regs;
33
89
-} IoTKitSecCtl;
34
@@ -XXX,XX +XXX,XX @@ static void puv3_ost_write(void *opaque, hwaddr offset,
90
+
35
DPRINTF("offset 0x%x, value 0x%x\n", offset, value);
91
+ uint32_t secppcintstat;
92
+ uint32_t secppcinten;
93
+ uint32_t secrespcfg;
94
+
95
+ IoTKitSecCtlPPC apb[IOTS_NUM_APB_PPC];
96
+ IoTKitSecCtlPPC apbexp[IOTS_NUM_APB_EXP_PPC];
97
+ IoTKitSecCtlPPC ahbexp[IOTS_NUM_APB_EXP_PPC];
98
+};
99
100
#endif
101
diff --git a/hw/misc/iotkit-secctl.c b/hw/misc/iotkit-secctl.c
102
index XXXXXXX..XXXXXXX 100644
103
--- a/hw/misc/iotkit-secctl.c
104
+++ b/hw/misc/iotkit-secctl.c
105
@@ -XXX,XX +XXX,XX @@ static const uint8_t iotkit_secctl_ns_idregs[] = {
106
0x0d, 0xf0, 0x05, 0xb1,
107
};
108
109
+/* The register sets for the various PPCs (AHB internal, APB internal,
110
+ * AHB expansion, APB expansion) are all set up so that they are
111
+ * in 16-aligned blocks so offsets 0xN0, 0xN4, 0xN8, 0xNC are PPCs
112
+ * 0, 1, 2, 3 of that type, so we can convert a register address offset
113
+ * into an an index into a PPC array easily.
114
+ */
115
+static inline int offset_to_ppc_idx(uint32_t offset)
116
+{
117
+ return extract32(offset, 2, 2);
118
+}
119
+
120
+typedef void PerPPCFunction(IoTKitSecCtlPPC *ppc);
121
+
122
+static void foreach_ppc(IoTKitSecCtl *s, PerPPCFunction *fn)
123
+{
124
+ int i;
125
+
126
+ for (i = 0; i < IOTS_NUM_APB_PPC; i++) {
127
+ fn(&s->apb[i]);
128
+ }
129
+ for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) {
130
+ fn(&s->apbexp[i]);
131
+ }
132
+ for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) {
133
+ fn(&s->ahbexp[i]);
134
+ }
135
+}
136
+
137
static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
138
uint64_t *pdata,
139
unsigned size, MemTxAttrs attrs)
140
{
141
uint64_t r;
142
uint32_t offset = addr & ~0x3;
143
+ IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
144
145
switch (offset) {
36
switch (offset) {
146
case A_AHBNSPPC0:
37
case 0x00: /* Match Register 0 */
147
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
38
+ ptimer_transaction_begin(s->ptimer);
148
r = 0;
39
s->reg_OSMR0 = value;
40
if (s->reg_OSMR0 > s->reg_OSCR) {
41
ptimer_set_count(s->ptimer, s->reg_OSMR0 - s->reg_OSCR);
42
@@ -XXX,XX +XXX,XX @@ static void puv3_ost_write(void *opaque, hwaddr offset,
43
(0xffffffff - s->reg_OSCR));
44
}
45
ptimer_run(s->ptimer, 2);
46
+ ptimer_transaction_commit(s->ptimer);
149
break;
47
break;
150
case A_SECRESPCFG:
48
case 0x14: /* Status Register */
151
- case A_NSCCFG:
49
assert(value == 0);
152
- case A_SECMPCINTSTATUS:
50
@@ -XXX,XX +XXX,XX @@ static void puv3_ost_realize(DeviceState *dev, Error **errp)
153
+ r = s->secrespcfg;
51
154
+ break;
52
sysbus_init_irq(sbd, &s->irq);
155
case A_SECPPCINTSTAT:
53
156
+ r = s->secppcintstat;
54
- s->bh = qemu_bh_new(puv3_ost_tick, s);
157
+ break;
55
- s->ptimer = ptimer_init_with_bh(s->bh, PTIMER_POLICY_DEFAULT);
158
case A_SECPPCINTEN:
56
+ s->ptimer = ptimer_init(puv3_ost_tick, s, PTIMER_POLICY_DEFAULT);
159
- case A_SECMSCINTSTAT:
57
+ ptimer_transaction_begin(s->ptimer);
160
- case A_SECMSCINTEN:
58
ptimer_set_freq(s->ptimer, 50 * 1000 * 1000);
161
- case A_BRGINTSTAT:
59
+ ptimer_transaction_commit(s->ptimer);
162
- case A_BRGINTEN:
60
163
+ r = s->secppcinten;
61
memory_region_init_io(&s->iomem, OBJECT(s), &puv3_ost_ops, s, "puv3_ost",
164
+ break;
62
PUV3_REGS_OFFSET);
165
case A_AHBNSPPCEXP0:
166
case A_AHBNSPPCEXP1:
167
case A_AHBNSPPCEXP2:
168
case A_AHBNSPPCEXP3:
169
+ r = s->ahbexp[offset_to_ppc_idx(offset)].ns;
170
+ break;
171
case A_APBNSPPC0:
172
case A_APBNSPPC1:
173
+ r = s->apb[offset_to_ppc_idx(offset)].ns;
174
+ break;
175
case A_APBNSPPCEXP0:
176
case A_APBNSPPCEXP1:
177
case A_APBNSPPCEXP2:
178
case A_APBNSPPCEXP3:
179
+ r = s->apbexp[offset_to_ppc_idx(offset)].ns;
180
+ break;
181
case A_AHBSPPPCEXP0:
182
case A_AHBSPPPCEXP1:
183
case A_AHBSPPPCEXP2:
184
case A_AHBSPPPCEXP3:
185
+ r = s->apbexp[offset_to_ppc_idx(offset)].sp;
186
+ break;
187
case A_APBSPPPC0:
188
case A_APBSPPPC1:
189
+ r = s->apb[offset_to_ppc_idx(offset)].sp;
190
+ break;
191
case A_APBSPPPCEXP0:
192
case A_APBSPPPCEXP1:
193
case A_APBSPPPCEXP2:
194
case A_APBSPPPCEXP3:
195
+ r = s->apbexp[offset_to_ppc_idx(offset)].sp;
196
+ break;
197
+ case A_NSCCFG:
198
+ case A_SECMPCINTSTATUS:
199
+ case A_SECMSCINTSTAT:
200
+ case A_SECMSCINTEN:
201
+ case A_BRGINTSTAT:
202
+ case A_BRGINTEN:
203
case A_NSMSCEXP:
204
qemu_log_mask(LOG_UNIMP,
205
"IoTKit SecCtl S block read: "
206
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
207
return MEMTX_OK;
208
}
209
210
+static void iotkit_secctl_update_ppc_ap(IoTKitSecCtlPPC *ppc)
211
+{
212
+ int i;
213
+
214
+ for (i = 0; i < ppc->numports; i++) {
215
+ bool v;
216
+
217
+ if (extract32(ppc->ns, i, 1)) {
218
+ v = extract32(ppc->nsp, i, 1);
219
+ } else {
220
+ v = extract32(ppc->sp, i, 1);
221
+ }
222
+ qemu_set_irq(ppc->ap[i], v);
223
+ }
224
+}
225
+
226
+static void iotkit_secctl_ppc_ns_write(IoTKitSecCtlPPC *ppc, uint32_t value)
227
+{
228
+ int i;
229
+
230
+ ppc->ns = value & MAKE_64BIT_MASK(0, ppc->numports);
231
+ for (i = 0; i < ppc->numports; i++) {
232
+ qemu_set_irq(ppc->nonsec[i], extract32(ppc->ns, i, 1));
233
+ }
234
+ iotkit_secctl_update_ppc_ap(ppc);
235
+}
236
+
237
+static void iotkit_secctl_ppc_sp_write(IoTKitSecCtlPPC *ppc, uint32_t value)
238
+{
239
+ ppc->sp = value & MAKE_64BIT_MASK(0, ppc->numports);
240
+ iotkit_secctl_update_ppc_ap(ppc);
241
+}
242
+
243
+static void iotkit_secctl_ppc_nsp_write(IoTKitSecCtlPPC *ppc, uint32_t value)
244
+{
245
+ ppc->nsp = value & MAKE_64BIT_MASK(0, ppc->numports);
246
+ iotkit_secctl_update_ppc_ap(ppc);
247
+}
248
+
249
+static void iotkit_secctl_ppc_update_irq_clear(IoTKitSecCtlPPC *ppc)
250
+{
251
+ uint32_t value = ppc->parent->secppcintstat;
252
+
253
+ qemu_set_irq(ppc->irq_clear, extract32(value, ppc->irq_bit_offset, 1));
254
+}
255
+
256
+static void iotkit_secctl_ppc_update_irq_enable(IoTKitSecCtlPPC *ppc)
257
+{
258
+ uint32_t value = ppc->parent->secppcinten;
259
+
260
+ qemu_set_irq(ppc->irq_enable, extract32(value, ppc->irq_bit_offset, 1));
261
+}
262
+
263
static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
264
uint64_t value,
265
unsigned size, MemTxAttrs attrs)
266
{
267
+ IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
268
uint32_t offset = addr;
269
+ IoTKitSecCtlPPC *ppc;
270
271
trace_iotkit_secctl_s_write(offset, value, size);
272
273
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
274
275
switch (offset) {
276
case A_SECRESPCFG:
277
- case A_NSCCFG:
278
+ value &= 1;
279
+ s->secrespcfg = value;
280
+ qemu_set_irq(s->sec_resp_cfg, s->secrespcfg);
281
+ break;
282
case A_SECPPCINTCLR:
283
+ value &= 0x00f000f3;
284
+ foreach_ppc(s, iotkit_secctl_ppc_update_irq_clear);
285
+ break;
286
case A_SECPPCINTEN:
287
- case A_SECMSCINTCLR:
288
- case A_SECMSCINTEN:
289
- case A_BRGINTCLR:
290
- case A_BRGINTEN:
291
+ s->secppcinten = value & 0x00f000f3;
292
+ foreach_ppc(s, iotkit_secctl_ppc_update_irq_enable);
293
+ break;
294
case A_AHBNSPPCEXP0:
295
case A_AHBNSPPCEXP1:
296
case A_AHBNSPPCEXP2:
297
case A_AHBNSPPCEXP3:
298
+ ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
299
+ iotkit_secctl_ppc_ns_write(ppc, value);
300
+ break;
301
case A_APBNSPPC0:
302
case A_APBNSPPC1:
303
+ ppc = &s->apb[offset_to_ppc_idx(offset)];
304
+ iotkit_secctl_ppc_ns_write(ppc, value);
305
+ break;
306
case A_APBNSPPCEXP0:
307
case A_APBNSPPCEXP1:
308
case A_APBNSPPCEXP2:
309
case A_APBNSPPCEXP3:
310
+ ppc = &s->apbexp[offset_to_ppc_idx(offset)];
311
+ iotkit_secctl_ppc_ns_write(ppc, value);
312
+ break;
313
case A_AHBSPPPCEXP0:
314
case A_AHBSPPPCEXP1:
315
case A_AHBSPPPCEXP2:
316
case A_AHBSPPPCEXP3:
317
+ ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
318
+ iotkit_secctl_ppc_sp_write(ppc, value);
319
+ break;
320
case A_APBSPPPC0:
321
case A_APBSPPPC1:
322
+ ppc = &s->apb[offset_to_ppc_idx(offset)];
323
+ iotkit_secctl_ppc_sp_write(ppc, value);
324
+ break;
325
case A_APBSPPPCEXP0:
326
case A_APBSPPPCEXP1:
327
case A_APBSPPPCEXP2:
328
case A_APBSPPPCEXP3:
329
+ ppc = &s->apbexp[offset_to_ppc_idx(offset)];
330
+ iotkit_secctl_ppc_sp_write(ppc, value);
331
+ break;
332
+ case A_NSCCFG:
333
+ case A_SECMSCINTCLR:
334
+ case A_SECMSCINTEN:
335
+ case A_BRGINTCLR:
336
+ case A_BRGINTEN:
337
qemu_log_mask(LOG_UNIMP,
338
"IoTKit SecCtl S block write: "
339
"unimplemented offset 0x%x\n", offset);
340
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_ns_read(void *opaque, hwaddr addr,
341
uint64_t *pdata,
342
unsigned size, MemTxAttrs attrs)
343
{
344
+ IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
345
uint64_t r;
346
uint32_t offset = addr & ~0x3;
347
348
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_ns_read(void *opaque, hwaddr addr,
349
case A_AHBNSPPPCEXP1:
350
case A_AHBNSPPPCEXP2:
351
case A_AHBNSPPPCEXP3:
352
+ r = s->ahbexp[offset_to_ppc_idx(offset)].nsp;
353
+ break;
354
case A_APBNSPPPC0:
355
case A_APBNSPPPC1:
356
+ r = s->apb[offset_to_ppc_idx(offset)].nsp;
357
+ break;
358
case A_APBNSPPPCEXP0:
359
case A_APBNSPPPCEXP1:
360
case A_APBNSPPPCEXP2:
361
case A_APBNSPPPCEXP3:
362
- qemu_log_mask(LOG_UNIMP,
363
- "IoTKit SecCtl NS block read: "
364
- "unimplemented offset 0x%x\n", offset);
365
+ r = s->apbexp[offset_to_ppc_idx(offset)].nsp;
366
break;
367
case A_PID4:
368
case A_PID5:
369
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_ns_write(void *opaque, hwaddr addr,
370
uint64_t value,
371
unsigned size, MemTxAttrs attrs)
372
{
373
+ IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
374
uint32_t offset = addr;
375
+ IoTKitSecCtlPPC *ppc;
376
377
trace_iotkit_secctl_ns_write(offset, value, size);
378
379
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_ns_write(void *opaque, hwaddr addr,
380
case A_AHBNSPPPCEXP1:
381
case A_AHBNSPPPCEXP2:
382
case A_AHBNSPPPCEXP3:
383
+ ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
384
+ iotkit_secctl_ppc_nsp_write(ppc, value);
385
+ break;
386
case A_APBNSPPPC0:
387
case A_APBNSPPPC1:
388
+ ppc = &s->apb[offset_to_ppc_idx(offset)];
389
+ iotkit_secctl_ppc_nsp_write(ppc, value);
390
+ break;
391
case A_APBNSPPPCEXP0:
392
case A_APBNSPPPCEXP1:
393
case A_APBNSPPPCEXP2:
394
case A_APBNSPPPCEXP3:
395
- qemu_log_mask(LOG_UNIMP,
396
- "IoTKit SecCtl NS block write: "
397
- "unimplemented offset 0x%x\n", offset);
398
+ ppc = &s->apbexp[offset_to_ppc_idx(offset)];
399
+ iotkit_secctl_ppc_nsp_write(ppc, value);
400
break;
401
case A_AHBNSPPPC0:
402
case A_PID4:
403
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps iotkit_secctl_ns_ops = {
404
.impl.max_access_size = 4,
405
};
406
407
+static void iotkit_secctl_reset_ppc(IoTKitSecCtlPPC *ppc)
408
+{
409
+ ppc->ns = 0;
410
+ ppc->sp = 0;
411
+ ppc->nsp = 0;
412
+}
413
+
414
static void iotkit_secctl_reset(DeviceState *dev)
415
{
416
+ IoTKitSecCtl *s = IOTKIT_SECCTL(dev);
417
418
+ s->secppcintstat = 0;
419
+ s->secppcinten = 0;
420
+ s->secrespcfg = 0;
421
+
422
+ foreach_ppc(s, iotkit_secctl_reset_ppc);
423
+}
424
+
425
+static void iotkit_secctl_ppc_irqstatus(void *opaque, int n, int level)
426
+{
427
+ IoTKitSecCtlPPC *ppc = opaque;
428
+ IoTKitSecCtl *s = IOTKIT_SECCTL(ppc->parent);
429
+ int irqbit = ppc->irq_bit_offset + n;
430
+
431
+ s->secppcintstat = deposit32(s->secppcintstat, irqbit, 1, level);
432
+}
433
+
434
+static void iotkit_secctl_init_ppc(IoTKitSecCtl *s,
435
+ IoTKitSecCtlPPC *ppc,
436
+ const char *name,
437
+ int numports,
438
+ int irq_bit_offset)
439
+{
440
+ char *gpioname;
441
+ DeviceState *dev = DEVICE(s);
442
+
443
+ ppc->numports = numports;
444
+ ppc->irq_bit_offset = irq_bit_offset;
445
+ ppc->parent = s;
446
+
447
+ gpioname = g_strdup_printf("%s_nonsec", name);
448
+ qdev_init_gpio_out_named(dev, ppc->nonsec, gpioname, numports);
449
+ g_free(gpioname);
450
+ gpioname = g_strdup_printf("%s_ap", name);
451
+ qdev_init_gpio_out_named(dev, ppc->ap, gpioname, numports);
452
+ g_free(gpioname);
453
+ gpioname = g_strdup_printf("%s_irq_enable", name);
454
+ qdev_init_gpio_out_named(dev, &ppc->irq_enable, gpioname, 1);
455
+ g_free(gpioname);
456
+ gpioname = g_strdup_printf("%s_irq_clear", name);
457
+ qdev_init_gpio_out_named(dev, &ppc->irq_clear, gpioname, 1);
458
+ g_free(gpioname);
459
+ gpioname = g_strdup_printf("%s_irq_status", name);
460
+ qdev_init_gpio_in_named_with_opaque(dev, iotkit_secctl_ppc_irqstatus,
461
+ ppc, gpioname, 1);
462
+ g_free(gpioname);
463
}
464
465
static void iotkit_secctl_init(Object *obj)
466
{
467
IoTKitSecCtl *s = IOTKIT_SECCTL(obj);
468
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
469
+ DeviceState *dev = DEVICE(obj);
470
+ int i;
471
+
472
+ iotkit_secctl_init_ppc(s, &s->apb[0], "apb_ppc0",
473
+ IOTS_APB_PPC0_NUM_PORTS, 0);
474
+ iotkit_secctl_init_ppc(s, &s->apb[1], "apb_ppc1",
475
+ IOTS_APB_PPC1_NUM_PORTS, 1);
476
+
477
+ for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) {
478
+ IoTKitSecCtlPPC *ppc = &s->apbexp[i];
479
+ char *ppcname = g_strdup_printf("apb_ppcexp%d", i);
480
+ iotkit_secctl_init_ppc(s, ppc, ppcname, IOTS_PPC_NUM_PORTS, 4 + i);
481
+ g_free(ppcname);
482
+ }
483
+ for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) {
484
+ IoTKitSecCtlPPC *ppc = &s->ahbexp[i];
485
+ char *ppcname = g_strdup_printf("ahb_ppcexp%d", i);
486
+ iotkit_secctl_init_ppc(s, ppc, ppcname, IOTS_PPC_NUM_PORTS, 20 + i);
487
+ g_free(ppcname);
488
+ }
489
+
490
+ qdev_init_gpio_out_named(dev, &s->sec_resp_cfg, "sec_resp_cfg", 1);
491
492
memory_region_init_io(&s->s_regs, obj, &iotkit_secctl_s_ops,
493
s, "iotkit-secctl-s-regs", 0x1000);
494
@@ -XXX,XX +XXX,XX @@ static void iotkit_secctl_init(Object *obj)
495
sysbus_init_mmio(sbd, &s->ns_regs);
496
}
497
498
+static const VMStateDescription iotkit_secctl_ppc_vmstate = {
499
+ .name = "iotkit-secctl-ppc",
500
+ .version_id = 1,
501
+ .minimum_version_id = 1,
502
+ .fields = (VMStateField[]) {
503
+ VMSTATE_UINT32(ns, IoTKitSecCtlPPC),
504
+ VMSTATE_UINT32(sp, IoTKitSecCtlPPC),
505
+ VMSTATE_UINT32(nsp, IoTKitSecCtlPPC),
506
+ VMSTATE_END_OF_LIST()
507
+ }
508
+};
509
+
510
static const VMStateDescription iotkit_secctl_vmstate = {
511
.name = "iotkit-secctl",
512
.version_id = 1,
513
.minimum_version_id = 1,
514
.fields = (VMStateField[]) {
515
+ VMSTATE_UINT32(secppcintstat, IoTKitSecCtl),
516
+ VMSTATE_UINT32(secppcinten, IoTKitSecCtl),
517
+ VMSTATE_UINT32(secrespcfg, IoTKitSecCtl),
518
+ VMSTATE_STRUCT_ARRAY(apb, IoTKitSecCtl, IOTS_NUM_APB_PPC, 1,
519
+ iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
520
+ VMSTATE_STRUCT_ARRAY(apbexp, IoTKitSecCtl, IOTS_NUM_APB_EXP_PPC, 1,
521
+ iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
522
+ VMSTATE_STRUCT_ARRAY(ahbexp, IoTKitSecCtl, IOTS_NUM_AHB_EXP_PPC, 1,
523
+ iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
524
VMSTATE_END_OF_LIST()
525
}
526
};
527
--
63
--
528
2.16.2
64
2.20.1
529
65
530
66
diff view generated by jsdifflib
1
The Arm IoT Kit includes a "security controller" which is largely a
1
Switch the sh_timer code away from bottom-half based ptimers to the
2
collection of registers for controlling the PPCs and other bits of
2
new transaction-based ptimer API. This just requires adding
3
glue in the system. This commit provides the initial skeleton of the
3
begin/commit calls around the various places that modify the ptimer
4
device, implementing just the ID registers, and a couple of read-only
4
state, and using the new ptimer_init() function to create the timer.
5
read-as-zero registers.
6
5
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20180220180325.29818-16-peter.maydell@linaro.org
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Message-id: 20191017132905.5604-3-peter.maydell@linaro.org
10
---
10
---
11
hw/misc/Makefile.objs | 1 +
11
hw/timer/sh_timer.c | 13 +++++++++----
12
include/hw/misc/iotkit-secctl.h | 39 ++++
12
1 file changed, 9 insertions(+), 4 deletions(-)
13
hw/misc/iotkit-secctl.c | 448 ++++++++++++++++++++++++++++++++++++++++
14
default-configs/arm-softmmu.mak | 1 +
15
hw/misc/trace-events | 7 +
16
5 files changed, 496 insertions(+)
17
create mode 100644 include/hw/misc/iotkit-secctl.h
18
create mode 100644 hw/misc/iotkit-secctl.c
19
13
20
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
14
diff --git a/hw/timer/sh_timer.c b/hw/timer/sh_timer.c
21
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/misc/Makefile.objs
16
--- a/hw/timer/sh_timer.c
23
+++ b/hw/misc/Makefile.objs
17
+++ b/hw/timer/sh_timer.c
24
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_MPS2_FPGAIO) += mps2-fpgaio.o
25
obj-$(CONFIG_MPS2_SCC) += mps2-scc.o
26
27
obj-$(CONFIG_TZ_PPC) += tz-ppc.o
28
+obj-$(CONFIG_IOTKIT_SECCTL) += iotkit-secctl.o
29
30
obj-$(CONFIG_PVPANIC) += pvpanic.o
31
obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
32
diff --git a/include/hw/misc/iotkit-secctl.h b/include/hw/misc/iotkit-secctl.h
33
new file mode 100644
34
index XXXXXXX..XXXXXXX
35
--- /dev/null
36
+++ b/include/hw/misc/iotkit-secctl.h
37
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@
38
+/*
19
#include "hw/irq.h"
39
+ * ARM IoT Kit security controller
20
#include "hw/sh4/sh.h"
40
+ *
21
#include "qemu/timer.h"
41
+ * Copyright (c) 2018 Linaro Limited
22
-#include "qemu/main-loop.h"
42
+ * Written by Peter Maydell
23
#include "hw/ptimer.h"
43
+ *
24
44
+ * This program is free software; you can redistribute it and/or modify
25
//#define DEBUG_TIMER
45
+ * it under the terms of the GNU General Public License version 2 or
26
@@ -XXX,XX +XXX,XX @@ static void sh_timer_write(void *opaque, hwaddr offset,
46
+ * (at your option) any later version.
27
switch (offset >> 2) {
47
+ */
28
case OFFSET_TCOR:
48
+
29
s->tcor = value;
49
+/* This is a model of the security controller which is part of the
30
+ ptimer_transaction_begin(s->timer);
50
+ * Arm IoT Kit and documented in
31
ptimer_set_limit(s->timer, s->tcor, 0);
51
+ * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
32
+ ptimer_transaction_commit(s->timer);
52
+ *
33
break;
53
+ * QEMU interface:
34
case OFFSET_TCNT:
54
+ * + sysbus MMIO region 0 is the "secure privilege control block" registers
35
s->tcnt = value;
55
+ * + sysbus MMIO region 1 is the "non-secure privilege control block" registers
36
+ ptimer_transaction_begin(s->timer);
56
+ */
37
ptimer_set_count(s->timer, s->tcnt);
57
+
38
+ ptimer_transaction_commit(s->timer);
58
+#ifndef IOTKIT_SECCTL_H
39
break;
59
+#define IOTKIT_SECCTL_H
40
case OFFSET_TCR:
60
+
41
+ ptimer_transaction_begin(s->timer);
61
+#include "hw/sysbus.h"
42
if (s->enabled) {
62
+
43
/* Pause the timer if it is running. This may cause some
63
+#define TYPE_IOTKIT_SECCTL "iotkit-secctl"
44
inaccuracy dure to rounding, but avoids a whole lot of other
64
+#define IOTKIT_SECCTL(obj) OBJECT_CHECK(IoTKitSecCtl, (obj), TYPE_IOTKIT_SECCTL)
45
@@ -XXX,XX +XXX,XX @@ static void sh_timer_write(void *opaque, hwaddr offset,
65
+
46
/* Restart the timer if still enabled. */
66
+typedef struct IoTKitSecCtl {
47
ptimer_run(s->timer, 0);
67
+ /*< private >*/
48
}
68
+ SysBusDevice parent_obj;
49
+ ptimer_transaction_commit(s->timer);
69
+
50
break;
70
+ /*< public >*/
51
case OFFSET_TCPR:
71
+
52
if (s->feat & TIMER_FEAT_CAPT) {
72
+ MemoryRegion s_regs;
53
@@ -XXX,XX +XXX,XX @@ static void sh_timer_start_stop(void *opaque, int enable)
73
+ MemoryRegion ns_regs;
54
printf("sh_timer_start_stop %d (%d)\n", enable, s->enabled);
74
+} IoTKitSecCtl;
55
#endif
75
+
56
76
+#endif
57
+ ptimer_transaction_begin(s->timer);
77
diff --git a/hw/misc/iotkit-secctl.c b/hw/misc/iotkit-secctl.c
58
if (s->enabled && !enable) {
78
new file mode 100644
59
ptimer_stop(s->timer);
79
index XXXXXXX..XXXXXXX
60
}
80
--- /dev/null
61
if (!s->enabled && enable) {
81
+++ b/hw/misc/iotkit-secctl.c
62
ptimer_run(s->timer, 0);
82
@@ -XXX,XX +XXX,XX @@
63
}
83
+/*
64
+ ptimer_transaction_commit(s->timer);
84
+ * Arm IoT Kit security controller
65
s->enabled = !!enable;
85
+ *
66
86
+ * Copyright (c) 2018 Linaro Limited
67
#ifdef DEBUG_TIMER
87
+ * Written by Peter Maydell
68
@@ -XXX,XX +XXX,XX @@ static void sh_timer_tick(void *opaque)
88
+ *
69
static void *sh_timer_init(uint32_t freq, int feat, qemu_irq irq)
89
+ * This program is free software; you can redistribute it and/or modify
70
{
90
+ * it under the terms of the GNU General Public License version 2 or
71
sh_timer_state *s;
91
+ * (at your option) any later version.
72
- QEMUBH *bh;
92
+ */
73
93
+
74
s = (sh_timer_state *)g_malloc0(sizeof(sh_timer_state));
94
+#include "qemu/osdep.h"
75
s->freq = freq;
95
+#include "qemu/log.h"
76
@@ -XXX,XX +XXX,XX @@ static void *sh_timer_init(uint32_t freq, int feat, qemu_irq irq)
96
+#include "qapi/error.h"
77
s->enabled = 0;
97
+#include "trace.h"
78
s->irq = irq;
98
+#include "hw/sysbus.h"
79
99
+#include "hw/registerfields.h"
80
- bh = qemu_bh_new(sh_timer_tick, s);
100
+#include "hw/misc/iotkit-secctl.h"
81
- s->timer = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
101
+
82
+ s->timer = ptimer_init(sh_timer_tick, s, PTIMER_POLICY_DEFAULT);
102
+/* Registers in the secure privilege control block */
83
103
+REG32(SECRESPCFG, 0x10)
84
sh_timer_write(s, OFFSET_TCOR >> 2, s->tcor);
104
+REG32(NSCCFG, 0x14)
85
sh_timer_write(s, OFFSET_TCNT >> 2, s->tcnt);
105
+REG32(SECMPCINTSTATUS, 0x1c)
106
+REG32(SECPPCINTSTAT, 0x20)
107
+REG32(SECPPCINTCLR, 0x24)
108
+REG32(SECPPCINTEN, 0x28)
109
+REG32(SECMSCINTSTAT, 0x30)
110
+REG32(SECMSCINTCLR, 0x34)
111
+REG32(SECMSCINTEN, 0x38)
112
+REG32(BRGINTSTAT, 0x40)
113
+REG32(BRGINTCLR, 0x44)
114
+REG32(BRGINTEN, 0x48)
115
+REG32(AHBNSPPC0, 0x50)
116
+REG32(AHBNSPPCEXP0, 0x60)
117
+REG32(AHBNSPPCEXP1, 0x64)
118
+REG32(AHBNSPPCEXP2, 0x68)
119
+REG32(AHBNSPPCEXP3, 0x6c)
120
+REG32(APBNSPPC0, 0x70)
121
+REG32(APBNSPPC1, 0x74)
122
+REG32(APBNSPPCEXP0, 0x80)
123
+REG32(APBNSPPCEXP1, 0x84)
124
+REG32(APBNSPPCEXP2, 0x88)
125
+REG32(APBNSPPCEXP3, 0x8c)
126
+REG32(AHBSPPPC0, 0x90)
127
+REG32(AHBSPPPCEXP0, 0xa0)
128
+REG32(AHBSPPPCEXP1, 0xa4)
129
+REG32(AHBSPPPCEXP2, 0xa8)
130
+REG32(AHBSPPPCEXP3, 0xac)
131
+REG32(APBSPPPC0, 0xb0)
132
+REG32(APBSPPPC1, 0xb4)
133
+REG32(APBSPPPCEXP0, 0xc0)
134
+REG32(APBSPPPCEXP1, 0xc4)
135
+REG32(APBSPPPCEXP2, 0xc8)
136
+REG32(APBSPPPCEXP3, 0xcc)
137
+REG32(NSMSCEXP, 0xd0)
138
+REG32(PID4, 0xfd0)
139
+REG32(PID5, 0xfd4)
140
+REG32(PID6, 0xfd8)
141
+REG32(PID7, 0xfdc)
142
+REG32(PID0, 0xfe0)
143
+REG32(PID1, 0xfe4)
144
+REG32(PID2, 0xfe8)
145
+REG32(PID3, 0xfec)
146
+REG32(CID0, 0xff0)
147
+REG32(CID1, 0xff4)
148
+REG32(CID2, 0xff8)
149
+REG32(CID3, 0xffc)
150
+
151
+/* Registers in the non-secure privilege control block */
152
+REG32(AHBNSPPPC0, 0x90)
153
+REG32(AHBNSPPPCEXP0, 0xa0)
154
+REG32(AHBNSPPPCEXP1, 0xa4)
155
+REG32(AHBNSPPPCEXP2, 0xa8)
156
+REG32(AHBNSPPPCEXP3, 0xac)
157
+REG32(APBNSPPPC0, 0xb0)
158
+REG32(APBNSPPPC1, 0xb4)
159
+REG32(APBNSPPPCEXP0, 0xc0)
160
+REG32(APBNSPPPCEXP1, 0xc4)
161
+REG32(APBNSPPPCEXP2, 0xc8)
162
+REG32(APBNSPPPCEXP3, 0xcc)
163
+/* PID and CID registers are also present in the NS block */
164
+
165
+static const uint8_t iotkit_secctl_s_idregs[] = {
166
+ 0x04, 0x00, 0x00, 0x00,
167
+ 0x52, 0xb8, 0x0b, 0x00,
168
+ 0x0d, 0xf0, 0x05, 0xb1,
169
+};
170
+
171
+static const uint8_t iotkit_secctl_ns_idregs[] = {
172
+ 0x04, 0x00, 0x00, 0x00,
173
+ 0x53, 0xb8, 0x0b, 0x00,
174
+ 0x0d, 0xf0, 0x05, 0xb1,
175
+};
176
+
177
+static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
178
+ uint64_t *pdata,
179
+ unsigned size, MemTxAttrs attrs)
180
+{
181
+ uint64_t r;
182
+ uint32_t offset = addr & ~0x3;
183
+
184
+ switch (offset) {
185
+ case A_AHBNSPPC0:
186
+ case A_AHBSPPPC0:
187
+ r = 0;
188
+ break;
189
+ case A_SECRESPCFG:
190
+ case A_NSCCFG:
191
+ case A_SECMPCINTSTATUS:
192
+ case A_SECPPCINTSTAT:
193
+ case A_SECPPCINTEN:
194
+ case A_SECMSCINTSTAT:
195
+ case A_SECMSCINTEN:
196
+ case A_BRGINTSTAT:
197
+ case A_BRGINTEN:
198
+ case A_AHBNSPPCEXP0:
199
+ case A_AHBNSPPCEXP1:
200
+ case A_AHBNSPPCEXP2:
201
+ case A_AHBNSPPCEXP3:
202
+ case A_APBNSPPC0:
203
+ case A_APBNSPPC1:
204
+ case A_APBNSPPCEXP0:
205
+ case A_APBNSPPCEXP1:
206
+ case A_APBNSPPCEXP2:
207
+ case A_APBNSPPCEXP3:
208
+ case A_AHBSPPPCEXP0:
209
+ case A_AHBSPPPCEXP1:
210
+ case A_AHBSPPPCEXP2:
211
+ case A_AHBSPPPCEXP3:
212
+ case A_APBSPPPC0:
213
+ case A_APBSPPPC1:
214
+ case A_APBSPPPCEXP0:
215
+ case A_APBSPPPCEXP1:
216
+ case A_APBSPPPCEXP2:
217
+ case A_APBSPPPCEXP3:
218
+ case A_NSMSCEXP:
219
+ qemu_log_mask(LOG_UNIMP,
220
+ "IoTKit SecCtl S block read: "
221
+ "unimplemented offset 0x%x\n", offset);
222
+ r = 0;
223
+ break;
224
+ case A_PID4:
225
+ case A_PID5:
226
+ case A_PID6:
227
+ case A_PID7:
228
+ case A_PID0:
229
+ case A_PID1:
230
+ case A_PID2:
231
+ case A_PID3:
232
+ case A_CID0:
233
+ case A_CID1:
234
+ case A_CID2:
235
+ case A_CID3:
236
+ r = iotkit_secctl_s_idregs[(offset - A_PID4) / 4];
237
+ break;
238
+ case A_SECPPCINTCLR:
239
+ case A_SECMSCINTCLR:
240
+ case A_BRGINTCLR:
241
+ qemu_log_mask(LOG_GUEST_ERROR,
242
+ "IotKit SecCtl S block read: write-only offset 0x%x\n",
243
+ offset);
244
+ r = 0;
245
+ break;
246
+ default:
247
+ qemu_log_mask(LOG_GUEST_ERROR,
248
+ "IotKit SecCtl S block read: bad offset 0x%x\n", offset);
249
+ r = 0;
250
+ break;
251
+ }
252
+
253
+ if (size != 4) {
254
+ /* None of our registers are access-sensitive, so just pull the right
255
+ * byte out of the word read result.
256
+ */
257
+ r = extract32(r, (addr & 3) * 8, size * 8);
258
+ }
259
+
260
+ trace_iotkit_secctl_s_read(offset, r, size);
261
+ *pdata = r;
262
+ return MEMTX_OK;
263
+}
264
+
265
+static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
266
+ uint64_t value,
267
+ unsigned size, MemTxAttrs attrs)
268
+{
269
+ uint32_t offset = addr;
270
+
271
+ trace_iotkit_secctl_s_write(offset, value, size);
272
+
273
+ if (size != 4) {
274
+ /* Byte and halfword writes are ignored */
275
+ qemu_log_mask(LOG_GUEST_ERROR,
276
+ "IotKit SecCtl S block write: bad size, ignored\n");
277
+ return MEMTX_OK;
278
+ }
279
+
280
+ switch (offset) {
281
+ case A_SECRESPCFG:
282
+ case A_NSCCFG:
283
+ case A_SECPPCINTCLR:
284
+ case A_SECPPCINTEN:
285
+ case A_SECMSCINTCLR:
286
+ case A_SECMSCINTEN:
287
+ case A_BRGINTCLR:
288
+ case A_BRGINTEN:
289
+ case A_AHBNSPPCEXP0:
290
+ case A_AHBNSPPCEXP1:
291
+ case A_AHBNSPPCEXP2:
292
+ case A_AHBNSPPCEXP3:
293
+ case A_APBNSPPC0:
294
+ case A_APBNSPPC1:
295
+ case A_APBNSPPCEXP0:
296
+ case A_APBNSPPCEXP1:
297
+ case A_APBNSPPCEXP2:
298
+ case A_APBNSPPCEXP3:
299
+ case A_AHBSPPPCEXP0:
300
+ case A_AHBSPPPCEXP1:
301
+ case A_AHBSPPPCEXP2:
302
+ case A_AHBSPPPCEXP3:
303
+ case A_APBSPPPC0:
304
+ case A_APBSPPPC1:
305
+ case A_APBSPPPCEXP0:
306
+ case A_APBSPPPCEXP1:
307
+ case A_APBSPPPCEXP2:
308
+ case A_APBSPPPCEXP3:
309
+ qemu_log_mask(LOG_UNIMP,
310
+ "IoTKit SecCtl S block write: "
311
+ "unimplemented offset 0x%x\n", offset);
312
+ break;
313
+ case A_SECMPCINTSTATUS:
314
+ case A_SECPPCINTSTAT:
315
+ case A_SECMSCINTSTAT:
316
+ case A_BRGINTSTAT:
317
+ case A_AHBNSPPC0:
318
+ case A_AHBSPPPC0:
319
+ case A_NSMSCEXP:
320
+ case A_PID4:
321
+ case A_PID5:
322
+ case A_PID6:
323
+ case A_PID7:
324
+ case A_PID0:
325
+ case A_PID1:
326
+ case A_PID2:
327
+ case A_PID3:
328
+ case A_CID0:
329
+ case A_CID1:
330
+ case A_CID2:
331
+ case A_CID3:
332
+ qemu_log_mask(LOG_GUEST_ERROR,
333
+ "IoTKit SecCtl S block write: "
334
+ "read-only offset 0x%x\n", offset);
335
+ break;
336
+ default:
337
+ qemu_log_mask(LOG_GUEST_ERROR,
338
+ "IotKit SecCtl S block write: bad offset 0x%x\n",
339
+ offset);
340
+ break;
341
+ }
342
+
343
+ return MEMTX_OK;
344
+}
345
+
346
+static MemTxResult iotkit_secctl_ns_read(void *opaque, hwaddr addr,
347
+ uint64_t *pdata,
348
+ unsigned size, MemTxAttrs attrs)
349
+{
350
+ uint64_t r;
351
+ uint32_t offset = addr & ~0x3;
352
+
353
+ switch (offset) {
354
+ case A_AHBNSPPPC0:
355
+ r = 0;
356
+ break;
357
+ case A_AHBNSPPPCEXP0:
358
+ case A_AHBNSPPPCEXP1:
359
+ case A_AHBNSPPPCEXP2:
360
+ case A_AHBNSPPPCEXP3:
361
+ case A_APBNSPPPC0:
362
+ case A_APBNSPPPC1:
363
+ case A_APBNSPPPCEXP0:
364
+ case A_APBNSPPPCEXP1:
365
+ case A_APBNSPPPCEXP2:
366
+ case A_APBNSPPPCEXP3:
367
+ qemu_log_mask(LOG_UNIMP,
368
+ "IoTKit SecCtl NS block read: "
369
+ "unimplemented offset 0x%x\n", offset);
370
+ break;
371
+ case A_PID4:
372
+ case A_PID5:
373
+ case A_PID6:
374
+ case A_PID7:
375
+ case A_PID0:
376
+ case A_PID1:
377
+ case A_PID2:
378
+ case A_PID3:
379
+ case A_CID0:
380
+ case A_CID1:
381
+ case A_CID2:
382
+ case A_CID3:
383
+ r = iotkit_secctl_ns_idregs[(offset - A_PID4) / 4];
384
+ break;
385
+ default:
386
+ qemu_log_mask(LOG_GUEST_ERROR,
387
+ "IotKit SecCtl NS block write: bad offset 0x%x\n",
388
+ offset);
389
+ r = 0;
390
+ break;
391
+ }
392
+
393
+ if (size != 4) {
394
+ /* None of our registers are access-sensitive, so just pull the right
395
+ * byte out of the word read result.
396
+ */
397
+ r = extract32(r, (addr & 3) * 8, size * 8);
398
+ }
399
+
400
+ trace_iotkit_secctl_ns_read(offset, r, size);
401
+ *pdata = r;
402
+ return MEMTX_OK;
403
+}
404
+
405
+static MemTxResult iotkit_secctl_ns_write(void *opaque, hwaddr addr,
406
+ uint64_t value,
407
+ unsigned size, MemTxAttrs attrs)
408
+{
409
+ uint32_t offset = addr;
410
+
411
+ trace_iotkit_secctl_ns_write(offset, value, size);
412
+
413
+ if (size != 4) {
414
+ /* Byte and halfword writes are ignored */
415
+ qemu_log_mask(LOG_GUEST_ERROR,
416
+ "IotKit SecCtl NS block write: bad size, ignored\n");
417
+ return MEMTX_OK;
418
+ }
419
+
420
+ switch (offset) {
421
+ case A_AHBNSPPPCEXP0:
422
+ case A_AHBNSPPPCEXP1:
423
+ case A_AHBNSPPPCEXP2:
424
+ case A_AHBNSPPPCEXP3:
425
+ case A_APBNSPPPC0:
426
+ case A_APBNSPPPC1:
427
+ case A_APBNSPPPCEXP0:
428
+ case A_APBNSPPPCEXP1:
429
+ case A_APBNSPPPCEXP2:
430
+ case A_APBNSPPPCEXP3:
431
+ qemu_log_mask(LOG_UNIMP,
432
+ "IoTKit SecCtl NS block write: "
433
+ "unimplemented offset 0x%x\n", offset);
434
+ break;
435
+ case A_AHBNSPPPC0:
436
+ case A_PID4:
437
+ case A_PID5:
438
+ case A_PID6:
439
+ case A_PID7:
440
+ case A_PID0:
441
+ case A_PID1:
442
+ case A_PID2:
443
+ case A_PID3:
444
+ case A_CID0:
445
+ case A_CID1:
446
+ case A_CID2:
447
+ case A_CID3:
448
+ qemu_log_mask(LOG_GUEST_ERROR,
449
+ "IoTKit SecCtl NS block write: "
450
+ "read-only offset 0x%x\n", offset);
451
+ break;
452
+ default:
453
+ qemu_log_mask(LOG_GUEST_ERROR,
454
+ "IotKit SecCtl NS block write: bad offset 0x%x\n",
455
+ offset);
456
+ break;
457
+ }
458
+
459
+ return MEMTX_OK;
460
+}
461
+
462
+static const MemoryRegionOps iotkit_secctl_s_ops = {
463
+ .read_with_attrs = iotkit_secctl_s_read,
464
+ .write_with_attrs = iotkit_secctl_s_write,
465
+ .endianness = DEVICE_LITTLE_ENDIAN,
466
+ .valid.min_access_size = 1,
467
+ .valid.max_access_size = 4,
468
+ .impl.min_access_size = 1,
469
+ .impl.max_access_size = 4,
470
+};
471
+
472
+static const MemoryRegionOps iotkit_secctl_ns_ops = {
473
+ .read_with_attrs = iotkit_secctl_ns_read,
474
+ .write_with_attrs = iotkit_secctl_ns_write,
475
+ .endianness = DEVICE_LITTLE_ENDIAN,
476
+ .valid.min_access_size = 1,
477
+ .valid.max_access_size = 4,
478
+ .impl.min_access_size = 1,
479
+ .impl.max_access_size = 4,
480
+};
481
+
482
+static void iotkit_secctl_reset(DeviceState *dev)
483
+{
484
+
485
+}
486
+
487
+static void iotkit_secctl_init(Object *obj)
488
+{
489
+ IoTKitSecCtl *s = IOTKIT_SECCTL(obj);
490
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
491
+
492
+ memory_region_init_io(&s->s_regs, obj, &iotkit_secctl_s_ops,
493
+ s, "iotkit-secctl-s-regs", 0x1000);
494
+ memory_region_init_io(&s->ns_regs, obj, &iotkit_secctl_ns_ops,
495
+ s, "iotkit-secctl-ns-regs", 0x1000);
496
+ sysbus_init_mmio(sbd, &s->s_regs);
497
+ sysbus_init_mmio(sbd, &s->ns_regs);
498
+}
499
+
500
+static const VMStateDescription iotkit_secctl_vmstate = {
501
+ .name = "iotkit-secctl",
502
+ .version_id = 1,
503
+ .minimum_version_id = 1,
504
+ .fields = (VMStateField[]) {
505
+ VMSTATE_END_OF_LIST()
506
+ }
507
+};
508
+
509
+static void iotkit_secctl_class_init(ObjectClass *klass, void *data)
510
+{
511
+ DeviceClass *dc = DEVICE_CLASS(klass);
512
+
513
+ dc->vmsd = &iotkit_secctl_vmstate;
514
+ dc->reset = iotkit_secctl_reset;
515
+}
516
+
517
+static const TypeInfo iotkit_secctl_info = {
518
+ .name = TYPE_IOTKIT_SECCTL,
519
+ .parent = TYPE_SYS_BUS_DEVICE,
520
+ .instance_size = sizeof(IoTKitSecCtl),
521
+ .instance_init = iotkit_secctl_init,
522
+ .class_init = iotkit_secctl_class_init,
523
+};
524
+
525
+static void iotkit_secctl_register_types(void)
526
+{
527
+ type_register_static(&iotkit_secctl_info);
528
+}
529
+
530
+type_init(iotkit_secctl_register_types);
531
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
532
index XXXXXXX..XXXXXXX 100644
533
--- a/default-configs/arm-softmmu.mak
534
+++ b/default-configs/arm-softmmu.mak
535
@@ -XXX,XX +XXX,XX @@ CONFIG_MPS2_FPGAIO=y
536
CONFIG_MPS2_SCC=y
537
538
CONFIG_TZ_PPC=y
539
+CONFIG_IOTKIT_SECCTL=y
540
541
CONFIG_VERSATILE_PCI=y
542
CONFIG_VERSATILE_I2C=y
543
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
544
index XXXXXXX..XXXXXXX 100644
545
--- a/hw/misc/trace-events
546
+++ b/hw/misc/trace-events
547
@@ -XXX,XX +XXX,XX @@ tz_ppc_irq_clear(int level) "TZ PPC: int_clear = %d"
548
tz_ppc_update_irq(int level) "TZ PPC: setting irq line to %d"
549
tz_ppc_read_blocked(int n, hwaddr offset, bool secure, bool user) "TZ PPC: port %d offset 0x%" HWADDR_PRIx " read (secure %d user %d) blocked"
550
tz_ppc_write_blocked(int n, hwaddr offset, bool secure, bool user) "TZ PPC: port %d offset 0x%" HWADDR_PRIx " write (secure %d user %d) blocked"
551
+
552
+# hw/misc/iotkit-secctl.c
553
+iotkit_secctl_s_read(uint32_t offset, uint64_t data, unsigned size) "IoTKit SecCtl S regs read: offset 0x%x data 0x%" PRIx64 " size %u"
554
+iotkit_secctl_s_write(uint32_t offset, uint64_t data, unsigned size) "IoTKit SecCtl S regs write: offset 0x%x data 0x%" PRIx64 " size %u"
555
+iotkit_secctl_ns_read(uint32_t offset, uint64_t data, unsigned size) "IoTKit SecCtl NS regs read: offset 0x%x data 0x%" PRIx64 " size %u"
556
+iotkit_secctl_ns_write(uint32_t offset, uint64_t data, unsigned size) "IoTKit SecCtl NS regs write: offset 0x%x data 0x%" PRIx64 " size %u"
557
+iotkit_secctl_reset(void) "IoTKit SecCtl: reset"
558
--
86
--
559
2.16.2
87
2.20.1
560
88
561
89
diff view generated by jsdifflib
1
Add a model of the TrustZone peripheral protection controller (PPC),
1
Switch the lm32_timer code away from bottom-half based ptimers to the
2
which is used to gate transactions to non-TZ-aware peripherals so
2
new transaction-based ptimer API. This just requires adding
3
that secure software can configure them to not be accessible to
3
begin/commit calls around the various places that modify the ptimer
4
non-secure software.
4
state, and using the new ptimer_init() function to create the ytimer.
5
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180220180325.29818-15-peter.maydell@linaro.org
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Message-id: 20191017132905.5604-4-peter.maydell@linaro.org
9
---
10
---
10
hw/misc/Makefile.objs | 2 +
11
hw/timer/lm32_timer.c | 13 +++++++++----
11
include/hw/misc/tz-ppc.h | 101 ++++++++++++++
12
1 file changed, 9 insertions(+), 4 deletions(-)
12
hw/misc/tz-ppc.c | 302 ++++++++++++++++++++++++++++++++++++++++
13
default-configs/arm-softmmu.mak | 2 +
14
hw/misc/trace-events | 11 ++
15
5 files changed, 418 insertions(+)
16
create mode 100644 include/hw/misc/tz-ppc.h
17
create mode 100644 hw/misc/tz-ppc.c
18
13
19
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
14
diff --git a/hw/timer/lm32_timer.c b/hw/timer/lm32_timer.c
20
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/misc/Makefile.objs
16
--- a/hw/timer/lm32_timer.c
22
+++ b/hw/misc/Makefile.objs
17
+++ b/hw/timer/lm32_timer.c
23
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_MIPS_ITU) += mips_itu.o
24
obj-$(CONFIG_MPS2_FPGAIO) += mps2-fpgaio.o
25
obj-$(CONFIG_MPS2_SCC) += mps2-scc.o
26
27
+obj-$(CONFIG_TZ_PPC) += tz-ppc.o
28
+
29
obj-$(CONFIG_PVPANIC) += pvpanic.o
30
obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
31
obj-$(CONFIG_AUX) += auxbus.o
32
diff --git a/include/hw/misc/tz-ppc.h b/include/hw/misc/tz-ppc.h
33
new file mode 100644
34
index XXXXXXX..XXXXXXX
35
--- /dev/null
36
+++ b/include/hw/misc/tz-ppc.h
37
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@
38
+/*
19
#include "hw/ptimer.h"
39
+ * ARM TrustZone peripheral protection controller emulation
20
#include "hw/qdev-properties.h"
40
+ *
21
#include "qemu/error-report.h"
41
+ * Copyright (c) 2018 Linaro Limited
22
-#include "qemu/main-loop.h"
42
+ * Written by Peter Maydell
23
#include "qemu/module.h"
43
+ *
24
44
+ * This program is free software; you can redistribute it and/or modify
25
#define DEFAULT_FREQUENCY (50*1000000)
45
+ * it under the terms of the GNU General Public License version 2 or
26
@@ -XXX,XX +XXX,XX @@ struct LM32TimerState {
46
+ * (at your option) any later version.
27
47
+ */
28
MemoryRegion iomem;
48
+
29
49
+/* This is a model of the TrustZone peripheral protection controller (PPC).
30
- QEMUBH *bh;
50
+ * It is documented in the ARM CoreLink SIE-200 System IP for Embedded TRM
31
ptimer_state *ptimer;
51
+ * (DDI 0571G):
32
52
+ * https://developer.arm.com/products/architecture/m-profile/docs/ddi0571/g
33
qemu_irq irq;
53
+ *
34
@@ -XXX,XX +XXX,XX @@ static void timer_write(void *opaque, hwaddr addr,
54
+ * The PPC sits in front of peripherals and allows secure software to
35
s->regs[R_SR] &= ~SR_TO;
55
+ * configure it to either pass through or reject transactions.
36
break;
56
+ * Rejected transactions may be configured to either be aborted, or to
37
case R_CR:
57
+ * behave as RAZ/WI. An interrupt can be signalled for a rejected transaction.
38
+ ptimer_transaction_begin(s->ptimer);
58
+ *
39
s->regs[R_CR] = value;
59
+ * The PPC has no register interface -- it is configured purely by a
40
if (s->regs[R_CR] & CR_START) {
60
+ * collection of input signals from other hardware in the system. Typically
41
ptimer_run(s->ptimer, 1);
61
+ * they are either hardwired or exposed in an ad-hoc register interface by
42
@@ -XXX,XX +XXX,XX @@ static void timer_write(void *opaque, hwaddr addr,
62
+ * the SoC that uses the PPC.
43
if (s->regs[R_CR] & CR_STOP) {
63
+ *
44
ptimer_stop(s->ptimer);
64
+ * This QEMU model can be used to model either the AHB5 or APB4 TZ PPC,
45
}
65
+ * since the only difference between them is that the AHB version has a
46
+ ptimer_transaction_commit(s->ptimer);
66
+ * "default" port which has no security checks applied. In QEMU the default
47
break;
67
+ * port can be emulated simply by wiring its downstream devices directly
48
case R_PERIOD:
68
+ * into the parent address space, since the PPC does not need to intercept
49
s->regs[R_PERIOD] = value;
69
+ * transactions there.
50
+ ptimer_transaction_begin(s->ptimer);
70
+ *
51
ptimer_set_count(s->ptimer, value);
71
+ * In the hardware, selection of which downstream port to use is done by
52
+ ptimer_transaction_commit(s->ptimer);
72
+ * the user's decode logic asserting one of the hsel[] signals. In QEMU,
53
break;
73
+ * we provide 16 MMIO regions, one per port, and the user maps these into
54
case R_SNAPSHOT:
74
+ * the desired addresses to implement the address decode.
55
error_report("lm32_timer: write access to read only register 0x"
75
+ *
56
@@ -XXX,XX +XXX,XX @@ static void timer_reset(DeviceState *d)
76
+ * QEMU interface:
57
for (i = 0; i < R_MAX; i++) {
77
+ * + sysbus MMIO regions 0..15: MemoryRegions defining the upstream end
58
s->regs[i] = 0;
78
+ * of each of the 16 ports of the PPC
59
}
79
+ * + Property "port[0..15]": MemoryRegion defining the downstream device(s)
60
+ ptimer_transaction_begin(s->ptimer);
80
+ * for each of the 16 ports of the PPC
61
ptimer_stop(s->ptimer);
81
+ * + Named GPIO inputs "cfg_nonsec[0..15]": set to 1 if the port should be
62
+ ptimer_transaction_commit(s->ptimer);
82
+ * accessible to NonSecure transactions
63
}
83
+ * + Named GPIO inputs "cfg_ap[0..15]": set to 1 if the port should be
64
84
+ * accessible to non-privileged transactions
65
static void lm32_timer_init(Object *obj)
85
+ * + Named GPIO input "cfg_sec_resp": set to 1 if a rejected transaction should
66
@@ -XXX,XX +XXX,XX @@ static void lm32_timer_realize(DeviceState *dev, Error **errp)
86
+ * result in a transaction error, or 0 for the transaction to RAZ/WI
67
{
87
+ * + Named GPIO input "irq_enable": set to 1 to enable interrupts
68
LM32TimerState *s = LM32_TIMER(dev);
88
+ * + Named GPIO input "irq_clear": set to 1 to clear a pending interrupt
69
89
+ * + Named GPIO output "irq": set for a transaction-failed interrupt
70
- s->bh = qemu_bh_new(timer_hit, s);
90
+ * + Property "NONSEC_MASK": if a bit is set in this mask then accesses to
71
- s->ptimer = ptimer_init_with_bh(s->bh, PTIMER_POLICY_DEFAULT);
91
+ * the associated port do not have the TZ security check performed. (This
72
+ s->ptimer = ptimer_init(timer_hit, s, PTIMER_POLICY_DEFAULT);
92
+ * corresponds to the hardware allowing this to be set as a Verilog
73
93
+ * parameter.)
74
+ ptimer_transaction_begin(s->ptimer);
94
+ */
75
ptimer_set_freq(s->ptimer, s->freq_hz);
95
+
76
+ ptimer_transaction_commit(s->ptimer);
96
+#ifndef TZ_PPC_H
77
}
97
+#define TZ_PPC_H
78
98
+
79
static const VMStateDescription vmstate_lm32_timer = {
99
+#include "hw/sysbus.h"
100
+
101
+#define TYPE_TZ_PPC "tz-ppc"
102
+#define TZ_PPC(obj) OBJECT_CHECK(TZPPC, (obj), TYPE_TZ_PPC)
103
+
104
+#define TZ_NUM_PORTS 16
105
+
106
+typedef struct TZPPC TZPPC;
107
+
108
+typedef struct TZPPCPort {
109
+ TZPPC *ppc;
110
+ MemoryRegion upstream;
111
+ AddressSpace downstream_as;
112
+ MemoryRegion *downstream;
113
+} TZPPCPort;
114
+
115
+struct TZPPC {
116
+ /*< private >*/
117
+ SysBusDevice parent_obj;
118
+
119
+ /*< public >*/
120
+
121
+ /* State: these just track the values of our input signals */
122
+ bool cfg_nonsec[TZ_NUM_PORTS];
123
+ bool cfg_ap[TZ_NUM_PORTS];
124
+ bool cfg_sec_resp;
125
+ bool irq_enable;
126
+ bool irq_clear;
127
+ /* State: are we asserting irq ? */
128
+ bool irq_status;
129
+
130
+ qemu_irq irq;
131
+
132
+ /* Properties */
133
+ uint32_t nonsec_mask;
134
+
135
+ TZPPCPort port[TZ_NUM_PORTS];
136
+};
137
+
138
+#endif
139
diff --git a/hw/misc/tz-ppc.c b/hw/misc/tz-ppc.c
140
new file mode 100644
141
index XXXXXXX..XXXXXXX
142
--- /dev/null
143
+++ b/hw/misc/tz-ppc.c
144
@@ -XXX,XX +XXX,XX @@
145
+/*
146
+ * ARM TrustZone peripheral protection controller emulation
147
+ *
148
+ * Copyright (c) 2018 Linaro Limited
149
+ * Written by Peter Maydell
150
+ *
151
+ * This program is free software; you can redistribute it and/or modify
152
+ * it under the terms of the GNU General Public License version 2 or
153
+ * (at your option) any later version.
154
+ */
155
+
156
+#include "qemu/osdep.h"
157
+#include "qemu/log.h"
158
+#include "qapi/error.h"
159
+#include "trace.h"
160
+#include "hw/sysbus.h"
161
+#include "hw/registerfields.h"
162
+#include "hw/misc/tz-ppc.h"
163
+
164
+static void tz_ppc_update_irq(TZPPC *s)
165
+{
166
+ bool level = s->irq_status && s->irq_enable;
167
+
168
+ trace_tz_ppc_update_irq(level);
169
+ qemu_set_irq(s->irq, level);
170
+}
171
+
172
+static void tz_ppc_cfg_nonsec(void *opaque, int n, int level)
173
+{
174
+ TZPPC *s = TZ_PPC(opaque);
175
+
176
+ assert(n < TZ_NUM_PORTS);
177
+ trace_tz_ppc_cfg_nonsec(n, level);
178
+ s->cfg_nonsec[n] = level;
179
+}
180
+
181
+static void tz_ppc_cfg_ap(void *opaque, int n, int level)
182
+{
183
+ TZPPC *s = TZ_PPC(opaque);
184
+
185
+ assert(n < TZ_NUM_PORTS);
186
+ trace_tz_ppc_cfg_ap(n, level);
187
+ s->cfg_ap[n] = level;
188
+}
189
+
190
+static void tz_ppc_cfg_sec_resp(void *opaque, int n, int level)
191
+{
192
+ TZPPC *s = TZ_PPC(opaque);
193
+
194
+ trace_tz_ppc_cfg_sec_resp(level);
195
+ s->cfg_sec_resp = level;
196
+}
197
+
198
+static void tz_ppc_irq_enable(void *opaque, int n, int level)
199
+{
200
+ TZPPC *s = TZ_PPC(opaque);
201
+
202
+ trace_tz_ppc_irq_enable(level);
203
+ s->irq_enable = level;
204
+ tz_ppc_update_irq(s);
205
+}
206
+
207
+static void tz_ppc_irq_clear(void *opaque, int n, int level)
208
+{
209
+ TZPPC *s = TZ_PPC(opaque);
210
+
211
+ trace_tz_ppc_irq_clear(level);
212
+
213
+ s->irq_clear = level;
214
+ if (level) {
215
+ s->irq_status = false;
216
+ tz_ppc_update_irq(s);
217
+ }
218
+}
219
+
220
+static bool tz_ppc_check(TZPPC *s, int n, MemTxAttrs attrs)
221
+{
222
+ /* Check whether to allow an access to port n; return true if
223
+ * the check passes, and false if the transaction must be blocked.
224
+ * If the latter, the caller must check cfg_sec_resp to determine
225
+ * whether to abort or RAZ/WI the transaction.
226
+ * The checks are:
227
+ * + nonsec_mask suppresses any check of the secure attribute
228
+ * + otherwise, block if cfg_nonsec is 1 and transaction is secure,
229
+ * or if cfg_nonsec is 0 and transaction is non-secure
230
+ * + block if transaction is usermode and cfg_ap is 0
231
+ */
232
+ if ((attrs.secure == s->cfg_nonsec[n] && !(s->nonsec_mask & (1 << n))) ||
233
+ (attrs.user && !s->cfg_ap[n])) {
234
+ /* Block the transaction. */
235
+ if (!s->irq_clear) {
236
+ /* Note that holding irq_clear high suppresses interrupts */
237
+ s->irq_status = true;
238
+ tz_ppc_update_irq(s);
239
+ }
240
+ return false;
241
+ }
242
+ return true;
243
+}
244
+
245
+static MemTxResult tz_ppc_read(void *opaque, hwaddr addr, uint64_t *pdata,
246
+ unsigned size, MemTxAttrs attrs)
247
+{
248
+ TZPPCPort *p = opaque;
249
+ TZPPC *s = p->ppc;
250
+ int n = p - s->port;
251
+ AddressSpace *as = &p->downstream_as;
252
+ uint64_t data;
253
+ MemTxResult res;
254
+
255
+ if (!tz_ppc_check(s, n, attrs)) {
256
+ trace_tz_ppc_read_blocked(n, addr, attrs.secure, attrs.user);
257
+ if (s->cfg_sec_resp) {
258
+ return MEMTX_ERROR;
259
+ } else {
260
+ *pdata = 0;
261
+ return MEMTX_OK;
262
+ }
263
+ }
264
+
265
+ switch (size) {
266
+ case 1:
267
+ data = address_space_ldub(as, addr, attrs, &res);
268
+ break;
269
+ case 2:
270
+ data = address_space_lduw_le(as, addr, attrs, &res);
271
+ break;
272
+ case 4:
273
+ data = address_space_ldl_le(as, addr, attrs, &res);
274
+ break;
275
+ case 8:
276
+ data = address_space_ldq_le(as, addr, attrs, &res);
277
+ break;
278
+ default:
279
+ g_assert_not_reached();
280
+ }
281
+ *pdata = data;
282
+ return res;
283
+}
284
+
285
+static MemTxResult tz_ppc_write(void *opaque, hwaddr addr, uint64_t val,
286
+ unsigned size, MemTxAttrs attrs)
287
+{
288
+ TZPPCPort *p = opaque;
289
+ TZPPC *s = p->ppc;
290
+ AddressSpace *as = &p->downstream_as;
291
+ int n = p - s->port;
292
+ MemTxResult res;
293
+
294
+ if (!tz_ppc_check(s, n, attrs)) {
295
+ trace_tz_ppc_write_blocked(n, addr, attrs.secure, attrs.user);
296
+ if (s->cfg_sec_resp) {
297
+ return MEMTX_ERROR;
298
+ } else {
299
+ return MEMTX_OK;
300
+ }
301
+ }
302
+
303
+ switch (size) {
304
+ case 1:
305
+ address_space_stb(as, addr, val, attrs, &res);
306
+ break;
307
+ case 2:
308
+ address_space_stw_le(as, addr, val, attrs, &res);
309
+ break;
310
+ case 4:
311
+ address_space_stl_le(as, addr, val, attrs, &res);
312
+ break;
313
+ case 8:
314
+ address_space_stq_le(as, addr, val, attrs, &res);
315
+ break;
316
+ default:
317
+ g_assert_not_reached();
318
+ }
319
+ return res;
320
+}
321
+
322
+static const MemoryRegionOps tz_ppc_ops = {
323
+ .read_with_attrs = tz_ppc_read,
324
+ .write_with_attrs = tz_ppc_write,
325
+ .endianness = DEVICE_LITTLE_ENDIAN,
326
+};
327
+
328
+static void tz_ppc_reset(DeviceState *dev)
329
+{
330
+ TZPPC *s = TZ_PPC(dev);
331
+
332
+ trace_tz_ppc_reset();
333
+ s->cfg_sec_resp = false;
334
+ memset(s->cfg_nonsec, 0, sizeof(s->cfg_nonsec));
335
+ memset(s->cfg_ap, 0, sizeof(s->cfg_ap));
336
+}
337
+
338
+static void tz_ppc_init(Object *obj)
339
+{
340
+ DeviceState *dev = DEVICE(obj);
341
+ TZPPC *s = TZ_PPC(obj);
342
+
343
+ qdev_init_gpio_in_named(dev, tz_ppc_cfg_nonsec, "cfg_nonsec", TZ_NUM_PORTS);
344
+ qdev_init_gpio_in_named(dev, tz_ppc_cfg_ap, "cfg_ap", TZ_NUM_PORTS);
345
+ qdev_init_gpio_in_named(dev, tz_ppc_cfg_sec_resp, "cfg_sec_resp", 1);
346
+ qdev_init_gpio_in_named(dev, tz_ppc_irq_enable, "irq_enable", 1);
347
+ qdev_init_gpio_in_named(dev, tz_ppc_irq_clear, "irq_clear", 1);
348
+ qdev_init_gpio_out_named(dev, &s->irq, "irq", 1);
349
+}
350
+
351
+static void tz_ppc_realize(DeviceState *dev, Error **errp)
352
+{
353
+ Object *obj = OBJECT(dev);
354
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
355
+ TZPPC *s = TZ_PPC(dev);
356
+ int i;
357
+
358
+ /* We can't create the upstream end of the port until realize,
359
+ * as we don't know the size of the MR used as the downstream until then.
360
+ */
361
+ for (i = 0; i < TZ_NUM_PORTS; i++) {
362
+ TZPPCPort *port = &s->port[i];
363
+ char *name;
364
+ uint64_t size;
365
+
366
+ if (!port->downstream) {
367
+ continue;
368
+ }
369
+
370
+ name = g_strdup_printf("tz-ppc-port[%d]", i);
371
+
372
+ port->ppc = s;
373
+ address_space_init(&port->downstream_as, port->downstream, name);
374
+
375
+ size = memory_region_size(port->downstream);
376
+ memory_region_init_io(&port->upstream, obj, &tz_ppc_ops,
377
+ port, name, size);
378
+ sysbus_init_mmio(sbd, &port->upstream);
379
+ g_free(name);
380
+ }
381
+}
382
+
383
+static const VMStateDescription tz_ppc_vmstate = {
384
+ .name = "tz-ppc",
385
+ .version_id = 1,
386
+ .minimum_version_id = 1,
387
+ .fields = (VMStateField[]) {
388
+ VMSTATE_BOOL_ARRAY(cfg_nonsec, TZPPC, 16),
389
+ VMSTATE_BOOL_ARRAY(cfg_ap, TZPPC, 16),
390
+ VMSTATE_BOOL(cfg_sec_resp, TZPPC),
391
+ VMSTATE_BOOL(irq_enable, TZPPC),
392
+ VMSTATE_BOOL(irq_clear, TZPPC),
393
+ VMSTATE_BOOL(irq_status, TZPPC),
394
+ VMSTATE_END_OF_LIST()
395
+ }
396
+};
397
+
398
+#define DEFINE_PORT(N) \
399
+ DEFINE_PROP_LINK("port[" #N "]", TZPPC, port[N].downstream, \
400
+ TYPE_MEMORY_REGION, MemoryRegion *)
401
+
402
+static Property tz_ppc_properties[] = {
403
+ DEFINE_PROP_UINT32("NONSEC_MASK", TZPPC, nonsec_mask, 0),
404
+ DEFINE_PORT(0),
405
+ DEFINE_PORT(1),
406
+ DEFINE_PORT(2),
407
+ DEFINE_PORT(3),
408
+ DEFINE_PORT(4),
409
+ DEFINE_PORT(5),
410
+ DEFINE_PORT(6),
411
+ DEFINE_PORT(7),
412
+ DEFINE_PORT(8),
413
+ DEFINE_PORT(9),
414
+ DEFINE_PORT(10),
415
+ DEFINE_PORT(11),
416
+ DEFINE_PORT(12),
417
+ DEFINE_PORT(13),
418
+ DEFINE_PORT(14),
419
+ DEFINE_PORT(15),
420
+ DEFINE_PROP_END_OF_LIST(),
421
+};
422
+
423
+static void tz_ppc_class_init(ObjectClass *klass, void *data)
424
+{
425
+ DeviceClass *dc = DEVICE_CLASS(klass);
426
+
427
+ dc->realize = tz_ppc_realize;
428
+ dc->vmsd = &tz_ppc_vmstate;
429
+ dc->reset = tz_ppc_reset;
430
+ dc->props = tz_ppc_properties;
431
+}
432
+
433
+static const TypeInfo tz_ppc_info = {
434
+ .name = TYPE_TZ_PPC,
435
+ .parent = TYPE_SYS_BUS_DEVICE,
436
+ .instance_size = sizeof(TZPPC),
437
+ .instance_init = tz_ppc_init,
438
+ .class_init = tz_ppc_class_init,
439
+};
440
+
441
+static void tz_ppc_register_types(void)
442
+{
443
+ type_register_static(&tz_ppc_info);
444
+}
445
+
446
+type_init(tz_ppc_register_types);
447
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
448
index XXXXXXX..XXXXXXX 100644
449
--- a/default-configs/arm-softmmu.mak
450
+++ b/default-configs/arm-softmmu.mak
451
@@ -XXX,XX +XXX,XX @@ CONFIG_CMSDK_APB_UART=y
452
CONFIG_MPS2_FPGAIO=y
453
CONFIG_MPS2_SCC=y
454
455
+CONFIG_TZ_PPC=y
456
+
457
CONFIG_VERSATILE_PCI=y
458
CONFIG_VERSATILE_I2C=y
459
460
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
461
index XXXXXXX..XXXXXXX 100644
462
--- a/hw/misc/trace-events
463
+++ b/hw/misc/trace-events
464
@@ -XXX,XX +XXX,XX @@ mos6522_get_next_irq_time(uint16_t latch, int64_t d, int64_t delta) "latch=%d co
465
mos6522_set_sr_int(void) "set sr_int"
466
mos6522_write(uint64_t addr, uint64_t val) "reg=0x%"PRIx64 " val=0x%"PRIx64
467
mos6522_read(uint64_t addr, unsigned val) "reg=0x%"PRIx64 " val=0x%x"
468
+
469
+# hw/misc/tz-ppc.c
470
+tz_ppc_reset(void) "TZ PPC: reset"
471
+tz_ppc_cfg_nonsec(int n, int level) "TZ PPC: cfg_nonsec[%d] = %d"
472
+tz_ppc_cfg_ap(int n, int level) "TZ PPC: cfg_ap[%d] = %d"
473
+tz_ppc_cfg_sec_resp(int level) "TZ PPC: cfg_sec_resp = %d"
474
+tz_ppc_irq_enable(int level) "TZ PPC: int_enable = %d"
475
+tz_ppc_irq_clear(int level) "TZ PPC: int_clear = %d"
476
+tz_ppc_update_irq(int level) "TZ PPC: setting irq line to %d"
477
+tz_ppc_read_blocked(int n, hwaddr offset, bool secure, bool user) "TZ PPC: port %d offset 0x%" HWADDR_PRIx " read (secure %d user %d) blocked"
478
+tz_ppc_write_blocked(int n, hwaddr offset, bool secure, bool user) "TZ PPC: port %d offset 0x%" HWADDR_PRIx " write (secure %d user %d) blocked"
479
--
80
--
480
2.16.2
81
2.20.1
481
82
482
83
diff view generated by jsdifflib
1
In v8M, the Implementation Defined Attribution Unit (IDAU) is
1
Switch the altera_timer code away from bottom-half based ptimers to
2
a small piece of hardware typically implemented in the SoC
2
the new transaction-based ptimer API. This just requires adding
3
which provides board or SoC specific security attribution
3
begin/commit calls around the various places that modify the ptimer
4
information for each address that the CPU performs MPU/SAU
4
state, and using the new ptimer_init() function to create the timer.
5
checks on. For QEMU, we model this with a QOM interface which
6
is implemented by the board or SoC object and connected to
7
the CPU using a link property.
8
9
This commit defines the new interface class, adds the link
10
property to the CPU object, and makes the SAU checking
11
code call the IDAU interface if one is present.
12
5
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20180220180325.29818-5-peter.maydell@linaro.org
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Message-id: 20191017132905.5604-6-peter.maydell@linaro.org
16
---
10
---
17
target/arm/cpu.h | 3 +++
11
hw/timer/altera_timer.c | 13 +++++++++----
18
target/arm/idau.h | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++
12
1 file changed, 9 insertions(+), 4 deletions(-)
19
target/arm/cpu.c | 15 +++++++++++++
20
target/arm/helper.c | 28 +++++++++++++++++++++---
21
4 files changed, 104 insertions(+), 3 deletions(-)
22
create mode 100644 target/arm/idau.h
23
13
24
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
diff --git a/hw/timer/altera_timer.c b/hw/timer/altera_timer.c
25
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/cpu.h
16
--- a/hw/timer/altera_timer.c
27
+++ b/target/arm/cpu.h
17
+++ b/hw/timer/altera_timer.c
28
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
29
/* MemoryRegion to use for secure physical accesses */
30
MemoryRegion *secure_memory;
31
32
+ /* For v8M, pointer to the IDAU interface provided by board/SoC */
33
+ Object *idau;
34
+
35
/* 'compatible' string for this CPU for Linux device trees */
36
const char *dtb_compatible;
37
38
diff --git a/target/arm/idau.h b/target/arm/idau.h
39
new file mode 100644
40
index XXXXXXX..XXXXXXX
41
--- /dev/null
42
+++ b/target/arm/idau.h
43
@@ -XXX,XX +XXX,XX @@
44
+/*
45
+ * QEMU ARM CPU -- interface for the Arm v8M IDAU
46
+ *
47
+ * Copyright (c) 2018 Linaro Ltd
48
+ *
49
+ * This program is free software; you can redistribute it and/or
50
+ * modify it under the terms of the GNU General Public License
51
+ * as published by the Free Software Foundation; either version 2
52
+ * of the License, or (at your option) any later version.
53
+ *
54
+ * This program is distributed in the hope that it will be useful,
55
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
56
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
57
+ * GNU General Public License for more details.
58
+ *
59
+ * You should have received a copy of the GNU General Public License
60
+ * along with this program; if not, see
61
+ * <http://www.gnu.org/licenses/gpl-2.0.html>
62
+ *
63
+ * In the v8M architecture, the IDAU is a small piece of hardware
64
+ * typically implemented in the SoC which provides board or SoC
65
+ * specific security attribution information for each address that
66
+ * the CPU performs MPU/SAU checks on. For QEMU, we model this with a
67
+ * QOM interface which is implemented by the board or SoC object and
68
+ * connected to the CPU using a link property.
69
+ */
70
+
71
+#ifndef TARGET_ARM_IDAU_H
72
+#define TARGET_ARM_IDAU_H
73
+
74
+#include "qom/object.h"
75
+
76
+#define TYPE_IDAU_INTERFACE "idau-interface"
77
+#define IDAU_INTERFACE(obj) \
78
+ INTERFACE_CHECK(IDAUInterface, (obj), TYPE_IDAU_INTERFACE)
79
+#define IDAU_INTERFACE_CLASS(class) \
80
+ OBJECT_CLASS_CHECK(IDAUInterfaceClass, (class), TYPE_IDAU_INTERFACE)
81
+#define IDAU_INTERFACE_GET_CLASS(obj) \
82
+ OBJECT_GET_CLASS(IDAUInterfaceClass, (obj), TYPE_IDAU_INTERFACE)
83
+
84
+typedef struct IDAUInterface {
85
+ Object parent;
86
+} IDAUInterface;
87
+
88
+#define IREGION_NOTVALID -1
89
+
90
+typedef struct IDAUInterfaceClass {
91
+ InterfaceClass parent;
92
+
93
+ /* Check the specified address and return the IDAU security information
94
+ * for it by filling in iregion, exempt, ns and nsc:
95
+ * iregion: IDAU region number, or IREGION_NOTVALID if not valid
96
+ * exempt: true if address is exempt from security attribution
97
+ * ns: true if the address is NonSecure
98
+ * nsc: true if the address is NonSecure-callable
99
+ */
100
+ void (*check)(IDAUInterface *ii, uint32_t address, int *iregion,
101
+ bool *exempt, bool *ns, bool *nsc);
102
+} IDAUInterfaceClass;
103
+
104
+#endif
105
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
106
index XXXXXXX..XXXXXXX 100644
107
--- a/target/arm/cpu.c
108
+++ b/target/arm/cpu.c
109
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@
110
*/
19
*/
111
20
112
#include "qemu/osdep.h"
21
#include "qemu/osdep.h"
113
+#include "target/arm/idau.h"
22
-#include "qemu/main-loop.h"
114
#include "qemu/error-report.h"
23
#include "qemu/module.h"
115
#include "qapi/error.h"
24
#include "qapi/error.h"
116
#include "cpu.h"
25
117
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_post_init(Object *obj)
26
@@ -XXX,XX +XXX,XX @@ typedef struct AlteraTimer {
27
MemoryRegion mmio;
28
qemu_irq irq;
29
uint32_t freq_hz;
30
- QEMUBH *bh;
31
ptimer_state *ptimer;
32
uint32_t regs[R_MAX];
33
} AlteraTimer;
34
@@ -XXX,XX +XXX,XX @@ static void timer_write(void *opaque, hwaddr addr,
35
break;
36
37
case R_CONTROL:
38
+ ptimer_transaction_begin(t->ptimer);
39
t->regs[R_CONTROL] = value & (CONTROL_ITO | CONTROL_CONT);
40
if ((value & CONTROL_START) &&
41
!(t->regs[R_STATUS] & STATUS_RUN)) {
42
@@ -XXX,XX +XXX,XX @@ static void timer_write(void *opaque, hwaddr addr,
43
ptimer_stop(t->ptimer);
44
t->regs[R_STATUS] &= ~STATUS_RUN;
118
}
45
}
119
}
46
+ ptimer_transaction_commit(t->ptimer);
120
47
break;
121
+ if (arm_feature(&cpu->env, ARM_FEATURE_M_SECURITY)) {
48
122
+ object_property_add_link(obj, "idau", TYPE_IDAU_INTERFACE, &cpu->idau,
49
case R_PERIODL:
123
+ qdev_prop_allow_set_link_before_realize,
50
case R_PERIODH:
124
+ OBJ_PROP_LINK_UNREF_ON_RELEASE,
51
+ ptimer_transaction_begin(t->ptimer);
125
+ &error_abort);
52
t->regs[addr] = value & 0xFFFF;
126
+ }
53
if (t->regs[R_STATUS] & STATUS_RUN) {
127
+
54
ptimer_stop(t->ptimer);
128
qdev_property_add_static(DEVICE(obj), &arm_cpu_cfgend_property,
55
@@ -XXX,XX +XXX,XX @@ static void timer_write(void *opaque, hwaddr addr,
129
&error_abort);
56
}
130
}
57
tvalue = (t->regs[R_PERIODH] << 16) | t->regs[R_PERIODL];
131
@@ -XXX,XX +XXX,XX @@ static const TypeInfo arm_cpu_type_info = {
58
ptimer_set_limit(t->ptimer, tvalue + 1, 1);
132
.class_init = arm_cpu_class_init,
59
+ ptimer_transaction_commit(t->ptimer);
133
};
60
break;
134
61
135
+static const TypeInfo idau_interface_type_info = {
62
case R_SNAPL:
136
+ .name = TYPE_IDAU_INTERFACE,
63
@@ -XXX,XX +XXX,XX @@ static void altera_timer_realize(DeviceState *dev, Error **errp)
137
+ .parent = TYPE_INTERFACE,
138
+ .class_size = sizeof(IDAUInterfaceClass),
139
+};
140
+
141
static void arm_cpu_register_types(void)
142
{
143
const ARMCPUInfo *info = arm_cpus;
144
145
type_register_static(&arm_cpu_type_info);
146
+ type_register_static(&idau_interface_type_info);
147
148
while (info->name) {
149
cpu_register(info);
150
diff --git a/target/arm/helper.c b/target/arm/helper.c
151
index XXXXXXX..XXXXXXX 100644
152
--- a/target/arm/helper.c
153
+++ b/target/arm/helper.c
154
@@ -XXX,XX +XXX,XX @@
155
#include "qemu/osdep.h"
156
+#include "target/arm/idau.h"
157
#include "trace.h"
158
#include "cpu.h"
159
#include "internals.h"
160
@@ -XXX,XX +XXX,XX @@ static void v8m_security_lookup(CPUARMState *env, uint32_t address,
161
*/
162
ARMCPU *cpu = arm_env_get_cpu(env);
163
int r;
164
+ bool idau_exempt = false, idau_ns = true, idau_nsc = true;
165
+ int idau_region = IREGION_NOTVALID;
166
167
- /* TODO: implement IDAU */
168
+ if (cpu->idau) {
169
+ IDAUInterfaceClass *iic = IDAU_INTERFACE_GET_CLASS(cpu->idau);
170
+ IDAUInterface *ii = IDAU_INTERFACE(cpu->idau);
171
+
172
+ iic->check(ii, address, &idau_region, &idau_exempt, &idau_ns,
173
+ &idau_nsc);
174
+ }
175
176
if (access_type == MMU_INST_FETCH && extract32(address, 28, 4) == 0xf) {
177
/* 0xf0000000..0xffffffff is always S for insn fetches */
178
return;
64
return;
179
}
65
}
180
66
181
- if (v8m_is_sau_exempt(env, address, access_type)) {
67
- t->bh = qemu_bh_new(timer_hit, t);
182
+ if (idau_exempt || v8m_is_sau_exempt(env, address, access_type)) {
68
- t->ptimer = ptimer_init_with_bh(t->bh, PTIMER_POLICY_DEFAULT);
183
sattrs->ns = !regime_is_secure(env, mmu_idx);
69
+ t->ptimer = ptimer_init(timer_hit, t, PTIMER_POLICY_DEFAULT);
184
return;
70
+ ptimer_transaction_begin(t->ptimer);
185
}
71
ptimer_set_freq(t->ptimer, t->freq_hz);
186
72
+ ptimer_transaction_commit(t->ptimer);
187
+ if (idau_region != IREGION_NOTVALID) {
73
188
+ sattrs->irvalid = true;
74
memory_region_init_io(&t->mmio, OBJECT(t), &timer_ops, t,
189
+ sattrs->iregion = idau_region;
75
TYPE_ALTERA_TIMER, R_MAX * sizeof(uint32_t));
190
+ }
76
@@ -XXX,XX +XXX,XX @@ static void altera_timer_reset(DeviceState *dev)
191
+
77
{
192
switch (env->sau.ctrl & 3) {
78
AlteraTimer *t = ALTERA_TIMER(dev);
193
case 0: /* SAU.ENABLE == 0, SAU.ALLNS == 0 */
79
194
break;
80
+ ptimer_transaction_begin(t->ptimer);
195
@@ -XXX,XX +XXX,XX @@ static void v8m_security_lookup(CPUARMState *env, uint32_t address,
81
ptimer_stop(t->ptimer);
196
}
82
ptimer_set_limit(t->ptimer, 0xffffffff, 1);
197
}
83
+ ptimer_transaction_commit(t->ptimer);
198
84
memset(t->regs, 0, sizeof(t->regs));
199
- /* TODO when we support the IDAU then it may override the result here */
200
+ /* The IDAU will override the SAU lookup results if it specifies
201
+ * higher security than the SAU does.
202
+ */
203
+ if (!idau_ns) {
204
+ if (sattrs->ns || (!idau_nsc && sattrs->nsc)) {
205
+ sattrs->ns = false;
206
+ sattrs->nsc = idau_nsc;
207
+ }
208
+ }
209
break;
210
}
211
}
85
}
86
212
--
87
--
213
2.16.2
88
2.20.1
214
89
215
90
diff view generated by jsdifflib
1
Add a Cortex-M33 definition. The M33 is an M profile CPU
1
Switch the etraxfs_timer code away from bottom-half based ptimers to
2
which implements the ARM v8M architecture, including the
2
the new transaction-based ptimer API. This just requires adding
3
M profile Security Extension.
3
begin/commit calls around the various places that modify the ptimer
4
state, and using the new ptimer_init() function to create the timer.
4
5
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180220180325.29818-9-peter.maydell@linaro.org
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Message-id: 20191017132905.5604-7-peter.maydell@linaro.org
8
---
10
---
9
target/arm/cpu.c | 31 +++++++++++++++++++++++++++++++
11
hw/timer/etraxfs_timer.c | 23 +++++++++++++----------
10
1 file changed, 31 insertions(+)
12
1 file changed, 13 insertions(+), 10 deletions(-)
11
13
12
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
14
diff --git a/hw/timer/etraxfs_timer.c b/hw/timer/etraxfs_timer.c
13
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/cpu.c
16
--- a/hw/timer/etraxfs_timer.c
15
+++ b/target/arm/cpu.c
17
+++ b/hw/timer/etraxfs_timer.c
16
@@ -XXX,XX +XXX,XX @@ static void cortex_m4_initfn(Object *obj)
18
@@ -XXX,XX +XXX,XX @@
17
cpu->id_isar5 = 0x00000000;
19
#include "hw/sysbus.h"
20
#include "sysemu/reset.h"
21
#include "sysemu/runstate.h"
22
-#include "qemu/main-loop.h"
23
#include "qemu/module.h"
24
#include "qemu/timer.h"
25
#include "hw/irq.h"
26
@@ -XXX,XX +XXX,XX @@ typedef struct ETRAXTimerState {
27
qemu_irq irq;
28
qemu_irq nmi;
29
30
- QEMUBH *bh_t0;
31
- QEMUBH *bh_t1;
32
- QEMUBH *bh_wd;
33
ptimer_state *ptimer_t0;
34
ptimer_state *ptimer_t1;
35
ptimer_state *ptimer_wd;
36
@@ -XXX,XX +XXX,XX @@ static void update_ctrl(ETRAXTimerState *t, int tnum)
37
}
38
39
D(printf ("freq_hz=%d div=%d\n", freq_hz, div));
40
+ ptimer_transaction_begin(timer);
41
ptimer_set_freq(timer, freq_hz);
42
ptimer_set_limit(timer, div, 0);
43
44
@@ -XXX,XX +XXX,XX @@ static void update_ctrl(ETRAXTimerState *t, int tnum)
45
abort();
46
break;
47
}
48
+ ptimer_transaction_commit(timer);
18
}
49
}
19
50
20
+static void cortex_m33_initfn(Object *obj)
51
static void timer_update_irq(ETRAXTimerState *t)
21
+{
52
@@ -XXX,XX +XXX,XX @@ static inline void timer_watchdog_update(ETRAXTimerState *t, uint32_t value)
22
+ ARMCPU *cpu = ARM_CPU(obj);
53
23
+
54
t->wd_hits = 0;
24
+ set_feature(&cpu->env, ARM_FEATURE_V8);
55
25
+ set_feature(&cpu->env, ARM_FEATURE_M);
56
+ ptimer_transaction_begin(t->ptimer_wd);
26
+ set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
57
ptimer_set_freq(t->ptimer_wd, 760);
27
+ set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
58
if (wd_cnt == 0)
28
+ cpu->midr = 0x410fd213; /* r0p3 */
59
wd_cnt = 256;
29
+ cpu->pmsav7_dregion = 16;
60
@@ -XXX,XX +XXX,XX @@ static inline void timer_watchdog_update(ETRAXTimerState *t, uint32_t value)
30
+ cpu->sau_sregion = 8;
61
ptimer_stop(t->ptimer_wd);
31
+ cpu->id_pfr0 = 0x00000030;
62
32
+ cpu->id_pfr1 = 0x00000210;
63
t->rw_wd_ctrl = value;
33
+ cpu->id_dfr0 = 0x00200000;
64
+ ptimer_transaction_commit(t->ptimer_wd);
34
+ cpu->id_afr0 = 0x00000000;
65
}
35
+ cpu->id_mmfr0 = 0x00101F40;
66
36
+ cpu->id_mmfr1 = 0x00000000;
67
static void
37
+ cpu->id_mmfr2 = 0x01000000;
68
@@ -XXX,XX +XXX,XX @@ static void etraxfs_timer_reset(void *opaque)
38
+ cpu->id_mmfr3 = 0x00000000;
39
+ cpu->id_isar0 = 0x01101110;
40
+ cpu->id_isar1 = 0x02212000;
41
+ cpu->id_isar2 = 0x20232232;
42
+ cpu->id_isar3 = 0x01111131;
43
+ cpu->id_isar4 = 0x01310132;
44
+ cpu->id_isar5 = 0x00000000;
45
+ cpu->clidr = 0x00000000;
46
+ cpu->ctr = 0x8000c000;
47
+}
48
+
49
static void arm_v7m_class_init(ObjectClass *oc, void *data)
50
{
69
{
51
CPUClass *cc = CPU_CLASS(oc);
70
ETRAXTimerState *t = opaque;
52
@@ -XXX,XX +XXX,XX @@ static const ARMCPUInfo arm_cpus[] = {
71
53
.class_init = arm_v7m_class_init },
72
+ ptimer_transaction_begin(t->ptimer_t0);
54
{ .name = "cortex-m4", .initfn = cortex_m4_initfn,
73
ptimer_stop(t->ptimer_t0);
55
.class_init = arm_v7m_class_init },
74
+ ptimer_transaction_commit(t->ptimer_t0);
56
+ { .name = "cortex-m33", .initfn = cortex_m33_initfn,
75
+ ptimer_transaction_begin(t->ptimer_t1);
57
+ .class_init = arm_v7m_class_init },
76
ptimer_stop(t->ptimer_t1);
58
{ .name = "cortex-r5", .initfn = cortex_r5_initfn },
77
+ ptimer_transaction_commit(t->ptimer_t1);
59
{ .name = "cortex-a7", .initfn = cortex_a7_initfn },
78
+ ptimer_transaction_begin(t->ptimer_wd);
60
{ .name = "cortex-a8", .initfn = cortex_a8_initfn },
79
ptimer_stop(t->ptimer_wd);
80
+ ptimer_transaction_commit(t->ptimer_wd);
81
t->rw_wd_ctrl = 0;
82
t->r_intr = 0;
83
t->rw_intr_mask = 0;
84
@@ -XXX,XX +XXX,XX @@ static void etraxfs_timer_realize(DeviceState *dev, Error **errp)
85
ETRAXTimerState *t = ETRAX_TIMER(dev);
86
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
87
88
- t->bh_t0 = qemu_bh_new(timer0_hit, t);
89
- t->bh_t1 = qemu_bh_new(timer1_hit, t);
90
- t->bh_wd = qemu_bh_new(watchdog_hit, t);
91
- t->ptimer_t0 = ptimer_init_with_bh(t->bh_t0, PTIMER_POLICY_DEFAULT);
92
- t->ptimer_t1 = ptimer_init_with_bh(t->bh_t1, PTIMER_POLICY_DEFAULT);
93
- t->ptimer_wd = ptimer_init_with_bh(t->bh_wd, PTIMER_POLICY_DEFAULT);
94
+ t->ptimer_t0 = ptimer_init(timer0_hit, t, PTIMER_POLICY_DEFAULT);
95
+ t->ptimer_t1 = ptimer_init(timer1_hit, t, PTIMER_POLICY_DEFAULT);
96
+ t->ptimer_wd = ptimer_init(watchdog_hit, t, PTIMER_POLICY_DEFAULT);
97
98
sysbus_init_irq(sbd, &t->irq);
99
sysbus_init_irq(sbd, &t->nmi);
61
--
100
--
62
2.16.2
101
2.20.1
63
102
64
103
diff view generated by jsdifflib
1
In some board or SoC models it is necessary to split a qemu_irq line
1
Switch the mcf5208 code away from bottom-half based ptimers to
2
so that one input can feed multiple outputs. We currently have
2
the new transaction-based ptimer API. This just requires adding
3
qemu_irq_split() for this, but that has several deficiencies:
3
begin/commit calls around the various places that modify the ptimer
4
* it can only handle splitting a line into two
4
state, and using the new ptimer_init() function to create the timer.
5
* it unavoidably leaks memory, so it can't be used
6
in a device that can be deleted
7
8
Implement a qdev device that encapsulates splitting of IRQs, with a
9
configurable number of outputs. (This is in some ways the inverse of
10
the TYPE_OR_IRQ device.)
11
5
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20180220180325.29818-13-peter.maydell@linaro.org
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Tested-by: Thomas Huth <huth@tuxfamily.org>
10
Message-id: 20191017132905.5604-9-peter.maydell@linaro.org
15
---
11
---
16
hw/core/Makefile.objs | 1 +
12
hw/m68k/mcf5208.c | 9 +++++----
17
include/hw/core/split-irq.h | 57 +++++++++++++++++++++++++++++
13
1 file changed, 5 insertions(+), 4 deletions(-)
18
include/hw/irq.h | 4 +-
19
hw/core/split-irq.c | 89 +++++++++++++++++++++++++++++++++++++++++++++
20
4 files changed, 150 insertions(+), 1 deletion(-)
21
create mode 100644 include/hw/core/split-irq.h
22
create mode 100644 hw/core/split-irq.c
23
14
24
diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs
15
diff --git a/hw/m68k/mcf5208.c b/hw/m68k/mcf5208.c
25
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/core/Makefile.objs
17
--- a/hw/m68k/mcf5208.c
27
+++ b/hw/core/Makefile.objs
18
+++ b/hw/m68k/mcf5208.c
28
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_FITLOADER) += loader-fit.o
29
common-obj-$(CONFIG_SOFTMMU) += qdev-properties-system.o
30
common-obj-$(CONFIG_SOFTMMU) += register.o
31
common-obj-$(CONFIG_SOFTMMU) += or-irq.o
32
+common-obj-$(CONFIG_SOFTMMU) += split-irq.o
33
common-obj-$(CONFIG_PLATFORM_BUS) += platform-bus.o
34
35
obj-$(CONFIG_SOFTMMU) += generic-loader.o
36
diff --git a/include/hw/core/split-irq.h b/include/hw/core/split-irq.h
37
new file mode 100644
38
index XXXXXXX..XXXXXXX
39
--- /dev/null
40
+++ b/include/hw/core/split-irq.h
41
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@
42
+/*
20
#include "qemu/osdep.h"
43
+ * IRQ splitter device.
21
#include "qemu/units.h"
44
+ *
22
#include "qemu/error-report.h"
45
+ * Copyright (c) 2018 Linaro Limited.
23
-#include "qemu/main-loop.h"
46
+ * Written by Peter Maydell
24
#include "qapi/error.h"
47
+ *
25
#include "qemu-common.h"
48
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
26
#include "cpu.h"
49
+ * of this software and associated documentation files (the "Software"), to deal
27
@@ -XXX,XX +XXX,XX @@ static void m5208_timer_write(void *opaque, hwaddr offset,
50
+ * in the Software without restriction, including without limitation the rights
28
return;
51
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
29
}
52
+ * copies of the Software, and to permit persons to whom the Software is
30
53
+ * furnished to do so, subject to the following conditions:
31
+ ptimer_transaction_begin(s->timer);
54
+ *
32
if (s->pcsr & PCSR_EN)
55
+ * The above copyright notice and this permission notice shall be included in
33
ptimer_stop(s->timer);
56
+ * all copies or substantial portions of the Software.
34
57
+ *
35
@@ -XXX,XX +XXX,XX @@ static void m5208_timer_write(void *opaque, hwaddr offset,
58
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
36
59
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
37
if (s->pcsr & PCSR_EN)
60
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
38
ptimer_run(s->timer, 0);
61
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
39
+ ptimer_transaction_commit(s->timer);
62
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
40
break;
63
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
41
case 2:
64
+ * THE SOFTWARE.
42
+ ptimer_transaction_begin(s->timer);
65
+ */
43
s->pmr = value;
66
+
44
s->pcsr &= ~PCSR_PIF;
67
+/* This is a simple device which has one GPIO input line and multiple
45
if ((s->pcsr & PCSR_RLD) == 0) {
68
+ * GPIO output lines. Any change on the input line is forwarded to all
46
@@ -XXX,XX +XXX,XX @@ static void m5208_timer_write(void *opaque, hwaddr offset,
69
+ * of the outputs.
47
} else {
70
+ *
48
ptimer_set_limit(s->timer, value, s->pcsr & PCSR_OVW);
71
+ * QEMU interface:
49
}
72
+ * + one unnamed GPIO input: the input line
50
+ ptimer_transaction_commit(s->timer);
73
+ * + N unnamed GPIO outputs: the output lines
51
break;
74
+ * + QOM property "num-lines": sets the number of output lines
52
case 4:
75
+ */
53
break;
76
+#ifndef HW_SPLIT_IRQ_H
54
@@ -XXX,XX +XXX,XX @@ static void mcf5208_sys_init(MemoryRegion *address_space, qemu_irq *pic)
77
+#define HW_SPLIT_IRQ_H
55
{
78
+
56
MemoryRegion *iomem = g_new(MemoryRegion, 1);
79
+#include "hw/irq.h"
57
m5208_timer_state *s;
80
+#include "hw/sysbus.h"
58
- QEMUBH *bh;
81
+#include "qom/object.h"
59
int i;
82
+
60
83
+#define TYPE_SPLIT_IRQ "split-irq"
61
/* SDRAMC. */
84
+
62
@@ -XXX,XX +XXX,XX @@ static void mcf5208_sys_init(MemoryRegion *address_space, qemu_irq *pic)
85
+#define MAX_SPLIT_LINES 16
63
/* Timers. */
86
+
64
for (i = 0; i < 2; i++) {
87
+typedef struct SplitIRQ SplitIRQ;
65
s = g_new0(m5208_timer_state, 1);
88
+
66
- bh = qemu_bh_new(m5208_timer_trigger, s);
89
+#define SPLIT_IRQ(obj) OBJECT_CHECK(SplitIRQ, (obj), TYPE_SPLIT_IRQ)
67
- s->timer = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
90
+
68
+ s->timer = ptimer_init(m5208_timer_trigger, s, PTIMER_POLICY_DEFAULT);
91
+struct SplitIRQ {
69
memory_region_init_io(&s->iomem, NULL, &m5208_timer_ops, s,
92
+ DeviceState parent_obj;
70
"m5208-timer", 0x00004000);
93
+
71
memory_region_add_subregion(address_space, 0xfc080000 + 0x4000 * i,
94
+ qemu_irq out_irq[MAX_SPLIT_LINES];
95
+ uint16_t num_lines;
96
+};
97
+
98
+#endif
99
diff --git a/include/hw/irq.h b/include/hw/irq.h
100
index XXXXXXX..XXXXXXX 100644
101
--- a/include/hw/irq.h
102
+++ b/include/hw/irq.h
103
@@ -XXX,XX +XXX,XX @@ void qemu_free_irq(qemu_irq irq);
104
/* Returns a new IRQ with opposite polarity. */
105
qemu_irq qemu_irq_invert(qemu_irq irq);
106
107
-/* Returns a new IRQ which feeds into both the passed IRQs */
108
+/* Returns a new IRQ which feeds into both the passed IRQs.
109
+ * It's probably better to use the TYPE_SPLIT_IRQ device instead.
110
+ */
111
qemu_irq qemu_irq_split(qemu_irq irq1, qemu_irq irq2);
112
113
/* Returns a new IRQ set which connects 1:1 to another IRQ set, which
114
diff --git a/hw/core/split-irq.c b/hw/core/split-irq.c
115
new file mode 100644
116
index XXXXXXX..XXXXXXX
117
--- /dev/null
118
+++ b/hw/core/split-irq.c
119
@@ -XXX,XX +XXX,XX @@
120
+/*
121
+ * IRQ splitter device.
122
+ *
123
+ * Copyright (c) 2018 Linaro Limited.
124
+ * Written by Peter Maydell
125
+ *
126
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
127
+ * of this software and associated documentation files (the "Software"), to deal
128
+ * in the Software without restriction, including without limitation the rights
129
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
130
+ * copies of the Software, and to permit persons to whom the Software is
131
+ * furnished to do so, subject to the following conditions:
132
+ *
133
+ * The above copyright notice and this permission notice shall be included in
134
+ * all copies or substantial portions of the Software.
135
+ *
136
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
137
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
138
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
139
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
140
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
141
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
142
+ * THE SOFTWARE.
143
+ */
144
+
145
+#include "qemu/osdep.h"
146
+#include "hw/core/split-irq.h"
147
+#include "qapi/error.h"
148
+
149
+static void split_irq_handler(void *opaque, int n, int level)
150
+{
151
+ SplitIRQ *s = SPLIT_IRQ(opaque);
152
+ int i;
153
+
154
+ for (i = 0; i < s->num_lines; i++) {
155
+ qemu_set_irq(s->out_irq[i], level);
156
+ }
157
+}
158
+
159
+static void split_irq_init(Object *obj)
160
+{
161
+ qdev_init_gpio_in(DEVICE(obj), split_irq_handler, 1);
162
+}
163
+
164
+static void split_irq_realize(DeviceState *dev, Error **errp)
165
+{
166
+ SplitIRQ *s = SPLIT_IRQ(dev);
167
+
168
+ if (s->num_lines < 1 || s->num_lines >= MAX_SPLIT_LINES) {
169
+ error_setg(errp,
170
+ "IRQ splitter number of lines %d is not between 1 and %d",
171
+ s->num_lines, MAX_SPLIT_LINES);
172
+ return;
173
+ }
174
+
175
+ qdev_init_gpio_out(dev, s->out_irq, s->num_lines);
176
+}
177
+
178
+static Property split_irq_properties[] = {
179
+ DEFINE_PROP_UINT16("num-lines", SplitIRQ, num_lines, 1),
180
+ DEFINE_PROP_END_OF_LIST(),
181
+};
182
+
183
+static void split_irq_class_init(ObjectClass *klass, void *data)
184
+{
185
+ DeviceClass *dc = DEVICE_CLASS(klass);
186
+
187
+ /* No state to reset or migrate */
188
+ dc->props = split_irq_properties;
189
+ dc->realize = split_irq_realize;
190
+
191
+ /* Reason: Needs to be wired up to work */
192
+ dc->user_creatable = false;
193
+}
194
+
195
+static const TypeInfo split_irq_type_info = {
196
+ .name = TYPE_SPLIT_IRQ,
197
+ .parent = TYPE_DEVICE,
198
+ .instance_size = sizeof(SplitIRQ),
199
+ .instance_init = split_irq_init,
200
+ .class_init = split_irq_class_init,
201
+};
202
+
203
+static void split_irq_register_types(void)
204
+{
205
+ type_register_static(&split_irq_type_info);
206
+}
207
+
208
+type_init(split_irq_register_types)
209
--
72
--
210
2.16.2
73
2.20.1
211
74
212
75
diff view generated by jsdifflib
1
Instead of loading kernels, device trees, and the like to
1
From: Richard Henderson <richard.henderson@linaro.org>
2
the system address space, use the CPU's address space. This
3
is important if we're trying to load the file to memory or
4
via an alias memory region that is provided by an SoC
5
object and thus not mapped into the system address space.
6
2
3
Create a function to compute the values of the TBFLAG_ANY bits
4
that will be cached. For now, the env->hflags variable is not
5
used, and the results are fed back to cpu_get_tb_cpu_state.
6
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20191018174431.1784-2-richard.henderson@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20180220180325.29818-3-peter.maydell@linaro.org
11
---
11
---
12
hw/arm/boot.c | 119 +++++++++++++++++++++++++++++++++++++---------------------
12
target/arm/cpu.h | 29 ++++++++++++++++++-----------
13
1 file changed, 76 insertions(+), 43 deletions(-)
13
target/arm/helper.c | 26 +++++++++++++++++++-------
14
2 files changed, 37 insertions(+), 18 deletions(-)
14
15
15
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/boot.c
18
--- a/target/arm/cpu.h
18
+++ b/hw/arm/boot.c
19
+++ b/target/arm/cpu.h
19
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
20
#define ARM64_TEXT_OFFSET_OFFSET 8
21
uint32_t pstate;
21
#define ARM64_MAGIC_OFFSET 56
22
uint32_t aarch64; /* 1 if CPU is in aarch64 state; inverse of PSTATE.nRW */
22
23
23
+static AddressSpace *arm_boot_address_space(ARMCPU *cpu,
24
+ /* Cached TBFLAGS state. See below for which bits are included. */
24
+ const struct arm_boot_info *info)
25
+ uint32_t hflags;
26
+
27
/* Frequently accessed CPSR bits are stored separately for efficiency.
28
This contains all the other bits. Use cpsr_{read,write} to access
29
the whole CPSR. */
30
@@ -XXX,XX +XXX,XX @@ typedef ARMCPU ArchCPU;
31
32
#include "exec/cpu-all.h"
33
34
-/* Bit usage in the TB flags field: bit 31 indicates whether we are
35
+/*
36
+ * Bit usage in the TB flags field: bit 31 indicates whether we are
37
* in 32 or 64 bit mode. The meaning of the other bits depends on that.
38
* We put flags which are shared between 32 and 64 bit mode at the top
39
* of the word, and flags which apply to only one mode at the bottom.
40
+ *
41
+ * Unless otherwise noted, these bits are cached in env->hflags.
42
*/
43
FIELD(TBFLAG_ANY, AARCH64_STATE, 31, 1)
44
FIELD(TBFLAG_ANY, MMUIDX, 28, 3)
45
FIELD(TBFLAG_ANY, SS_ACTIVE, 27, 1)
46
-FIELD(TBFLAG_ANY, PSTATE_SS, 26, 1)
47
+FIELD(TBFLAG_ANY, PSTATE_SS, 26, 1) /* Not cached. */
48
/* Target EL if we take a floating-point-disabled exception */
49
FIELD(TBFLAG_ANY, FPEXC_EL, 24, 2)
50
FIELD(TBFLAG_ANY, BE_DATA, 23, 1)
51
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_ANY, BE_DATA, 23, 1)
52
FIELD(TBFLAG_ANY, DEBUG_TARGET_EL, 21, 2)
53
54
/* Bit usage when in AArch32 state: */
55
-FIELD(TBFLAG_A32, THUMB, 0, 1)
56
-FIELD(TBFLAG_A32, VECLEN, 1, 3)
57
-FIELD(TBFLAG_A32, VECSTRIDE, 4, 2)
58
+FIELD(TBFLAG_A32, THUMB, 0, 1) /* Not cached. */
59
+FIELD(TBFLAG_A32, VECLEN, 1, 3) /* Not cached. */
60
+FIELD(TBFLAG_A32, VECSTRIDE, 4, 2) /* Not cached. */
61
/*
62
* We store the bottom two bits of the CPAR as TB flags and handle
63
* checks on the other bits at runtime. This shares the same bits as
64
* VECSTRIDE, which is OK as no XScale CPU has VFP.
65
+ * Not cached, because VECLEN+VECSTRIDE are not cached.
66
*/
67
FIELD(TBFLAG_A32, XSCALE_CPAR, 4, 2)
68
/*
69
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_A32, XSCALE_CPAR, 4, 2)
70
* the same thing as the current security state of the processor!
71
*/
72
FIELD(TBFLAG_A32, NS, 6, 1)
73
-FIELD(TBFLAG_A32, VFPEN, 7, 1)
74
-FIELD(TBFLAG_A32, CONDEXEC, 8, 8)
75
+FIELD(TBFLAG_A32, VFPEN, 7, 1) /* Not cached. */
76
+FIELD(TBFLAG_A32, CONDEXEC, 8, 8) /* Not cached. */
77
FIELD(TBFLAG_A32, SCTLR_B, 16, 1)
78
/* For M profile only, set if FPCCR.LSPACT is set */
79
-FIELD(TBFLAG_A32, LSPACT, 18, 1)
80
+FIELD(TBFLAG_A32, LSPACT, 18, 1) /* Not cached. */
81
/* For M profile only, set if we must create a new FP context */
82
-FIELD(TBFLAG_A32, NEW_FP_CTXT_NEEDED, 19, 1)
83
+FIELD(TBFLAG_A32, NEW_FP_CTXT_NEEDED, 19, 1) /* Not cached. */
84
/* For M profile only, set if FPCCR.S does not match current security state */
85
-FIELD(TBFLAG_A32, FPCCR_S_WRONG, 20, 1)
86
+FIELD(TBFLAG_A32, FPCCR_S_WRONG, 20, 1) /* Not cached. */
87
/* For M profile only, Handler (ie not Thread) mode */
88
FIELD(TBFLAG_A32, HANDLER, 21, 1)
89
/* For M profile only, whether we should generate stack-limit checks */
90
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_A64, SVEEXC_EL, 2, 2)
91
FIELD(TBFLAG_A64, ZCR_LEN, 4, 4)
92
FIELD(TBFLAG_A64, PAUTH_ACTIVE, 8, 1)
93
FIELD(TBFLAG_A64, BT, 9, 1)
94
-FIELD(TBFLAG_A64, BTYPE, 10, 2)
95
+FIELD(TBFLAG_A64, BTYPE, 10, 2) /* Not cached. */
96
FIELD(TBFLAG_A64, TBID, 12, 2)
97
98
static inline bool bswap_code(bool sctlr_b)
99
diff --git a/target/arm/helper.c b/target/arm/helper.c
100
index XXXXXXX..XXXXXXX 100644
101
--- a/target/arm/helper.c
102
+++ b/target/arm/helper.c
103
@@ -XXX,XX +XXX,XX @@ ARMMMUIdx arm_stage1_mmu_idx(CPUARMState *env)
104
}
105
#endif
106
107
+static uint32_t rebuild_hflags_common(CPUARMState *env, int fp_el,
108
+ ARMMMUIdx mmu_idx, uint32_t flags)
25
+{
109
+{
26
+ /* Return the address space to use for bootloader reads and writes.
110
+ flags = FIELD_DP32(flags, TBFLAG_ANY, FPEXC_EL, fp_el);
27
+ * We prefer the secure address space if the CPU has it and we're
111
+ flags = FIELD_DP32(flags, TBFLAG_ANY, MMUIDX,
28
+ * going to boot the guest into it.
112
+ arm_to_core_mmu_idx(mmu_idx));
29
+ */
30
+ int asidx;
31
+ CPUState *cs = CPU(cpu);
32
+
113
+
33
+ if (arm_feature(&cpu->env, ARM_FEATURE_EL3) && info->secure_boot) {
114
+ if (arm_cpu_data_is_big_endian(env)) {
34
+ asidx = ARMASIdx_S;
115
+ flags = FIELD_DP32(flags, TBFLAG_ANY, BE_DATA, 1);
35
+ } else {
36
+ asidx = ARMASIdx_NS;
37
+ }
116
+ }
38
+
117
+ if (arm_singlestep_active(env)) {
39
+ return cpu_get_address_space(cs, asidx);
118
+ flags = FIELD_DP32(flags, TBFLAG_ANY, SS_ACTIVE, 1);
119
+ }
120
+ return flags;
40
+}
121
+}
41
+
122
+
42
typedef enum {
123
void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
43
FIXUP_NONE = 0, /* do nothing */
124
target_ulong *cs_base, uint32_t *pflags)
44
FIXUP_TERMINATOR, /* end of insns */
45
@@ -XXX,XX +XXX,XX @@ static const ARMInsnFixup smpboot[] = {
46
};
47
48
static void write_bootloader(const char *name, hwaddr addr,
49
- const ARMInsnFixup *insns, uint32_t *fixupcontext)
50
+ const ARMInsnFixup *insns, uint32_t *fixupcontext,
51
+ AddressSpace *as)
52
{
125
{
53
/* Fix up the specified bootloader fragment and write it into
126
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
54
* guest memory using rom_add_blob_fixed(). fixupcontext is
55
@@ -XXX,XX +XXX,XX @@ static void write_bootloader(const char *name, hwaddr addr,
56
code[i] = tswap32(insn);
57
}
58
59
- rom_add_blob_fixed(name, code, len * sizeof(uint32_t), addr);
60
+ rom_add_blob_fixed_as(name, code, len * sizeof(uint32_t), addr, as);
61
62
g_free(code);
63
}
64
@@ -XXX,XX +XXX,XX @@ static void default_write_secondary(ARMCPU *cpu,
65
const struct arm_boot_info *info)
66
{
67
uint32_t fixupcontext[FIXUP_MAX];
68
+ AddressSpace *as = arm_boot_address_space(cpu, info);
69
70
fixupcontext[FIXUP_GIC_CPU_IF] = info->gic_cpu_if_addr;
71
fixupcontext[FIXUP_BOOTREG] = info->smp_bootreg_addr;
72
@@ -XXX,XX +XXX,XX @@ static void default_write_secondary(ARMCPU *cpu,
73
}
74
75
write_bootloader("smpboot", info->smp_loader_start,
76
- smpboot, fixupcontext);
77
+ smpboot, fixupcontext, as);
78
}
79
80
void arm_write_secure_board_setup_dummy_smc(ARMCPU *cpu,
81
const struct arm_boot_info *info,
82
hwaddr mvbar_addr)
83
{
84
+ AddressSpace *as = arm_boot_address_space(cpu, info);
85
int n;
86
uint32_t mvbar_blob[] = {
87
/* mvbar_addr: secure monitor vectors
88
@@ -XXX,XX +XXX,XX @@ void arm_write_secure_board_setup_dummy_smc(ARMCPU *cpu,
89
for (n = 0; n < ARRAY_SIZE(mvbar_blob); n++) {
90
mvbar_blob[n] = tswap32(mvbar_blob[n]);
91
}
92
- rom_add_blob_fixed("board-setup-mvbar", mvbar_blob, sizeof(mvbar_blob),
93
- mvbar_addr);
94
+ rom_add_blob_fixed_as("board-setup-mvbar", mvbar_blob, sizeof(mvbar_blob),
95
+ mvbar_addr, as);
96
97
for (n = 0; n < ARRAY_SIZE(board_setup_blob); n++) {
98
board_setup_blob[n] = tswap32(board_setup_blob[n]);
99
}
100
- rom_add_blob_fixed("board-setup", board_setup_blob,
101
- sizeof(board_setup_blob), info->board_setup_addr);
102
+ rom_add_blob_fixed_as("board-setup", board_setup_blob,
103
+ sizeof(board_setup_blob), info->board_setup_addr, as);
104
}
105
106
static void default_reset_secondary(ARMCPU *cpu,
107
const struct arm_boot_info *info)
108
{
109
+ AddressSpace *as = arm_boot_address_space(cpu, info);
110
CPUState *cs = CPU(cpu);
111
112
- address_space_stl_notdirty(&address_space_memory, info->smp_bootreg_addr,
113
+ address_space_stl_notdirty(as, info->smp_bootreg_addr,
114
0, MEMTXATTRS_UNSPECIFIED, NULL);
115
cpu_set_pc(cs, info->smp_loader_start);
116
}
117
@@ -XXX,XX +XXX,XX @@ static inline bool have_dtb(const struct arm_boot_info *info)
118
}
119
120
#define WRITE_WORD(p, value) do { \
121
- address_space_stl_notdirty(&address_space_memory, p, value, \
122
+ address_space_stl_notdirty(as, p, value, \
123
MEMTXATTRS_UNSPECIFIED, NULL); \
124
p += 4; \
125
} while (0)
126
127
-static void set_kernel_args(const struct arm_boot_info *info)
128
+static void set_kernel_args(const struct arm_boot_info *info, AddressSpace *as)
129
{
130
int initrd_size = info->initrd_size;
131
hwaddr base = info->loader_start;
132
@@ -XXX,XX +XXX,XX @@ static void set_kernel_args(const struct arm_boot_info *info)
133
int cmdline_size;
134
135
cmdline_size = strlen(info->kernel_cmdline);
136
- cpu_physical_memory_write(p + 8, info->kernel_cmdline,
137
- cmdline_size + 1);
138
+ address_space_write(as, p + 8, MEMTXATTRS_UNSPECIFIED,
139
+ (const uint8_t *)info->kernel_cmdline,
140
+ cmdline_size + 1);
141
cmdline_size = (cmdline_size >> 2) + 1;
142
WRITE_WORD(p, cmdline_size + 2);
143
WRITE_WORD(p, 0x54410009);
144
@@ -XXX,XX +XXX,XX @@ static void set_kernel_args(const struct arm_boot_info *info)
145
atag_board_len = (info->atag_board(info, atag_board_buf) + 3) & ~3;
146
WRITE_WORD(p, (atag_board_len + 8) >> 2);
147
WRITE_WORD(p, 0x414f4d50);
148
- cpu_physical_memory_write(p, atag_board_buf, atag_board_len);
149
+ address_space_write(as, p, MEMTXATTRS_UNSPECIFIED,
150
+ atag_board_buf, atag_board_len);
151
p += atag_board_len;
152
}
153
/* ATAG_END */
154
@@ -XXX,XX +XXX,XX @@ static void set_kernel_args(const struct arm_boot_info *info)
155
WRITE_WORD(p, 0);
156
}
157
158
-static void set_kernel_args_old(const struct arm_boot_info *info)
159
+static void set_kernel_args_old(const struct arm_boot_info *info,
160
+ AddressSpace *as)
161
{
162
hwaddr p;
163
const char *s;
164
@@ -XXX,XX +XXX,XX @@ static void set_kernel_args_old(const struct arm_boot_info *info)
165
}
166
s = info->kernel_cmdline;
167
if (s) {
168
- cpu_physical_memory_write(p, s, strlen(s) + 1);
169
+ address_space_write(as, p, MEMTXATTRS_UNSPECIFIED,
170
+ (const uint8_t *)s, strlen(s) + 1);
171
} else {
172
WRITE_WORD(p, 0);
173
}
174
@@ -XXX,XX +XXX,XX @@ static void fdt_add_psci_node(void *fdt)
175
* @addr: the address to load the image at
176
* @binfo: struct describing the boot environment
177
* @addr_limit: upper limit of the available memory area at @addr
178
+ * @as: address space to load image to
179
*
180
* Load a device tree supplied by the machine or by the user with the
181
* '-dtb' command line option, and put it at offset @addr in target
182
@@ -XXX,XX +XXX,XX @@ static void fdt_add_psci_node(void *fdt)
183
* Note: Must not be called unless have_dtb(binfo) is true.
184
*/
185
static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
186
- hwaddr addr_limit)
187
+ hwaddr addr_limit, AddressSpace *as)
188
{
189
void *fdt = NULL;
190
int size, rc;
191
@@ -XXX,XX +XXX,XX @@ static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
192
/* Put the DTB into the memory map as a ROM image: this will ensure
193
* the DTB is copied again upon reset, even if addr points into RAM.
194
*/
195
- rom_add_blob_fixed("dtb", fdt, size, addr);
196
+ rom_add_blob_fixed_as("dtb", fdt, size, addr, as);
197
198
g_free(fdt);
199
200
@@ -XXX,XX +XXX,XX @@ static void do_cpu_reset(void *opaque)
201
}
202
203
if (cs == first_cpu) {
204
+ AddressSpace *as = arm_boot_address_space(cpu, info);
205
+
206
cpu_set_pc(cs, info->loader_start);
207
208
if (!have_dtb(info)) {
209
if (old_param) {
210
- set_kernel_args_old(info);
211
+ set_kernel_args_old(info, as);
212
} else {
213
- set_kernel_args(info);
214
+ set_kernel_args(info, as);
215
}
216
}
217
} else {
218
@@ -XXX,XX +XXX,XX @@ static int do_arm_linux_init(Object *obj, void *opaque)
219
220
static uint64_t arm_load_elf(struct arm_boot_info *info, uint64_t *pentry,
221
uint64_t *lowaddr, uint64_t *highaddr,
222
- int elf_machine)
223
+ int elf_machine, AddressSpace *as)
224
{
225
bool elf_is64;
226
union {
227
@@ -XXX,XX +XXX,XX @@ static uint64_t arm_load_elf(struct arm_boot_info *info, uint64_t *pentry,
228
}
127
}
229
}
128
}
230
129
231
- ret = load_elf(info->kernel_filename, NULL, NULL,
130
- flags = FIELD_DP32(flags, TBFLAG_ANY, MMUIDX, arm_to_core_mmu_idx(mmu_idx));
232
- pentry, lowaddr, highaddr, big_endian, elf_machine,
131
+ flags = rebuild_hflags_common(env, fp_el, mmu_idx, flags);
233
- 1, data_swab);
132
234
+ ret = load_elf_as(info->kernel_filename, NULL, NULL,
133
/* The SS_ACTIVE and PSTATE_SS bits correspond to the state machine
235
+ pentry, lowaddr, highaddr, big_endian, elf_machine,
134
* states defined in the ARM ARM for software singlestep:
236
+ 1, data_swab, as);
135
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
237
if (ret <= 0) {
136
* 0 x Inactive (the TB flag for SS is always 0)
238
/* The header loaded but the image didn't */
137
* 1 0 Active-pending
239
exit(1);
138
* 1 1 Active-not-pending
240
@@ -XXX,XX +XXX,XX @@ static uint64_t arm_load_elf(struct arm_boot_info *info, uint64_t *pentry,
139
+ * SS_ACTIVE is set in hflags; PSTATE_SS is computed every TB.
241
}
140
*/
242
141
- if (arm_singlestep_active(env)) {
243
static uint64_t load_aarch64_image(const char *filename, hwaddr mem_base,
142
- flags = FIELD_DP32(flags, TBFLAG_ANY, SS_ACTIVE, 1);
244
- hwaddr *entry)
143
+ if (FIELD_EX32(flags, TBFLAG_ANY, SS_ACTIVE)) {
245
+ hwaddr *entry, AddressSpace *as)
144
if (is_a64(env)) {
246
{
145
if (env->pstate & PSTATE_SS) {
247
hwaddr kernel_load_offset = KERNEL64_LOAD_ADDR;
146
flags = FIELD_DP32(flags, TBFLAG_ANY, PSTATE_SS, 1);
248
uint8_t *buffer;
147
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
249
@@ -XXX,XX +XXX,XX @@ static uint64_t load_aarch64_image(const char *filename, hwaddr mem_base,
250
}
251
252
*entry = mem_base + kernel_load_offset;
253
- rom_add_blob_fixed(filename, buffer, size, *entry);
254
+ rom_add_blob_fixed_as(filename, buffer, size, *entry, as);
255
256
g_free(buffer);
257
258
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
259
ARMCPU *cpu = n->cpu;
260
struct arm_boot_info *info =
261
container_of(n, struct arm_boot_info, load_kernel_notifier);
262
+ AddressSpace *as = arm_boot_address_space(cpu, info);
263
264
/* The board code is not supposed to set secure_board_setup unless
265
* running its code in secure mode is actually possible, and KVM
266
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
267
* the kernel is supposed to be loaded by the bootloader), copy the
268
* DTB to the base of RAM for the bootloader to pick up.
269
*/
270
- if (load_dtb(info->loader_start, info, 0) < 0) {
271
+ if (load_dtb(info->loader_start, info, 0, as) < 0) {
272
exit(1);
273
}
274
}
275
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
276
277
/* Assume that raw images are linux kernels, and ELF images are not. */
278
kernel_size = arm_load_elf(info, &elf_entry, &elf_low_addr,
279
- &elf_high_addr, elf_machine);
280
+ &elf_high_addr, elf_machine, as);
281
if (kernel_size > 0 && have_dtb(info)) {
282
/* If there is still some room left at the base of RAM, try and put
283
* the DTB there like we do for images loaded with -bios or -pflash.
284
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
285
if (elf_low_addr < info->loader_start) {
286
elf_low_addr = 0;
287
}
288
- if (load_dtb(info->loader_start, info, elf_low_addr) < 0) {
289
+ if (load_dtb(info->loader_start, info, elf_low_addr, as) < 0) {
290
exit(1);
291
}
148
}
292
}
149
}
293
}
150
}
294
entry = elf_entry;
151
- if (arm_cpu_data_is_big_endian(env)) {
295
if (kernel_size < 0) {
152
- flags = FIELD_DP32(flags, TBFLAG_ANY, BE_DATA, 1);
296
- kernel_size = load_uimage(info->kernel_filename, &entry, NULL,
153
- }
297
- &is_linux, NULL, NULL);
154
- flags = FIELD_DP32(flags, TBFLAG_ANY, FPEXC_EL, fp_el);
298
+ kernel_size = load_uimage_as(info->kernel_filename, &entry, NULL,
155
299
+ &is_linux, NULL, NULL, as);
156
if (arm_v7m_is_handler_mode(env)) {
300
}
157
flags = FIELD_DP32(flags, TBFLAG_A32, HANDLER, 1);
301
if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64) && kernel_size < 0) {
302
kernel_size = load_aarch64_image(info->kernel_filename,
303
- info->loader_start, &entry);
304
+ info->loader_start, &entry, as);
305
is_linux = 1;
306
} else if (kernel_size < 0) {
307
/* 32-bit ARM */
308
entry = info->loader_start + KERNEL_LOAD_ADDR;
309
- kernel_size = load_image_targphys(info->kernel_filename, entry,
310
- info->ram_size - KERNEL_LOAD_ADDR);
311
+ kernel_size = load_image_targphys_as(info->kernel_filename, entry,
312
+ info->ram_size - KERNEL_LOAD_ADDR,
313
+ as);
314
is_linux = 1;
315
}
316
if (kernel_size < 0) {
317
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
318
uint32_t fixupcontext[FIXUP_MAX];
319
320
if (info->initrd_filename) {
321
- initrd_size = load_ramdisk(info->initrd_filename,
322
- info->initrd_start,
323
- info->ram_size -
324
- info->initrd_start);
325
+ initrd_size = load_ramdisk_as(info->initrd_filename,
326
+ info->initrd_start,
327
+ info->ram_size - info->initrd_start,
328
+ as);
329
if (initrd_size < 0) {
330
- initrd_size = load_image_targphys(info->initrd_filename,
331
- info->initrd_start,
332
- info->ram_size -
333
- info->initrd_start);
334
+ initrd_size = load_image_targphys_as(info->initrd_filename,
335
+ info->initrd_start,
336
+ info->ram_size -
337
+ info->initrd_start,
338
+ as);
339
}
340
if (initrd_size < 0) {
341
error_report("could not load initrd '%s'",
342
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
343
344
/* Place the DTB after the initrd in memory with alignment. */
345
dtb_start = QEMU_ALIGN_UP(info->initrd_start + initrd_size, align);
346
- if (load_dtb(dtb_start, info, 0) < 0) {
347
+ if (load_dtb(dtb_start, info, 0, as) < 0) {
348
exit(1);
349
}
350
fixupcontext[FIXUP_ARGPTR] = dtb_start;
351
@@ -XXX,XX +XXX,XX @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
352
fixupcontext[FIXUP_ENTRYPOINT] = entry;
353
354
write_bootloader("bootloader", info->loader_start,
355
- primary_loader, fixupcontext);
356
+ primary_loader, fixupcontext, as);
357
358
if (info->nb_cpus > 1) {
359
info->write_secondary_boot(cpu, info);
360
--
158
--
361
2.16.2
159
2.20.1
362
160
363
161
diff view generated by jsdifflib
1
Model the Arm IoT Kit documented in
1
From: Richard Henderson <richard.henderson@linaro.org>
2
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
3
2
4
The Arm IoT Kit is a subsystem which includes a CPU and some devices,
3
Create a function to compute the values of the TBFLAG_A64 bits
5
and is intended be extended by adding extra devices to form a
4
that will be cached. For now, the env->hflags variable is not
6
complete system. It is used in the MPS2 board's AN505 image for the
5
used, and the results are fed back to cpu_get_tb_cpu_state.
7
Cortex-M33.
8
6
7
Note that not all BTI related flags are cached, so we have to
8
test the BTI feature twice -- once for those bits moved out to
9
rebuild_hflags_a64 and once for those bits that remain in
10
cpu_get_tb_cpu_state.
11
12
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20191018174431.1784-3-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20180220180325.29818-19-peter.maydell@linaro.org
12
---
16
---
13
hw/arm/Makefile.objs | 1 +
17
target/arm/helper.c | 131 +++++++++++++++++++++++---------------------
14
include/hw/arm/iotkit.h | 109 ++++++++
18
1 file changed, 69 insertions(+), 62 deletions(-)
15
hw/arm/iotkit.c | 598 ++++++++++++++++++++++++++++++++++++++++
16
default-configs/arm-softmmu.mak | 1 +
17
4 files changed, 709 insertions(+)
18
create mode 100644 include/hw/arm/iotkit.h
19
create mode 100644 hw/arm/iotkit.c
20
19
21
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
20
diff --git a/target/arm/helper.c b/target/arm/helper.c
22
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/arm/Makefile.objs
22
--- a/target/arm/helper.c
24
+++ b/hw/arm/Makefile.objs
23
+++ b/target/arm/helper.c
25
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o
24
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_common(CPUARMState *env, int fp_el,
26
obj-$(CONFIG_ASPEED_SOC) += aspeed_soc.o aspeed.o
25
return flags;
27
obj-$(CONFIG_MPS2) += mps2.o
26
}
28
obj-$(CONFIG_MSF2) += msf2-soc.o msf2-som.o
27
29
+obj-$(CONFIG_IOTKIT) += iotkit.o
28
+static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
30
diff --git a/include/hw/arm/iotkit.h b/include/hw/arm/iotkit.h
29
+ ARMMMUIdx mmu_idx)
31
new file mode 100644
30
+{
32
index XXXXXXX..XXXXXXX
31
+ ARMMMUIdx stage1 = stage_1_mmu_idx(mmu_idx);
33
--- /dev/null
32
+ ARMVAParameters p0 = aa64_va_parameters_both(env, 0, stage1);
34
+++ b/include/hw/arm/iotkit.h
33
+ uint32_t flags = 0;
35
@@ -XXX,XX +XXX,XX @@
34
+ uint64_t sctlr;
36
+/*
35
+ int tbii, tbid;
37
+ * ARM IoT Kit
38
+ *
39
+ * Copyright (c) 2018 Linaro Limited
40
+ * Written by Peter Maydell
41
+ *
42
+ * This program is free software; you can redistribute it and/or modify
43
+ * it under the terms of the GNU General Public License version 2 or
44
+ * (at your option) any later version.
45
+ */
46
+
36
+
47
+/* This is a model of the Arm IoT Kit which is documented in
37
+ flags = FIELD_DP32(flags, TBFLAG_ANY, AARCH64_STATE, 1);
48
+ * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
49
+ * It contains:
50
+ * a Cortex-M33
51
+ * the IDAU
52
+ * some timers and watchdogs
53
+ * two peripheral protection controllers
54
+ * a memory protection controller
55
+ * a security controller
56
+ * a bus fabric which arranges that some parts of the address
57
+ * space are secure and non-secure aliases of each other
58
+ *
59
+ * QEMU interface:
60
+ * + QOM property "memory" is a MemoryRegion containing the devices provided
61
+ * by the board model.
62
+ * + QOM property "MAINCLK" is the frequency of the main system clock
63
+ * + QOM property "EXP_NUMIRQ" sets the number of expansion interrupts
64
+ * + Named GPIO inputs "EXP_IRQ" 0..n are the expansion interrupts, which
65
+ * are wired to the NVIC lines 32 .. n+32
66
+ * Controlling up to 4 AHB expansion PPBs which a system using the IoTKit
67
+ * might provide:
68
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_nonsec[0..15]
69
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_ap[0..15]
70
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_irq_enable
71
+ * + named GPIO outputs apb_ppcexp{0,1,2,3}_irq_clear
72
+ * + named GPIO inputs apb_ppcexp{0,1,2,3}_irq_status
73
+ * Controlling each of the 4 expansion AHB PPCs which a system using the IoTKit
74
+ * might provide:
75
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_nonsec[0..15]
76
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_ap[0..15]
77
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_enable
78
+ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_clear
79
+ * + named GPIO inputs ahb_ppcexp{0,1,2,3}_irq_status
80
+ */
81
+
38
+
82
+#ifndef IOTKIT_H
39
+ /* FIXME: ARMv8.1-VHE S2 translation regime. */
83
+#define IOTKIT_H
40
+ if (regime_el(env, stage1) < 2) {
84
+
41
+ ARMVAParameters p1 = aa64_va_parameters_both(env, -1, stage1);
85
+#include "hw/sysbus.h"
42
+ tbid = (p1.tbi << 1) | p0.tbi;
86
+#include "hw/arm/armv7m.h"
43
+ tbii = tbid & ~((p1.tbid << 1) | p0.tbid);
87
+#include "hw/misc/iotkit-secctl.h"
44
+ } else {
88
+#include "hw/misc/tz-ppc.h"
45
+ tbid = p0.tbi;
89
+#include "hw/timer/cmsdk-apb-timer.h"
46
+ tbii = tbid & !p0.tbid;
90
+#include "hw/misc/unimp.h"
91
+#include "hw/or-irq.h"
92
+#include "hw/core/split-irq.h"
93
+
94
+#define TYPE_IOTKIT "iotkit"
95
+#define IOTKIT(obj) OBJECT_CHECK(IoTKit, (obj), TYPE_IOTKIT)
96
+
97
+/* We have an IRQ splitter and an OR gate input for each external PPC
98
+ * and the 2 internal PPCs
99
+ */
100
+#define NUM_EXTERNAL_PPCS (IOTS_NUM_AHB_EXP_PPC + IOTS_NUM_APB_EXP_PPC)
101
+#define NUM_PPCS (NUM_EXTERNAL_PPCS + 2)
102
+
103
+typedef struct IoTKit {
104
+ /*< private >*/
105
+ SysBusDevice parent_obj;
106
+
107
+ /*< public >*/
108
+ ARMv7MState armv7m;
109
+ IoTKitSecCtl secctl;
110
+ TZPPC apb_ppc0;
111
+ TZPPC apb_ppc1;
112
+ CMSDKAPBTIMER timer0;
113
+ CMSDKAPBTIMER timer1;
114
+ qemu_or_irq ppc_irq_orgate;
115
+ SplitIRQ sec_resp_splitter;
116
+ SplitIRQ ppc_irq_splitter[NUM_PPCS];
117
+
118
+ UnimplementedDeviceState dualtimer;
119
+ UnimplementedDeviceState s32ktimer;
120
+
121
+ MemoryRegion container;
122
+ MemoryRegion alias1;
123
+ MemoryRegion alias2;
124
+ MemoryRegion alias3;
125
+ MemoryRegion sram0;
126
+
127
+ qemu_irq *exp_irqs;
128
+ qemu_irq ppc0_irq;
129
+ qemu_irq ppc1_irq;
130
+ qemu_irq sec_resp_cfg;
131
+ qemu_irq sec_resp_cfg_in;
132
+ qemu_irq nsc_cfg_in;
133
+
134
+ qemu_irq irq_status_in[NUM_EXTERNAL_PPCS];
135
+
136
+ uint32_t nsccfg;
137
+
138
+ /* Properties */
139
+ MemoryRegion *board_memory;
140
+ uint32_t exp_numirq;
141
+ uint32_t mainclk_frq;
142
+} IoTKit;
143
+
144
+#endif
145
diff --git a/hw/arm/iotkit.c b/hw/arm/iotkit.c
146
new file mode 100644
147
index XXXXXXX..XXXXXXX
148
--- /dev/null
149
+++ b/hw/arm/iotkit.c
150
@@ -XXX,XX +XXX,XX @@
151
+/*
152
+ * Arm IoT Kit
153
+ *
154
+ * Copyright (c) 2018 Linaro Limited
155
+ * Written by Peter Maydell
156
+ *
157
+ * This program is free software; you can redistribute it and/or modify
158
+ * it under the terms of the GNU General Public License version 2 or
159
+ * (at your option) any later version.
160
+ */
161
+
162
+#include "qemu/osdep.h"
163
+#include "qemu/log.h"
164
+#include "qapi/error.h"
165
+#include "trace.h"
166
+#include "hw/sysbus.h"
167
+#include "hw/registerfields.h"
168
+#include "hw/arm/iotkit.h"
169
+#include "hw/misc/unimp.h"
170
+#include "hw/arm/arm.h"
171
+
172
+/* Create an alias region of @size bytes starting at @base
173
+ * which mirrors the memory starting at @orig.
174
+ */
175
+static void make_alias(IoTKit *s, MemoryRegion *mr, const char *name,
176
+ hwaddr base, hwaddr size, hwaddr orig)
177
+{
178
+ memory_region_init_alias(mr, NULL, name, &s->container, orig, size);
179
+ /* The alias is even lower priority than unimplemented_device regions */
180
+ memory_region_add_subregion_overlap(&s->container, base, mr, -1500);
181
+}
182
+
183
+static void init_sysbus_child(Object *parent, const char *childname,
184
+ void *child, size_t childsize,
185
+ const char *childtype)
186
+{
187
+ object_initialize(child, childsize, childtype);
188
+ object_property_add_child(parent, childname, OBJECT(child), &error_abort);
189
+ qdev_set_parent_bus(DEVICE(child), sysbus_get_default());
190
+}
191
+
192
+static void irq_status_forwarder(void *opaque, int n, int level)
193
+{
194
+ qemu_irq destirq = opaque;
195
+
196
+ qemu_set_irq(destirq, level);
197
+}
198
+
199
+static void nsccfg_handler(void *opaque, int n, int level)
200
+{
201
+ IoTKit *s = IOTKIT(opaque);
202
+
203
+ s->nsccfg = level;
204
+}
205
+
206
+static void iotkit_forward_ppc(IoTKit *s, const char *ppcname, int ppcnum)
207
+{
208
+ /* Each of the 4 AHB and 4 APB PPCs that might be present in a
209
+ * system using the IoTKit has a collection of control lines which
210
+ * are provided by the security controller and which we want to
211
+ * expose as control lines on the IoTKit device itself, so the
212
+ * code using the IoTKit can wire them up to the PPCs.
213
+ */
214
+ SplitIRQ *splitter = &s->ppc_irq_splitter[ppcnum];
215
+ DeviceState *iotkitdev = DEVICE(s);
216
+ DeviceState *dev_secctl = DEVICE(&s->secctl);
217
+ DeviceState *dev_splitter = DEVICE(splitter);
218
+ char *name;
219
+
220
+ name = g_strdup_printf("%s_nonsec", ppcname);
221
+ qdev_pass_gpios(dev_secctl, iotkitdev, name);
222
+ g_free(name);
223
+ name = g_strdup_printf("%s_ap", ppcname);
224
+ qdev_pass_gpios(dev_secctl, iotkitdev, name);
225
+ g_free(name);
226
+ name = g_strdup_printf("%s_irq_enable", ppcname);
227
+ qdev_pass_gpios(dev_secctl, iotkitdev, name);
228
+ g_free(name);
229
+ name = g_strdup_printf("%s_irq_clear", ppcname);
230
+ qdev_pass_gpios(dev_secctl, iotkitdev, name);
231
+ g_free(name);
232
+
233
+ /* irq_status is a little more tricky, because we need to
234
+ * split it so we can send it both to the security controller
235
+ * and to our OR gate for the NVIC interrupt line.
236
+ * Connect up the splitter's outputs, and create a GPIO input
237
+ * which will pass the line state to the input splitter.
238
+ */
239
+ name = g_strdup_printf("%s_irq_status", ppcname);
240
+ qdev_connect_gpio_out(dev_splitter, 0,
241
+ qdev_get_gpio_in_named(dev_secctl,
242
+ name, 0));
243
+ qdev_connect_gpio_out(dev_splitter, 1,
244
+ qdev_get_gpio_in(DEVICE(&s->ppc_irq_orgate), ppcnum));
245
+ s->irq_status_in[ppcnum] = qdev_get_gpio_in(dev_splitter, 0);
246
+ qdev_init_gpio_in_named_with_opaque(iotkitdev, irq_status_forwarder,
247
+ s->irq_status_in[ppcnum], name, 1);
248
+ g_free(name);
249
+}
250
+
251
+static void iotkit_forward_sec_resp_cfg(IoTKit *s)
252
+{
253
+ /* Forward the 3rd output from the splitter device as a
254
+ * named GPIO output of the iotkit object.
255
+ */
256
+ DeviceState *dev = DEVICE(s);
257
+ DeviceState *dev_splitter = DEVICE(&s->sec_resp_splitter);
258
+
259
+ qdev_init_gpio_out_named(dev, &s->sec_resp_cfg, "sec_resp_cfg", 1);
260
+ s->sec_resp_cfg_in = qemu_allocate_irq(irq_status_forwarder,
261
+ s->sec_resp_cfg, 1);
262
+ qdev_connect_gpio_out(dev_splitter, 2, s->sec_resp_cfg_in);
263
+}
264
+
265
+static void iotkit_init(Object *obj)
266
+{
267
+ IoTKit *s = IOTKIT(obj);
268
+ int i;
269
+
270
+ memory_region_init(&s->container, obj, "iotkit-container", UINT64_MAX);
271
+
272
+ init_sysbus_child(obj, "armv7m", &s->armv7m, sizeof(s->armv7m),
273
+ TYPE_ARMV7M);
274
+ qdev_prop_set_string(DEVICE(&s->armv7m), "cpu-type",
275
+ ARM_CPU_TYPE_NAME("cortex-m33"));
276
+
277
+ init_sysbus_child(obj, "secctl", &s->secctl, sizeof(s->secctl),
278
+ TYPE_IOTKIT_SECCTL);
279
+ init_sysbus_child(obj, "apb-ppc0", &s->apb_ppc0, sizeof(s->apb_ppc0),
280
+ TYPE_TZ_PPC);
281
+ init_sysbus_child(obj, "apb-ppc1", &s->apb_ppc1, sizeof(s->apb_ppc1),
282
+ TYPE_TZ_PPC);
283
+ init_sysbus_child(obj, "timer0", &s->timer0, sizeof(s->timer0),
284
+ TYPE_CMSDK_APB_TIMER);
285
+ init_sysbus_child(obj, "timer1", &s->timer1, sizeof(s->timer1),
286
+ TYPE_CMSDK_APB_TIMER);
287
+ init_sysbus_child(obj, "dualtimer", &s->dualtimer, sizeof(s->dualtimer),
288
+ TYPE_UNIMPLEMENTED_DEVICE);
289
+ object_initialize(&s->ppc_irq_orgate, sizeof(s->ppc_irq_orgate),
290
+ TYPE_OR_IRQ);
291
+ object_property_add_child(obj, "ppc-irq-orgate",
292
+ OBJECT(&s->ppc_irq_orgate), &error_abort);
293
+ object_initialize(&s->sec_resp_splitter, sizeof(s->sec_resp_splitter),
294
+ TYPE_SPLIT_IRQ);
295
+ object_property_add_child(obj, "sec-resp-splitter",
296
+ OBJECT(&s->sec_resp_splitter), &error_abort);
297
+ for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) {
298
+ char *name = g_strdup_printf("ppc-irq-splitter-%d", i);
299
+ SplitIRQ *splitter = &s->ppc_irq_splitter[i];
300
+
301
+ object_initialize(splitter, sizeof(*splitter), TYPE_SPLIT_IRQ);
302
+ object_property_add_child(obj, name, OBJECT(splitter), &error_abort);
303
+ }
304
+ init_sysbus_child(obj, "s32ktimer", &s->s32ktimer, sizeof(s->s32ktimer),
305
+ TYPE_UNIMPLEMENTED_DEVICE);
306
+}
307
+
308
+static void iotkit_exp_irq(void *opaque, int n, int level)
309
+{
310
+ IoTKit *s = IOTKIT(opaque);
311
+
312
+ qemu_set_irq(s->exp_irqs[n], level);
313
+}
314
+
315
+static void iotkit_realize(DeviceState *dev, Error **errp)
316
+{
317
+ IoTKit *s = IOTKIT(dev);
318
+ int i;
319
+ MemoryRegion *mr;
320
+ Error *err = NULL;
321
+ SysBusDevice *sbd_apb_ppc0;
322
+ SysBusDevice *sbd_secctl;
323
+ DeviceState *dev_apb_ppc0;
324
+ DeviceState *dev_apb_ppc1;
325
+ DeviceState *dev_secctl;
326
+ DeviceState *dev_splitter;
327
+
328
+ if (!s->board_memory) {
329
+ error_setg(errp, "memory property was not set");
330
+ return;
331
+ }
47
+ }
332
+
48
+
333
+ if (!s->mainclk_frq) {
49
+ flags = FIELD_DP32(flags, TBFLAG_A64, TBII, tbii);
334
+ error_setg(errp, "MAINCLK property was not set");
50
+ flags = FIELD_DP32(flags, TBFLAG_A64, TBID, tbid);
335
+ return;
51
+
52
+ if (cpu_isar_feature(aa64_sve, env_archcpu(env))) {
53
+ int sve_el = sve_exception_el(env, el);
54
+ uint32_t zcr_len;
55
+
56
+ /*
57
+ * If SVE is disabled, but FP is enabled,
58
+ * then the effective len is 0.
59
+ */
60
+ if (sve_el != 0 && fp_el == 0) {
61
+ zcr_len = 0;
62
+ } else {
63
+ zcr_len = sve_zcr_len_for_el(env, el);
64
+ }
65
+ flags = FIELD_DP32(flags, TBFLAG_A64, SVEEXC_EL, sve_el);
66
+ flags = FIELD_DP32(flags, TBFLAG_A64, ZCR_LEN, zcr_len);
336
+ }
67
+ }
337
+
68
+
338
+ /* Handling of which devices should be available only to secure
69
+ sctlr = arm_sctlr(env, el);
339
+ * code is usually done differently for M profile than for A profile.
340
+ * Instead of putting some devices only into the secure address space,
341
+ * devices exist in both address spaces but with hard-wired security
342
+ * permissions that will cause the CPU to fault for non-secure accesses.
343
+ *
344
+ * The IoTKit has an IDAU (Implementation Defined Access Unit),
345
+ * which specifies hard-wired security permissions for different
346
+ * areas of the physical address space. For the IoTKit IDAU, the
347
+ * top 4 bits of the physical address are the IDAU region ID, and
348
+ * if bit 28 (ie the lowest bit of the ID) is 0 then this is an NS
349
+ * region, otherwise it is an S region.
350
+ *
351
+ * The various devices and RAMs are generally all mapped twice,
352
+ * once into a region that the IDAU defines as secure and once
353
+ * into a non-secure region. They sit behind either a Memory
354
+ * Protection Controller (for RAM) or a Peripheral Protection
355
+ * Controller (for devices), which allow a more fine grained
356
+ * configuration of whether non-secure accesses are permitted.
357
+ *
358
+ * (The other place that guest software can configure security
359
+ * permissions is in the architected SAU (Security Attribution
360
+ * Unit), which is entirely inside the CPU. The IDAU can upgrade
361
+ * the security attributes for a region to more restrictive than
362
+ * the SAU specifies, but cannot downgrade them.)
363
+ *
364
+ * 0x10000000..0x1fffffff alias of 0x00000000..0x0fffffff
365
+ * 0x20000000..0x2007ffff 32KB FPGA block RAM
366
+ * 0x30000000..0x3fffffff alias of 0x20000000..0x2fffffff
367
+ * 0x40000000..0x4000ffff base peripheral region 1
368
+ * 0x40010000..0x4001ffff CPU peripherals (none for IoTKit)
369
+ * 0x40020000..0x4002ffff system control element peripherals
370
+ * 0x40080000..0x400fffff base peripheral region 2
371
+ * 0x50000000..0x5fffffff alias of 0x40000000..0x4fffffff
372
+ */
373
+
70
+
374
+ memory_region_add_subregion_overlap(&s->container, 0, s->board_memory, -1);
71
+ if (cpu_isar_feature(aa64_pauth, env_archcpu(env))) {
375
+
72
+ /*
376
+ qdev_prop_set_uint32(DEVICE(&s->armv7m), "num-irq", s->exp_numirq + 32);
73
+ * In order to save space in flags, we record only whether
377
+ /* In real hardware the initial Secure VTOR is set from the INITSVTOR0
74
+ * pauth is "inactive", meaning all insns are implemented as
378
+ * register in the IoT Kit System Control Register block, and the
75
+ * a nop, or "active" when some action must be performed.
379
+ * initial value of that is in turn specifiable by the FPGA that
76
+ * The decision of which action to take is left to a helper.
380
+ * instantiates the IoT Kit. In QEMU we don't implement this wrinkle,
77
+ */
381
+ * and simply set the CPU's init-svtor to the IoT Kit default value.
78
+ if (sctlr & (SCTLR_EnIA | SCTLR_EnIB | SCTLR_EnDA | SCTLR_EnDB)) {
382
+ */
79
+ flags = FIELD_DP32(flags, TBFLAG_A64, PAUTH_ACTIVE, 1);
383
+ qdev_prop_set_uint32(DEVICE(&s->armv7m), "init-svtor", 0x10000000);
384
+ object_property_set_link(OBJECT(&s->armv7m), OBJECT(&s->container),
385
+ "memory", &err);
386
+ if (err) {
387
+ error_propagate(errp, err);
388
+ return;
389
+ }
390
+ object_property_set_link(OBJECT(&s->armv7m), OBJECT(s), "idau", &err);
391
+ if (err) {
392
+ error_propagate(errp, err);
393
+ return;
394
+ }
395
+ object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err);
396
+ if (err) {
397
+ error_propagate(errp, err);
398
+ return;
399
+ }
400
+
401
+ /* Connect our EXP_IRQ GPIOs to the NVIC's lines 32 and up. */
402
+ s->exp_irqs = g_new(qemu_irq, s->exp_numirq);
403
+ for (i = 0; i < s->exp_numirq; i++) {
404
+ s->exp_irqs[i] = qdev_get_gpio_in(DEVICE(&s->armv7m), i + 32);
405
+ }
406
+ qdev_init_gpio_in_named(dev, iotkit_exp_irq, "EXP_IRQ", s->exp_numirq);
407
+
408
+ /* Set up the big aliases first */
409
+ make_alias(s, &s->alias1, "alias 1", 0x10000000, 0x10000000, 0x00000000);
410
+ make_alias(s, &s->alias2, "alias 2", 0x30000000, 0x10000000, 0x20000000);
411
+ /* The 0x50000000..0x5fffffff region is not a pure alias: it has
412
+ * a few extra devices that only appear there (generally the
413
+ * control interfaces for the protection controllers).
414
+ * We implement this by mapping those devices over the top of this
415
+ * alias MR at a higher priority.
416
+ */
417
+ make_alias(s, &s->alias3, "alias 3", 0x50000000, 0x10000000, 0x40000000);
418
+
419
+ /* This RAM should be behind a Memory Protection Controller, but we
420
+ * don't implement that yet.
421
+ */
422
+ memory_region_init_ram(&s->sram0, NULL, "iotkit.sram0", 0x00008000, &err);
423
+ if (err) {
424
+ error_propagate(errp, err);
425
+ return;
426
+ }
427
+ memory_region_add_subregion(&s->container, 0x20000000, &s->sram0);
428
+
429
+ /* Security controller */
430
+ object_property_set_bool(OBJECT(&s->secctl), true, "realized", &err);
431
+ if (err) {
432
+ error_propagate(errp, err);
433
+ return;
434
+ }
435
+ sbd_secctl = SYS_BUS_DEVICE(&s->secctl);
436
+ dev_secctl = DEVICE(&s->secctl);
437
+ sysbus_mmio_map(sbd_secctl, 0, 0x50080000);
438
+ sysbus_mmio_map(sbd_secctl, 1, 0x40080000);
439
+
440
+ s->nsc_cfg_in = qemu_allocate_irq(nsccfg_handler, s, 1);
441
+ qdev_connect_gpio_out_named(dev_secctl, "nsc_cfg", 0, s->nsc_cfg_in);
442
+
443
+ /* The sec_resp_cfg output from the security controller must be split into
444
+ * multiple lines, one for each of the PPCs within the IoTKit and one
445
+ * that will be an output from the IoTKit to the system.
446
+ */
447
+ object_property_set_int(OBJECT(&s->sec_resp_splitter), 3,
448
+ "num-lines", &err);
449
+ if (err) {
450
+ error_propagate(errp, err);
451
+ return;
452
+ }
453
+ object_property_set_bool(OBJECT(&s->sec_resp_splitter), true,
454
+ "realized", &err);
455
+ if (err) {
456
+ error_propagate(errp, err);
457
+ return;
458
+ }
459
+ dev_splitter = DEVICE(&s->sec_resp_splitter);
460
+ qdev_connect_gpio_out_named(dev_secctl, "sec_resp_cfg", 0,
461
+ qdev_get_gpio_in(dev_splitter, 0));
462
+
463
+ /* Devices behind APB PPC0:
464
+ * 0x40000000: timer0
465
+ * 0x40001000: timer1
466
+ * 0x40002000: dual timer
467
+ * We must configure and realize each downstream device and connect
468
+ * it to the appropriate PPC port; then we can realize the PPC and
469
+ * map its upstream ends to the right place in the container.
470
+ */
471
+ qdev_prop_set_uint32(DEVICE(&s->timer0), "pclk-frq", s->mainclk_frq);
472
+ object_property_set_bool(OBJECT(&s->timer0), true, "realized", &err);
473
+ if (err) {
474
+ error_propagate(errp, err);
475
+ return;
476
+ }
477
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer0), 0,
478
+ qdev_get_gpio_in(DEVICE(&s->armv7m), 3));
479
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer0), 0);
480
+ object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[0]", &err);
481
+ if (err) {
482
+ error_propagate(errp, err);
483
+ return;
484
+ }
485
+
486
+ qdev_prop_set_uint32(DEVICE(&s->timer1), "pclk-frq", s->mainclk_frq);
487
+ object_property_set_bool(OBJECT(&s->timer1), true, "realized", &err);
488
+ if (err) {
489
+ error_propagate(errp, err);
490
+ return;
491
+ }
492
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer1), 0,
493
+ qdev_get_gpio_in(DEVICE(&s->armv7m), 3));
494
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer1), 0);
495
+ object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[1]", &err);
496
+ if (err) {
497
+ error_propagate(errp, err);
498
+ return;
499
+ }
500
+
501
+ qdev_prop_set_string(DEVICE(&s->dualtimer), "name", "Dual timer");
502
+ qdev_prop_set_uint64(DEVICE(&s->dualtimer), "size", 0x1000);
503
+ object_property_set_bool(OBJECT(&s->dualtimer), true, "realized", &err);
504
+ if (err) {
505
+ error_propagate(errp, err);
506
+ return;
507
+ }
508
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dualtimer), 0);
509
+ object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[2]", &err);
510
+ if (err) {
511
+ error_propagate(errp, err);
512
+ return;
513
+ }
514
+
515
+ object_property_set_bool(OBJECT(&s->apb_ppc0), true, "realized", &err);
516
+ if (err) {
517
+ error_propagate(errp, err);
518
+ return;
519
+ }
520
+
521
+ sbd_apb_ppc0 = SYS_BUS_DEVICE(&s->apb_ppc0);
522
+ dev_apb_ppc0 = DEVICE(&s->apb_ppc0);
523
+
524
+ mr = sysbus_mmio_get_region(sbd_apb_ppc0, 0);
525
+ memory_region_add_subregion(&s->container, 0x40000000, mr);
526
+ mr = sysbus_mmio_get_region(sbd_apb_ppc0, 1);
527
+ memory_region_add_subregion(&s->container, 0x40001000, mr);
528
+ mr = sysbus_mmio_get_region(sbd_apb_ppc0, 2);
529
+ memory_region_add_subregion(&s->container, 0x40002000, mr);
530
+ for (i = 0; i < IOTS_APB_PPC0_NUM_PORTS; i++) {
531
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_nonsec", i,
532
+ qdev_get_gpio_in_named(dev_apb_ppc0,
533
+ "cfg_nonsec", i));
534
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_ap", i,
535
+ qdev_get_gpio_in_named(dev_apb_ppc0,
536
+ "cfg_ap", i));
537
+ }
538
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_irq_enable", 0,
539
+ qdev_get_gpio_in_named(dev_apb_ppc0,
540
+ "irq_enable", 0));
541
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_irq_clear", 0,
542
+ qdev_get_gpio_in_named(dev_apb_ppc0,
543
+ "irq_clear", 0));
544
+ qdev_connect_gpio_out(dev_splitter, 0,
545
+ qdev_get_gpio_in_named(dev_apb_ppc0,
546
+ "cfg_sec_resp", 0));
547
+
548
+ /* All the PPC irq lines (from the 2 internal PPCs and the 8 external
549
+ * ones) are sent individually to the security controller, and also
550
+ * ORed together to give a single combined PPC interrupt to the NVIC.
551
+ */
552
+ object_property_set_int(OBJECT(&s->ppc_irq_orgate),
553
+ NUM_PPCS, "num-lines", &err);
554
+ if (err) {
555
+ error_propagate(errp, err);
556
+ return;
557
+ }
558
+ object_property_set_bool(OBJECT(&s->ppc_irq_orgate), true,
559
+ "realized", &err);
560
+ if (err) {
561
+ error_propagate(errp, err);
562
+ return;
563
+ }
564
+ qdev_connect_gpio_out(DEVICE(&s->ppc_irq_orgate), 0,
565
+ qdev_get_gpio_in(DEVICE(&s->armv7m), 10));
566
+
567
+ /* 0x40010000 .. 0x4001ffff: private CPU region: unused in IoTKit */
568
+
569
+ /* 0x40020000 .. 0x4002ffff : IoTKit system control peripheral region */
570
+ /* Devices behind APB PPC1:
571
+ * 0x4002f000: S32K timer
572
+ */
573
+ qdev_prop_set_string(DEVICE(&s->s32ktimer), "name", "S32KTIMER");
574
+ qdev_prop_set_uint64(DEVICE(&s->s32ktimer), "size", 0x1000);
575
+ object_property_set_bool(OBJECT(&s->s32ktimer), true, "realized", &err);
576
+ if (err) {
577
+ error_propagate(errp, err);
578
+ return;
579
+ }
580
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->s32ktimer), 0);
581
+ object_property_set_link(OBJECT(&s->apb_ppc1), OBJECT(mr), "port[0]", &err);
582
+ if (err) {
583
+ error_propagate(errp, err);
584
+ return;
585
+ }
586
+
587
+ object_property_set_bool(OBJECT(&s->apb_ppc1), true, "realized", &err);
588
+ if (err) {
589
+ error_propagate(errp, err);
590
+ return;
591
+ }
592
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->apb_ppc1), 0);
593
+ memory_region_add_subregion(&s->container, 0x4002f000, mr);
594
+
595
+ dev_apb_ppc1 = DEVICE(&s->apb_ppc1);
596
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_nonsec", 0,
597
+ qdev_get_gpio_in_named(dev_apb_ppc1,
598
+ "cfg_nonsec", 0));
599
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_ap", 0,
600
+ qdev_get_gpio_in_named(dev_apb_ppc1,
601
+ "cfg_ap", 0));
602
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_irq_enable", 0,
603
+ qdev_get_gpio_in_named(dev_apb_ppc1,
604
+ "irq_enable", 0));
605
+ qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_irq_clear", 0,
606
+ qdev_get_gpio_in_named(dev_apb_ppc1,
607
+ "irq_clear", 0));
608
+ qdev_connect_gpio_out(dev_splitter, 1,
609
+ qdev_get_gpio_in_named(dev_apb_ppc1,
610
+ "cfg_sec_resp", 0));
611
+
612
+ /* Using create_unimplemented_device() maps the stub into the
613
+ * system address space rather than into our container, but the
614
+ * overall effect to the guest is the same.
615
+ */
616
+ create_unimplemented_device("SYSINFO", 0x40020000, 0x1000);
617
+
618
+ create_unimplemented_device("SYSCONTROL", 0x50021000, 0x1000);
619
+ create_unimplemented_device("S32KWATCHDOG", 0x5002e000, 0x1000);
620
+
621
+ /* 0x40080000 .. 0x4008ffff : IoTKit second Base peripheral region */
622
+
623
+ create_unimplemented_device("NS watchdog", 0x40081000, 0x1000);
624
+ create_unimplemented_device("S watchdog", 0x50081000, 0x1000);
625
+
626
+ create_unimplemented_device("SRAM0 MPC", 0x50083000, 0x1000);
627
+
628
+ for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) {
629
+ Object *splitter = OBJECT(&s->ppc_irq_splitter[i]);
630
+
631
+ object_property_set_int(splitter, 2, "num-lines", &err);
632
+ if (err) {
633
+ error_propagate(errp, err);
634
+ return;
635
+ }
636
+ object_property_set_bool(splitter, true, "realized", &err);
637
+ if (err) {
638
+ error_propagate(errp, err);
639
+ return;
640
+ }
80
+ }
641
+ }
81
+ }
642
+
82
+
643
+ for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) {
83
+ if (cpu_isar_feature(aa64_bti, env_archcpu(env))) {
644
+ char *ppcname = g_strdup_printf("ahb_ppcexp%d", i);
84
+ /* Note that SCTLR_EL[23].BT == SCTLR_BT1. */
645
+
85
+ if (sctlr & (el == 0 ? SCTLR_BT0 : SCTLR_BT1)) {
646
+ iotkit_forward_ppc(s, ppcname, i);
86
+ flags = FIELD_DP32(flags, TBFLAG_A64, BT, 1);
647
+ g_free(ppcname);
87
+ }
648
+ }
88
+ }
649
+
89
+
650
+ for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) {
90
+ return rebuild_hflags_common(env, fp_el, mmu_idx, flags);
651
+ char *ppcname = g_strdup_printf("apb_ppcexp%d", i);
652
+
653
+ iotkit_forward_ppc(s, ppcname, i + IOTS_NUM_AHB_EXP_PPC);
654
+ g_free(ppcname);
655
+ }
656
+
657
+ for (i = NUM_EXTERNAL_PPCS; i < NUM_PPCS; i++) {
658
+ /* Wire up IRQ splitter for internal PPCs */
659
+ DeviceState *devs = DEVICE(&s->ppc_irq_splitter[i]);
660
+ char *gpioname = g_strdup_printf("apb_ppc%d_irq_status",
661
+ i - NUM_EXTERNAL_PPCS);
662
+ TZPPC *ppc = (i == NUM_EXTERNAL_PPCS) ? &s->apb_ppc0 : &s->apb_ppc1;
663
+
664
+ qdev_connect_gpio_out(devs, 0,
665
+ qdev_get_gpio_in_named(dev_secctl, gpioname, 0));
666
+ qdev_connect_gpio_out(devs, 1,
667
+ qdev_get_gpio_in(DEVICE(&s->ppc_irq_orgate), i));
668
+ qdev_connect_gpio_out_named(DEVICE(ppc), "irq", 0,
669
+ qdev_get_gpio_in(devs, 0));
670
+ }
671
+
672
+ iotkit_forward_sec_resp_cfg(s);
673
+
674
+ system_clock_scale = NANOSECONDS_PER_SECOND / s->mainclk_frq;
675
+}
91
+}
676
+
92
+
677
+static void iotkit_idau_check(IDAUInterface *ii, uint32_t address,
93
void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
678
+ int *iregion, bool *exempt, bool *ns, bool *nsc)
94
target_ulong *cs_base, uint32_t *pflags)
679
+{
95
{
680
+ /* For IoTKit systems the IDAU responses are simple logical functions
96
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
681
+ * of the address bits. The NSC attribute is guest-adjustable via the
97
uint32_t flags = 0;
682
+ * NSCCFG register in the security controller.
98
683
+ */
99
if (is_a64(env)) {
684
+ IoTKit *s = IOTKIT(ii);
100
- ARMCPU *cpu = env_archcpu(env);
685
+ int region = extract32(address, 28, 4);
101
- uint64_t sctlr;
686
+
102
-
687
+ *ns = !(region & 1);
103
*pc = env->pc;
688
+ *nsc = (region == 1 && (s->nsccfg & 1)) || (region == 3 && (s->nsccfg & 2));
104
- flags = FIELD_DP32(flags, TBFLAG_ANY, AARCH64_STATE, 1);
689
+ /* 0xe0000000..0xe00fffff and 0xf0000000..0xf00fffff are exempt */
105
-
690
+ *exempt = (address & 0xeff00000) == 0xe0000000;
106
- /* Get control bits for tagged addresses. */
691
+ *iregion = region;
107
- {
692
+}
108
- ARMMMUIdx stage1 = stage_1_mmu_idx(mmu_idx);
693
+
109
- ARMVAParameters p0 = aa64_va_parameters_both(env, 0, stage1);
694
+static const VMStateDescription iotkit_vmstate = {
110
- int tbii, tbid;
695
+ .name = "iotkit",
111
-
696
+ .version_id = 1,
112
- /* FIXME: ARMv8.1-VHE S2 translation regime. */
697
+ .minimum_version_id = 1,
113
- if (regime_el(env, stage1) < 2) {
698
+ .fields = (VMStateField[]) {
114
- ARMVAParameters p1 = aa64_va_parameters_both(env, -1, stage1);
699
+ VMSTATE_UINT32(nsccfg, IoTKit),
115
- tbid = (p1.tbi << 1) | p0.tbi;
700
+ VMSTATE_END_OF_LIST()
116
- tbii = tbid & ~((p1.tbid << 1) | p0.tbid);
117
- } else {
118
- tbid = p0.tbi;
119
- tbii = tbid & !p0.tbid;
120
- }
121
-
122
- flags = FIELD_DP32(flags, TBFLAG_A64, TBII, tbii);
123
- flags = FIELD_DP32(flags, TBFLAG_A64, TBID, tbid);
124
- }
125
-
126
- if (cpu_isar_feature(aa64_sve, cpu)) {
127
- int sve_el = sve_exception_el(env, current_el);
128
- uint32_t zcr_len;
129
-
130
- /* If SVE is disabled, but FP is enabled,
131
- * then the effective len is 0.
132
- */
133
- if (sve_el != 0 && fp_el == 0) {
134
- zcr_len = 0;
135
- } else {
136
- zcr_len = sve_zcr_len_for_el(env, current_el);
137
- }
138
- flags = FIELD_DP32(flags, TBFLAG_A64, SVEEXC_EL, sve_el);
139
- flags = FIELD_DP32(flags, TBFLAG_A64, ZCR_LEN, zcr_len);
140
- }
141
-
142
- sctlr = arm_sctlr(env, current_el);
143
-
144
- if (cpu_isar_feature(aa64_pauth, cpu)) {
145
- /*
146
- * In order to save space in flags, we record only whether
147
- * pauth is "inactive", meaning all insns are implemented as
148
- * a nop, or "active" when some action must be performed.
149
- * The decision of which action to take is left to a helper.
150
- */
151
- if (sctlr & (SCTLR_EnIA | SCTLR_EnIB | SCTLR_EnDA | SCTLR_EnDB)) {
152
- flags = FIELD_DP32(flags, TBFLAG_A64, PAUTH_ACTIVE, 1);
153
- }
154
- }
155
-
156
- if (cpu_isar_feature(aa64_bti, cpu)) {
157
- /* Note that SCTLR_EL[23].BT == SCTLR_BT1. */
158
- if (sctlr & (current_el == 0 ? SCTLR_BT0 : SCTLR_BT1)) {
159
- flags = FIELD_DP32(flags, TBFLAG_A64, BT, 1);
160
- }
161
+ flags = rebuild_hflags_a64(env, current_el, fp_el, mmu_idx);
162
+ if (cpu_isar_feature(aa64_bti, env_archcpu(env))) {
163
flags = FIELD_DP32(flags, TBFLAG_A64, BTYPE, env->btype);
164
}
165
} else {
166
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
167
flags = FIELD_DP32(flags, TBFLAG_A32,
168
XSCALE_CPAR, env->cp15.c15_cpar);
169
}
170
- }
171
172
- flags = rebuild_hflags_common(env, fp_el, mmu_idx, flags);
173
+ flags = rebuild_hflags_common(env, fp_el, mmu_idx, flags);
701
+ }
174
+ }
702
+};
175
703
+
176
/* The SS_ACTIVE and PSTATE_SS bits correspond to the state machine
704
+static Property iotkit_properties[] = {
177
* states defined in the ARM ARM for software singlestep:
705
+ DEFINE_PROP_LINK("memory", IoTKit, board_memory, TYPE_MEMORY_REGION,
706
+ MemoryRegion *),
707
+ DEFINE_PROP_UINT32("EXP_NUMIRQ", IoTKit, exp_numirq, 64),
708
+ DEFINE_PROP_UINT32("MAINCLK", IoTKit, mainclk_frq, 0),
709
+ DEFINE_PROP_END_OF_LIST()
710
+};
711
+
712
+static void iotkit_reset(DeviceState *dev)
713
+{
714
+ IoTKit *s = IOTKIT(dev);
715
+
716
+ s->nsccfg = 0;
717
+}
718
+
719
+static void iotkit_class_init(ObjectClass *klass, void *data)
720
+{
721
+ DeviceClass *dc = DEVICE_CLASS(klass);
722
+ IDAUInterfaceClass *iic = IDAU_INTERFACE_CLASS(klass);
723
+
724
+ dc->realize = iotkit_realize;
725
+ dc->vmsd = &iotkit_vmstate;
726
+ dc->props = iotkit_properties;
727
+ dc->reset = iotkit_reset;
728
+ iic->check = iotkit_idau_check;
729
+}
730
+
731
+static const TypeInfo iotkit_info = {
732
+ .name = TYPE_IOTKIT,
733
+ .parent = TYPE_SYS_BUS_DEVICE,
734
+ .instance_size = sizeof(IoTKit),
735
+ .instance_init = iotkit_init,
736
+ .class_init = iotkit_class_init,
737
+ .interfaces = (InterfaceInfo[]) {
738
+ { TYPE_IDAU_INTERFACE },
739
+ { }
740
+ }
741
+};
742
+
743
+static void iotkit_register_types(void)
744
+{
745
+ type_register_static(&iotkit_info);
746
+}
747
+
748
+type_init(iotkit_register_types);
749
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
750
index XXXXXXX..XXXXXXX 100644
751
--- a/default-configs/arm-softmmu.mak
752
+++ b/default-configs/arm-softmmu.mak
753
@@ -XXX,XX +XXX,XX @@ CONFIG_MPS2_FPGAIO=y
754
CONFIG_MPS2_SCC=y
755
756
CONFIG_TZ_PPC=y
757
+CONFIG_IOTKIT=y
758
CONFIG_IOTKIT_SECCTL=y
759
760
CONFIG_VERSATILE_PCI=y
761
--
178
--
762
2.16.2
179
2.20.1
763
180
764
181
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Create a function to compute the values of the TBFLAG_A32 bits
4
that will be cached, and are used by all profiles.
5
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Message-id: 20180228193125.20577-15-richard.henderson@linaro.org
8
Message-id: 20191018174431.1784-4-richard.henderson@linaro.org
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
10
---
8
target/arm/translate.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++
11
target/arm/helper.c | 16 +++++++++++-----
9
1 file changed, 61 insertions(+)
12
1 file changed, 11 insertions(+), 5 deletions(-)
10
13
11
diff --git a/target/arm/translate.c b/target/arm/translate.c
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
12
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate.c
16
--- a/target/arm/helper.c
14
+++ b/target/arm/translate.c
17
+++ b/target/arm/helper.c
15
@@ -XXX,XX +XXX,XX @@ static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
18
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_common(CPUARMState *env, int fp_el,
16
return 0;
19
return flags;
17
}
20
}
18
21
19
+/* Advanced SIMD two registers and a scalar extension.
22
+static uint32_t rebuild_hflags_common_32(CPUARMState *env, int fp_el,
20
+ * 31 24 23 22 20 16 12 11 10 9 8 3 0
23
+ ARMMMUIdx mmu_idx, uint32_t flags)
21
+ * +-----------------+----+---+----+----+----+---+----+---+----+---------+----+
24
+{
22
+ * | 1 1 1 1 1 1 1 0 | o1 | D | o2 | Vn | Vd | 1 | o3 | 0 | o4 | N Q M U | Vm |
25
+ flags = FIELD_DP32(flags, TBFLAG_A32, SCTLR_B, arm_sctlr_b(env));
23
+ * +-----------------+----+---+----+----+----+---+----+---+----+---------+----+
26
+ flags = FIELD_DP32(flags, TBFLAG_A32, NS, !access_secure_reg(env));
24
+ *
25
+ */
26
+
27
+
27
+static int disas_neon_insn_2reg_scalar_ext(DisasContext *s, uint32_t insn)
28
+ return rebuild_hflags_common(env, fp_el, mmu_idx, flags);
28
+{
29
+ int rd, rn, rm, rot, size, opr_sz;
30
+ TCGv_ptr fpst;
31
+ bool q;
32
+
33
+ q = extract32(insn, 6, 1);
34
+ VFP_DREG_D(rd, insn);
35
+ VFP_DREG_N(rn, insn);
36
+ VFP_DREG_M(rm, insn);
37
+ if ((rd | rn) & q) {
38
+ return 1;
39
+ }
40
+
41
+ if ((insn & 0xff000f10) == 0xfe000800) {
42
+ /* VCMLA (indexed) -- 1111 1110 S.RR .... .... 1000 ...0 .... */
43
+ rot = extract32(insn, 20, 2);
44
+ size = extract32(insn, 23, 1);
45
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_FCMA)
46
+ || (!size && !arm_dc_feature(s, ARM_FEATURE_V8_FP16))) {
47
+ return 1;
48
+ }
49
+ } else {
50
+ return 1;
51
+ }
52
+
53
+ if (s->fp_excp_el) {
54
+ gen_exception_insn(s, 4, EXCP_UDEF,
55
+ syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
56
+ return 0;
57
+ }
58
+ if (!s->vfp_enabled) {
59
+ return 1;
60
+ }
61
+
62
+ opr_sz = (1 + q) * 8;
63
+ fpst = get_fpstatus_ptr(1);
64
+ tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
65
+ vfp_reg_offset(1, rn),
66
+ vfp_reg_offset(1, rm), fpst,
67
+ opr_sz, opr_sz, rot,
68
+ size ? gen_helper_gvec_fcmlas_idx
69
+ : gen_helper_gvec_fcmlah_idx);
70
+ tcg_temp_free_ptr(fpst);
71
+ return 0;
72
+}
29
+}
73
+
30
+
74
static int disas_coproc_insn(DisasContext *s, uint32_t insn)
31
static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
32
ARMMMUIdx mmu_idx)
75
{
33
{
76
int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
34
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
77
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
35
ARMMMUIdx mmu_idx = arm_mmu_idx(env);
78
goto illegal_op;
36
int current_el = arm_current_el(env);
79
}
37
int fp_el = fp_exception_el(env, current_el);
80
return;
38
- uint32_t flags = 0;
81
+ } else if ((insn & 0x0f000a00) == 0x0e000800
39
+ uint32_t flags;
82
+ && arm_dc_feature(s, ARM_FEATURE_V8)) {
40
83
+ if (disas_neon_insn_2reg_scalar_ext(s, insn)) {
41
if (is_a64(env)) {
84
+ goto illegal_op;
42
*pc = env->pc;
85
+ }
43
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
86
+ return;
44
}
87
} else if ((insn & 0x0fe00000) == 0x0c400000) {
45
} else {
88
/* Coprocessor double register transfer. */
46
*pc = env->regs[15];
89
ARCH(5TE);
47
+ flags = rebuild_hflags_common_32(env, fp_el, mmu_idx, 0);
48
flags = FIELD_DP32(flags, TBFLAG_A32, THUMB, env->thumb);
49
flags = FIELD_DP32(flags, TBFLAG_A32, VECLEN, env->vfp.vec_len);
50
flags = FIELD_DP32(flags, TBFLAG_A32, VECSTRIDE, env->vfp.vec_stride);
51
flags = FIELD_DP32(flags, TBFLAG_A32, CONDEXEC, env->condexec_bits);
52
- flags = FIELD_DP32(flags, TBFLAG_A32, SCTLR_B, arm_sctlr_b(env));
53
- flags = FIELD_DP32(flags, TBFLAG_A32, NS, !access_secure_reg(env));
54
if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)
55
|| arm_el_is_aa64(env, 1) || arm_feature(env, ARM_FEATURE_M)) {
56
flags = FIELD_DP32(flags, TBFLAG_A32, VFPEN, 1);
57
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
58
flags = FIELD_DP32(flags, TBFLAG_A32,
59
XSCALE_CPAR, env->cp15.c15_cpar);
60
}
61
-
62
- flags = rebuild_hflags_common(env, fp_el, mmu_idx, flags);
63
}
64
65
/* The SS_ACTIVE and PSTATE_SS bits correspond to the state machine
90
--
66
--
91
2.16.2
67
2.20.1
92
68
93
69
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Not enabled anywhere yet.
3
Set TBFLAG_ANY.BE_DATA in rebuild_hflags_common_32 and
4
rebuild_hflags_a64 instead of rebuild_hflags_common, where we do
5
not need to re-test is_a64() nor re-compute the various inputs.
4
6
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180228193125.20577-11-richard.henderson@linaro.org
9
Message-id: 20191018174431.1784-5-richard.henderson@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
target/arm/cpu.h | 1 +
12
target/arm/cpu.h | 49 +++++++++++++++++++++++++++------------------
11
linux-user/elfload.c | 1 +
13
target/arm/helper.c | 16 +++++++++++----
12
2 files changed, 2 insertions(+)
14
2 files changed, 42 insertions(+), 23 deletions(-)
13
15
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.h
18
--- a/target/arm/cpu.h
17
+++ b/target/arm/cpu.h
19
+++ b/target/arm/cpu.h
18
@@ -XXX,XX +XXX,XX @@ enum arm_features {
20
@@ -XXX,XX +XXX,XX @@ static inline uint64_t arm_sctlr(CPUARMState *env, int el)
19
ARM_FEATURE_V8_SM4, /* implements SM4 part of v8 Crypto Extensions */
21
}
20
ARM_FEATURE_V8_RDM, /* implements v8.1 simd round multiply */
22
}
21
ARM_FEATURE_V8_FP16, /* implements v8.2 half-precision float */
23
22
+ ARM_FEATURE_V8_FCMA, /* has complex number part of v8.3 extensions. */
24
+static inline bool arm_cpu_data_is_big_endian_a32(CPUARMState *env,
23
};
25
+ bool sctlr_b)
24
26
+{
25
static inline int arm_feature(CPUARMState *env, int feature)
27
+#ifdef CONFIG_USER_ONLY
26
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
28
+ /*
29
+ * In system mode, BE32 is modelled in line with the
30
+ * architecture (as word-invariant big-endianness), where loads
31
+ * and stores are done little endian but from addresses which
32
+ * are adjusted by XORing with the appropriate constant. So the
33
+ * endianness to use for the raw data access is not affected by
34
+ * SCTLR.B.
35
+ * In user mode, however, we model BE32 as byte-invariant
36
+ * big-endianness (because user-only code cannot tell the
37
+ * difference), and so we need to use a data access endianness
38
+ * that depends on SCTLR.B.
39
+ */
40
+ if (sctlr_b) {
41
+ return true;
42
+ }
43
+#endif
44
+ /* In 32bit endianness is determined by looking at CPSR's E bit */
45
+ return env->uncached_cpsr & CPSR_E;
46
+}
47
+
48
+static inline bool arm_cpu_data_is_big_endian_a64(int el, uint64_t sctlr)
49
+{
50
+ return sctlr & (el ? SCTLR_EE : SCTLR_E0E);
51
+}
52
53
/* Return true if the processor is in big-endian mode. */
54
static inline bool arm_cpu_data_is_big_endian(CPUARMState *env)
55
{
56
- /* In 32bit endianness is determined by looking at CPSR's E bit */
57
if (!is_a64(env)) {
58
- return
59
-#ifdef CONFIG_USER_ONLY
60
- /* In system mode, BE32 is modelled in line with the
61
- * architecture (as word-invariant big-endianness), where loads
62
- * and stores are done little endian but from addresses which
63
- * are adjusted by XORing with the appropriate constant. So the
64
- * endianness to use for the raw data access is not affected by
65
- * SCTLR.B.
66
- * In user mode, however, we model BE32 as byte-invariant
67
- * big-endianness (because user-only code cannot tell the
68
- * difference), and so we need to use a data access endianness
69
- * that depends on SCTLR.B.
70
- */
71
- arm_sctlr_b(env) ||
72
-#endif
73
- ((env->uncached_cpsr & CPSR_E) ? 1 : 0);
74
+ return arm_cpu_data_is_big_endian_a32(env, arm_sctlr_b(env));
75
} else {
76
int cur_el = arm_current_el(env);
77
uint64_t sctlr = arm_sctlr(env, cur_el);
78
-
79
- return (sctlr & (cur_el ? SCTLR_EE : SCTLR_E0E)) != 0;
80
+ return arm_cpu_data_is_big_endian_a64(cur_el, sctlr);
81
}
82
}
83
84
diff --git a/target/arm/helper.c b/target/arm/helper.c
27
index XXXXXXX..XXXXXXX 100644
85
index XXXXXXX..XXXXXXX 100644
28
--- a/linux-user/elfload.c
86
--- a/target/arm/helper.c
29
+++ b/linux-user/elfload.c
87
+++ b/target/arm/helper.c
30
@@ -XXX,XX +XXX,XX @@ static uint32_t get_elf_hwcap(void)
88
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_common(CPUARMState *env, int fp_el,
31
GET_FEATURE(ARM_FEATURE_V8_FP16,
89
flags = FIELD_DP32(flags, TBFLAG_ANY, MMUIDX,
32
ARM_HWCAP_A64_FPHP | ARM_HWCAP_A64_ASIMDHP);
90
arm_to_core_mmu_idx(mmu_idx));
33
GET_FEATURE(ARM_FEATURE_V8_RDM, ARM_HWCAP_A64_ASIMDRDM);
91
34
+ GET_FEATURE(ARM_FEATURE_V8_FCMA, ARM_HWCAP_A64_FCMA);
92
- if (arm_cpu_data_is_big_endian(env)) {
35
#undef GET_FEATURE
93
- flags = FIELD_DP32(flags, TBFLAG_ANY, BE_DATA, 1);
36
94
- }
37
return hwcaps;
95
if (arm_singlestep_active(env)) {
96
flags = FIELD_DP32(flags, TBFLAG_ANY, SS_ACTIVE, 1);
97
}
98
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_common(CPUARMState *env, int fp_el,
99
static uint32_t rebuild_hflags_common_32(CPUARMState *env, int fp_el,
100
ARMMMUIdx mmu_idx, uint32_t flags)
101
{
102
- flags = FIELD_DP32(flags, TBFLAG_A32, SCTLR_B, arm_sctlr_b(env));
103
+ bool sctlr_b = arm_sctlr_b(env);
104
+
105
+ if (sctlr_b) {
106
+ flags = FIELD_DP32(flags, TBFLAG_A32, SCTLR_B, 1);
107
+ }
108
+ if (arm_cpu_data_is_big_endian_a32(env, sctlr_b)) {
109
+ flags = FIELD_DP32(flags, TBFLAG_ANY, BE_DATA, 1);
110
+ }
111
flags = FIELD_DP32(flags, TBFLAG_A32, NS, !access_secure_reg(env));
112
113
return rebuild_hflags_common(env, fp_el, mmu_idx, flags);
114
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
115
116
sctlr = arm_sctlr(env, el);
117
118
+ if (arm_cpu_data_is_big_endian_a64(el, sctlr)) {
119
+ flags = FIELD_DP32(flags, TBFLAG_ANY, BE_DATA, 1);
120
+ }
121
+
122
if (cpu_isar_feature(aa64_pauth, env_archcpu(env))) {
123
/*
124
* In order to save space in flags, we record only whether
38
--
125
--
39
2.16.2
126
2.20.1
40
127
41
128
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Create a function to compute the values of the TBFLAG_A32 bits
4
that will be cached, and are used by M-profile.
5
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20191018174431.1784-6-richard.henderson@linaro.org
5
Message-id: 20180228193125.20577-14-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
10
---
8
target/arm/translate.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++
11
target/arm/helper.c | 45 ++++++++++++++++++++++++++++++---------------
9
1 file changed, 68 insertions(+)
12
1 file changed, 30 insertions(+), 15 deletions(-)
10
13
11
diff --git a/target/arm/translate.c b/target/arm/translate.c
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
12
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate.c
16
--- a/target/arm/helper.c
14
+++ b/target/arm/translate.c
17
+++ b/target/arm/helper.c
15
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
18
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_common_32(CPUARMState *env, int fp_el,
16
return 0;
19
return rebuild_hflags_common(env, fp_el, mmu_idx, flags);
17
}
20
}
18
21
19
+/* Advanced SIMD three registers of the same length extension.
22
+static uint32_t rebuild_hflags_m32(CPUARMState *env, int fp_el,
20
+ * 31 25 23 22 20 16 12 11 10 9 8 3 0
23
+ ARMMMUIdx mmu_idx)
21
+ * +---------------+-----+---+-----+----+----+---+----+---+----+---------+----+
22
+ * | 1 1 1 1 1 1 0 | op1 | D | op2 | Vn | Vd | 1 | o3 | 0 | o4 | N Q M U | Vm |
23
+ * +---------------+-----+---+-----+----+----+---+----+---+----+---------+----+
24
+ */
25
+static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
26
+{
24
+{
27
+ gen_helper_gvec_3_ptr *fn_gvec_ptr;
25
+ uint32_t flags = 0;
28
+ int rd, rn, rm, rot, size, opr_sz;
29
+ TCGv_ptr fpst;
30
+ bool q;
31
+
26
+
32
+ q = extract32(insn, 6, 1);
27
+ if (arm_v7m_is_handler_mode(env)) {
33
+ VFP_DREG_D(rd, insn);
28
+ flags = FIELD_DP32(flags, TBFLAG_A32, HANDLER, 1);
34
+ VFP_DREG_N(rn, insn);
35
+ VFP_DREG_M(rm, insn);
36
+ if ((rd | rn | rm) & q) {
37
+ return 1;
38
+ }
29
+ }
39
+
30
+
40
+ if ((insn & 0xfe200f10) == 0xfc200800) {
31
+ /*
41
+ /* VCMLA -- 1111 110R R.1S .... .... 1000 ...0 .... */
32
+ * v8M always applies stack limit checks unless CCR.STKOFHFNMIGN
42
+ size = extract32(insn, 20, 1);
33
+ * is suppressing them because the requested execution priority
43
+ rot = extract32(insn, 23, 2);
34
+ * is less than 0.
44
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_FCMA)
35
+ */
45
+ || (!size && !arm_dc_feature(s, ARM_FEATURE_V8_FP16))) {
36
+ if (arm_feature(env, ARM_FEATURE_V8) &&
46
+ return 1;
37
+ !((mmu_idx & ARM_MMU_IDX_M_NEGPRI) &&
47
+ }
38
+ (env->v7m.ccr[env->v7m.secure] & R_V7M_CCR_STKOFHFNMIGN_MASK))) {
48
+ fn_gvec_ptr = size ? gen_helper_gvec_fcmlas : gen_helper_gvec_fcmlah;
39
+ flags = FIELD_DP32(flags, TBFLAG_A32, STACKCHECK, 1);
49
+ } else if ((insn & 0xfea00f10) == 0xfc800800) {
50
+ /* VCADD -- 1111 110R 1.0S .... .... 1000 ...0 .... */
51
+ size = extract32(insn, 20, 1);
52
+ rot = extract32(insn, 24, 1);
53
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_FCMA)
54
+ || (!size && !arm_dc_feature(s, ARM_FEATURE_V8_FP16))) {
55
+ return 1;
56
+ }
57
+ fn_gvec_ptr = size ? gen_helper_gvec_fcadds : gen_helper_gvec_fcaddh;
58
+ } else {
59
+ return 1;
60
+ }
40
+ }
61
+
41
+
62
+ if (s->fp_excp_el) {
42
+ return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags);
63
+ gen_exception_insn(s, 4, EXCP_UDEF,
64
+ syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
65
+ return 0;
66
+ }
67
+ if (!s->vfp_enabled) {
68
+ return 1;
69
+ }
70
+
71
+ opr_sz = (1 + q) * 8;
72
+ fpst = get_fpstatus_ptr(1);
73
+ tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
74
+ vfp_reg_offset(1, rn),
75
+ vfp_reg_offset(1, rm), fpst,
76
+ opr_sz, opr_sz, rot, fn_gvec_ptr);
77
+ tcg_temp_free_ptr(fpst);
78
+ return 0;
79
+}
43
+}
80
+
44
+
81
static int disas_coproc_insn(DisasContext *s, uint32_t insn)
45
static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
46
ARMMMUIdx mmu_idx)
82
{
47
{
83
int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
48
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
84
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
49
}
85
}
50
} else {
86
}
51
*pc = env->regs[15];
87
}
52
- flags = rebuild_hflags_common_32(env, fp_el, mmu_idx, 0);
88
+ } else if ((insn & 0x0e000a00) == 0x0c000800
53
+
89
+ && arm_dc_feature(s, ARM_FEATURE_V8)) {
54
+ if (arm_feature(env, ARM_FEATURE_M)) {
90
+ if (disas_neon_insn_3same_ext(s, insn)) {
55
+ flags = rebuild_hflags_m32(env, fp_el, mmu_idx);
91
+ goto illegal_op;
56
+ } else {
92
+ }
57
+ flags = rebuild_hflags_common_32(env, fp_el, mmu_idx, 0);
93
+ return;
58
+ }
94
} else if ((insn & 0x0fe00000) == 0x0c400000) {
59
+
95
/* Coprocessor double register transfer. */
60
flags = FIELD_DP32(flags, TBFLAG_A32, THUMB, env->thumb);
96
ARCH(5TE);
61
flags = FIELD_DP32(flags, TBFLAG_A32, VECLEN, env->vfp.vec_len);
62
flags = FIELD_DP32(flags, TBFLAG_A32, VECSTRIDE, env->vfp.vec_stride);
63
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
64
}
65
}
66
67
- if (arm_v7m_is_handler_mode(env)) {
68
- flags = FIELD_DP32(flags, TBFLAG_A32, HANDLER, 1);
69
- }
70
-
71
- /* v8M always applies stack limit checks unless CCR.STKOFHFNMIGN is
72
- * suppressing them because the requested execution priority is less than 0.
73
- */
74
- if (arm_feature(env, ARM_FEATURE_V8) &&
75
- arm_feature(env, ARM_FEATURE_M) &&
76
- !((mmu_idx & ARM_MMU_IDX_M_NEGPRI) &&
77
- (env->v7m.ccr[env->v7m.secure] & R_V7M_CCR_STKOFHFNMIGN_MASK))) {
78
- flags = FIELD_DP32(flags, TBFLAG_A32, STACKCHECK, 1);
79
- }
80
-
81
if (arm_feature(env, ARM_FEATURE_M_SECURITY) &&
82
FIELD_EX32(env->v7m.fpccr[M_REG_S], V7M_FPCCR, S) != env->v7m.secure) {
83
flags = FIELD_DP32(flags, TBFLAG_A32, FPCCR_S_WRONG, 1);
97
--
84
--
98
2.16.2
85
2.20.1
99
86
100
87
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
Hoist the computation of some TBFLAG_A32 bits that only apply to
4
M-profile under a single test for ARM_FEATURE_M.
5
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20191018174431.1784-7-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/helper.c | 49 +++++++++++++++++++++------------------------
12
1 file changed, 23 insertions(+), 26 deletions(-)
13
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
17
+++ b/target/arm/helper.c
18
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
19
20
if (arm_feature(env, ARM_FEATURE_M)) {
21
flags = rebuild_hflags_m32(env, fp_el, mmu_idx);
22
+
23
+ if (arm_feature(env, ARM_FEATURE_M_SECURITY) &&
24
+ FIELD_EX32(env->v7m.fpccr[M_REG_S], V7M_FPCCR, S)
25
+ != env->v7m.secure) {
26
+ flags = FIELD_DP32(flags, TBFLAG_A32, FPCCR_S_WRONG, 1);
27
+ }
28
+
29
+ if ((env->v7m.fpccr[env->v7m.secure] & R_V7M_FPCCR_ASPEN_MASK) &&
30
+ (!(env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK) ||
31
+ (env->v7m.secure &&
32
+ !(env->v7m.control[M_REG_S] & R_V7M_CONTROL_SFPA_MASK)))) {
33
+ /*
34
+ * ASPEN is set, but FPCA/SFPA indicate that there is no
35
+ * active FP context; we must create a new FP context before
36
+ * executing any FP insn.
37
+ */
38
+ flags = FIELD_DP32(flags, TBFLAG_A32, NEW_FP_CTXT_NEEDED, 1);
39
+ }
40
+
41
+ bool is_secure = env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_S_MASK;
42
+ if (env->v7m.fpccr[is_secure] & R_V7M_FPCCR_LSPACT_MASK) {
43
+ flags = FIELD_DP32(flags, TBFLAG_A32, LSPACT, 1);
44
+ }
45
} else {
46
flags = rebuild_hflags_common_32(env, fp_el, mmu_idx, 0);
47
}
48
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
49
}
50
}
51
52
- if (arm_feature(env, ARM_FEATURE_M_SECURITY) &&
53
- FIELD_EX32(env->v7m.fpccr[M_REG_S], V7M_FPCCR, S) != env->v7m.secure) {
54
- flags = FIELD_DP32(flags, TBFLAG_A32, FPCCR_S_WRONG, 1);
55
- }
56
-
57
- if (arm_feature(env, ARM_FEATURE_M) &&
58
- (env->v7m.fpccr[env->v7m.secure] & R_V7M_FPCCR_ASPEN_MASK) &&
59
- (!(env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK) ||
60
- (env->v7m.secure &&
61
- !(env->v7m.control[M_REG_S] & R_V7M_CONTROL_SFPA_MASK)))) {
62
- /*
63
- * ASPEN is set, but FPCA/SFPA indicate that there is no active
64
- * FP context; we must create a new FP context before executing
65
- * any FP insn.
66
- */
67
- flags = FIELD_DP32(flags, TBFLAG_A32, NEW_FP_CTXT_NEEDED, 1);
68
- }
69
-
70
- if (arm_feature(env, ARM_FEATURE_M)) {
71
- bool is_secure = env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_S_MASK;
72
-
73
- if (env->v7m.fpccr[is_secure] & R_V7M_FPCCR_LSPACT_MASK) {
74
- flags = FIELD_DP32(flags, TBFLAG_A32, LSPACT, 1);
75
- }
76
- }
77
-
78
if (!arm_feature(env, ARM_FEATURE_M)) {
79
int target_el = arm_debug_target_el(env);
80
81
--
82
2.20.1
83
84
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
3
Currently a trivial wrapper for rebuild_hflags_common_32.
4
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180228193125.20577-6-richard.henderson@linaro.org
7
Message-id: 20191018174431.1784-8-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
9
---
8
target/arm/helper.h | 9 +++++
10
target/arm/helper.c | 8 +++++++-
9
target/arm/translate-a64.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++
11
1 file changed, 7 insertions(+), 1 deletion(-)
10
target/arm/vec_helper.c | 74 +++++++++++++++++++++++++++++++++++++++++
11
3 files changed, 166 insertions(+)
12
12
13
diff --git a/target/arm/helper.h b/target/arm/helper.h
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.h
15
--- a/target/arm/helper.c
16
+++ b/target/arm/helper.h
16
+++ b/target/arm/helper.c
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_2(dc_zva, void, env, i64)
17
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_m32(CPUARMState *env, int fp_el,
18
DEF_HELPER_FLAGS_2(neon_pmull_64_lo, TCG_CALL_NO_RWG_SE, i64, i64, i64)
18
return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags);
19
DEF_HELPER_FLAGS_2(neon_pmull_64_hi, TCG_CALL_NO_RWG_SE, i64, i64, i64)
20
21
+DEF_HELPER_FLAGS_5(gvec_qrdmlah_s16, TCG_CALL_NO_RWG,
22
+ void, ptr, ptr, ptr, ptr, i32)
23
+DEF_HELPER_FLAGS_5(gvec_qrdmlsh_s16, TCG_CALL_NO_RWG,
24
+ void, ptr, ptr, ptr, ptr, i32)
25
+DEF_HELPER_FLAGS_5(gvec_qrdmlah_s32, TCG_CALL_NO_RWG,
26
+ void, ptr, ptr, ptr, ptr, i32)
27
+DEF_HELPER_FLAGS_5(gvec_qrdmlsh_s32, TCG_CALL_NO_RWG,
28
+ void, ptr, ptr, ptr, ptr, i32)
29
+
30
#ifdef TARGET_AARCH64
31
#include "helper-a64.h"
32
#endif
33
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/translate-a64.c
36
+++ b/target/arm/translate-a64.c
37
@@ -XXX,XX +XXX,XX @@ static void gen_gvec_op3(DisasContext *s, bool is_q, int rd,
38
vec_full_reg_size(s), gvec_op);
39
}
19
}
40
20
41
+/* Expand a 3-operand + env pointer operation using
21
+static uint32_t rebuild_hflags_a32(CPUARMState *env, int fp_el,
42
+ * an out-of-line helper.
22
+ ARMMMUIdx mmu_idx)
43
+ */
44
+static void gen_gvec_op3_env(DisasContext *s, bool is_q, int rd,
45
+ int rn, int rm, gen_helper_gvec_3_ptr *fn)
46
+{
23
+{
47
+ tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
24
+ return rebuild_hflags_common_32(env, fp_el, mmu_idx, 0);
48
+ vec_full_reg_offset(s, rn),
49
+ vec_full_reg_offset(s, rm), cpu_env,
50
+ is_q ? 16 : 8, vec_full_reg_size(s), 0, fn);
51
+}
25
+}
52
+
26
+
53
/* Set ZF and NF based on a 64 bit result. This is alas fiddlier
27
static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
54
* than the 32 bit equivalent.
28
ARMMMUIdx mmu_idx)
55
*/
56
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_fp16(DisasContext *s, uint32_t insn)
57
clear_vec_high(s, is_q, rd);
58
}
59
60
+/* AdvSIMD three same extra
61
+ * 31 30 29 28 24 23 22 21 20 16 15 14 11 10 9 5 4 0
62
+ * +---+---+---+-----------+------+---+------+---+--------+---+----+----+
63
+ * | 0 | Q | U | 0 1 1 1 0 | size | 0 | Rm | 1 | opcode | 1 | Rn | Rd |
64
+ * +---+---+---+-----------+------+---+------+---+--------+---+----+----+
65
+ */
66
+static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
67
+{
68
+ int rd = extract32(insn, 0, 5);
69
+ int rn = extract32(insn, 5, 5);
70
+ int opcode = extract32(insn, 11, 4);
71
+ int rm = extract32(insn, 16, 5);
72
+ int size = extract32(insn, 22, 2);
73
+ bool u = extract32(insn, 29, 1);
74
+ bool is_q = extract32(insn, 30, 1);
75
+ int feature;
76
+
77
+ switch (u * 16 + opcode) {
78
+ case 0x10: /* SQRDMLAH (vector) */
79
+ case 0x11: /* SQRDMLSH (vector) */
80
+ if (size != 1 && size != 2) {
81
+ unallocated_encoding(s);
82
+ return;
83
+ }
84
+ feature = ARM_FEATURE_V8_RDM;
85
+ break;
86
+ default:
87
+ unallocated_encoding(s);
88
+ return;
89
+ }
90
+ if (!arm_dc_feature(s, feature)) {
91
+ unallocated_encoding(s);
92
+ return;
93
+ }
94
+ if (!fp_access_check(s)) {
95
+ return;
96
+ }
97
+
98
+ switch (opcode) {
99
+ case 0x0: /* SQRDMLAH (vector) */
100
+ switch (size) {
101
+ case 1:
102
+ gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlah_s16);
103
+ break;
104
+ case 2:
105
+ gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlah_s32);
106
+ break;
107
+ default:
108
+ g_assert_not_reached();
109
+ }
110
+ return;
111
+
112
+ case 0x1: /* SQRDMLSH (vector) */
113
+ switch (size) {
114
+ case 1:
115
+ gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlsh_s16);
116
+ break;
117
+ case 2:
118
+ gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlsh_s32);
119
+ break;
120
+ default:
121
+ g_assert_not_reached();
122
+ }
123
+ return;
124
+
125
+ default:
126
+ g_assert_not_reached();
127
+ }
128
+}
129
+
130
static void handle_2misc_widening(DisasContext *s, int opcode, bool is_q,
131
int size, int rn, int rd)
132
{
29
{
133
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_imm2(DisasContext *s, uint32_t insn)
30
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
134
static const AArch64DecodeTable data_proc_simd[] = {
31
flags = FIELD_DP32(flags, TBFLAG_A32, LSPACT, 1);
135
/* pattern , mask , fn */
32
}
136
{ 0x0e200400, 0x9f200400, disas_simd_three_reg_same },
33
} else {
137
+ { 0x0e008400, 0x9f208400, disas_simd_three_reg_same_extra },
34
- flags = rebuild_hflags_common_32(env, fp_el, mmu_idx, 0);
138
{ 0x0e200000, 0x9f200c00, disas_simd_three_reg_diff },
35
+ flags = rebuild_hflags_a32(env, fp_el, mmu_idx);
139
{ 0x0e200800, 0x9f3e0c00, disas_simd_two_reg_misc },
36
}
140
{ 0x0e300800, 0x9f3e0c00, disas_simd_across_lanes },
37
141
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
38
flags = FIELD_DP32(flags, TBFLAG_A32, THUMB, env->thumb);
142
index XXXXXXX..XXXXXXX 100644
143
--- a/target/arm/vec_helper.c
144
+++ b/target/arm/vec_helper.c
145
@@ -XXX,XX +XXX,XX @@
146
147
#define SET_QC() env->vfp.xregs[ARM_VFP_FPSCR] |= CPSR_Q
148
149
+static void clear_tail(void *vd, uintptr_t opr_sz, uintptr_t max_sz)
150
+{
151
+ uint64_t *d = vd + opr_sz;
152
+ uintptr_t i;
153
+
154
+ for (i = opr_sz; i < max_sz; i += 8) {
155
+ *d++ = 0;
156
+ }
157
+}
158
+
159
/* Signed saturating rounding doubling multiply-accumulate high half, 16-bit */
160
static uint16_t inl_qrdmlah_s16(CPUARMState *env, int16_t src1,
161
int16_t src2, int16_t src3)
162
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(neon_qrdmlah_s16)(CPUARMState *env, uint32_t src1,
163
return deposit32(e1, 16, 16, e2);
164
}
165
166
+void HELPER(gvec_qrdmlah_s16)(void *vd, void *vn, void *vm,
167
+ void *ve, uint32_t desc)
168
+{
169
+ uintptr_t opr_sz = simd_oprsz(desc);
170
+ int16_t *d = vd;
171
+ int16_t *n = vn;
172
+ int16_t *m = vm;
173
+ CPUARMState *env = ve;
174
+ uintptr_t i;
175
+
176
+ for (i = 0; i < opr_sz / 2; ++i) {
177
+ d[i] = inl_qrdmlah_s16(env, n[i], m[i], d[i]);
178
+ }
179
+ clear_tail(d, opr_sz, simd_maxsz(desc));
180
+}
181
+
182
/* Signed saturating rounding doubling multiply-subtract high half, 16-bit */
183
static uint16_t inl_qrdmlsh_s16(CPUARMState *env, int16_t src1,
184
int16_t src2, int16_t src3)
185
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(neon_qrdmlsh_s16)(CPUARMState *env, uint32_t src1,
186
return deposit32(e1, 16, 16, e2);
187
}
188
189
+void HELPER(gvec_qrdmlsh_s16)(void *vd, void *vn, void *vm,
190
+ void *ve, uint32_t desc)
191
+{
192
+ uintptr_t opr_sz = simd_oprsz(desc);
193
+ int16_t *d = vd;
194
+ int16_t *n = vn;
195
+ int16_t *m = vm;
196
+ CPUARMState *env = ve;
197
+ uintptr_t i;
198
+
199
+ for (i = 0; i < opr_sz / 2; ++i) {
200
+ d[i] = inl_qrdmlsh_s16(env, n[i], m[i], d[i]);
201
+ }
202
+ clear_tail(d, opr_sz, simd_maxsz(desc));
203
+}
204
+
205
/* Signed saturating rounding doubling multiply-accumulate high half, 32-bit */
206
uint32_t HELPER(neon_qrdmlah_s32)(CPUARMState *env, int32_t src1,
207
int32_t src2, int32_t src3)
208
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(neon_qrdmlah_s32)(CPUARMState *env, int32_t src1,
209
return ret;
210
}
211
212
+void HELPER(gvec_qrdmlah_s32)(void *vd, void *vn, void *vm,
213
+ void *ve, uint32_t desc)
214
+{
215
+ uintptr_t opr_sz = simd_oprsz(desc);
216
+ int32_t *d = vd;
217
+ int32_t *n = vn;
218
+ int32_t *m = vm;
219
+ CPUARMState *env = ve;
220
+ uintptr_t i;
221
+
222
+ for (i = 0; i < opr_sz / 4; ++i) {
223
+ d[i] = helper_neon_qrdmlah_s32(env, n[i], m[i], d[i]);
224
+ }
225
+ clear_tail(d, opr_sz, simd_maxsz(desc));
226
+}
227
+
228
/* Signed saturating rounding doubling multiply-subtract high half, 32-bit */
229
uint32_t HELPER(neon_qrdmlsh_s32)(CPUARMState *env, int32_t src1,
230
int32_t src2, int32_t src3)
231
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(neon_qrdmlsh_s32)(CPUARMState *env, int32_t src1,
232
}
233
return ret;
234
}
235
+
236
+void HELPER(gvec_qrdmlsh_s32)(void *vd, void *vn, void *vm,
237
+ void *ve, uint32_t desc)
238
+{
239
+ uintptr_t opr_sz = simd_oprsz(desc);
240
+ int32_t *d = vd;
241
+ int32_t *n = vn;
242
+ int32_t *m = vm;
243
+ CPUARMState *env = ve;
244
+ uintptr_t i;
245
+
246
+ for (i = 0; i < opr_sz / 4; ++i) {
247
+ d[i] = helper_neon_qrdmlsh_s32(env, n[i], m[i], d[i]);
248
+ }
249
+ clear_tail(d, opr_sz, simd_maxsz(desc));
250
+}
251
--
39
--
252
2.16.2
40
2.20.1
253
41
254
42
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
3
Create a function to compute the values of the TBFLAG_ANY bits
4
that will be cached, and are used by A-profile.
2
5
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180228193125.20577-5-richard.henderson@linaro.org
8
Message-id: 20191018174431.1784-9-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
10
---
8
target/arm/Makefile.objs | 2 +-
11
target/arm/helper.c | 20 ++++++++++++--------
9
target/arm/helper.h | 4 ++
12
1 file changed, 12 insertions(+), 8 deletions(-)
10
target/arm/translate-a64.c | 84 ++++++++++++++++++++++++++++++++++
11
target/arm/vec_helper.c | 109 +++++++++++++++++++++++++++++++++++++++++++++
12
4 files changed, 198 insertions(+), 1 deletion(-)
13
create mode 100644 target/arm/vec_helper.c
14
13
15
diff --git a/target/arm/Makefile.objs b/target/arm/Makefile.objs
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/Makefile.objs
16
--- a/target/arm/helper.c
18
+++ b/target/arm/Makefile.objs
17
+++ b/target/arm/helper.c
19
@@ -XXX,XX +XXX,XX @@ obj-$(call land,$(CONFIG_KVM),$(call lnot,$(TARGET_AARCH64))) += kvm32.o
18
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_m32(CPUARMState *env, int fp_el,
20
obj-$(call land,$(CONFIG_KVM),$(TARGET_AARCH64)) += kvm64.o
19
return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags);
21
obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o
22
obj-y += translate.o op_helper.o helper.o cpu.o
23
-obj-y += neon_helper.o iwmmxt_helper.o
24
+obj-y += neon_helper.o iwmmxt_helper.o vec_helper.o
25
obj-y += gdbstub.o
26
obj-$(TARGET_AARCH64) += cpu64.o translate-a64.o helper-a64.o gdbstub64.o
27
obj-y += crypto_helper.o
28
diff --git a/target/arm/helper.h b/target/arm/helper.h
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/helper.h
31
+++ b/target/arm/helper.h
32
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_1(neon_rbit_u8, TCG_CALL_NO_RWG_SE, i32, i32)
33
34
DEF_HELPER_3(neon_qdmulh_s16, i32, env, i32, i32)
35
DEF_HELPER_3(neon_qrdmulh_s16, i32, env, i32, i32)
36
+DEF_HELPER_4(neon_qrdmlah_s16, i32, env, i32, i32, i32)
37
+DEF_HELPER_4(neon_qrdmlsh_s16, i32, env, i32, i32, i32)
38
DEF_HELPER_3(neon_qdmulh_s32, i32, env, i32, i32)
39
DEF_HELPER_3(neon_qrdmulh_s32, i32, env, i32, i32)
40
+DEF_HELPER_4(neon_qrdmlah_s32, i32, env, s32, s32, s32)
41
+DEF_HELPER_4(neon_qrdmlsh_s32, i32, env, s32, s32, s32)
42
43
DEF_HELPER_1(neon_narrow_u8, i32, i64)
44
DEF_HELPER_1(neon_narrow_u16, i32, i64)
45
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/target/arm/translate-a64.c
48
+++ b/target/arm/translate-a64.c
49
@@ -XXX,XX +XXX,XX @@ static void disas_simd_scalar_three_reg_same_fp16(DisasContext *s,
50
tcg_temp_free_ptr(fpst);
51
}
20
}
52
21
53
+/* AdvSIMD scalar three same extra
22
+static uint32_t rebuild_hflags_aprofile(CPUARMState *env)
54
+ * 31 30 29 28 24 23 22 21 20 16 15 14 11 10 9 5 4 0
55
+ * +-----+---+-----------+------+---+------+---+--------+---+----+----+
56
+ * | 0 1 | U | 1 1 1 1 0 | size | 0 | Rm | 1 | opcode | 1 | Rn | Rd |
57
+ * +-----+---+-----------+------+---+------+---+--------+---+----+----+
58
+ */
59
+static void disas_simd_scalar_three_reg_same_extra(DisasContext *s,
60
+ uint32_t insn)
61
+{
23
+{
62
+ int rd = extract32(insn, 0, 5);
24
+ int flags = 0;
63
+ int rn = extract32(insn, 5, 5);
64
+ int opcode = extract32(insn, 11, 4);
65
+ int rm = extract32(insn, 16, 5);
66
+ int size = extract32(insn, 22, 2);
67
+ bool u = extract32(insn, 29, 1);
68
+ TCGv_i32 ele1, ele2, ele3;
69
+ TCGv_i64 res;
70
+ int feature;
71
+
25
+
72
+ switch (u * 16 + opcode) {
26
+ flags = FIELD_DP32(flags, TBFLAG_ANY, DEBUG_TARGET_EL,
73
+ case 0x10: /* SQRDMLAH (vector) */
27
+ arm_debug_target_el(env));
74
+ case 0x11: /* SQRDMLSH (vector) */
28
+ return flags;
75
+ if (size != 1 && size != 2) {
76
+ unallocated_encoding(s);
77
+ return;
78
+ }
79
+ feature = ARM_FEATURE_V8_RDM;
80
+ break;
81
+ default:
82
+ unallocated_encoding(s);
83
+ return;
84
+ }
85
+ if (!arm_dc_feature(s, feature)) {
86
+ unallocated_encoding(s);
87
+ return;
88
+ }
89
+ if (!fp_access_check(s)) {
90
+ return;
91
+ }
92
+
93
+ /* Do a single operation on the lowest element in the vector.
94
+ * We use the standard Neon helpers and rely on 0 OP 0 == 0
95
+ * with no side effects for all these operations.
96
+ * OPTME: special-purpose helpers would avoid doing some
97
+ * unnecessary work in the helper for the 16 bit cases.
98
+ */
99
+ ele1 = tcg_temp_new_i32();
100
+ ele2 = tcg_temp_new_i32();
101
+ ele3 = tcg_temp_new_i32();
102
+
103
+ read_vec_element_i32(s, ele1, rn, 0, size);
104
+ read_vec_element_i32(s, ele2, rm, 0, size);
105
+ read_vec_element_i32(s, ele3, rd, 0, size);
106
+
107
+ switch (opcode) {
108
+ case 0x0: /* SQRDMLAH */
109
+ if (size == 1) {
110
+ gen_helper_neon_qrdmlah_s16(ele3, cpu_env, ele1, ele2, ele3);
111
+ } else {
112
+ gen_helper_neon_qrdmlah_s32(ele3, cpu_env, ele1, ele2, ele3);
113
+ }
114
+ break;
115
+ case 0x1: /* SQRDMLSH */
116
+ if (size == 1) {
117
+ gen_helper_neon_qrdmlsh_s16(ele3, cpu_env, ele1, ele2, ele3);
118
+ } else {
119
+ gen_helper_neon_qrdmlsh_s32(ele3, cpu_env, ele1, ele2, ele3);
120
+ }
121
+ break;
122
+ default:
123
+ g_assert_not_reached();
124
+ }
125
+ tcg_temp_free_i32(ele1);
126
+ tcg_temp_free_i32(ele2);
127
+
128
+ res = tcg_temp_new_i64();
129
+ tcg_gen_extu_i32_i64(res, ele3);
130
+ tcg_temp_free_i32(ele3);
131
+
132
+ write_fp_dreg(s, rd, res);
133
+ tcg_temp_free_i64(res);
134
+}
29
+}
135
+
30
+
136
static void handle_2misc_64(DisasContext *s, int opcode, bool u,
31
static uint32_t rebuild_hflags_a32(CPUARMState *env, int fp_el,
137
TCGv_i64 tcg_rd, TCGv_i64 tcg_rn,
32
ARMMMUIdx mmu_idx)
138
TCGv_i32 tcg_rmode, TCGv_ptr tcg_fpstatus)
33
{
139
@@ -XXX,XX +XXX,XX @@ static const AArch64DecodeTable data_proc_simd[] = {
34
- return rebuild_hflags_common_32(env, fp_el, mmu_idx, 0);
140
{ 0x0e000800, 0xbf208c00, disas_simd_zip_trn },
35
+ uint32_t flags = rebuild_hflags_aprofile(env);
141
{ 0x2e000000, 0xbf208400, disas_simd_ext },
36
+ return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags);
142
{ 0x5e200400, 0xdf200400, disas_simd_scalar_three_reg_same },
37
}
143
+ { 0x5e008400, 0xdf208400, disas_simd_scalar_three_reg_same_extra },
38
144
{ 0x5e200000, 0xdf200c00, disas_simd_scalar_three_reg_diff },
39
static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
145
{ 0x5e200800, 0xdf3e0c00, disas_simd_scalar_two_reg_misc },
40
ARMMMUIdx mmu_idx)
146
{ 0x5e300800, 0xdf3e0c00, disas_simd_scalar_pairwise },
41
{
147
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
42
+ uint32_t flags = rebuild_hflags_aprofile(env);
148
new file mode 100644
43
ARMMMUIdx stage1 = stage_1_mmu_idx(mmu_idx);
149
index XXXXXXX..XXXXXXX
44
ARMVAParameters p0 = aa64_va_parameters_both(env, 0, stage1);
150
--- /dev/null
45
- uint32_t flags = 0;
151
+++ b/target/arm/vec_helper.c
46
uint64_t sctlr;
152
@@ -XXX,XX +XXX,XX @@
47
int tbii, tbid;
153
+/*
48
154
+ * ARM AdvSIMD / SVE Vector Operations
49
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
155
+ *
50
}
156
+ * Copyright (c) 2018 Linaro
51
}
157
+ *
52
158
+ * This library is free software; you can redistribute it and/or
53
- if (!arm_feature(env, ARM_FEATURE_M)) {
159
+ * modify it under the terms of the GNU Lesser General Public
54
- int target_el = arm_debug_target_el(env);
160
+ * License as published by the Free Software Foundation; either
55
-
161
+ * version 2 of the License, or (at your option) any later version.
56
- flags = FIELD_DP32(flags, TBFLAG_ANY, DEBUG_TARGET_EL, target_el);
162
+ *
57
- }
163
+ * This library is distributed in the hope that it will be useful,
58
-
164
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
59
*pflags = flags;
165
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
60
*cs_base = 0;
166
+ * Lesser General Public License for more details.
61
}
167
+ *
168
+ * You should have received a copy of the GNU Lesser General Public
169
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
170
+ */
171
+
172
+#include "qemu/osdep.h"
173
+#include "cpu.h"
174
+#include "exec/exec-all.h"
175
+#include "exec/helper-proto.h"
176
+#include "tcg/tcg-gvec-desc.h"
177
+
178
+
179
+#define SET_QC() env->vfp.xregs[ARM_VFP_FPSCR] |= CPSR_Q
180
+
181
+/* Signed saturating rounding doubling multiply-accumulate high half, 16-bit */
182
+static uint16_t inl_qrdmlah_s16(CPUARMState *env, int16_t src1,
183
+ int16_t src2, int16_t src3)
184
+{
185
+ /* Simplify:
186
+ * = ((a3 << 16) + ((e1 * e2) << 1) + (1 << 15)) >> 16
187
+ * = ((a3 << 15) + (e1 * e2) + (1 << 14)) >> 15
188
+ */
189
+ int32_t ret = (int32_t)src1 * src2;
190
+ ret = ((int32_t)src3 << 15) + ret + (1 << 14);
191
+ ret >>= 15;
192
+ if (ret != (int16_t)ret) {
193
+ SET_QC();
194
+ ret = (ret < 0 ? -0x8000 : 0x7fff);
195
+ }
196
+ return ret;
197
+}
198
+
199
+uint32_t HELPER(neon_qrdmlah_s16)(CPUARMState *env, uint32_t src1,
200
+ uint32_t src2, uint32_t src3)
201
+{
202
+ uint16_t e1 = inl_qrdmlah_s16(env, src1, src2, src3);
203
+ uint16_t e2 = inl_qrdmlah_s16(env, src1 >> 16, src2 >> 16, src3 >> 16);
204
+ return deposit32(e1, 16, 16, e2);
205
+}
206
+
207
+/* Signed saturating rounding doubling multiply-subtract high half, 16-bit */
208
+static uint16_t inl_qrdmlsh_s16(CPUARMState *env, int16_t src1,
209
+ int16_t src2, int16_t src3)
210
+{
211
+ /* Similarly, using subtraction:
212
+ * = ((a3 << 16) - ((e1 * e2) << 1) + (1 << 15)) >> 16
213
+ * = ((a3 << 15) - (e1 * e2) + (1 << 14)) >> 15
214
+ */
215
+ int32_t ret = (int32_t)src1 * src2;
216
+ ret = ((int32_t)src3 << 15) - ret + (1 << 14);
217
+ ret >>= 15;
218
+ if (ret != (int16_t)ret) {
219
+ SET_QC();
220
+ ret = (ret < 0 ? -0x8000 : 0x7fff);
221
+ }
222
+ return ret;
223
+}
224
+
225
+uint32_t HELPER(neon_qrdmlsh_s16)(CPUARMState *env, uint32_t src1,
226
+ uint32_t src2, uint32_t src3)
227
+{
228
+ uint16_t e1 = inl_qrdmlsh_s16(env, src1, src2, src3);
229
+ uint16_t e2 = inl_qrdmlsh_s16(env, src1 >> 16, src2 >> 16, src3 >> 16);
230
+ return deposit32(e1, 16, 16, e2);
231
+}
232
+
233
+/* Signed saturating rounding doubling multiply-accumulate high half, 32-bit */
234
+uint32_t HELPER(neon_qrdmlah_s32)(CPUARMState *env, int32_t src1,
235
+ int32_t src2, int32_t src3)
236
+{
237
+ /* Simplify similarly to int_qrdmlah_s16 above. */
238
+ int64_t ret = (int64_t)src1 * src2;
239
+ ret = ((int64_t)src3 << 31) + ret + (1 << 30);
240
+ ret >>= 31;
241
+ if (ret != (int32_t)ret) {
242
+ SET_QC();
243
+ ret = (ret < 0 ? INT32_MIN : INT32_MAX);
244
+ }
245
+ return ret;
246
+}
247
+
248
+/* Signed saturating rounding doubling multiply-subtract high half, 32-bit */
249
+uint32_t HELPER(neon_qrdmlsh_s32)(CPUARMState *env, int32_t src1,
250
+ int32_t src2, int32_t src3)
251
+{
252
+ /* Simplify similarly to int_qrdmlsh_s16 above. */
253
+ int64_t ret = (int64_t)src1 * src2;
254
+ ret = ((int64_t)src3 << 31) - ret + (1 << 30);
255
+ ret >>= 31;
256
+ if (ret != (int32_t)ret) {
257
+ SET_QC();
258
+ ret = (ret < 0 ? INT32_MIN : INT32_MAX);
259
+ }
260
+ return ret;
261
+}
262
--
62
--
263
2.16.2
63
2.20.1
264
64
265
65
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Enable it for the "any" CPU used by *-linux-user.
3
We do not need to compute any of these values for M-profile.
4
Further, XSCALE_CPAR overlaps VECSTRIDE so obviously the two
5
sets must be mutually exclusive.
4
6
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20191018174431.1784-10-richard.henderson@linaro.org
7
Message-id: 20180228193125.20577-10-richard.henderson@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
target/arm/cpu.c | 1 +
12
target/arm/helper.c | 21 ++++++++++++++-------
11
target/arm/cpu64.c | 1 +
13
1 file changed, 14 insertions(+), 7 deletions(-)
12
2 files changed, 2 insertions(+)
13
14
14
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.c
17
--- a/target/arm/helper.c
17
+++ b/target/arm/cpu.c
18
+++ b/target/arm/helper.c
18
@@ -XXX,XX +XXX,XX @@ static void arm_any_initfn(Object *obj)
19
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
19
set_feature(&cpu->env, ARM_FEATURE_V8_SHA256);
20
}
20
set_feature(&cpu->env, ARM_FEATURE_V8_PMULL);
21
} else {
21
set_feature(&cpu->env, ARM_FEATURE_CRC);
22
flags = rebuild_hflags_a32(env, fp_el, mmu_idx);
22
+ set_feature(&cpu->env, ARM_FEATURE_V8_RDM);
23
+
23
cpu->midr = 0xffffffff;
24
+ /*
24
}
25
+ * Note that XSCALE_CPAR shares bits with VECSTRIDE.
25
#endif
26
+ * Note that VECLEN+VECSTRIDE are RES0 for M-profile.
26
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
27
+ */
27
index XXXXXXX..XXXXXXX 100644
28
+ if (arm_feature(env, ARM_FEATURE_XSCALE)) {
28
--- a/target/arm/cpu64.c
29
+ flags = FIELD_DP32(flags, TBFLAG_A32,
29
+++ b/target/arm/cpu64.c
30
+ XSCALE_CPAR, env->cp15.c15_cpar);
30
@@ -XXX,XX +XXX,XX @@ static void aarch64_any_initfn(Object *obj)
31
+ } else {
31
set_feature(&cpu->env, ARM_FEATURE_V8_SM4);
32
+ flags = FIELD_DP32(flags, TBFLAG_A32, VECLEN,
32
set_feature(&cpu->env, ARM_FEATURE_V8_PMULL);
33
+ env->vfp.vec_len);
33
set_feature(&cpu->env, ARM_FEATURE_CRC);
34
+ flags = FIELD_DP32(flags, TBFLAG_A32, VECSTRIDE,
34
+ set_feature(&cpu->env, ARM_FEATURE_V8_RDM);
35
+ env->vfp.vec_stride);
35
set_feature(&cpu->env, ARM_FEATURE_V8_FP16);
36
+ }
36
cpu->ctr = 0x80038003; /* 32 byte I and D cacheline size, VIPT icache */
37
}
37
cpu->dcz_blocksize = 7; /* 512 bytes */
38
39
flags = FIELD_DP32(flags, TBFLAG_A32, THUMB, env->thumb);
40
- flags = FIELD_DP32(flags, TBFLAG_A32, VECLEN, env->vfp.vec_len);
41
- flags = FIELD_DP32(flags, TBFLAG_A32, VECSTRIDE, env->vfp.vec_stride);
42
flags = FIELD_DP32(flags, TBFLAG_A32, CONDEXEC, env->condexec_bits);
43
if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)
44
|| arm_el_is_aa64(env, 1) || arm_feature(env, ARM_FEATURE_M)) {
45
flags = FIELD_DP32(flags, TBFLAG_A32, VFPEN, 1);
46
}
47
- /* Note that XSCALE_CPAR shares bits with VECSTRIDE */
48
- if (arm_feature(env, ARM_FEATURE_XSCALE)) {
49
- flags = FIELD_DP32(flags, TBFLAG_A32,
50
- XSCALE_CPAR, env->cp15.c15_cpar);
51
- }
52
}
53
54
/* The SS_ACTIVE and PSTATE_SS bits correspond to the state machine
38
--
55
--
39
2.16.2
56
2.20.1
40
57
41
58
diff view generated by jsdifflib
1
Add remaining easy registers to iotkit-secctl:
1
From: Richard Henderson <richard.henderson@linaro.org>
2
* NSCCFG just routes its two bits out to external GPIO lines
3
* BRGINSTAT/BRGINTCLR/BRGINTEN can be dummies, because QEMU's
4
bus fabric can never report errors
5
2
3
Hoist the variable load for PSTATE into the existing test vs is_a64.
4
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20191018174431.1784-11-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20180220180325.29818-18-peter.maydell@linaro.org
8
---
9
---
9
include/hw/misc/iotkit-secctl.h | 4 ++++
10
target/arm/helper.c | 20 ++++++++------------
10
hw/misc/iotkit-secctl.c | 32 ++++++++++++++++++++++++++------
11
1 file changed, 8 insertions(+), 12 deletions(-)
11
2 files changed, 30 insertions(+), 6 deletions(-)
12
12
13
diff --git a/include/hw/misc/iotkit-secctl.h b/include/hw/misc/iotkit-secctl.h
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/misc/iotkit-secctl.h
15
--- a/target/arm/helper.c
16
+++ b/include/hw/misc/iotkit-secctl.h
16
+++ b/target/arm/helper.c
17
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
18
* + sysbus MMIO region 1 is the "non-secure privilege control block" registers
18
ARMMMUIdx mmu_idx = arm_mmu_idx(env);
19
* + named GPIO output "sec_resp_cfg" indicating whether blocked accesses
19
int current_el = arm_current_el(env);
20
* should RAZ/WI or bus error
20
int fp_el = fp_exception_el(env, current_el);
21
+ * + named GPIO output "nsc_cfg" whose value tracks the NSCCFG register value
21
- uint32_t flags;
22
* Controlling the 2 APB PPCs in the IoTKit:
22
+ uint32_t flags, pstate_for_ss;
23
* + named GPIO outputs apb_ppc0_nonsec[0..2] and apb_ppc1_nonsec
23
24
* + named GPIO outputs apb_ppc0_ap[0..2] and apb_ppc1_ap
24
if (is_a64(env)) {
25
@@ -XXX,XX +XXX,XX @@ struct IoTKitSecCtl {
25
*pc = env->pc;
26
26
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
27
/*< public >*/
27
if (cpu_isar_feature(aa64_bti, env_archcpu(env))) {
28
qemu_irq sec_resp_cfg;
28
flags = FIELD_DP32(flags, TBFLAG_A64, BTYPE, env->btype);
29
+ qemu_irq nsc_cfg_irq;
29
}
30
30
+ pstate_for_ss = env->pstate;
31
MemoryRegion s_regs;
31
} else {
32
MemoryRegion ns_regs;
32
*pc = env->regs[15];
33
@@ -XXX,XX +XXX,XX @@ struct IoTKitSecCtl {
33
34
uint32_t secppcintstat;
34
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
35
uint32_t secppcinten;
35
|| arm_el_is_aa64(env, 1) || arm_feature(env, ARM_FEATURE_M)) {
36
uint32_t secrespcfg;
36
flags = FIELD_DP32(flags, TBFLAG_A32, VFPEN, 1);
37
+ uint32_t nsccfg;
37
}
38
+ uint32_t brginten;
38
+ pstate_for_ss = env->uncached_cpsr;
39
40
IoTKitSecCtlPPC apb[IOTS_NUM_APB_PPC];
41
IoTKitSecCtlPPC apbexp[IOTS_NUM_APB_EXP_PPC];
42
diff --git a/hw/misc/iotkit-secctl.c b/hw/misc/iotkit-secctl.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/hw/misc/iotkit-secctl.c
45
+++ b/hw/misc/iotkit-secctl.c
46
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
47
case A_SECRESPCFG:
48
r = s->secrespcfg;
49
break;
50
+ case A_NSCCFG:
51
+ r = s->nsccfg;
52
+ break;
53
case A_SECPPCINTSTAT:
54
r = s->secppcintstat;
55
break;
56
case A_SECPPCINTEN:
57
r = s->secppcinten;
58
break;
59
+ case A_BRGINTSTAT:
60
+ /* QEMU's bus fabric can never report errors as it doesn't buffer
61
+ * writes, so we never report bridge interrupts.
62
+ */
63
+ r = 0;
64
+ break;
65
+ case A_BRGINTEN:
66
+ r = s->brginten;
67
+ break;
68
case A_AHBNSPPCEXP0:
69
case A_AHBNSPPCEXP1:
70
case A_AHBNSPPCEXP2:
71
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
72
case A_APBSPPPCEXP3:
73
r = s->apbexp[offset_to_ppc_idx(offset)].sp;
74
break;
75
- case A_NSCCFG:
76
case A_SECMPCINTSTATUS:
77
case A_SECMSCINTSTAT:
78
case A_SECMSCINTEN:
79
- case A_BRGINTSTAT:
80
- case A_BRGINTEN:
81
case A_NSMSCEXP:
82
qemu_log_mask(LOG_UNIMP,
83
"IoTKit SecCtl S block read: "
84
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
85
}
39
}
86
40
87
switch (offset) {
41
- /* The SS_ACTIVE and PSTATE_SS bits correspond to the state machine
88
+ case A_NSCCFG:
42
+ /*
89
+ s->nsccfg = value & 3;
43
+ * The SS_ACTIVE and PSTATE_SS bits correspond to the state machine
90
+ qemu_set_irq(s->nsc_cfg_irq, s->nsccfg);
44
* states defined in the ARM ARM for software singlestep:
91
+ break;
45
* SS_ACTIVE PSTATE.SS State
92
case A_SECRESPCFG:
46
* 0 x Inactive (the TB flag for SS is always 0)
93
value &= 1;
47
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
94
s->secrespcfg = value;
48
* 1 1 Active-not-pending
95
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
49
* SS_ACTIVE is set in hflags; PSTATE_SS is computed every TB.
96
s->secppcinten = value & 0x00f000f3;
50
*/
97
foreach_ppc(s, iotkit_secctl_ppc_update_irq_enable);
51
- if (FIELD_EX32(flags, TBFLAG_ANY, SS_ACTIVE)) {
98
break;
52
- if (is_a64(env)) {
99
+ case A_BRGINTCLR:
53
- if (env->pstate & PSTATE_SS) {
100
+ break;
54
- flags = FIELD_DP32(flags, TBFLAG_ANY, PSTATE_SS, 1);
101
+ case A_BRGINTEN:
55
- }
102
+ s->brginten = value & 0xffff0000;
56
- } else {
103
+ break;
57
- if (env->uncached_cpsr & PSTATE_SS) {
104
case A_AHBNSPPCEXP0:
58
- flags = FIELD_DP32(flags, TBFLAG_ANY, PSTATE_SS, 1);
105
case A_AHBNSPPCEXP1:
59
- }
106
case A_AHBNSPPCEXP2:
60
- }
107
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
61
+ if (FIELD_EX32(flags, TBFLAG_ANY, SS_ACTIVE) &&
108
ppc = &s->apbexp[offset_to_ppc_idx(offset)];
62
+ (pstate_for_ss & PSTATE_SS)) {
109
iotkit_secctl_ppc_sp_write(ppc, value);
63
+ flags = FIELD_DP32(flags, TBFLAG_ANY, PSTATE_SS, 1);
110
break;
111
- case A_NSCCFG:
112
case A_SECMSCINTCLR:
113
case A_SECMSCINTEN:
114
- case A_BRGINTCLR:
115
- case A_BRGINTEN:
116
qemu_log_mask(LOG_UNIMP,
117
"IoTKit SecCtl S block write: "
118
"unimplemented offset 0x%x\n", offset);
119
@@ -XXX,XX +XXX,XX @@ static void iotkit_secctl_reset(DeviceState *dev)
120
s->secppcintstat = 0;
121
s->secppcinten = 0;
122
s->secrespcfg = 0;
123
+ s->nsccfg = 0;
124
+ s->brginten = 0;
125
126
foreach_ppc(s, iotkit_secctl_reset_ppc);
127
}
128
@@ -XXX,XX +XXX,XX @@ static void iotkit_secctl_init(Object *obj)
129
}
64
}
130
65
131
qdev_init_gpio_out_named(dev, &s->sec_resp_cfg, "sec_resp_cfg", 1);
66
*pflags = flags;
132
+ qdev_init_gpio_out_named(dev, &s->nsc_cfg_irq, "nsc_cfg", 1);
133
134
memory_region_init_io(&s->s_regs, obj, &iotkit_secctl_s_ops,
135
s, "iotkit-secctl-s-regs", 0x1000);
136
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription iotkit_secctl_vmstate = {
137
VMSTATE_UINT32(secppcintstat, IoTKitSecCtl),
138
VMSTATE_UINT32(secppcinten, IoTKitSecCtl),
139
VMSTATE_UINT32(secrespcfg, IoTKitSecCtl),
140
+ VMSTATE_UINT32(nsccfg, IoTKitSecCtl),
141
+ VMSTATE_UINT32(brginten, IoTKitSecCtl),
142
VMSTATE_STRUCT_ARRAY(apb, IoTKitSecCtl, IOTS_NUM_APB_PPC, 1,
143
iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
144
VMSTATE_STRUCT_ARRAY(apbexp, IoTKitSecCtl, IOTS_NUM_APB_EXP_PPC, 1,
145
--
67
--
146
2.16.2
68
2.20.1
147
69
148
70
diff view generated by jsdifflib
1
The Cortex-M33 allows the system to specify the reset value of the
1
From: Richard Henderson <richard.henderson@linaro.org>
2
secure Vector Table Offset Register (VTOR) by asserting config
3
signals. In particular, guest images for the MPS2 AN505 board rely
4
on the MPS2's initial VTOR being correct for that board.
5
Implement a QEMU property so board and SoC code can set the reset
6
value to the correct value.
7
2
3
There are 3 conditions that each enable this flag. M-profile always
4
enables; A-profile with EL1 as AA64 always enables. Both of these
5
conditions can easily be cached. The final condition relies on the
6
FPEXC register which we are not prepared to cache.
7
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20191018174431.1784-12-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20180220180325.29818-7-peter.maydell@linaro.org
11
---
12
---
12
target/arm/cpu.h | 3 +++
13
target/arm/cpu.h | 2 +-
13
target/arm/cpu.c | 18 ++++++++++++++----
14
target/arm/helper.c | 14 ++++++++++----
14
2 files changed, 17 insertions(+), 4 deletions(-)
15
2 files changed, 11 insertions(+), 5 deletions(-)
15
16
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu.h
19
--- a/target/arm/cpu.h
19
+++ b/target/arm/cpu.h
20
+++ b/target/arm/cpu.h
20
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
21
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_A32, XSCALE_CPAR, 4, 2)
21
*/
22
* the same thing as the current security state of the processor!
22
uint32_t psci_conduit;
23
*/
23
24
FIELD(TBFLAG_A32, NS, 6, 1)
24
+ /* For v8M, initial value of the Secure VTOR */
25
-FIELD(TBFLAG_A32, VFPEN, 7, 1) /* Not cached. */
25
+ uint32_t init_svtor;
26
+FIELD(TBFLAG_A32, VFPEN, 7, 1) /* Partially cached, minus FPEXC. */
27
FIELD(TBFLAG_A32, CONDEXEC, 8, 8) /* Not cached. */
28
FIELD(TBFLAG_A32, SCTLR_B, 16, 1)
29
/* For M profile only, set if FPCCR.LSPACT is set */
30
diff --git a/target/arm/helper.c b/target/arm/helper.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/helper.c
33
+++ b/target/arm/helper.c
34
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_m32(CPUARMState *env, int fp_el,
35
{
36
uint32_t flags = 0;
37
38
+ /* v8M always enables the fpu. */
39
+ flags = FIELD_DP32(flags, TBFLAG_A32, VFPEN, 1);
26
+
40
+
27
/* [QEMU_]KVM_ARM_TARGET_* constant for this CPU, or
41
if (arm_v7m_is_handler_mode(env)) {
28
* QEMU_KVM_ARM_TARGET_NONE if the kernel doesn't support this CPU type.
42
flags = FIELD_DP32(flags, TBFLAG_A32, HANDLER, 1);
29
*/
43
}
30
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
44
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_a32(CPUARMState *env, int fp_el,
31
index XXXXXXX..XXXXXXX 100644
45
ARMMMUIdx mmu_idx)
32
--- a/target/arm/cpu.c
46
{
33
+++ b/target/arm/cpu.c
47
uint32_t flags = rebuild_hflags_aprofile(env);
34
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
35
uint32_t initial_msp; /* Loaded from 0x0 */
36
uint32_t initial_pc; /* Loaded from 0x4 */
37
uint8_t *rom;
38
+ uint32_t vecbase;
39
40
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
41
env->v7m.secure = true;
42
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
43
/* Unlike A/R profile, M profile defines the reset LR value */
44
env->regs[14] = 0xffffffff;
45
46
- /* Load the initial SP and PC from the vector table at address 0 */
47
- rom = rom_ptr(0);
48
+ env->v7m.vecbase[M_REG_S] = cpu->init_svtor & 0xffffff80;
49
+
48
+
50
+ /* Load the initial SP and PC from offset 0 and 4 in the vector table */
49
+ if (arm_el_is_aa64(env, 1)) {
51
+ vecbase = env->v7m.vecbase[env->v7m.secure];
50
+ flags = FIELD_DP32(flags, TBFLAG_A32, VFPEN, 1);
52
+ rom = rom_ptr(vecbase);
51
+ }
53
if (rom) {
52
return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags);
54
/* Address zero is covered by ROM which hasn't yet been
53
}
55
* copied into physical memory.
54
56
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
55
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
57
* it got copied into memory. In the latter case, rom_ptr
56
flags = FIELD_DP32(flags, TBFLAG_A32, VECSTRIDE,
58
* will return a NULL pointer and we should use ldl_phys instead.
57
env->vfp.vec_stride);
59
*/
58
}
60
- initial_msp = ldl_phys(s->as, 0);
59
+ if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) {
61
- initial_pc = ldl_phys(s->as, 4);
60
+ flags = FIELD_DP32(flags, TBFLAG_A32, VFPEN, 1);
62
+ initial_msp = ldl_phys(s->as, vecbase);
61
+ }
63
+ initial_pc = ldl_phys(s->as, vecbase + 4);
64
}
62
}
65
63
66
env->regs[13] = initial_msp & 0xFFFFFFFC;
64
flags = FIELD_DP32(flags, TBFLAG_A32, THUMB, env->thumb);
67
@@ -XXX,XX +XXX,XX @@ static Property arm_cpu_pmsav7_dregion_property =
65
flags = FIELD_DP32(flags, TBFLAG_A32, CONDEXEC, env->condexec_bits);
68
pmsav7_dregion,
66
- if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)
69
qdev_prop_uint32, uint32_t);
67
- || arm_el_is_aa64(env, 1) || arm_feature(env, ARM_FEATURE_M)) {
70
68
- flags = FIELD_DP32(flags, TBFLAG_A32, VFPEN, 1);
71
+/* M profile: initial value of the Secure VTOR */
69
- }
72
+static Property arm_cpu_initsvtor_property =
70
pstate_for_ss = env->uncached_cpsr;
73
+ DEFINE_PROP_UINT32("init-svtor", ARMCPU, init_svtor, 0);
74
+
75
static void arm_cpu_post_init(Object *obj)
76
{
77
ARMCPU *cpu = ARM_CPU(obj);
78
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_post_init(Object *obj)
79
qdev_prop_allow_set_link_before_realize,
80
OBJ_PROP_LINK_UNREF_ON_RELEASE,
81
&error_abort);
82
+ qdev_property_add_static(DEVICE(obj), &arm_cpu_initsvtor_property,
83
+ &error_abort);
84
}
71
}
85
72
86
qdev_property_add_static(DEVICE(obj), &arm_cpu_cfgend_property,
87
--
73
--
88
2.16.2
74
2.20.1
89
75
90
76
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Not enabled anywhere yet.
3
This function assumes nothing about the current state of the cpu,
4
and writes the computed value to env->hflags.
4
5
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180228193125.20577-2-richard.henderson@linaro.org
8
Message-id: 20191018174431.1784-13-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
10
---
11
target/arm/cpu.h | 1 +
11
target/arm/cpu.h | 6 ++++++
12
linux-user/elfload.c | 1 +
12
target/arm/helper.c | 30 ++++++++++++++++++++++--------
13
2 files changed, 2 insertions(+)
13
2 files changed, 28 insertions(+), 8 deletions(-)
14
14
15
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
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/cpu.h
17
--- a/target/arm/cpu.h
18
+++ b/target/arm/cpu.h
18
+++ b/target/arm/cpu.h
19
@@ -XXX,XX +XXX,XX @@ enum arm_features {
19
@@ -XXX,XX +XXX,XX @@ void arm_register_pre_el_change_hook(ARMCPU *cpu, ARMELChangeHookFn *hook,
20
ARM_FEATURE_V8_SHA3, /* implements SHA3 part of v8 Crypto Extensions */
20
void arm_register_el_change_hook(ARMCPU *cpu, ARMELChangeHookFn *hook, void
21
ARM_FEATURE_V8_SM3, /* implements SM3 part of v8 Crypto Extensions */
21
*opaque);
22
ARM_FEATURE_V8_SM4, /* implements SM4 part of v8 Crypto Extensions */
22
23
+ ARM_FEATURE_V8_RDM, /* implements v8.1 simd round multiply */
23
+/**
24
ARM_FEATURE_V8_FP16, /* implements v8.2 half-precision float */
24
+ * arm_rebuild_hflags:
25
};
25
+ * Rebuild the cached TBFLAGS for arbitrary changed processor state.
26
26
+ */
27
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
27
+void arm_rebuild_hflags(CPUARMState *env);
28
+
29
/**
30
* aa32_vfp_dreg:
31
* Return a pointer to the Dn register within env in 32-bit mode.
32
diff --git a/target/arm/helper.c b/target/arm/helper.c
28
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
29
--- a/linux-user/elfload.c
34
--- a/target/arm/helper.c
30
+++ b/linux-user/elfload.c
35
+++ b/target/arm/helper.c
31
@@ -XXX,XX +XXX,XX @@ static uint32_t get_elf_hwcap(void)
36
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
32
GET_FEATURE(ARM_FEATURE_V8_SHA512, ARM_HWCAP_A64_SHA512);
37
return rebuild_hflags_common(env, fp_el, mmu_idx, flags);
33
GET_FEATURE(ARM_FEATURE_V8_FP16,
38
}
34
ARM_HWCAP_A64_FPHP | ARM_HWCAP_A64_ASIMDHP);
39
35
+ GET_FEATURE(ARM_FEATURE_V8_RDM, ARM_HWCAP_A64_ASIMDRDM);
40
+static uint32_t rebuild_hflags_internal(CPUARMState *env)
36
#undef GET_FEATURE
41
+{
37
42
+ int el = arm_current_el(env);
38
return hwcaps;
43
+ int fp_el = fp_exception_el(env, el);
44
+ ARMMMUIdx mmu_idx = arm_mmu_idx(env);
45
+
46
+ if (is_a64(env)) {
47
+ return rebuild_hflags_a64(env, el, fp_el, mmu_idx);
48
+ } else if (arm_feature(env, ARM_FEATURE_M)) {
49
+ return rebuild_hflags_m32(env, fp_el, mmu_idx);
50
+ } else {
51
+ return rebuild_hflags_a32(env, fp_el, mmu_idx);
52
+ }
53
+}
54
+
55
+void arm_rebuild_hflags(CPUARMState *env)
56
+{
57
+ env->hflags = rebuild_hflags_internal(env);
58
+}
59
+
60
void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
61
target_ulong *cs_base, uint32_t *pflags)
62
{
63
- ARMMMUIdx mmu_idx = arm_mmu_idx(env);
64
- int current_el = arm_current_el(env);
65
- int fp_el = fp_exception_el(env, current_el);
66
uint32_t flags, pstate_for_ss;
67
68
+ flags = rebuild_hflags_internal(env);
69
+
70
if (is_a64(env)) {
71
*pc = env->pc;
72
- flags = rebuild_hflags_a64(env, current_el, fp_el, mmu_idx);
73
if (cpu_isar_feature(aa64_bti, env_archcpu(env))) {
74
flags = FIELD_DP32(flags, TBFLAG_A64, BTYPE, env->btype);
75
}
76
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
77
*pc = env->regs[15];
78
79
if (arm_feature(env, ARM_FEATURE_M)) {
80
- flags = rebuild_hflags_m32(env, fp_el, mmu_idx);
81
-
82
if (arm_feature(env, ARM_FEATURE_M_SECURITY) &&
83
FIELD_EX32(env->v7m.fpccr[M_REG_S], V7M_FPCCR, S)
84
!= env->v7m.secure) {
85
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
86
flags = FIELD_DP32(flags, TBFLAG_A32, LSPACT, 1);
87
}
88
} else {
89
- flags = rebuild_hflags_a32(env, fp_el, mmu_idx);
90
-
91
/*
92
* Note that XSCALE_CPAR shares bits with VECSTRIDE.
93
* Note that VECLEN+VECSTRIDE are RES0 for M-profile.
39
--
94
--
40
2.16.2
95
2.20.1
41
96
42
97
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Avoid calling arm_current_el() twice.
4
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Message-id: 20180228193125.20577-13-richard.henderson@linaro.org
8
Message-id: 20191018174431.1784-14-richard.henderson@linaro.org
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
[PMM: renamed e1/e2/e3/e4 to use the same naming as the version
7
of the pseudocode in the Arm ARM]
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
---
10
target/arm/helper.h | 11 ++++
11
target/arm/internals.h | 9 +++++++++
11
target/arm/translate-a64.c | 94 +++++++++++++++++++++++++---
12
target/arm/helper.c | 12 +++++++-----
12
target/arm/vec_helper.c | 149 +++++++++++++++++++++++++++++++++++++++++++++
13
2 files changed, 16 insertions(+), 5 deletions(-)
13
3 files changed, 246 insertions(+), 8 deletions(-)
14
14
15
diff --git a/target/arm/helper.h b/target/arm/helper.h
15
diff --git a/target/arm/internals.h b/target/arm/internals.h
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.h
17
--- a/target/arm/internals.h
18
+++ b/target/arm/helper.h
18
+++ b/target/arm/internals.h
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_fcadds, TCG_CALL_NO_RWG,
19
@@ -XXX,XX +XXX,XX @@ void arm_cpu_update_virq(ARMCPU *cpu);
20
DEF_HELPER_FLAGS_5(gvec_fcaddd, TCG_CALL_NO_RWG,
20
*/
21
void, ptr, ptr, ptr, ptr, i32)
21
void arm_cpu_update_vfiq(ARMCPU *cpu);
22
22
23
+DEF_HELPER_FLAGS_5(gvec_fcmlah, TCG_CALL_NO_RWG,
23
+/**
24
+ void, ptr, ptr, ptr, ptr, i32)
24
+ * arm_mmu_idx_el:
25
+DEF_HELPER_FLAGS_5(gvec_fcmlah_idx, TCG_CALL_NO_RWG,
25
+ * @env: The cpu environment
26
+ void, ptr, ptr, ptr, ptr, i32)
26
+ * @el: The EL to use.
27
+DEF_HELPER_FLAGS_5(gvec_fcmlas, TCG_CALL_NO_RWG,
27
+ *
28
+ void, ptr, ptr, ptr, ptr, i32)
28
+ * Return the full ARMMMUIdx for the translation regime for EL.
29
+DEF_HELPER_FLAGS_5(gvec_fcmlas_idx, TCG_CALL_NO_RWG,
29
+ */
30
+ void, ptr, ptr, ptr, ptr, i32)
30
+ARMMMUIdx arm_mmu_idx_el(CPUARMState *env, int el);
31
+DEF_HELPER_FLAGS_5(gvec_fcmlad, TCG_CALL_NO_RWG,
32
+ void, ptr, ptr, ptr, ptr, i32)
33
+
31
+
34
#ifdef TARGET_AARCH64
32
/**
35
#include "helper-a64.h"
33
* arm_mmu_idx:
34
* @env: The cpu environment
35
diff --git a/target/arm/helper.c b/target/arm/helper.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/arm/helper.c
38
+++ b/target/arm/helper.c
39
@@ -XXX,XX +XXX,XX @@ ARMMMUIdx arm_v7m_mmu_idx_for_secstate(CPUARMState *env, bool secstate)
40
}
36
#endif
41
#endif
37
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
42
38
index XXXXXXX..XXXXXXX 100644
43
-ARMMMUIdx arm_mmu_idx(CPUARMState *env)
39
--- a/target/arm/translate-a64.c
44
+ARMMMUIdx arm_mmu_idx_el(CPUARMState *env, int el)
40
+++ b/target/arm/translate-a64.c
45
{
41
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
46
- int el;
42
}
47
-
43
feature = ARM_FEATURE_V8_RDM;
48
if (arm_feature(env, ARM_FEATURE_M)) {
44
break;
49
return arm_v7m_mmu_idx_for_secstate(env, env->v7m.secure);
45
+ case 0x8: /* FCMLA, #0 */
46
+ case 0x9: /* FCMLA, #90 */
47
+ case 0xa: /* FCMLA, #180 */
48
+ case 0xb: /* FCMLA, #270 */
49
case 0xc: /* FCADD, #90 */
50
case 0xe: /* FCADD, #270 */
51
if (size == 0
52
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
53
}
54
return;
55
56
+ case 0x8: /* FCMLA, #0 */
57
+ case 0x9: /* FCMLA, #90 */
58
+ case 0xa: /* FCMLA, #180 */
59
+ case 0xb: /* FCMLA, #270 */
60
+ rot = extract32(opcode, 0, 2);
61
+ switch (size) {
62
+ case 1:
63
+ gen_gvec_op3_fpst(s, is_q, rd, rn, rm, true, rot,
64
+ gen_helper_gvec_fcmlah);
65
+ break;
66
+ case 2:
67
+ gen_gvec_op3_fpst(s, is_q, rd, rn, rm, false, rot,
68
+ gen_helper_gvec_fcmlas);
69
+ break;
70
+ case 3:
71
+ gen_gvec_op3_fpst(s, is_q, rd, rn, rm, false, rot,
72
+ gen_helper_gvec_fcmlad);
73
+ break;
74
+ default:
75
+ g_assert_not_reached();
76
+ }
77
+ return;
78
+
79
case 0xc: /* FCADD, #90 */
80
case 0xe: /* FCADD, #270 */
81
rot = extract32(opcode, 1, 1);
82
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
83
int rn = extract32(insn, 5, 5);
84
int rd = extract32(insn, 0, 5);
85
bool is_long = false;
86
- bool is_fp = false;
87
+ int is_fp = 0;
88
bool is_fp16 = false;
89
int index;
90
TCGv_ptr fpst;
91
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
92
case 0x05: /* FMLS */
93
case 0x09: /* FMUL */
94
case 0x19: /* FMULX */
95
- is_fp = true;
96
+ is_fp = 1;
97
break;
98
case 0x1d: /* SQRDMLAH */
99
case 0x1f: /* SQRDMLSH */
100
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
101
return;
102
}
103
break;
104
+ case 0x11: /* FCMLA #0 */
105
+ case 0x13: /* FCMLA #90 */
106
+ case 0x15: /* FCMLA #180 */
107
+ case 0x17: /* FCMLA #270 */
108
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_FCMA)) {
109
+ unallocated_encoding(s);
110
+ return;
111
+ }
112
+ is_fp = 2;
113
+ break;
114
default:
115
unallocated_encoding(s);
116
return;
117
}
50
}
118
51
119
- if (is_fp) {
52
- el = arm_current_el(env);
120
+ switch (is_fp) {
53
if (el < 2 && arm_is_secure_below_el3(env)) {
121
+ case 1: /* normal fp */
54
return ARMMMUIdx_S1SE0 + el;
122
/* convert insn encoded size to TCGMemOp size */
55
} else {
123
switch (size) {
56
@@ -XXX,XX +XXX,XX @@ ARMMMUIdx arm_mmu_idx(CPUARMState *env)
124
case 0: /* half-precision */
125
- if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
126
- unallocated_encoding(s);
127
- return;
128
- }
129
size = MO_16;
130
+ is_fp16 = true;
131
break;
132
case MO_32: /* single precision */
133
case MO_64: /* double precision */
134
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
135
unallocated_encoding(s);
136
return;
137
}
138
- } else {
139
+ break;
140
+
141
+ case 2: /* complex fp */
142
+ /* Each indexable element is a complex pair. */
143
+ size <<= 1;
144
+ switch (size) {
145
+ case MO_32:
146
+ if (h && !is_q) {
147
+ unallocated_encoding(s);
148
+ return;
149
+ }
150
+ is_fp16 = true;
151
+ break;
152
+ case MO_64:
153
+ break;
154
+ default:
155
+ unallocated_encoding(s);
156
+ return;
157
+ }
158
+ break;
159
+
160
+ default: /* integer */
161
switch (size) {
162
case MO_8:
163
case MO_64:
164
unallocated_encoding(s);
165
return;
166
}
167
+ break;
168
+ }
169
+ if (is_fp16 && !arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
170
+ unallocated_encoding(s);
171
+ return;
172
}
57
}
173
174
/* Given TCGMemOp size, adjust register and indexing. */
175
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
176
fpst = NULL;
177
}
178
179
+ switch (16 * u + opcode) {
180
+ case 0x11: /* FCMLA #0 */
181
+ case 0x13: /* FCMLA #90 */
182
+ case 0x15: /* FCMLA #180 */
183
+ case 0x17: /* FCMLA #270 */
184
+ tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
185
+ vec_full_reg_offset(s, rn),
186
+ vec_reg_offset(s, rm, index, size), fpst,
187
+ is_q ? 16 : 8, vec_full_reg_size(s),
188
+ extract32(insn, 13, 2), /* rot */
189
+ size == MO_64
190
+ ? gen_helper_gvec_fcmlas_idx
191
+ : gen_helper_gvec_fcmlah_idx);
192
+ tcg_temp_free_ptr(fpst);
193
+ return;
194
+ }
195
+
196
if (size == 3) {
197
TCGv_i64 tcg_idx = tcg_temp_new_i64();
198
int pass;
199
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
200
index XXXXXXX..XXXXXXX 100644
201
--- a/target/arm/vec_helper.c
202
+++ b/target/arm/vec_helper.c
203
@@ -XXX,XX +XXX,XX @@ void HELPER(gvec_fcaddd)(void *vd, void *vn, void *vm,
204
}
205
clear_tail(d, opr_sz, simd_maxsz(desc));
206
}
58
}
207
+
59
208
+void HELPER(gvec_fcmlah)(void *vd, void *vn, void *vm,
60
+ARMMMUIdx arm_mmu_idx(CPUARMState *env)
209
+ void *vfpst, uint32_t desc)
210
+{
61
+{
211
+ uintptr_t opr_sz = simd_oprsz(desc);
62
+ return arm_mmu_idx_el(env, arm_current_el(env));
212
+ float16 *d = vd;
213
+ float16 *n = vn;
214
+ float16 *m = vm;
215
+ float_status *fpst = vfpst;
216
+ intptr_t flip = extract32(desc, SIMD_DATA_SHIFT, 1);
217
+ uint32_t neg_imag = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
218
+ uint32_t neg_real = flip ^ neg_imag;
219
+ uintptr_t i;
220
+
221
+ /* Shift boolean to the sign bit so we can xor to negate. */
222
+ neg_real <<= 15;
223
+ neg_imag <<= 15;
224
+
225
+ for (i = 0; i < opr_sz / 2; i += 2) {
226
+ float16 e2 = n[H2(i + flip)];
227
+ float16 e1 = m[H2(i + flip)] ^ neg_real;
228
+ float16 e4 = e2;
229
+ float16 e3 = m[H2(i + 1 - flip)] ^ neg_imag;
230
+
231
+ d[H2(i)] = float16_muladd(e2, e1, d[H2(i)], 0, fpst);
232
+ d[H2(i + 1)] = float16_muladd(e4, e3, d[H2(i + 1)], 0, fpst);
233
+ }
234
+ clear_tail(d, opr_sz, simd_maxsz(desc));
235
+}
63
+}
236
+
64
+
237
+void HELPER(gvec_fcmlah_idx)(void *vd, void *vn, void *vm,
65
int cpu_mmu_index(CPUARMState *env, bool ifetch)
238
+ void *vfpst, uint32_t desc)
66
{
239
+{
67
return arm_to_core_mmu_idx(arm_mmu_idx(env));
240
+ uintptr_t opr_sz = simd_oprsz(desc);
68
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_internal(CPUARMState *env)
241
+ float16 *d = vd;
69
{
242
+ float16 *n = vn;
70
int el = arm_current_el(env);
243
+ float16 *m = vm;
71
int fp_el = fp_exception_el(env, el);
244
+ float_status *fpst = vfpst;
72
- ARMMMUIdx mmu_idx = arm_mmu_idx(env);
245
+ intptr_t flip = extract32(desc, SIMD_DATA_SHIFT, 1);
73
+ ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el);
246
+ uint32_t neg_imag = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
74
247
+ uint32_t neg_real = flip ^ neg_imag;
75
if (is_a64(env)) {
248
+ uintptr_t i;
76
return rebuild_hflags_a64(env, el, fp_el, mmu_idx);
249
+ float16 e1 = m[H2(flip)];
250
+ float16 e3 = m[H2(1 - flip)];
251
+
252
+ /* Shift boolean to the sign bit so we can xor to negate. */
253
+ neg_real <<= 15;
254
+ neg_imag <<= 15;
255
+ e1 ^= neg_real;
256
+ e3 ^= neg_imag;
257
+
258
+ for (i = 0; i < opr_sz / 2; i += 2) {
259
+ float16 e2 = n[H2(i + flip)];
260
+ float16 e4 = e2;
261
+
262
+ d[H2(i)] = float16_muladd(e2, e1, d[H2(i)], 0, fpst);
263
+ d[H2(i + 1)] = float16_muladd(e4, e3, d[H2(i + 1)], 0, fpst);
264
+ }
265
+ clear_tail(d, opr_sz, simd_maxsz(desc));
266
+}
267
+
268
+void HELPER(gvec_fcmlas)(void *vd, void *vn, void *vm,
269
+ void *vfpst, uint32_t desc)
270
+{
271
+ uintptr_t opr_sz = simd_oprsz(desc);
272
+ float32 *d = vd;
273
+ float32 *n = vn;
274
+ float32 *m = vm;
275
+ float_status *fpst = vfpst;
276
+ intptr_t flip = extract32(desc, SIMD_DATA_SHIFT, 1);
277
+ uint32_t neg_imag = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
278
+ uint32_t neg_real = flip ^ neg_imag;
279
+ uintptr_t i;
280
+
281
+ /* Shift boolean to the sign bit so we can xor to negate. */
282
+ neg_real <<= 31;
283
+ neg_imag <<= 31;
284
+
285
+ for (i = 0; i < opr_sz / 4; i += 2) {
286
+ float32 e2 = n[H4(i + flip)];
287
+ float32 e1 = m[H4(i + flip)] ^ neg_real;
288
+ float32 e4 = e2;
289
+ float32 e3 = m[H4(i + 1 - flip)] ^ neg_imag;
290
+
291
+ d[H4(i)] = float32_muladd(e2, e1, d[H4(i)], 0, fpst);
292
+ d[H4(i + 1)] = float32_muladd(e4, e3, d[H4(i + 1)], 0, fpst);
293
+ }
294
+ clear_tail(d, opr_sz, simd_maxsz(desc));
295
+}
296
+
297
+void HELPER(gvec_fcmlas_idx)(void *vd, void *vn, void *vm,
298
+ void *vfpst, uint32_t desc)
299
+{
300
+ uintptr_t opr_sz = simd_oprsz(desc);
301
+ float32 *d = vd;
302
+ float32 *n = vn;
303
+ float32 *m = vm;
304
+ float_status *fpst = vfpst;
305
+ intptr_t flip = extract32(desc, SIMD_DATA_SHIFT, 1);
306
+ uint32_t neg_imag = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
307
+ uint32_t neg_real = flip ^ neg_imag;
308
+ uintptr_t i;
309
+ float32 e1 = m[H4(flip)];
310
+ float32 e3 = m[H4(1 - flip)];
311
+
312
+ /* Shift boolean to the sign bit so we can xor to negate. */
313
+ neg_real <<= 31;
314
+ neg_imag <<= 31;
315
+ e1 ^= neg_real;
316
+ e3 ^= neg_imag;
317
+
318
+ for (i = 0; i < opr_sz / 4; i += 2) {
319
+ float32 e2 = n[H4(i + flip)];
320
+ float32 e4 = e2;
321
+
322
+ d[H4(i)] = float32_muladd(e2, e1, d[H4(i)], 0, fpst);
323
+ d[H4(i + 1)] = float32_muladd(e4, e3, d[H4(i + 1)], 0, fpst);
324
+ }
325
+ clear_tail(d, opr_sz, simd_maxsz(desc));
326
+}
327
+
328
+void HELPER(gvec_fcmlad)(void *vd, void *vn, void *vm,
329
+ void *vfpst, uint32_t desc)
330
+{
331
+ uintptr_t opr_sz = simd_oprsz(desc);
332
+ float64 *d = vd;
333
+ float64 *n = vn;
334
+ float64 *m = vm;
335
+ float_status *fpst = vfpst;
336
+ intptr_t flip = extract32(desc, SIMD_DATA_SHIFT, 1);
337
+ uint64_t neg_imag = extract32(desc, SIMD_DATA_SHIFT + 1, 1);
338
+ uint64_t neg_real = flip ^ neg_imag;
339
+ uintptr_t i;
340
+
341
+ /* Shift boolean to the sign bit so we can xor to negate. */
342
+ neg_real <<= 63;
343
+ neg_imag <<= 63;
344
+
345
+ for (i = 0; i < opr_sz / 8; i += 2) {
346
+ float64 e2 = n[i + flip];
347
+ float64 e1 = m[i + flip] ^ neg_real;
348
+ float64 e4 = e2;
349
+ float64 e3 = m[i + 1 - flip] ^ neg_imag;
350
+
351
+ d[i] = float64_muladd(e2, e1, d[i], 0, fpst);
352
+ d[i + 1] = float64_muladd(e4, e3, d[i + 1], 0, fpst);
353
+ }
354
+ clear_tail(d, opr_sz, simd_maxsz(desc));
355
+}
356
--
77
--
357
2.16.2
78
2.20.1
358
79
359
80
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The integer size check was already outside of the opcode switch;
3
By performing this store early, we avoid having to save and restore
4
move the floating-point size check outside as well. Unify the
4
the register holding the address around any function calls.
5
size vs index adjustment between fp and integer paths.
6
5
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20191018174431.1784-15-richard.henderson@linaro.org
9
Message-id: 20180228193125.20577-4-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
10
---
12
target/arm/translate-a64.c | 65 +++++++++++++++++++++++-----------------------
11
target/arm/helper.c | 2 +-
13
1 file changed, 32 insertions(+), 33 deletions(-)
12
1 file changed, 1 insertion(+), 1 deletion(-)
14
13
15
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate-a64.c
16
--- a/target/arm/helper.c
18
+++ b/target/arm/translate-a64.c
17
+++ b/target/arm/helper.c
19
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
18
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
20
case 0x05: /* FMLS */
19
{
21
case 0x09: /* FMUL */
20
uint32_t flags, pstate_for_ss;
22
case 0x19: /* FMULX */
21
23
- if (size == 1) {
22
+ *cs_base = 0;
24
- unallocated_encoding(s);
23
flags = rebuild_hflags_internal(env);
25
- return;
24
26
- }
25
if (is_a64(env)) {
27
is_fp = true;
26
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
28
break;
29
default:
30
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
31
if (is_fp) {
32
/* convert insn encoded size to TCGMemOp size */
33
switch (size) {
34
- case 2: /* single precision */
35
- size = MO_32;
36
- index = h << 1 | l;
37
- rm |= (m << 4);
38
- break;
39
- case 3: /* double precision */
40
- size = MO_64;
41
- if (l || !is_q) {
42
+ case 0: /* half-precision */
43
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
44
unallocated_encoding(s);
45
return;
46
}
47
- index = h;
48
- rm |= (m << 4);
49
- break;
50
- case 0: /* half precision */
51
size = MO_16;
52
- index = h << 2 | l << 1 | m;
53
- is_fp16 = true;
54
- if (arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
55
- break;
56
- }
57
- /* fallthru */
58
- default: /* unallocated */
59
- unallocated_encoding(s);
60
- return;
61
- }
62
- } else {
63
- switch (size) {
64
- case 1:
65
- index = h << 2 | l << 1 | m;
66
break;
67
- case 2:
68
- index = h << 1 | l;
69
- rm |= (m << 4);
70
+ case MO_32: /* single precision */
71
+ case MO_64: /* double precision */
72
break;
73
default:
74
unallocated_encoding(s);
75
return;
76
}
77
+ } else {
78
+ switch (size) {
79
+ case MO_8:
80
+ case MO_64:
81
+ unallocated_encoding(s);
82
+ return;
83
+ }
84
+ }
85
+
86
+ /* Given TCGMemOp size, adjust register and indexing. */
87
+ switch (size) {
88
+ case MO_16:
89
+ index = h << 2 | l << 1 | m;
90
+ break;
91
+ case MO_32:
92
+ index = h << 1 | l;
93
+ rm |= m << 4;
94
+ break;
95
+ case MO_64:
96
+ if (l || !is_q) {
97
+ unallocated_encoding(s);
98
+ return;
99
+ }
100
+ index = h;
101
+ rm |= m << 4;
102
+ break;
103
+ default:
104
+ g_assert_not_reached();
105
}
27
}
106
28
107
if (!fp_access_check(s)) {
29
*pflags = flags;
30
- *cs_base = 0;
31
}
32
33
#ifdef TARGET_AARCH64
108
--
34
--
109
2.16.2
35
2.20.1
110
36
111
37
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
3
This functions are given the mode and el state of the cpu
4
and writes the computed value to env->hflags.
2
5
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180228193125.20577-12-richard.henderson@linaro.org
8
Message-id: 20191018174431.1784-16-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
10
---
8
target/arm/helper.h | 7 ++++
11
target/arm/helper.h | 4 ++++
9
target/arm/translate-a64.c | 48 ++++++++++++++++++++++-
12
target/arm/helper.c | 24 ++++++++++++++++++++++++
10
target/arm/vec_helper.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++
13
2 files changed, 28 insertions(+)
11
3 files changed, 151 insertions(+), 1 deletion(-)
12
14
13
diff --git a/target/arm/helper.h b/target/arm/helper.h
15
diff --git a/target/arm/helper.h b/target/arm/helper.h
14
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.h
17
--- a/target/arm/helper.h
16
+++ b/target/arm/helper.h
18
+++ b/target/arm/helper.h
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_qrdmlah_s32, TCG_CALL_NO_RWG,
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_4(msr_banked, void, env, i32, i32, i32)
18
DEF_HELPER_FLAGS_5(gvec_qrdmlsh_s32, TCG_CALL_NO_RWG,
20
DEF_HELPER_2(get_user_reg, i32, env, i32)
19
void, ptr, ptr, ptr, ptr, i32)
21
DEF_HELPER_3(set_user_reg, void, env, i32, i32)
20
22
21
+DEF_HELPER_FLAGS_5(gvec_fcaddh, TCG_CALL_NO_RWG,
23
+DEF_HELPER_FLAGS_2(rebuild_hflags_m32, TCG_CALL_NO_RWG, void, env, int)
22
+ void, ptr, ptr, ptr, ptr, i32)
24
+DEF_HELPER_FLAGS_2(rebuild_hflags_a32, TCG_CALL_NO_RWG, void, env, int)
23
+DEF_HELPER_FLAGS_5(gvec_fcadds, TCG_CALL_NO_RWG,
25
+DEF_HELPER_FLAGS_2(rebuild_hflags_a64, TCG_CALL_NO_RWG, void, env, int)
24
+ void, ptr, ptr, ptr, ptr, i32)
25
+DEF_HELPER_FLAGS_5(gvec_fcaddd, TCG_CALL_NO_RWG,
26
+ void, ptr, ptr, ptr, ptr, i32)
27
+
26
+
28
#ifdef TARGET_AARCH64
27
DEF_HELPER_1(vfp_get_fpscr, i32, env)
29
#include "helper-a64.h"
28
DEF_HELPER_2(vfp_set_fpscr, void, env, i32)
30
#endif
29
31
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
30
diff --git a/target/arm/helper.c b/target/arm/helper.c
32
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/translate-a64.c
32
--- a/target/arm/helper.c
34
+++ b/target/arm/translate-a64.c
33
+++ b/target/arm/helper.c
35
@@ -XXX,XX +XXX,XX @@ static void gen_gvec_op3_env(DisasContext *s, bool is_q, int rd,
34
@@ -XXX,XX +XXX,XX @@ void arm_rebuild_hflags(CPUARMState *env)
36
is_q ? 16 : 8, vec_full_reg_size(s), 0, fn);
35
env->hflags = rebuild_hflags_internal(env);
37
}
36
}
38
37
39
+/* Expand a 3-operand + fpstatus pointer + simd data value operation using
38
+void HELPER(rebuild_hflags_m32)(CPUARMState *env, int el)
40
+ * an out-of-line helper.
41
+ */
42
+static void gen_gvec_op3_fpst(DisasContext *s, bool is_q, int rd, int rn,
43
+ int rm, bool is_fp16, int data,
44
+ gen_helper_gvec_3_ptr *fn)
45
+{
39
+{
46
+ TCGv_ptr fpst = get_fpstatus_ptr(is_fp16);
40
+ int fp_el = fp_exception_el(env, el);
47
+ tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
41
+ ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el);
48
+ vec_full_reg_offset(s, rn),
42
+
49
+ vec_full_reg_offset(s, rm), fpst,
43
+ env->hflags = rebuild_hflags_m32(env, fp_el, mmu_idx);
50
+ is_q ? 16 : 8, vec_full_reg_size(s), data, fn);
51
+ tcg_temp_free_ptr(fpst);
52
+}
44
+}
53
+
45
+
54
/* Set ZF and NF based on a 64 bit result. This is alas fiddlier
46
+void HELPER(rebuild_hflags_a32)(CPUARMState *env, int el)
55
* than the 32 bit equivalent.
47
+{
56
*/
48
+ int fp_el = fp_exception_el(env, el);
57
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
49
+ ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el);
58
int size = extract32(insn, 22, 2);
59
bool u = extract32(insn, 29, 1);
60
bool is_q = extract32(insn, 30, 1);
61
- int feature;
62
+ int feature, rot;
63
64
switch (u * 16 + opcode) {
65
case 0x10: /* SQRDMLAH (vector) */
66
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
67
}
68
feature = ARM_FEATURE_V8_RDM;
69
break;
70
+ case 0xc: /* FCADD, #90 */
71
+ case 0xe: /* FCADD, #270 */
72
+ if (size == 0
73
+ || (size == 1 && !arm_dc_feature(s, ARM_FEATURE_V8_FP16))
74
+ || (size == 3 && !is_q)) {
75
+ unallocated_encoding(s);
76
+ return;
77
+ }
78
+ feature = ARM_FEATURE_V8_FCMA;
79
+ break;
80
default:
81
unallocated_encoding(s);
82
return;
83
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
84
}
85
return;
86
87
+ case 0xc: /* FCADD, #90 */
88
+ case 0xe: /* FCADD, #270 */
89
+ rot = extract32(opcode, 1, 1);
90
+ switch (size) {
91
+ case 1:
92
+ gen_gvec_op3_fpst(s, is_q, rd, rn, rm, size == 1, rot,
93
+ gen_helper_gvec_fcaddh);
94
+ break;
95
+ case 2:
96
+ gen_gvec_op3_fpst(s, is_q, rd, rn, rm, size == 1, rot,
97
+ gen_helper_gvec_fcadds);
98
+ break;
99
+ case 3:
100
+ gen_gvec_op3_fpst(s, is_q, rd, rn, rm, size == 1, rot,
101
+ gen_helper_gvec_fcaddd);
102
+ break;
103
+ default:
104
+ g_assert_not_reached();
105
+ }
106
+ return;
107
+
50
+
108
default:
51
+ env->hflags = rebuild_hflags_a32(env, fp_el, mmu_idx);
109
g_assert_not_reached();
110
}
111
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
112
index XXXXXXX..XXXXXXX 100644
113
--- a/target/arm/vec_helper.c
114
+++ b/target/arm/vec_helper.c
115
@@ -XXX,XX +XXX,XX @@
116
#include "exec/exec-all.h"
117
#include "exec/helper-proto.h"
118
#include "tcg/tcg-gvec-desc.h"
119
+#include "fpu/softfloat.h"
120
121
122
+/* Note that vector data is stored in host-endian 64-bit chunks,
123
+ so addressing units smaller than that needs a host-endian fixup. */
124
+#ifdef HOST_WORDS_BIGENDIAN
125
+#define H1(x) ((x) ^ 7)
126
+#define H2(x) ((x) ^ 3)
127
+#define H4(x) ((x) ^ 1)
128
+#else
129
+#define H1(x) (x)
130
+#define H2(x) (x)
131
+#define H4(x) (x)
132
+#endif
133
+
134
#define SET_QC() env->vfp.xregs[ARM_VFP_FPSCR] |= CPSR_Q
135
136
static void clear_tail(void *vd, uintptr_t opr_sz, uintptr_t max_sz)
137
@@ -XXX,XX +XXX,XX @@ void HELPER(gvec_qrdmlsh_s32)(void *vd, void *vn, void *vm,
138
}
139
clear_tail(d, opr_sz, simd_maxsz(desc));
140
}
141
+
142
+void HELPER(gvec_fcaddh)(void *vd, void *vn, void *vm,
143
+ void *vfpst, uint32_t desc)
144
+{
145
+ uintptr_t opr_sz = simd_oprsz(desc);
146
+ float16 *d = vd;
147
+ float16 *n = vn;
148
+ float16 *m = vm;
149
+ float_status *fpst = vfpst;
150
+ uint32_t neg_real = extract32(desc, SIMD_DATA_SHIFT, 1);
151
+ uint32_t neg_imag = neg_real ^ 1;
152
+ uintptr_t i;
153
+
154
+ /* Shift boolean to the sign bit so we can xor to negate. */
155
+ neg_real <<= 15;
156
+ neg_imag <<= 15;
157
+
158
+ for (i = 0; i < opr_sz / 2; i += 2) {
159
+ float16 e0 = n[H2(i)];
160
+ float16 e1 = m[H2(i + 1)] ^ neg_imag;
161
+ float16 e2 = n[H2(i + 1)];
162
+ float16 e3 = m[H2(i)] ^ neg_real;
163
+
164
+ d[H2(i)] = float16_add(e0, e1, fpst);
165
+ d[H2(i + 1)] = float16_add(e2, e3, fpst);
166
+ }
167
+ clear_tail(d, opr_sz, simd_maxsz(desc));
168
+}
52
+}
169
+
53
+
170
+void HELPER(gvec_fcadds)(void *vd, void *vn, void *vm,
54
+void HELPER(rebuild_hflags_a64)(CPUARMState *env, int el)
171
+ void *vfpst, uint32_t desc)
172
+{
55
+{
173
+ uintptr_t opr_sz = simd_oprsz(desc);
56
+ int fp_el = fp_exception_el(env, el);
174
+ float32 *d = vd;
57
+ ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el);
175
+ float32 *n = vn;
176
+ float32 *m = vm;
177
+ float_status *fpst = vfpst;
178
+ uint32_t neg_real = extract32(desc, SIMD_DATA_SHIFT, 1);
179
+ uint32_t neg_imag = neg_real ^ 1;
180
+ uintptr_t i;
181
+
58
+
182
+ /* Shift boolean to the sign bit so we can xor to negate. */
59
+ env->hflags = rebuild_hflags_a64(env, el, fp_el, mmu_idx);
183
+ neg_real <<= 31;
184
+ neg_imag <<= 31;
185
+
186
+ for (i = 0; i < opr_sz / 4; i += 2) {
187
+ float32 e0 = n[H4(i)];
188
+ float32 e1 = m[H4(i + 1)] ^ neg_imag;
189
+ float32 e2 = n[H4(i + 1)];
190
+ float32 e3 = m[H4(i)] ^ neg_real;
191
+
192
+ d[H4(i)] = float32_add(e0, e1, fpst);
193
+ d[H4(i + 1)] = float32_add(e2, e3, fpst);
194
+ }
195
+ clear_tail(d, opr_sz, simd_maxsz(desc));
196
+}
60
+}
197
+
61
+
198
+void HELPER(gvec_fcaddd)(void *vd, void *vn, void *vm,
62
void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
199
+ void *vfpst, uint32_t desc)
63
target_ulong *cs_base, uint32_t *pflags)
200
+{
64
{
201
+ uintptr_t opr_sz = simd_oprsz(desc);
202
+ float64 *d = vd;
203
+ float64 *n = vn;
204
+ float64 *m = vm;
205
+ float_status *fpst = vfpst;
206
+ uint64_t neg_real = extract64(desc, SIMD_DATA_SHIFT, 1);
207
+ uint64_t neg_imag = neg_real ^ 1;
208
+ uintptr_t i;
209
+
210
+ /* Shift boolean to the sign bit so we can xor to negate. */
211
+ neg_real <<= 63;
212
+ neg_imag <<= 63;
213
+
214
+ for (i = 0; i < opr_sz / 8; i += 2) {
215
+ float64 e0 = n[i];
216
+ float64 e1 = m[i + 1] ^ neg_imag;
217
+ float64 e2 = n[i + 1];
218
+ float64 e3 = m[i] ^ neg_real;
219
+
220
+ d[i] = float64_add(e0, e1, fpst);
221
+ d[i + 1] = float64_add(e2, e3, fpst);
222
+ }
223
+ clear_tail(d, opr_sz, simd_maxsz(desc));
224
+}
225
--
65
--
226
2.16.2
66
2.20.1
227
67
228
68
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Enable it for the "any" CPU used by *-linux-user.
3
Begin setting, but not relying upon, env->hflags.
4
4
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20191018174431.1784-17-richard.henderson@linaro.org
7
Message-id: 20180228193125.20577-17-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
9
---
10
target/arm/cpu.c | 1 +
10
linux-user/syscall.c | 1 +
11
target/arm/cpu64.c | 1 +
11
target/arm/cpu.c | 1 +
12
2 files changed, 2 insertions(+)
12
target/arm/helper-a64.c | 3 +++
13
target/arm/helper.c | 2 ++
14
target/arm/machine.c | 1 +
15
target/arm/op_helper.c | 1 +
16
6 files changed, 9 insertions(+)
13
17
18
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/linux-user/syscall.c
21
+++ b/linux-user/syscall.c
22
@@ -XXX,XX +XXX,XX @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
23
aarch64_sve_narrow_vq(env, vq);
24
}
25
env->vfp.zcr_el[1] = vq - 1;
26
+ arm_rebuild_hflags(env);
27
ret = vq * 16;
28
}
29
return ret;
14
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
30
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
15
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.c
32
--- a/target/arm/cpu.c
17
+++ b/target/arm/cpu.c
33
+++ b/target/arm/cpu.c
18
@@ -XXX,XX +XXX,XX @@ static void arm_any_initfn(Object *obj)
34
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
19
set_feature(&cpu->env, ARM_FEATURE_V8_PMULL);
35
20
set_feature(&cpu->env, ARM_FEATURE_CRC);
36
hw_breakpoint_update_all(cpu);
21
set_feature(&cpu->env, ARM_FEATURE_V8_RDM);
37
hw_watchpoint_update_all(cpu);
22
+ set_feature(&cpu->env, ARM_FEATURE_V8_FCMA);
38
+ arm_rebuild_hflags(env);
23
cpu->midr = 0xffffffff;
24
}
39
}
25
#endif
40
26
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
41
bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
42
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
27
index XXXXXXX..XXXXXXX 100644
43
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/cpu64.c
44
--- a/target/arm/helper-a64.c
29
+++ b/target/arm/cpu64.c
45
+++ b/target/arm/helper-a64.c
30
@@ -XXX,XX +XXX,XX @@ static void aarch64_any_initfn(Object *obj)
46
@@ -XXX,XX +XXX,XX @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
31
set_feature(&cpu->env, ARM_FEATURE_CRC);
47
} else {
32
set_feature(&cpu->env, ARM_FEATURE_V8_RDM);
48
env->regs[15] = new_pc & ~0x3;
33
set_feature(&cpu->env, ARM_FEATURE_V8_FP16);
49
}
34
+ set_feature(&cpu->env, ARM_FEATURE_V8_FCMA);
50
+ helper_rebuild_hflags_a32(env, new_el);
35
cpu->ctr = 0x80038003; /* 32 byte I and D cacheline size, VIPT icache */
51
qemu_log_mask(CPU_LOG_INT, "Exception return from AArch64 EL%d to "
36
cpu->dcz_blocksize = 7; /* 512 bytes */
52
"AArch32 EL%d PC 0x%" PRIx32 "\n",
53
cur_el, new_el, env->regs[15]);
54
@@ -XXX,XX +XXX,XX @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
55
}
56
aarch64_restore_sp(env, new_el);
57
env->pc = new_pc;
58
+ helper_rebuild_hflags_a64(env, new_el);
59
qemu_log_mask(CPU_LOG_INT, "Exception return from AArch64 EL%d to "
60
"AArch64 EL%d PC 0x%" PRIx64 "\n",
61
cur_el, new_el, env->pc);
62
}
63
+
64
/*
65
* Note that cur_el can never be 0. If new_el is 0, then
66
* el0_a64 is return_to_aa64, else el0_a64 is ignored.
67
diff --git a/target/arm/helper.c b/target/arm/helper.c
68
index XXXXXXX..XXXXXXX 100644
69
--- a/target/arm/helper.c
70
+++ b/target/arm/helper.c
71
@@ -XXX,XX +XXX,XX @@ static void take_aarch32_exception(CPUARMState *env, int new_mode,
72
env->regs[14] = env->regs[15] + offset;
73
}
74
env->regs[15] = newpc;
75
+ arm_rebuild_hflags(env);
37
}
76
}
77
78
static void arm_cpu_do_interrupt_aarch32_hyp(CPUState *cs)
79
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
80
pstate_write(env, PSTATE_DAIF | new_mode);
81
env->aarch64 = 1;
82
aarch64_restore_sp(env, new_el);
83
+ helper_rebuild_hflags_a64(env, new_el);
84
85
env->pc = addr;
86
87
diff --git a/target/arm/machine.c b/target/arm/machine.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/target/arm/machine.c
90
+++ b/target/arm/machine.c
91
@@ -XXX,XX +XXX,XX @@ static int cpu_post_load(void *opaque, int version_id)
92
if (!kvm_enabled()) {
93
pmu_op_finish(&cpu->env);
94
}
95
+ arm_rebuild_hflags(&cpu->env);
96
97
return 0;
98
}
99
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
100
index XXXXXXX..XXXXXXX 100644
101
--- a/target/arm/op_helper.c
102
+++ b/target/arm/op_helper.c
103
@@ -XXX,XX +XXX,XX @@ void HELPER(cpsr_write_eret)(CPUARMState *env, uint32_t val)
104
* state. Do the masking now.
105
*/
106
env->regs[15] &= (env->thumb ? ~1 : ~3);
107
+ arm_rebuild_hflags(env);
108
109
qemu_mutex_lock_iothread();
110
arm_call_el_change_hook(env_archcpu(env));
38
--
111
--
39
2.16.2
112
2.20.1
40
113
41
114
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
3
Continue setting, but not relying upon, env->hflags.
2
4
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180228193125.20577-7-richard.henderson@linaro.org
7
Message-id: 20191018174431.1784-18-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
9
---
8
target/arm/translate-a64.c | 29 +++++++++++++++++++++++++++++
10
target/arm/translate-a64.c | 13 +++++++++++--
9
1 file changed, 29 insertions(+)
11
target/arm/translate.c | 28 +++++++++++++++++++++++-----
12
2 files changed, 34 insertions(+), 7 deletions(-)
10
13
11
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
14
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
12
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate-a64.c
16
--- a/target/arm/translate-a64.c
14
+++ b/target/arm/translate-a64.c
17
+++ b/target/arm/translate-a64.c
15
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
18
@@ -XXX,XX +XXX,XX @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
16
case 0x19: /* FMULX */
19
if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
17
is_fp = true;
20
/* I/O operations must end the TB here (whether read or write) */
18
break;
21
s->base.is_jmp = DISAS_UPDATE;
19
+ case 0x1d: /* SQRDMLAH */
22
- } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
20
+ case 0x1f: /* SQRDMLSH */
23
- /* We default to ending the TB on a coprocessor register write,
21
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_RDM)) {
24
+ }
22
+ unallocated_encoding(s);
25
+ if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
23
+ return;
26
+ /*
27
+ * A write to any coprocessor regiser that ends a TB
28
+ * must rebuild the hflags for the next TB.
29
+ */
30
+ TCGv_i32 tcg_el = tcg_const_i32(s->current_el);
31
+ gen_helper_rebuild_hflags_a64(cpu_env, tcg_el);
32
+ tcg_temp_free_i32(tcg_el);
33
+ /*
34
+ * We default to ending the TB on a coprocessor register write,
35
* but allow this to be suppressed by the register definition
36
* (usually only necessary to work around guest bugs).
37
*/
38
diff --git a/target/arm/translate.c b/target/arm/translate.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/target/arm/translate.c
41
+++ b/target/arm/translate.c
42
@@ -XXX,XX +XXX,XX @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn)
43
ri = get_arm_cp_reginfo(s->cp_regs,
44
ENCODE_CP_REG(cpnum, is64, s->ns, crn, crm, opc1, opc2));
45
if (ri) {
46
+ bool need_exit_tb;
47
+
48
/* Check access permissions */
49
if (!cp_access_ok(s->current_el, ri, isread)) {
50
return 1;
51
@@ -XXX,XX +XXX,XX @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn)
52
}
53
}
54
55
- if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
56
- /* I/O operations must end the TB here (whether read or write) */
57
- gen_lookup_tb(s);
58
- } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
59
- /* We default to ending the TB on a coprocessor register write,
60
+ /* I/O operations must end the TB here (whether read or write) */
61
+ need_exit_tb = ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) &&
62
+ (ri->type & ARM_CP_IO));
63
+
64
+ if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
65
+ /*
66
+ * A write to any coprocessor regiser that ends a TB
67
+ * must rebuild the hflags for the next TB.
68
+ */
69
+ TCGv_i32 tcg_el = tcg_const_i32(s->current_el);
70
+ if (arm_dc_feature(s, ARM_FEATURE_M)) {
71
+ gen_helper_rebuild_hflags_m32(cpu_env, tcg_el);
72
+ } else {
73
+ gen_helper_rebuild_hflags_a32(cpu_env, tcg_el);
74
+ }
75
+ tcg_temp_free_i32(tcg_el);
76
+ /*
77
+ * We default to ending the TB on a coprocessor register write,
78
* but allow this to be suppressed by the register definition
79
* (usually only necessary to work around guest bugs).
80
*/
81
+ need_exit_tb = true;
24
+ }
82
+ }
25
+ break;
83
+ if (need_exit_tb) {
26
default:
84
gen_lookup_tb(s);
27
unallocated_encoding(s);
85
}
28
return;
86
29
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
30
tcg_op, tcg_idx);
31
}
32
break;
33
+ case 0x1d: /* SQRDMLAH */
34
+ read_vec_element_i32(s, tcg_res, rd, pass,
35
+ is_scalar ? size : MO_32);
36
+ if (size == 1) {
37
+ gen_helper_neon_qrdmlah_s16(tcg_res, cpu_env,
38
+ tcg_op, tcg_idx, tcg_res);
39
+ } else {
40
+ gen_helper_neon_qrdmlah_s32(tcg_res, cpu_env,
41
+ tcg_op, tcg_idx, tcg_res);
42
+ }
43
+ break;
44
+ case 0x1f: /* SQRDMLSH */
45
+ read_vec_element_i32(s, tcg_res, rd, pass,
46
+ is_scalar ? size : MO_32);
47
+ if (size == 1) {
48
+ gen_helper_neon_qrdmlsh_s16(tcg_res, cpu_env,
49
+ tcg_op, tcg_idx, tcg_res);
50
+ } else {
51
+ gen_helper_neon_qrdmlsh_s32(tcg_res, cpu_env,
52
+ tcg_op, tcg_idx, tcg_res);
53
+ }
54
+ break;
55
default:
56
g_assert_not_reached();
57
}
58
--
87
--
59
2.16.2
88
2.20.1
60
89
61
90
diff view generated by jsdifflib
1
From: Alistair Francis <alistair.francis@xilinx.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
3
Continue setting, but not relying upon, env->hflags.
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20191018174431.1784-19-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
9
---
8
include/hw/arm/xlnx-zynqmp.h | 2 ++
10
target/arm/op_helper.c | 3 +++
9
hw/arm/xlnx-zynqmp.c | 14 ++++++++++++++
11
1 file changed, 3 insertions(+)
10
2 files changed, 16 insertions(+)
11
12
12
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
13
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
13
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
14
--- a/include/hw/arm/xlnx-zynqmp.h
15
--- a/target/arm/op_helper.c
15
+++ b/include/hw/arm/xlnx-zynqmp.h
16
+++ b/target/arm/op_helper.c
16
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(usat16)(CPUARMState *env, uint32_t x, uint32_t shift)
17
#include "hw/dma/xlnx_dpdma.h"
18
void HELPER(setend)(CPUARMState *env)
18
#include "hw/display/xlnx_dp.h"
19
{
19
#include "hw/intc/xlnx-zynqmp-ipi.h"
20
env->uncached_cpsr ^= CPSR_E;
20
+#include "hw/timer/xlnx-zynqmp-rtc.h"
21
+ arm_rebuild_hflags(env);
21
22
#define TYPE_XLNX_ZYNQMP "xlnx,zynqmp"
23
#define XLNX_ZYNQMP(obj) OBJECT_CHECK(XlnxZynqMPState, (obj), \
24
@@ -XXX,XX +XXX,XX @@ typedef struct XlnxZynqMPState {
25
XlnxDPState dp;
26
XlnxDPDMAState dpdma;
27
XlnxZynqMPIPI ipi;
28
+ XlnxZynqMPRTC rtc;
29
30
char *boot_cpu;
31
ARMCPU *boot_cpu_ptr;
32
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/hw/arm/xlnx-zynqmp.c
35
+++ b/hw/arm/xlnx-zynqmp.c
36
@@ -XXX,XX +XXX,XX @@
37
#define IPI_ADDR 0xFF300000
38
#define IPI_IRQ 64
39
40
+#define RTC_ADDR 0xffa60000
41
+#define RTC_IRQ 26
42
+
43
#define SDHCI_CAPABILITIES 0x280737ec6481 /* Datasheet: UG1085 (v1.7) */
44
45
static const uint64_t gem_addr[XLNX_ZYNQMP_NUM_GEMS] = {
46
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_init(Object *obj)
47
48
object_initialize(&s->ipi, sizeof(s->ipi), TYPE_XLNX_ZYNQMP_IPI);
49
qdev_set_parent_bus(DEVICE(&s->ipi), sysbus_get_default());
50
+
51
+ object_initialize(&s->rtc, sizeof(s->rtc), TYPE_XLNX_ZYNQMP_RTC);
52
+ qdev_set_parent_bus(DEVICE(&s->rtc), sysbus_get_default());
53
}
22
}
54
23
55
static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
24
/* Function checks whether WFx (WFI/WFE) instructions are set up to be trapped.
56
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
25
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(cpsr_read)(CPUARMState *env)
57
}
26
void HELPER(cpsr_write)(CPUARMState *env, uint32_t val, uint32_t mask)
58
sysbus_mmio_map(SYS_BUS_DEVICE(&s->ipi), 0, IPI_ADDR);
27
{
59
sysbus_connect_irq(SYS_BUS_DEVICE(&s->ipi), 0, gic_spi[IPI_IRQ]);
28
cpsr_write(env, val, mask, CPSRWriteByInstr);
60
+
29
+ /* TODO: Not all cpsr bits are relevant to hflags. */
61
+ object_property_set_bool(OBJECT(&s->rtc), true, "realized", &err);
30
+ arm_rebuild_hflags(env);
62
+ if (err) {
63
+ error_propagate(errp, err);
64
+ return;
65
+ }
66
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->rtc), 0, RTC_ADDR);
67
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->rtc), 0, gic_spi[RTC_IRQ]);
68
}
31
}
69
32
70
static Property xlnx_zynqmp_props[] = {
33
/* Write the CPSR for a 32-bit exception return */
71
--
34
--
72
2.16.2
35
2.20.1
73
36
74
37
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Happily, the bits are in the same places compared to a32.
3
Continue setting, but not relying upon, env->hflags.
4
4
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20180228193125.20577-16-richard.henderson@linaro.org
6
Message-id: 20191018174431.1784-20-richard.henderson@linaro.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
9
---
10
target/arm/translate.c | 14 +++++++++++++-
10
target/arm/helper.c | 10 ++++++++++
11
1 file changed, 13 insertions(+), 1 deletion(-)
11
1 file changed, 10 insertions(+)
12
12
13
diff --git a/target/arm/translate.c b/target/arm/translate.c
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate.c
15
--- a/target/arm/helper.c
16
+++ b/target/arm/translate.c
16
+++ b/target/arm/helper.c
17
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
17
@@ -XXX,XX +XXX,XX @@ static void sctlr_write(CPUARMState *env, const ARMCPRegInfo *ri,
18
default_exception_el(s));
18
/* ??? Lots of these bits are not implemented. */
19
break;
19
/* This may enable/disable the MMU, so do a TLB flush. */
20
}
20
tlb_flush(CPU(cpu));
21
- if (((insn >> 24) & 3) == 3) {
21
+
22
+ if ((insn & 0xfe000a00) == 0xfc000800
22
+ if (ri->type & ARM_CP_SUPPRESS_TB_END) {
23
+ && arm_dc_feature(s, ARM_FEATURE_V8)) {
23
+ /*
24
+ /* The Thumb2 and ARM encodings are identical. */
24
+ * Normally we would always end the TB on an SCTLR write; see the
25
+ if (disas_neon_insn_3same_ext(s, insn)) {
25
+ * comment in ARMCPRegInfo sctlr initialization below for why Xscale
26
+ goto illegal_op;
26
+ * is special. Setting ARM_CP_SUPPRESS_TB_END also stops the rebuild
27
+ }
27
+ * of hflags from the translator, so do it here.
28
+ } else if ((insn & 0xff000a00) == 0xfe000800
28
+ */
29
+ && arm_dc_feature(s, ARM_FEATURE_V8)) {
29
+ arm_rebuild_hflags(env);
30
+ /* The Thumb2 and ARM encodings are identical. */
30
+ }
31
+ if (disas_neon_insn_2reg_scalar_ext(s, insn)) {
31
}
32
+ goto illegal_op;
32
33
+ }
33
static CPAccessResult fpexc32_access(CPUARMState *env, const ARMCPRegInfo *ri,
34
+ } else if (((insn >> 24) & 3) == 3) {
35
/* Translate into the equivalent ARM encoding. */
36
insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
37
if (disas_neon_data_insn(s, insn)) {
38
--
34
--
39
2.16.2
35
2.20.1
40
36
41
37
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
3
Continue setting, but not relying upon, env->hflags.
4
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180228193125.20577-8-richard.henderson@linaro.org
7
Message-id: 20191018174431.1784-21-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
9
---
8
target/arm/translate.c | 86 +++++++++++++++++++++++++++++++++++++++-----------
10
target/arm/m_helper.c | 6 ++++++
9
1 file changed, 67 insertions(+), 19 deletions(-)
11
target/arm/translate.c | 5 ++++-
12
2 files changed, 10 insertions(+), 1 deletion(-)
10
13
14
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/m_helper.c
17
+++ b/target/arm/m_helper.c
18
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_bxns)(CPUARMState *env, uint32_t dest)
19
switch_v7m_security_state(env, dest & 1);
20
env->thumb = 1;
21
env->regs[15] = dest & ~1;
22
+ arm_rebuild_hflags(env);
23
}
24
25
void HELPER(v7m_blxns)(CPUARMState *env, uint32_t dest)
26
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_blxns)(CPUARMState *env, uint32_t dest)
27
switch_v7m_security_state(env, 0);
28
env->thumb = 1;
29
env->regs[15] = dest;
30
+ arm_rebuild_hflags(env);
31
}
32
33
static uint32_t *get_v7m_sp_ptr(CPUARMState *env, bool secure, bool threadmode,
34
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
35
env->regs[14] = lr;
36
env->regs[15] = addr & 0xfffffffe;
37
env->thumb = addr & 1;
38
+ arm_rebuild_hflags(env);
39
}
40
41
static void v7m_update_fpccr(CPUARMState *env, uint32_t frameptr,
42
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
43
44
/* Otherwise, we have a successful exception exit. */
45
arm_clear_exclusive(env);
46
+ arm_rebuild_hflags(env);
47
qemu_log_mask(CPU_LOG_INT, "...successful exception return\n");
48
}
49
50
@@ -XXX,XX +XXX,XX @@ static bool do_v7m_function_return(ARMCPU *cpu)
51
xpsr_write(env, 0, XPSR_IT);
52
env->thumb = newpc & 1;
53
env->regs[15] = newpc & ~1;
54
+ arm_rebuild_hflags(env);
55
56
qemu_log_mask(CPU_LOG_INT, "...function return successful\n");
57
return true;
58
@@ -XXX,XX +XXX,XX @@ static bool v7m_handle_execute_nsc(ARMCPU *cpu)
59
switch_v7m_security_state(env, true);
60
xpsr_write(env, 0, XPSR_IT);
61
env->regs[15] += 4;
62
+ arm_rebuild_hflags(env);
63
return true;
64
65
gen_invep:
11
diff --git a/target/arm/translate.c b/target/arm/translate.c
66
diff --git a/target/arm/translate.c b/target/arm/translate.c
12
index XXXXXXX..XXXXXXX 100644
67
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate.c
68
--- a/target/arm/translate.c
14
+++ b/target/arm/translate.c
69
+++ b/target/arm/translate.c
15
@@ -XXX,XX +XXX,XX @@
70
@@ -XXX,XX +XXX,XX @@ static bool trans_MRS_v7m(DisasContext *s, arg_MRS_v7m *a)
16
#include "disas/disas.h"
71
17
#include "exec/exec-all.h"
72
static bool trans_MSR_v7m(DisasContext *s, arg_MSR_v7m *a)
18
#include "tcg-op.h"
73
{
19
+#include "tcg-op-gvec.h"
74
- TCGv_i32 addr, reg;
20
#include "qemu/log.h"
75
+ TCGv_i32 addr, reg, el;
21
#include "qemu/bitops.h"
76
22
#include "arm_ldst.h"
77
if (!arm_dc_feature(s, ARM_FEATURE_M)) {
23
@@ -XXX,XX +XXX,XX @@ static void gen_neon_narrow_op(int op, int u, int size,
78
return false;
24
#define NEON_3R_VPMAX 20
79
@@ -XXX,XX +XXX,XX @@ static bool trans_MSR_v7m(DisasContext *s, arg_MSR_v7m *a)
25
#define NEON_3R_VPMIN 21
80
gen_helper_v7m_msr(cpu_env, addr, reg);
26
#define NEON_3R_VQDMULH_VQRDMULH 22
81
tcg_temp_free_i32(addr);
27
-#define NEON_3R_VPADD 23
82
tcg_temp_free_i32(reg);
28
+#define NEON_3R_VPADD_VQRDMLAH 23
83
+ el = tcg_const_i32(s->current_el);
29
#define NEON_3R_SHA 24 /* SHA1C,SHA1P,SHA1M,SHA1SU0,SHA256H{2},SHA256SU1 */
84
+ gen_helper_rebuild_hflags_m32(cpu_env, el);
30
-#define NEON_3R_VFM 25 /* VFMA, VFMS : float fused multiply-add */
85
+ tcg_temp_free_i32(el);
31
+#define NEON_3R_VFM_VQRDMLSH 25 /* VFMA, VFMS, VQRDMLSH */
86
gen_lookup_tb(s);
32
#define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */
87
return true;
33
#define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */
88
}
34
#define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */
35
@@ -XXX,XX +XXX,XX @@ static const uint8_t neon_3r_sizes[] = {
36
[NEON_3R_VPMAX] = 0x7,
37
[NEON_3R_VPMIN] = 0x7,
38
[NEON_3R_VQDMULH_VQRDMULH] = 0x6,
39
- [NEON_3R_VPADD] = 0x7,
40
+ [NEON_3R_VPADD_VQRDMLAH] = 0x7,
41
[NEON_3R_SHA] = 0xf, /* size field encodes op type */
42
- [NEON_3R_VFM] = 0x5, /* size bit 1 encodes op */
43
+ [NEON_3R_VFM_VQRDMLSH] = 0x7, /* For VFM, size bit 1 encodes op */
44
[NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */
45
[NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */
46
[NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */
47
@@ -XXX,XX +XXX,XX @@ static const uint8_t neon_2rm_sizes[] = {
48
[NEON_2RM_VCVT_UF] = 0x4,
49
};
50
51
+
52
+/* Expand v8.1 simd helper. */
53
+static int do_v81_helper(DisasContext *s, gen_helper_gvec_3_ptr *fn,
54
+ int q, int rd, int rn, int rm)
55
+{
56
+ if (arm_dc_feature(s, ARM_FEATURE_V8_RDM)) {
57
+ int opr_sz = (1 + q) * 8;
58
+ tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
59
+ vfp_reg_offset(1, rn),
60
+ vfp_reg_offset(1, rm), cpu_env,
61
+ opr_sz, opr_sz, 0, fn);
62
+ return 0;
63
+ }
64
+ return 1;
65
+}
66
+
67
/* Translate a NEON data processing instruction. Return nonzero if the
68
instruction is invalid.
69
We process data in a mixture of 32-bit and 64-bit chunks.
70
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
71
if (q && ((rd | rn | rm) & 1)) {
72
return 1;
73
}
74
- /*
75
- * The SHA-1/SHA-256 3-register instructions require special treatment
76
- * here, as their size field is overloaded as an op type selector, and
77
- * they all consume their input in a single pass.
78
- */
79
- if (op == NEON_3R_SHA) {
80
+ switch (op) {
81
+ case NEON_3R_SHA:
82
+ /* The SHA-1/SHA-256 3-register instructions require special
83
+ * treatment here, as their size field is overloaded as an
84
+ * op type selector, and they all consume their input in a
85
+ * single pass.
86
+ */
87
if (!q) {
88
return 1;
89
}
90
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
91
tcg_temp_free_ptr(ptr2);
92
tcg_temp_free_ptr(ptr3);
93
return 0;
94
+
95
+ case NEON_3R_VPADD_VQRDMLAH:
96
+ if (!u) {
97
+ break; /* VPADD */
98
+ }
99
+ /* VQRDMLAH */
100
+ switch (size) {
101
+ case 1:
102
+ return do_v81_helper(s, gen_helper_gvec_qrdmlah_s16,
103
+ q, rd, rn, rm);
104
+ case 2:
105
+ return do_v81_helper(s, gen_helper_gvec_qrdmlah_s32,
106
+ q, rd, rn, rm);
107
+ }
108
+ return 1;
109
+
110
+ case NEON_3R_VFM_VQRDMLSH:
111
+ if (!u) {
112
+ /* VFM, VFMS */
113
+ if (size == 1) {
114
+ return 1;
115
+ }
116
+ break;
117
+ }
118
+ /* VQRDMLSH */
119
+ switch (size) {
120
+ case 1:
121
+ return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s16,
122
+ q, rd, rn, rm);
123
+ case 2:
124
+ return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s32,
125
+ q, rd, rn, rm);
126
+ }
127
+ return 1;
128
}
129
if (size == 3 && op != NEON_3R_LOGIC) {
130
/* 64-bit element instructions. */
131
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
132
rm = rtmp;
133
}
134
break;
135
- case NEON_3R_VPADD:
136
- if (u) {
137
- return 1;
138
- }
139
- /* Fall through */
140
+ case NEON_3R_VPADD_VQRDMLAH:
141
case NEON_3R_VPMAX:
142
case NEON_3R_VPMIN:
143
pairwise = 1;
144
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
145
return 1;
146
}
147
break;
148
- case NEON_3R_VFM:
149
- if (!arm_dc_feature(s, ARM_FEATURE_VFP4) || u) {
150
+ case NEON_3R_VFM_VQRDMLSH:
151
+ if (!arm_dc_feature(s, ARM_FEATURE_VFP4)) {
152
return 1;
153
}
154
break;
155
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
156
}
157
}
158
break;
159
- case NEON_3R_VPADD:
160
+ case NEON_3R_VPADD_VQRDMLAH:
161
switch (size) {
162
case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
163
case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
164
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
165
}
166
}
167
break;
168
- case NEON_3R_VFM:
169
+ case NEON_3R_VFM_VQRDMLSH:
170
{
171
/* VFMA, VFMS: fused multiply-add */
172
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
173
--
89
--
174
2.16.2
90
2.20.1
175
91
176
92
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Allow the translate subroutines to return false for invalid insns.
3
Continue setting, but not relying upon, env->hflags.
4
4
5
At present we can of course invoke an invalid insn exception from within
5
Suggested-by: Peter Maydell <peter.maydell@linaro.org>
6
the translate subroutine, but in the short term this consolidates code.
7
In the long term it would allow the decodetree language to support
8
overlapping patterns for ISA extensions.
9
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20180227232618.2908-1-richard.henderson@linaro.org
7
Message-id: 20191018174431.1784-22-richard.henderson@linaro.org
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
10
---
15
scripts/decodetree.py | 5 ++---
11
hw/intc/armv7m_nvic.c | 22 +++++++++++++---------
16
1 file changed, 2 insertions(+), 3 deletions(-)
12
1 file changed, 13 insertions(+), 9 deletions(-)
17
13
18
diff --git a/scripts/decodetree.py b/scripts/decodetree.py
14
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
19
index XXXXXXX..XXXXXXX 100755
15
index XXXXXXX..XXXXXXX 100644
20
--- a/scripts/decodetree.py
16
--- a/hw/intc/armv7m_nvic.c
21
+++ b/scripts/decodetree.py
17
+++ b/hw/intc/armv7m_nvic.c
22
@@ -XXX,XX +XXX,XX @@ class Pattern(General):
18
@@ -XXX,XX +XXX,XX @@ static MemTxResult nvic_sysreg_write(void *opaque, hwaddr addr,
23
global translate_prefix
19
}
24
output('typedef ', self.base.base.struct_name(),
20
}
25
' arg_', self.name, ';\n')
21
nvic_irq_update(s);
26
- output(translate_scope, 'void ', translate_prefix, '_', self.name,
22
- return MEMTX_OK;
27
+ output(translate_scope, 'bool ', translate_prefix, '_', self.name,
23
+ goto exit_ok;
28
'(DisasContext *ctx, arg_', self.name,
24
case 0x200 ... 0x23f: /* NVIC Set pend */
29
' *a, ', insntype, ' insn);\n')
25
/* the special logic in armv7m_nvic_set_pending()
30
26
* is not needed since IRQs are never escalated
31
@@ -XXX,XX +XXX,XX @@ class Pattern(General):
27
@@ -XXX,XX +XXX,XX @@ static MemTxResult nvic_sysreg_write(void *opaque, hwaddr addr,
32
output(ind, self.base.extract_name(), '(&u.f_', arg, ', insn);\n')
28
}
33
for n, f in self.fields.items():
29
}
34
output(ind, 'u.f_', arg, '.', n, ' = ', f.str_extract(), ';\n')
30
nvic_irq_update(s);
35
- output(ind, translate_prefix, '_', self.name,
31
- return MEMTX_OK;
36
+ output(ind, 'return ', translate_prefix, '_', self.name,
32
+ goto exit_ok;
37
'(ctx, &u.f_', arg, ', insn);\n')
33
case 0x300 ... 0x33f: /* NVIC Active */
38
- output(ind, 'return true;\n')
34
- return MEMTX_OK; /* R/O */
39
# end Pattern
35
+ goto exit_ok; /* R/O */
40
36
case 0x400 ... 0x5ef: /* NVIC Priority */
37
startvec = (offset - 0x400) + NVIC_FIRST_IRQ; /* vector # */
38
39
@@ -XXX,XX +XXX,XX @@ static MemTxResult nvic_sysreg_write(void *opaque, hwaddr addr,
40
}
41
}
42
nvic_irq_update(s);
43
- return MEMTX_OK;
44
+ goto exit_ok;
45
case 0xd18 ... 0xd1b: /* System Handler Priority (SHPR1) */
46
if (!arm_feature(&s->cpu->env, ARM_FEATURE_M_MAIN)) {
47
- return MEMTX_OK;
48
+ goto exit_ok;
49
}
50
/* fall through */
51
case 0xd1c ... 0xd23: /* System Handler Priority (SHPR2, SHPR3) */
52
@@ -XXX,XX +XXX,XX @@ static MemTxResult nvic_sysreg_write(void *opaque, hwaddr addr,
53
set_prio(s, hdlidx, sbank, newprio);
54
}
55
nvic_irq_update(s);
56
- return MEMTX_OK;
57
+ goto exit_ok;
58
case 0xd28 ... 0xd2b: /* Configurable Fault Status (CFSR) */
59
if (!arm_feature(&s->cpu->env, ARM_FEATURE_M_MAIN)) {
60
- return MEMTX_OK;
61
+ goto exit_ok;
62
}
63
/* All bits are W1C, so construct 32 bit value with 0s in
64
* the parts not written by the access size
65
@@ -XXX,XX +XXX,XX @@ static MemTxResult nvic_sysreg_write(void *opaque, hwaddr addr,
66
*/
67
s->cpu->env.v7m.cfsr[M_REG_NS] &= ~(value & R_V7M_CFSR_BFSR_MASK);
68
}
69
- return MEMTX_OK;
70
+ goto exit_ok;
71
}
72
if (size == 4) {
73
nvic_writel(s, offset, value, attrs);
74
- return MEMTX_OK;
75
+ goto exit_ok;
76
}
77
qemu_log_mask(LOG_GUEST_ERROR,
78
"NVIC: Bad write of size %d at offset 0x%x\n", size, offset);
79
/* This is UNPREDICTABLE; treat as RAZ/WI */
80
+
81
+ exit_ok:
82
+ /* Ensure any changes made are reflected in the cached hflags. */
83
+ arm_rebuild_hflags(&s->cpu->env);
84
return MEMTX_OK;
85
}
41
86
42
--
87
--
43
2.16.2
88
2.20.1
44
89
45
90
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Include the U bit in the switches rather than testing separately.
3
This is the payoff.
4
4
5
From perf record -g data of ubuntu 18 boot and shutdown:
6
7
BEFORE:
8
9
- 23.02% 2.82% qemu-system-aar [.] helper_lookup_tb_ptr
10
- 20.22% helper_lookup_tb_ptr
11
+ 10.05% tb_htable_lookup
12
- 9.13% cpu_get_tb_cpu_state
13
3.20% aa64_va_parameters_both
14
0.55% fp_exception_el
15
16
- 11.66% 4.74% qemu-system-aar [.] cpu_get_tb_cpu_state
17
- 6.96% cpu_get_tb_cpu_state
18
3.63% aa64_va_parameters_both
19
0.60% fp_exception_el
20
0.53% sve_exception_el
21
22
AFTER:
23
24
- 16.40% 3.40% qemu-system-aar [.] helper_lookup_tb_ptr
25
- 13.03% helper_lookup_tb_ptr
26
+ 11.19% tb_htable_lookup
27
0.55% cpu_get_tb_cpu_state
28
29
0.98% 0.71% qemu-system-aar [.] cpu_get_tb_cpu_state
30
31
0.87% 0.24% qemu-system-aar [.] rebuild_hflags_a64
32
33
Before, helper_lookup_tb_ptr is the second hottest function in the
34
application, consuming almost a quarter of the runtime. Within the
35
entire execution, cpu_get_tb_cpu_state consumes about 12%.
36
37
After, helper_lookup_tb_ptr has dropped to the fourth hottest function,
38
with consumption dropping to a sixth of the runtime. Within the
39
entire execution, cpu_get_tb_cpu_state has dropped below 1%, and the
40
supporting function to rebuild hflags also consumes about 1%.
41
42
Assertions are retained for --enable-debug-tcg.
43
44
Tested-by: Alex Bennée <alex.bennee@linaro.org>
45
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
46
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
47
Message-id: 20191018174431.1784-23-richard.henderson@linaro.org
7
Message-id: 20180228193125.20577-3-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
48
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
49
---
10
target/arm/translate-a64.c | 129 +++++++++++++++++++++------------------------
50
target/arm/helper.c | 9 ++++++---
11
1 file changed, 61 insertions(+), 68 deletions(-)
51
1 file changed, 6 insertions(+), 3 deletions(-)
12
52
13
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
53
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
index XXXXXXX..XXXXXXX 100644
54
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-a64.c
55
--- a/target/arm/helper.c
16
+++ b/target/arm/translate-a64.c
56
+++ b/target/arm/helper.c
17
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
57
@@ -XXX,XX +XXX,XX @@ void HELPER(rebuild_hflags_a64)(CPUARMState *env, int el)
18
int index;
58
void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
19
TCGv_ptr fpst;
59
target_ulong *cs_base, uint32_t *pflags)
20
60
{
21
- switch (opcode) {
61
- uint32_t flags, pstate_for_ss;
22
- case 0x0: /* MLA */
62
+ uint32_t flags = env->hflags;
23
- case 0x4: /* MLS */
63
+ uint32_t pstate_for_ss;
24
- if (!u || is_scalar) {
64
25
+ switch (16 * u + opcode) {
65
*cs_base = 0;
26
+ case 0x08: /* MUL */
66
- flags = rebuild_hflags_internal(env);
27
+ case 0x10: /* MLA */
67
+#ifdef CONFIG_DEBUG_TCG
28
+ case 0x14: /* MLS */
68
+ assert(flags == rebuild_hflags_internal(env));
29
+ if (is_scalar) {
69
+#endif
30
unallocated_encoding(s);
70
31
return;
71
- if (is_a64(env)) {
32
}
72
+ if (FIELD_EX32(flags, TBFLAG_ANY, AARCH64_STATE)) {
33
break;
73
*pc = env->pc;
34
- case 0x2: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */
74
if (cpu_isar_feature(aa64_bti, env_archcpu(env))) {
35
- case 0x6: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */
75
flags = FIELD_DP32(flags, TBFLAG_A64, BTYPE, env->btype);
36
- case 0xa: /* SMULL, SMULL2, UMULL, UMULL2 */
37
+ case 0x02: /* SMLAL, SMLAL2 */
38
+ case 0x12: /* UMLAL, UMLAL2 */
39
+ case 0x06: /* SMLSL, SMLSL2 */
40
+ case 0x16: /* UMLSL, UMLSL2 */
41
+ case 0x0a: /* SMULL, SMULL2 */
42
+ case 0x1a: /* UMULL, UMULL2 */
43
if (is_scalar) {
44
unallocated_encoding(s);
45
return;
46
}
47
is_long = true;
48
break;
49
- case 0x3: /* SQDMLAL, SQDMLAL2 */
50
- case 0x7: /* SQDMLSL, SQDMLSL2 */
51
- case 0xb: /* SQDMULL, SQDMULL2 */
52
+ case 0x03: /* SQDMLAL, SQDMLAL2 */
53
+ case 0x07: /* SQDMLSL, SQDMLSL2 */
54
+ case 0x0b: /* SQDMULL, SQDMULL2 */
55
is_long = true;
56
- /* fall through */
57
- case 0xc: /* SQDMULH */
58
- case 0xd: /* SQRDMULH */
59
- if (u) {
60
- unallocated_encoding(s);
61
- return;
62
- }
63
break;
64
- case 0x8: /* MUL */
65
- if (u || is_scalar) {
66
- unallocated_encoding(s);
67
- return;
68
- }
69
+ case 0x0c: /* SQDMULH */
70
+ case 0x0d: /* SQRDMULH */
71
break;
72
- case 0x1: /* FMLA */
73
- case 0x5: /* FMLS */
74
- if (u) {
75
- unallocated_encoding(s);
76
- return;
77
- }
78
- /* fall through */
79
- case 0x9: /* FMUL, FMULX */
80
+ case 0x01: /* FMLA */
81
+ case 0x05: /* FMLS */
82
+ case 0x09: /* FMUL */
83
+ case 0x19: /* FMULX */
84
if (size == 1) {
85
unallocated_encoding(s);
86
return;
87
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
88
89
read_vec_element(s, tcg_op, rn, pass, MO_64);
90
91
- switch (opcode) {
92
- case 0x5: /* FMLS */
93
+ switch (16 * u + opcode) {
94
+ case 0x05: /* FMLS */
95
/* As usual for ARM, separate negation for fused multiply-add */
96
gen_helper_vfp_negd(tcg_op, tcg_op);
97
/* fall through */
98
- case 0x1: /* FMLA */
99
+ case 0x01: /* FMLA */
100
read_vec_element(s, tcg_res, rd, pass, MO_64);
101
gen_helper_vfp_muladdd(tcg_res, tcg_op, tcg_idx, tcg_res, fpst);
102
break;
103
- case 0x9: /* FMUL, FMULX */
104
- if (u) {
105
- gen_helper_vfp_mulxd(tcg_res, tcg_op, tcg_idx, fpst);
106
- } else {
107
- gen_helper_vfp_muld(tcg_res, tcg_op, tcg_idx, fpst);
108
- }
109
+ case 0x09: /* FMUL */
110
+ gen_helper_vfp_muld(tcg_res, tcg_op, tcg_idx, fpst);
111
+ break;
112
+ case 0x19: /* FMULX */
113
+ gen_helper_vfp_mulxd(tcg_res, tcg_op, tcg_idx, fpst);
114
break;
115
default:
116
g_assert_not_reached();
117
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
118
119
read_vec_element_i32(s, tcg_op, rn, pass, is_scalar ? size : MO_32);
120
121
- switch (opcode) {
122
- case 0x0: /* MLA */
123
- case 0x4: /* MLS */
124
- case 0x8: /* MUL */
125
+ switch (16 * u + opcode) {
126
+ case 0x08: /* MUL */
127
+ case 0x10: /* MLA */
128
+ case 0x14: /* MLS */
129
{
130
static NeonGenTwoOpFn * const fns[2][2] = {
131
{ gen_helper_neon_add_u16, gen_helper_neon_sub_u16 },
132
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
133
genfn(tcg_res, tcg_op, tcg_res);
134
break;
135
}
136
- case 0x5: /* FMLS */
137
- case 0x1: /* FMLA */
138
+ case 0x05: /* FMLS */
139
+ case 0x01: /* FMLA */
140
read_vec_element_i32(s, tcg_res, rd, pass,
141
is_scalar ? size : MO_32);
142
switch (size) {
143
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
144
g_assert_not_reached();
145
}
146
break;
147
- case 0x9: /* FMUL, FMULX */
148
+ case 0x09: /* FMUL */
149
switch (size) {
150
case 1:
151
- if (u) {
152
- if (is_scalar) {
153
- gen_helper_advsimd_mulxh(tcg_res, tcg_op,
154
- tcg_idx, fpst);
155
- } else {
156
- gen_helper_advsimd_mulx2h(tcg_res, tcg_op,
157
- tcg_idx, fpst);
158
- }
159
+ if (is_scalar) {
160
+ gen_helper_advsimd_mulh(tcg_res, tcg_op,
161
+ tcg_idx, fpst);
162
} else {
163
- if (is_scalar) {
164
- gen_helper_advsimd_mulh(tcg_res, tcg_op,
165
- tcg_idx, fpst);
166
- } else {
167
- gen_helper_advsimd_mul2h(tcg_res, tcg_op,
168
- tcg_idx, fpst);
169
- }
170
+ gen_helper_advsimd_mul2h(tcg_res, tcg_op,
171
+ tcg_idx, fpst);
172
}
173
break;
174
case 2:
175
- if (u) {
176
- gen_helper_vfp_mulxs(tcg_res, tcg_op, tcg_idx, fpst);
177
- } else {
178
- gen_helper_vfp_muls(tcg_res, tcg_op, tcg_idx, fpst);
179
- }
180
+ gen_helper_vfp_muls(tcg_res, tcg_op, tcg_idx, fpst);
181
break;
182
default:
183
g_assert_not_reached();
184
}
185
break;
186
- case 0xc: /* SQDMULH */
187
+ case 0x19: /* FMULX */
188
+ switch (size) {
189
+ case 1:
190
+ if (is_scalar) {
191
+ gen_helper_advsimd_mulxh(tcg_res, tcg_op,
192
+ tcg_idx, fpst);
193
+ } else {
194
+ gen_helper_advsimd_mulx2h(tcg_res, tcg_op,
195
+ tcg_idx, fpst);
196
+ }
197
+ break;
198
+ case 2:
199
+ gen_helper_vfp_mulxs(tcg_res, tcg_op, tcg_idx, fpst);
200
+ break;
201
+ default:
202
+ g_assert_not_reached();
203
+ }
204
+ break;
205
+ case 0x0c: /* SQDMULH */
206
if (size == 1) {
207
gen_helper_neon_qdmulh_s16(tcg_res, cpu_env,
208
tcg_op, tcg_idx);
209
@@ -XXX,XX +XXX,XX @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
210
tcg_op, tcg_idx);
211
}
212
break;
213
- case 0xd: /* SQRDMULH */
214
+ case 0x0d: /* SQRDMULH */
215
if (size == 1) {
216
gen_helper_neon_qrdmulh_s16(tcg_res, cpu_env,
217
tcg_op, tcg_idx);
218
--
76
--
219
2.16.2
77
2.20.1
220
78
221
79
diff view generated by jsdifflib
1
Add a function load_ramdisk_as() which behaves like the existing
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
load_ramdisk() but allows the caller to specify the AddressSpace
3
to use. This matches the pattern we have already for various
4
other loader functions.
5
2
3
This file keeps the various QDev blocks separated by comments.
4
5
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Cleber Rosa <crosa@redhat.com>
7
Message-id: 20191005154748.21718-3-f4bug@amsat.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20180220180325.29818-2-peter.maydell@linaro.org
10
---
9
---
11
include/hw/loader.h | 12 +++++++++++-
10
hw/sd/sdhci.c | 3 ++-
12
hw/core/loader.c | 8 +++++++-
11
1 file changed, 2 insertions(+), 1 deletion(-)
13
2 files changed, 18 insertions(+), 2 deletions(-)
14
12
15
diff --git a/include/hw/loader.h b/include/hw/loader.h
13
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
16
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/loader.h
15
--- a/hw/sd/sdhci.c
18
+++ b/include/hw/loader.h
16
+++ b/hw/sd/sdhci.c
19
@@ -XXX,XX +XXX,XX @@ int load_uimage(const char *filename, hwaddr *ep,
17
@@ -XXX,XX +XXX,XX @@ static const TypeInfo sdhci_bus_info = {
20
void *translate_opaque);
18
.class_init = sdhci_bus_class_init,
21
19
};
22
/**
20
23
- * load_ramdisk:
21
+/* --- qdev i.MX eSDHC --- */
24
+ * load_ramdisk_as:
25
* @filename: Path to the ramdisk image
26
* @addr: Memory address to load the ramdisk to
27
* @max_sz: Maximum allowed ramdisk size (for non-u-boot ramdisks)
28
+ * @as: The AddressSpace to load the ELF to. The value of address_space_memory
29
+ * is used if nothing is supplied here.
30
*
31
* Load a ramdisk image with U-Boot header to the specified memory
32
* address.
33
*
34
* Returns the size of the loaded image on success, -1 otherwise.
35
*/
36
+int load_ramdisk_as(const char *filename, hwaddr addr, uint64_t max_sz,
37
+ AddressSpace *as);
38
+
22
+
39
+/**
23
static uint64_t usdhc_read(void *opaque, hwaddr offset, unsigned size)
40
+ * load_ramdisk:
41
+ * Same as load_ramdisk_as(), but doesn't allow the caller to specify
42
+ * an AddressSpace.
43
+ */
44
int load_ramdisk(const char *filename, hwaddr addr, uint64_t max_sz);
45
46
ssize_t gunzip(void *dst, size_t dstlen, uint8_t *src, size_t srclen);
47
diff --git a/hw/core/loader.c b/hw/core/loader.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/hw/core/loader.c
50
+++ b/hw/core/loader.c
51
@@ -XXX,XX +XXX,XX @@ int load_uimage_as(const char *filename, hwaddr *ep, hwaddr *loadaddr,
52
53
/* Load a ramdisk. */
54
int load_ramdisk(const char *filename, hwaddr addr, uint64_t max_sz)
55
+{
56
+ return load_ramdisk_as(filename, addr, max_sz, NULL);
57
+}
58
+
59
+int load_ramdisk_as(const char *filename, hwaddr addr, uint64_t max_sz,
60
+ AddressSpace *as)
61
{
24
{
62
return load_uboot_image(filename, NULL, &addr, NULL, IH_TYPE_RAMDISK,
25
SDHCIState *s = SYSBUS_SDHCI(opaque);
63
- NULL, NULL, NULL);
26
@@ -XXX,XX +XXX,XX @@ usdhc_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
64
+ NULL, NULL, as);
27
}
65
}
28
}
66
29
67
/* Load a gzip-compressed kernel to a dynamically allocated buffer. */
30
-
31
static const MemoryRegionOps usdhc_mmio_ops = {
32
.read = usdhc_read,
33
.write = usdhc_write,
68
--
34
--
69
2.16.2
35
2.20.1
70
36
71
37
diff view generated by jsdifflib
1
The MPS2 AN505 FPGA image includes a "FPGA control block"
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
which is a small set of registers handling LEDs, buttons
3
and some counters.
4
2
3
The Linux kernel access few S3C-specific registers [1] to set some
4
clock. We don't care about this part for device emulation [2]. Add
5
a dummy device to properly ignore these accesses, so we can focus
6
on the important registers missing.
7
8
[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/mmc/host/sdhci-s3c-regs.h?h=cc014f3
9
[2] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/mmc/host/sdhci-s3c.c?h=v5.3#n263
10
11
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org>
13
Message-id: 20191005154748.21718-4-f4bug@amsat.org
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180220180325.29818-14-peter.maydell@linaro.org
8
---
15
---
9
hw/misc/Makefile.objs | 1 +
16
include/hw/sd/sdhci.h | 2 ++
10
include/hw/misc/mps2-fpgaio.h | 43 ++++++++++
17
hw/sd/sdhci.c | 65 +++++++++++++++++++++++++++++++++++++++++++
11
hw/misc/mps2-fpgaio.c | 176 ++++++++++++++++++++++++++++++++++++++++
18
2 files changed, 67 insertions(+)
12
default-configs/arm-softmmu.mak | 1 +
13
hw/misc/trace-events | 6 ++
14
5 files changed, 227 insertions(+)
15
create mode 100644 include/hw/misc/mps2-fpgaio.h
16
create mode 100644 hw/misc/mps2-fpgaio.c
17
19
18
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
20
diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h
19
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/misc/Makefile.objs
22
--- a/include/hw/sd/sdhci.h
21
+++ b/hw/misc/Makefile.objs
23
+++ b/include/hw/sd/sdhci.h
22
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_STM32F2XX_SYSCFG) += stm32f2xx_syscfg.o
24
@@ -XXX,XX +XXX,XX @@ typedef struct SDHCIState {
23
obj-$(CONFIG_MIPS_CPS) += mips_cmgcr.o
25
24
obj-$(CONFIG_MIPS_CPS) += mips_cpc.o
26
#define TYPE_IMX_USDHC "imx-usdhc"
25
obj-$(CONFIG_MIPS_ITU) += mips_itu.o
27
26
+obj-$(CONFIG_MPS2_FPGAIO) += mps2-fpgaio.o
28
+#define TYPE_S3C_SDHCI "s3c-sdhci"
27
obj-$(CONFIG_MPS2_SCC) += mps2-scc.o
28
29
obj-$(CONFIG_PVPANIC) += pvpanic.o
30
diff --git a/include/hw/misc/mps2-fpgaio.h b/include/hw/misc/mps2-fpgaio.h
31
new file mode 100644
32
index XXXXXXX..XXXXXXX
33
--- /dev/null
34
+++ b/include/hw/misc/mps2-fpgaio.h
35
@@ -XXX,XX +XXX,XX @@
36
+/*
37
+ * ARM MPS2 FPGAIO emulation
38
+ *
39
+ * Copyright (c) 2018 Linaro Limited
40
+ * Written by Peter Maydell
41
+ *
42
+ * This program is free software; you can redistribute it and/or modify
43
+ * it under the terms of the GNU General Public License version 2 or
44
+ * (at your option) any later version.
45
+ */
46
+
29
+
47
+/* This is a model of the FPGAIO register block in the AN505
30
#endif /* SDHCI_H */
48
+ * FPGA image for the MPS2 dev board; it is documented in the
31
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
49
+ * application note:
32
index XXXXXXX..XXXXXXX 100644
50
+ * http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
33
--- a/hw/sd/sdhci.c
51
+ *
34
+++ b/hw/sd/sdhci.c
52
+ * QEMU interface:
35
@@ -XXX,XX +XXX,XX @@ static const TypeInfo imx_usdhc_info = {
53
+ * + sysbus MMIO region 0: the register bank
36
.instance_init = imx_usdhc_init,
54
+ */
37
};
38
39
+/* --- qdev Samsung s3c --- */
55
+
40
+
56
+#ifndef MPS2_FPGAIO_H
41
+#define S3C_SDHCI_CONTROL2 0x80
57
+#define MPS2_FPGAIO_H
42
+#define S3C_SDHCI_CONTROL3 0x84
43
+#define S3C_SDHCI_CONTROL4 0x8c
58
+
44
+
59
+#include "hw/sysbus.h"
45
+static uint64_t sdhci_s3c_read(void *opaque, hwaddr offset, unsigned size)
60
+
61
+#define TYPE_MPS2_FPGAIO "mps2-fpgaio"
62
+#define MPS2_FPGAIO(obj) OBJECT_CHECK(MPS2FPGAIO, (obj), TYPE_MPS2_FPGAIO)
63
+
64
+typedef struct {
65
+ /*< private >*/
66
+ SysBusDevice parent_obj;
67
+
68
+ /*< public >*/
69
+ MemoryRegion iomem;
70
+
71
+ uint32_t led0;
72
+ uint32_t prescale;
73
+ uint32_t misc;
74
+
75
+ uint32_t prescale_clk;
76
+} MPS2FPGAIO;
77
+
78
+#endif
79
diff --git a/hw/misc/mps2-fpgaio.c b/hw/misc/mps2-fpgaio.c
80
new file mode 100644
81
index XXXXXXX..XXXXXXX
82
--- /dev/null
83
+++ b/hw/misc/mps2-fpgaio.c
84
@@ -XXX,XX +XXX,XX @@
85
+/*
86
+ * ARM MPS2 AN505 FPGAIO emulation
87
+ *
88
+ * Copyright (c) 2018 Linaro Limited
89
+ * Written by Peter Maydell
90
+ *
91
+ * This program is free software; you can redistribute it and/or modify
92
+ * it under the terms of the GNU General Public License version 2 or
93
+ * (at your option) any later version.
94
+ */
95
+
96
+/* This is a model of the "FPGA system control and I/O" block found
97
+ * in the AN505 FPGA image for the MPS2 devboard.
98
+ * It is documented in AN505:
99
+ * http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
100
+ */
101
+
102
+#include "qemu/osdep.h"
103
+#include "qemu/log.h"
104
+#include "qapi/error.h"
105
+#include "trace.h"
106
+#include "hw/sysbus.h"
107
+#include "hw/registerfields.h"
108
+#include "hw/misc/mps2-fpgaio.h"
109
+
110
+REG32(LED0, 0)
111
+REG32(BUTTON, 8)
112
+REG32(CLK1HZ, 0x10)
113
+REG32(CLK100HZ, 0x14)
114
+REG32(COUNTER, 0x18)
115
+REG32(PRESCALE, 0x1c)
116
+REG32(PSCNTR, 0x20)
117
+REG32(MISC, 0x4c)
118
+
119
+static uint64_t mps2_fpgaio_read(void *opaque, hwaddr offset, unsigned size)
120
+{
46
+{
121
+ MPS2FPGAIO *s = MPS2_FPGAIO(opaque);
47
+ uint64_t ret;
122
+ uint64_t r;
123
+
48
+
124
+ switch (offset) {
49
+ switch (offset) {
125
+ case A_LED0:
50
+ case S3C_SDHCI_CONTROL2:
126
+ r = s->led0;
51
+ case S3C_SDHCI_CONTROL3:
127
+ break;
52
+ case S3C_SDHCI_CONTROL4:
128
+ case A_BUTTON:
53
+ /* ignore */
129
+ /* User-pressable board buttons. We don't model that, so just return
54
+ ret = 0;
130
+ * zeroes.
131
+ */
132
+ r = 0;
133
+ break;
134
+ case A_PRESCALE:
135
+ r = s->prescale;
136
+ break;
137
+ case A_MISC:
138
+ r = s->misc;
139
+ break;
140
+ case A_CLK1HZ:
141
+ case A_CLK100HZ:
142
+ case A_COUNTER:
143
+ case A_PSCNTR:
144
+ /* These are all upcounters of various frequencies. */
145
+ qemu_log_mask(LOG_UNIMP, "MPS2 FPGAIO: counters unimplemented\n");
146
+ r = 0;
147
+ break;
55
+ break;
148
+ default:
56
+ default:
149
+ qemu_log_mask(LOG_GUEST_ERROR,
57
+ ret = sdhci_read(opaque, offset, size);
150
+ "MPS2 FPGAIO read: bad offset %x\n", (int) offset);
151
+ r = 0;
152
+ break;
58
+ break;
153
+ }
59
+ }
154
+
60
+
155
+ trace_mps2_fpgaio_read(offset, r, size);
61
+ return ret;
156
+ return r;
157
+}
62
+}
158
+
63
+
159
+static void mps2_fpgaio_write(void *opaque, hwaddr offset, uint64_t value,
64
+static void sdhci_s3c_write(void *opaque, hwaddr offset, uint64_t val,
160
+ unsigned size)
65
+ unsigned size)
161
+{
66
+{
162
+ MPS2FPGAIO *s = MPS2_FPGAIO(opaque);
163
+
164
+ trace_mps2_fpgaio_write(offset, value, size);
165
+
166
+ switch (offset) {
67
+ switch (offset) {
167
+ case A_LED0:
68
+ case S3C_SDHCI_CONTROL2:
168
+ /* LED bits [1:0] control board LEDs. We don't currently have
69
+ case S3C_SDHCI_CONTROL3:
169
+ * a mechanism for displaying this graphically, so use a trace event.
70
+ case S3C_SDHCI_CONTROL4:
170
+ */
71
+ /* ignore */
171
+ trace_mps2_fpgaio_leds(value & 0x02 ? '*' : '.',
172
+ value & 0x01 ? '*' : '.');
173
+ s->led0 = value & 0x3;
174
+ break;
175
+ case A_PRESCALE:
176
+ s->prescale = value;
177
+ break;
178
+ case A_MISC:
179
+ /* These are control bits for some of the other devices on the
180
+ * board (SPI, CLCD, etc). We don't implement that yet, so just
181
+ * make the bits read as written.
182
+ */
183
+ qemu_log_mask(LOG_UNIMP,
184
+ "MPS2 FPGAIO: MISC control bits unimplemented\n");
185
+ s->misc = value;
186
+ break;
72
+ break;
187
+ default:
73
+ default:
188
+ qemu_log_mask(LOG_GUEST_ERROR,
74
+ sdhci_write(opaque, offset, val, size);
189
+ "MPS2 FPGAIO write: bad offset 0x%x\n", (int) offset);
190
+ break;
75
+ break;
191
+ }
76
+ }
192
+}
77
+}
193
+
78
+
194
+static const MemoryRegionOps mps2_fpgaio_ops = {
79
+static const MemoryRegionOps sdhci_s3c_mmio_ops = {
195
+ .read = mps2_fpgaio_read,
80
+ .read = sdhci_s3c_read,
196
+ .write = mps2_fpgaio_write,
81
+ .write = sdhci_s3c_write,
82
+ .valid = {
83
+ .min_access_size = 1,
84
+ .max_access_size = 4,
85
+ .unaligned = false
86
+ },
197
+ .endianness = DEVICE_LITTLE_ENDIAN,
87
+ .endianness = DEVICE_LITTLE_ENDIAN,
198
+};
88
+};
199
+
89
+
200
+static void mps2_fpgaio_reset(DeviceState *dev)
90
+static void sdhci_s3c_init(Object *obj)
201
+{
91
+{
202
+ MPS2FPGAIO *s = MPS2_FPGAIO(dev);
92
+ SDHCIState *s = SYSBUS_SDHCI(obj);
203
+
93
+
204
+ trace_mps2_fpgaio_reset();
94
+ s->io_ops = &sdhci_s3c_mmio_ops;
205
+ s->led0 = 0;
206
+ s->prescale = 0;
207
+ s->misc = 0;
208
+}
95
+}
209
+
96
+
210
+static void mps2_fpgaio_init(Object *obj)
97
+static const TypeInfo sdhci_s3c_info = {
211
+{
98
+ .name = TYPE_S3C_SDHCI ,
212
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
99
+ .parent = TYPE_SYSBUS_SDHCI,
213
+ MPS2FPGAIO *s = MPS2_FPGAIO(obj);
100
+ .instance_init = sdhci_s3c_init,
214
+
215
+ memory_region_init_io(&s->iomem, obj, &mps2_fpgaio_ops, s,
216
+ "mps2-fpgaio", 0x1000);
217
+ sysbus_init_mmio(sbd, &s->iomem);
218
+}
219
+
220
+static const VMStateDescription mps2_fpgaio_vmstate = {
221
+ .name = "mps2-fpgaio",
222
+ .version_id = 1,
223
+ .minimum_version_id = 1,
224
+ .fields = (VMStateField[]) {
225
+ VMSTATE_UINT32(led0, MPS2FPGAIO),
226
+ VMSTATE_UINT32(prescale, MPS2FPGAIO),
227
+ VMSTATE_UINT32(misc, MPS2FPGAIO),
228
+ VMSTATE_END_OF_LIST()
229
+ }
230
+};
101
+};
231
+
102
+
232
+static Property mps2_fpgaio_properties[] = {
103
static void sdhci_register_types(void)
233
+ /* Frequency of the prescale counter */
104
{
234
+ DEFINE_PROP_UINT32("prescale-clk", MPS2FPGAIO, prescale_clk, 20000000),
105
type_register_static(&sdhci_sysbus_info);
235
+ DEFINE_PROP_END_OF_LIST(),
106
type_register_static(&sdhci_bus_info);
236
+};
107
type_register_static(&imx_usdhc_info);
237
+
108
+ type_register_static(&sdhci_s3c_info);
238
+static void mps2_fpgaio_class_init(ObjectClass *klass, void *data)
109
}
239
+{
110
240
+ DeviceClass *dc = DEVICE_CLASS(klass);
111
type_init(sdhci_register_types)
241
+
242
+ dc->vmsd = &mps2_fpgaio_vmstate;
243
+ dc->reset = mps2_fpgaio_reset;
244
+ dc->props = mps2_fpgaio_properties;
245
+}
246
+
247
+static const TypeInfo mps2_fpgaio_info = {
248
+ .name = TYPE_MPS2_FPGAIO,
249
+ .parent = TYPE_SYS_BUS_DEVICE,
250
+ .instance_size = sizeof(MPS2FPGAIO),
251
+ .instance_init = mps2_fpgaio_init,
252
+ .class_init = mps2_fpgaio_class_init,
253
+};
254
+
255
+static void mps2_fpgaio_register_types(void)
256
+{
257
+ type_register_static(&mps2_fpgaio_info);
258
+}
259
+
260
+type_init(mps2_fpgaio_register_types);
261
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
262
index XXXXXXX..XXXXXXX 100644
263
--- a/default-configs/arm-softmmu.mak
264
+++ b/default-configs/arm-softmmu.mak
265
@@ -XXX,XX +XXX,XX @@ CONFIG_STM32F205_SOC=y
266
CONFIG_CMSDK_APB_TIMER=y
267
CONFIG_CMSDK_APB_UART=y
268
269
+CONFIG_MPS2_FPGAIO=y
270
CONFIG_MPS2_SCC=y
271
272
CONFIG_VERSATILE_PCI=y
273
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
274
index XXXXXXX..XXXXXXX 100644
275
--- a/hw/misc/trace-events
276
+++ b/hw/misc/trace-events
277
@@ -XXX,XX +XXX,XX @@ mps2_scc_leds(char led7, char led6, char led5, char led4, char led3, char led2,
278
mps2_scc_cfg_write(unsigned function, unsigned device, uint32_t value) "MPS2 SCC config write: function %d device %d data 0x%" PRIx32
279
mps2_scc_cfg_read(unsigned function, unsigned device, uint32_t value) "MPS2 SCC config read: function %d device %d data 0x%" PRIx32
280
281
+# hw/misc/mps2_fpgaio.c
282
+mps2_fpgaio_read(uint64_t offset, uint64_t data, unsigned size) "MPS2 FPGAIO read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
283
+mps2_fpgaio_write(uint64_t offset, uint64_t data, unsigned size) "MPS2 FPGAIO write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
284
+mps2_fpgaio_reset(void) "MPS2 FPGAIO: reset"
285
+mps2_fpgaio_leds(char led1, char led0) "MPS2 FPGAIO LEDs: %c%c"
286
+
287
# hw/misc/msf2-sysreg.c
288
msf2_sysreg_write(uint64_t offset, uint32_t val, uint32_t prev) "msf2-sysreg write: addr 0x%08" HWADDR_PRIx " data 0x%" PRIx32 " prev 0x%" PRIx32
289
msf2_sysreg_read(uint64_t offset, uint32_t val) "msf2-sysreg read: addr 0x%08" HWADDR_PRIx " data 0x%08" PRIx32
290
--
112
--
291
2.16.2
113
2.20.1
292
114
293
115
diff view generated by jsdifflib
1
From: Alistair Francis <alistair.francis@xilinx.com>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
Initial commit of the ZynqMP RTC device.
3
The Exynos SoC has specific SDHCI registers. Use the s3c SDHCI
4
model which handle these specific registers.
4
5
5
Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
6
This silents the following "SDHC ... not implemented" warnings so
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
we can focus on the important registers missing:
8
9
$ qemu-system-arm ... -d unimp \
10
-append "... root=/dev/mmcblk0 rootfstype=ext4 rw rootwait" \
11
-drive file=linux-build-test/rootfs/arm/rootfs-armv5.ext2,if=sd,format=raw
12
[...]
13
[ 25.744858] sdhci: Secure Digital Host Controller Interface driver
14
[ 25.745862] sdhci: Copyright(c) Pierre Ossman
15
[ 25.783188] s3c-sdhci 12530000.sdhci: clock source 2: mmc_busclk.2 (12000000 Hz)
16
SDHC rd_4b @0x80 not implemented
17
SDHC wr_4b @0x80 <- 0x00000020 not implemented
18
SDHC wr_4b @0x8c <- 0x00030000 not implemented
19
SDHC rd_4b @0x80 not implemented
20
SDHC wr_4b @0x80 <- 0xc0004100 not implemented
21
SDHC wr_4b @0x84 <- 0x80808080 not implemented
22
[ 26.013318] mmc0: SDHCI controller on samsung-hsmmc [12530000.sdhci] using ADMA
23
[ 26.032318] Synopsys Designware Multimedia Card Interface Driver
24
[ 42.024885] Waiting for root device /dev/mmcblk0...
25
26
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
27
Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org>
28
Message-id: 20191005154748.21718-5-f4bug@amsat.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
29
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
30
---
9
hw/timer/Makefile.objs | 1 +
31
hw/arm/exynos4210.c | 2 +-
10
include/hw/timer/xlnx-zynqmp-rtc.h | 84 +++++++++++++++
32
1 file changed, 1 insertion(+), 1 deletion(-)
11
hw/timer/xlnx-zynqmp-rtc.c | 214 +++++++++++++++++++++++++++++++++++++
12
3 files changed, 299 insertions(+)
13
create mode 100644 include/hw/timer/xlnx-zynqmp-rtc.h
14
create mode 100644 hw/timer/xlnx-zynqmp-rtc.c
15
33
16
diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs
34
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
17
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/timer/Makefile.objs
36
--- a/hw/arm/exynos4210.c
19
+++ b/hw/timer/Makefile.objs
37
+++ b/hw/arm/exynos4210.c
20
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_IMX) += imx_epit.o
38
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
21
common-obj-$(CONFIG_IMX) += imx_gpt.o
39
* public datasheet which is very similar (implementing
22
common-obj-$(CONFIG_LM32) += lm32_timer.o
40
* MMC Specification Version 4.0 being the only difference noted)
23
common-obj-$(CONFIG_MILKYMIST) += milkymist-sysctl.o
41
*/
24
+common-obj-$(CONFIG_XLNX_ZYNQMP) += xlnx-zynqmp-rtc.o
42
- dev = qdev_create(NULL, TYPE_SYSBUS_SDHCI);
25
43
+ dev = qdev_create(NULL, TYPE_S3C_SDHCI);
26
obj-$(CONFIG_ALTERA_TIMER) += altera_timer.o
44
qdev_prop_set_uint64(dev, "capareg", EXYNOS4210_SDHCI_CAPABILITIES);
27
obj-$(CONFIG_EXYNOS4) += exynos4210_mct.o
45
qdev_init_nofail(dev);
28
diff --git a/include/hw/timer/xlnx-zynqmp-rtc.h b/include/hw/timer/xlnx-zynqmp-rtc.h
46
29
new file mode 100644
30
index XXXXXXX..XXXXXXX
31
--- /dev/null
32
+++ b/include/hw/timer/xlnx-zynqmp-rtc.h
33
@@ -XXX,XX +XXX,XX @@
34
+/*
35
+ * QEMU model of the Xilinx ZynqMP Real Time Clock (RTC).
36
+ *
37
+ * Copyright (c) 2017 Xilinx Inc.
38
+ *
39
+ * Written-by: Alistair Francis <alistair.francis@xilinx.com>
40
+ *
41
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
42
+ * of this software and associated documentation files (the "Software"), to deal
43
+ * in the Software without restriction, including without limitation the rights
44
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
45
+ * copies of the Software, and to permit persons to whom the Software is
46
+ * furnished to do so, subject to the following conditions:
47
+ *
48
+ * The above copyright notice and this permission notice shall be included in
49
+ * all copies or substantial portions of the Software.
50
+ *
51
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
52
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
53
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
54
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
55
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
56
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
57
+ * THE SOFTWARE.
58
+ */
59
+
60
+#include "hw/register.h"
61
+
62
+#define TYPE_XLNX_ZYNQMP_RTC "xlnx-zynmp.rtc"
63
+
64
+#define XLNX_ZYNQMP_RTC(obj) \
65
+ OBJECT_CHECK(XlnxZynqMPRTC, (obj), TYPE_XLNX_ZYNQMP_RTC)
66
+
67
+REG32(SET_TIME_WRITE, 0x0)
68
+REG32(SET_TIME_READ, 0x4)
69
+REG32(CALIB_WRITE, 0x8)
70
+ FIELD(CALIB_WRITE, FRACTION_EN, 20, 1)
71
+ FIELD(CALIB_WRITE, FRACTION_DATA, 16, 4)
72
+ FIELD(CALIB_WRITE, MAX_TICK, 0, 16)
73
+REG32(CALIB_READ, 0xc)
74
+ FIELD(CALIB_READ, FRACTION_EN, 20, 1)
75
+ FIELD(CALIB_READ, FRACTION_DATA, 16, 4)
76
+ FIELD(CALIB_READ, MAX_TICK, 0, 16)
77
+REG32(CURRENT_TIME, 0x10)
78
+REG32(CURRENT_TICK, 0x14)
79
+ FIELD(CURRENT_TICK, VALUE, 0, 16)
80
+REG32(ALARM, 0x18)
81
+REG32(RTC_INT_STATUS, 0x20)
82
+ FIELD(RTC_INT_STATUS, ALARM, 1, 1)
83
+ FIELD(RTC_INT_STATUS, SECONDS, 0, 1)
84
+REG32(RTC_INT_MASK, 0x24)
85
+ FIELD(RTC_INT_MASK, ALARM, 1, 1)
86
+ FIELD(RTC_INT_MASK, SECONDS, 0, 1)
87
+REG32(RTC_INT_EN, 0x28)
88
+ FIELD(RTC_INT_EN, ALARM, 1, 1)
89
+ FIELD(RTC_INT_EN, SECONDS, 0, 1)
90
+REG32(RTC_INT_DIS, 0x2c)
91
+ FIELD(RTC_INT_DIS, ALARM, 1, 1)
92
+ FIELD(RTC_INT_DIS, SECONDS, 0, 1)
93
+REG32(ADDR_ERROR, 0x30)
94
+ FIELD(ADDR_ERROR, STATUS, 0, 1)
95
+REG32(ADDR_ERROR_INT_MASK, 0x34)
96
+ FIELD(ADDR_ERROR_INT_MASK, MASK, 0, 1)
97
+REG32(ADDR_ERROR_INT_EN, 0x38)
98
+ FIELD(ADDR_ERROR_INT_EN, MASK, 0, 1)
99
+REG32(ADDR_ERROR_INT_DIS, 0x3c)
100
+ FIELD(ADDR_ERROR_INT_DIS, MASK, 0, 1)
101
+REG32(CONTROL, 0x40)
102
+ FIELD(CONTROL, BATTERY_DISABLE, 31, 1)
103
+ FIELD(CONTROL, OSC_CNTRL, 24, 4)
104
+ FIELD(CONTROL, SLVERR_ENABLE, 0, 1)
105
+REG32(SAFETY_CHK, 0x50)
106
+
107
+#define XLNX_ZYNQMP_RTC_R_MAX (R_SAFETY_CHK + 1)
108
+
109
+typedef struct XlnxZynqMPRTC {
110
+ SysBusDevice parent_obj;
111
+ MemoryRegion iomem;
112
+ qemu_irq irq_rtc_int;
113
+ qemu_irq irq_addr_error_int;
114
+
115
+ uint32_t regs[XLNX_ZYNQMP_RTC_R_MAX];
116
+ RegisterInfo regs_info[XLNX_ZYNQMP_RTC_R_MAX];
117
+} XlnxZynqMPRTC;
118
diff --git a/hw/timer/xlnx-zynqmp-rtc.c b/hw/timer/xlnx-zynqmp-rtc.c
119
new file mode 100644
120
index XXXXXXX..XXXXXXX
121
--- /dev/null
122
+++ b/hw/timer/xlnx-zynqmp-rtc.c
123
@@ -XXX,XX +XXX,XX @@
124
+/*
125
+ * QEMU model of the Xilinx ZynqMP Real Time Clock (RTC).
126
+ *
127
+ * Copyright (c) 2017 Xilinx Inc.
128
+ *
129
+ * Written-by: Alistair Francis <alistair.francis@xilinx.com>
130
+ *
131
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
132
+ * of this software and associated documentation files (the "Software"), to deal
133
+ * in the Software without restriction, including without limitation the rights
134
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
135
+ * copies of the Software, and to permit persons to whom the Software is
136
+ * furnished to do so, subject to the following conditions:
137
+ *
138
+ * The above copyright notice and this permission notice shall be included in
139
+ * all copies or substantial portions of the Software.
140
+ *
141
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
142
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
143
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
144
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
145
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
146
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
147
+ * THE SOFTWARE.
148
+ */
149
+
150
+#include "qemu/osdep.h"
151
+#include "hw/sysbus.h"
152
+#include "hw/register.h"
153
+#include "qemu/bitops.h"
154
+#include "qemu/log.h"
155
+#include "hw/timer/xlnx-zynqmp-rtc.h"
156
+
157
+#ifndef XLNX_ZYNQMP_RTC_ERR_DEBUG
158
+#define XLNX_ZYNQMP_RTC_ERR_DEBUG 0
159
+#endif
160
+
161
+static void rtc_int_update_irq(XlnxZynqMPRTC *s)
162
+{
163
+ bool pending = s->regs[R_RTC_INT_STATUS] & ~s->regs[R_RTC_INT_MASK];
164
+ qemu_set_irq(s->irq_rtc_int, pending);
165
+}
166
+
167
+static void addr_error_int_update_irq(XlnxZynqMPRTC *s)
168
+{
169
+ bool pending = s->regs[R_ADDR_ERROR] & ~s->regs[R_ADDR_ERROR_INT_MASK];
170
+ qemu_set_irq(s->irq_addr_error_int, pending);
171
+}
172
+
173
+static void rtc_int_status_postw(RegisterInfo *reg, uint64_t val64)
174
+{
175
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
176
+ rtc_int_update_irq(s);
177
+}
178
+
179
+static uint64_t rtc_int_en_prew(RegisterInfo *reg, uint64_t val64)
180
+{
181
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
182
+
183
+ s->regs[R_RTC_INT_MASK] &= (uint32_t) ~val64;
184
+ rtc_int_update_irq(s);
185
+ return 0;
186
+}
187
+
188
+static uint64_t rtc_int_dis_prew(RegisterInfo *reg, uint64_t val64)
189
+{
190
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
191
+
192
+ s->regs[R_RTC_INT_MASK] |= (uint32_t) val64;
193
+ rtc_int_update_irq(s);
194
+ return 0;
195
+}
196
+
197
+static void addr_error_postw(RegisterInfo *reg, uint64_t val64)
198
+{
199
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
200
+ addr_error_int_update_irq(s);
201
+}
202
+
203
+static uint64_t addr_error_int_en_prew(RegisterInfo *reg, uint64_t val64)
204
+{
205
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
206
+
207
+ s->regs[R_ADDR_ERROR_INT_MASK] &= (uint32_t) ~val64;
208
+ addr_error_int_update_irq(s);
209
+ return 0;
210
+}
211
+
212
+static uint64_t addr_error_int_dis_prew(RegisterInfo *reg, uint64_t val64)
213
+{
214
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
215
+
216
+ s->regs[R_ADDR_ERROR_INT_MASK] |= (uint32_t) val64;
217
+ addr_error_int_update_irq(s);
218
+ return 0;
219
+}
220
+
221
+static const RegisterAccessInfo rtc_regs_info[] = {
222
+ { .name = "SET_TIME_WRITE", .addr = A_SET_TIME_WRITE,
223
+ },{ .name = "SET_TIME_READ", .addr = A_SET_TIME_READ,
224
+ .ro = 0xffffffff,
225
+ },{ .name = "CALIB_WRITE", .addr = A_CALIB_WRITE,
226
+ },{ .name = "CALIB_READ", .addr = A_CALIB_READ,
227
+ .ro = 0x1fffff,
228
+ },{ .name = "CURRENT_TIME", .addr = A_CURRENT_TIME,
229
+ .ro = 0xffffffff,
230
+ },{ .name = "CURRENT_TICK", .addr = A_CURRENT_TICK,
231
+ .ro = 0xffff,
232
+ },{ .name = "ALARM", .addr = A_ALARM,
233
+ },{ .name = "RTC_INT_STATUS", .addr = A_RTC_INT_STATUS,
234
+ .w1c = 0x3,
235
+ .post_write = rtc_int_status_postw,
236
+ },{ .name = "RTC_INT_MASK", .addr = A_RTC_INT_MASK,
237
+ .reset = 0x3,
238
+ .ro = 0x3,
239
+ },{ .name = "RTC_INT_EN", .addr = A_RTC_INT_EN,
240
+ .pre_write = rtc_int_en_prew,
241
+ },{ .name = "RTC_INT_DIS", .addr = A_RTC_INT_DIS,
242
+ .pre_write = rtc_int_dis_prew,
243
+ },{ .name = "ADDR_ERROR", .addr = A_ADDR_ERROR,
244
+ .w1c = 0x1,
245
+ .post_write = addr_error_postw,
246
+ },{ .name = "ADDR_ERROR_INT_MASK", .addr = A_ADDR_ERROR_INT_MASK,
247
+ .reset = 0x1,
248
+ .ro = 0x1,
249
+ },{ .name = "ADDR_ERROR_INT_EN", .addr = A_ADDR_ERROR_INT_EN,
250
+ .pre_write = addr_error_int_en_prew,
251
+ },{ .name = "ADDR_ERROR_INT_DIS", .addr = A_ADDR_ERROR_INT_DIS,
252
+ .pre_write = addr_error_int_dis_prew,
253
+ },{ .name = "CONTROL", .addr = A_CONTROL,
254
+ .reset = 0x1000000,
255
+ .rsvd = 0x70fffffe,
256
+ },{ .name = "SAFETY_CHK", .addr = A_SAFETY_CHK,
257
+ }
258
+};
259
+
260
+static void rtc_reset(DeviceState *dev)
261
+{
262
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(dev);
263
+ unsigned int i;
264
+
265
+ for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
266
+ register_reset(&s->regs_info[i]);
267
+ }
268
+
269
+ rtc_int_update_irq(s);
270
+ addr_error_int_update_irq(s);
271
+}
272
+
273
+static const MemoryRegionOps rtc_ops = {
274
+ .read = register_read_memory,
275
+ .write = register_write_memory,
276
+ .endianness = DEVICE_LITTLE_ENDIAN,
277
+ .valid = {
278
+ .min_access_size = 4,
279
+ .max_access_size = 4,
280
+ },
281
+};
282
+
283
+static void rtc_init(Object *obj)
284
+{
285
+ XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(obj);
286
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
287
+ RegisterInfoArray *reg_array;
288
+
289
+ memory_region_init(&s->iomem, obj, TYPE_XLNX_ZYNQMP_RTC,
290
+ XLNX_ZYNQMP_RTC_R_MAX * 4);
291
+ reg_array =
292
+ register_init_block32(DEVICE(obj), rtc_regs_info,
293
+ ARRAY_SIZE(rtc_regs_info),
294
+ s->regs_info, s->regs,
295
+ &rtc_ops,
296
+ XLNX_ZYNQMP_RTC_ERR_DEBUG,
297
+ XLNX_ZYNQMP_RTC_R_MAX * 4);
298
+ memory_region_add_subregion(&s->iomem,
299
+ 0x0,
300
+ &reg_array->mem);
301
+ sysbus_init_mmio(sbd, &s->iomem);
302
+ sysbus_init_irq(sbd, &s->irq_rtc_int);
303
+ sysbus_init_irq(sbd, &s->irq_addr_error_int);
304
+}
305
+
306
+static const VMStateDescription vmstate_rtc = {
307
+ .name = TYPE_XLNX_ZYNQMP_RTC,
308
+ .version_id = 1,
309
+ .minimum_version_id = 1,
310
+ .fields = (VMStateField[]) {
311
+ VMSTATE_UINT32_ARRAY(regs, XlnxZynqMPRTC, XLNX_ZYNQMP_RTC_R_MAX),
312
+ VMSTATE_END_OF_LIST(),
313
+ }
314
+};
315
+
316
+static void rtc_class_init(ObjectClass *klass, void *data)
317
+{
318
+ DeviceClass *dc = DEVICE_CLASS(klass);
319
+
320
+ dc->reset = rtc_reset;
321
+ dc->vmsd = &vmstate_rtc;
322
+}
323
+
324
+static const TypeInfo rtc_info = {
325
+ .name = TYPE_XLNX_ZYNQMP_RTC,
326
+ .parent = TYPE_SYS_BUS_DEVICE,
327
+ .instance_size = sizeof(XlnxZynqMPRTC),
328
+ .class_init = rtc_class_init,
329
+ .instance_init = rtc_init,
330
+};
331
+
332
+static void rtc_register_types(void)
333
+{
334
+ type_register_static(&rtc_info);
335
+}
336
+
337
+type_init(rtc_register_types)
338
--
47
--
339
2.16.2
48
2.20.1
340
49
341
50
diff view generated by jsdifflib
1
The or-irq.h header file is missing the customary guard against
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
multiple inclusion, which means compilation fails if it gets
3
included twice. Fix the omission.
4
2
3
IEC binary prefixes ease code review: the unit is explicit.
4
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Message-id: 20191021190653.9511-2-philmd@redhat.com
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180220180325.29818-11-peter.maydell@linaro.org
9
---
10
---
10
include/hw/or-irq.h | 5 +++++
11
hw/arm/xilinx_zynq.c | 3 ++-
11
1 file changed, 5 insertions(+)
12
1 file changed, 2 insertions(+), 1 deletion(-)
12
13
13
diff --git a/include/hw/or-irq.h b/include/hw/or-irq.h
14
diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/or-irq.h
16
--- a/hw/arm/xilinx_zynq.c
16
+++ b/include/hw/or-irq.h
17
+++ b/hw/arm/xilinx_zynq.c
17
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@
18
* THE SOFTWARE.
19
*/
19
*/
20
20
21
+#ifndef HW_OR_IRQ_H
21
#include "qemu/osdep.h"
22
+#define HW_OR_IRQ_H
22
+#include "qemu/units.h"
23
+
23
#include "qapi/error.h"
24
#include "hw/irq.h"
24
#include "cpu.h"
25
#include "hw/sysbus.h"
25
#include "hw/sysbus.h"
26
#include "qom/object.h"
26
@@ -XXX,XX +XXX,XX @@ static void zynq_init(MachineState *machine)
27
@@ -XXX,XX +XXX,XX @@ struct OrIRQState {
27
memory_region_add_subregion(address_space_mem, 0, ext_ram);
28
bool levels[MAX_OR_LINES];
28
29
uint16_t num_lines;
29
/* 256K of on-chip memory */
30
};
30
- memory_region_init_ram(ocm_ram, NULL, "zynq.ocm_ram", 256 << 10,
31
+
31
+ memory_region_init_ram(ocm_ram, NULL, "zynq.ocm_ram", 256 * KiB,
32
+#endif
32
&error_fatal);
33
memory_region_add_subregion(address_space_mem, 0xFFFC0000, ocm_ram);
34
33
--
35
--
34
2.16.2
36
2.20.1
35
37
36
38
diff view generated by jsdifflib
1
Define a new board model for the MPS2 with an AN505 FPGA image
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
containing a Cortex-M33. Since the FPGA images for TrustZone
3
cores (AN505, and the similar AN519 for Cortex-M23) have a
4
significantly different layout of devices to the non-TrustZone
5
images, we use a new source file rather than shoehorning them
6
into the existing mps2.c.
7
2
3
IEC binary prefixes ease code review: the unit is explicit.
4
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Message-id: 20191021190653.9511-3-philmd@redhat.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20180220180325.29818-20-peter.maydell@linaro.org
11
---
10
---
12
hw/arm/Makefile.objs | 1 +
11
hw/arm/mps2-tz.c | 3 ++-
13
hw/arm/mps2-tz.c | 503 +++++++++++++++++++++++++++++++++++++++++++++++++++
12
hw/arm/mps2.c | 3 ++-
14
2 files changed, 504 insertions(+)
13
2 files changed, 4 insertions(+), 2 deletions(-)
15
create mode 100644 hw/arm/mps2-tz.c
16
14
17
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
15
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
18
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/Makefile.objs
17
--- a/hw/arm/mps2-tz.c
20
+++ b/hw/arm/Makefile.objs
21
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o
22
obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o
23
obj-$(CONFIG_ASPEED_SOC) += aspeed_soc.o aspeed.o
24
obj-$(CONFIG_MPS2) += mps2.o
25
+obj-$(CONFIG_MPS2) += mps2-tz.o
26
obj-$(CONFIG_MSF2) += msf2-soc.o msf2-som.o
27
obj-$(CONFIG_IOTKIT) += iotkit.o
28
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
29
new file mode 100644
30
index XXXXXXX..XXXXXXX
31
--- /dev/null
32
+++ b/hw/arm/mps2-tz.c
18
+++ b/hw/arm/mps2-tz.c
33
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@
34
+/*
20
*/
35
+ * ARM V2M MPS2 board emulation, trustzone aware FPGA images
21
36
+ *
22
#include "qemu/osdep.h"
37
+ * Copyright (c) 2017 Linaro Limited
23
+#include "qemu/units.h"
38
+ * Written by Peter Maydell
24
#include "qapi/error.h"
39
+ *
25
#include "qemu/error-report.h"
40
+ * This program is free software; you can redistribute it and/or modify
26
#include "hw/arm/boot.h"
41
+ * it under the terms of the GNU General Public License version 2 or
27
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
42
+ * (at your option) any later version.
28
* call the 16MB our "system memory", as it's the largest lump.
43
+ */
29
*/
44
+
30
memory_region_allocate_system_memory(&mms->psram,
45
+/* The MPS2 and MPS2+ dev boards are FPGA based (the 2+ has a bigger
31
- NULL, "mps.ram", 0x01000000);
46
+ * FPGA but is otherwise the same as the 2). Since the CPU itself
32
+ NULL, "mps.ram", 16 * MiB);
47
+ * and most of the devices are in the FPGA, the details of the board
33
memory_region_add_subregion(system_memory, 0x80000000, &mms->psram);
48
+ * as seen by the guest depend significantly on the FPGA image.
34
49
+ * This source file covers the following FPGA images, for TrustZone cores:
35
/* The overflow IRQs for all UARTs are ORed together.
50
+ * "mps2-an505" -- Cortex-M33 as documented in ARM Application Note AN505
36
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
51
+ *
37
index XXXXXXX..XXXXXXX 100644
52
+ * Links to the TRM for the board itself and to the various Application
38
--- a/hw/arm/mps2.c
53
+ * Notes which document the FPGA images can be found here:
39
+++ b/hw/arm/mps2.c
54
+ * https://developer.arm.com/products/system-design/development-boards/fpga-prototyping-boards/mps2
40
@@ -XXX,XX +XXX,XX @@
55
+ *
41
*/
56
+ * Board TRM:
42
57
+ * http://infocenter.arm.com/help/topic/com.arm.doc.100112_0200_06_en/versatile_express_cortex_m_prototyping_systems_v2m_mps2_and_v2m_mps2plus_technical_reference_100112_0200_06_en.pdf
43
#include "qemu/osdep.h"
58
+ * Application Note AN505:
44
+#include "qemu/units.h"
59
+ * http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
45
#include "qapi/error.h"
60
+ *
46
#include "qemu/error-report.h"
61
+ * The AN505 defers to the Cortex-M33 processor ARMv8M IoT Kit FVP User Guide
47
#include "hw/arm/boot.h"
62
+ * (ARM ECM0601256) for the details of some of the device layout:
48
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
63
+ * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
49
* zbt_boot_ctrl is always zero).
64
+ */
50
*/
65
+
51
memory_region_allocate_system_memory(&mms->psram,
66
+#include "qemu/osdep.h"
52
- NULL, "mps.ram", 0x1000000);
67
+#include "qapi/error.h"
53
+ NULL, "mps.ram", 16 * MiB);
68
+#include "qemu/error-report.h"
54
memory_region_add_subregion(system_memory, 0x21000000, &mms->psram);
69
+#include "hw/arm/arm.h"
55
70
+#include "hw/arm/armv7m.h"
56
switch (mmc->fpga_type) {
71
+#include "hw/or-irq.h"
72
+#include "hw/boards.h"
73
+#include "exec/address-spaces.h"
74
+#include "sysemu/sysemu.h"
75
+#include "hw/misc/unimp.h"
76
+#include "hw/char/cmsdk-apb-uart.h"
77
+#include "hw/timer/cmsdk-apb-timer.h"
78
+#include "hw/misc/mps2-scc.h"
79
+#include "hw/misc/mps2-fpgaio.h"
80
+#include "hw/arm/iotkit.h"
81
+#include "hw/devices.h"
82
+#include "net/net.h"
83
+#include "hw/core/split-irq.h"
84
+
85
+typedef enum MPS2TZFPGAType {
86
+ FPGA_AN505,
87
+} MPS2TZFPGAType;
88
+
89
+typedef struct {
90
+ MachineClass parent;
91
+ MPS2TZFPGAType fpga_type;
92
+ uint32_t scc_id;
93
+} MPS2TZMachineClass;
94
+
95
+typedef struct {
96
+ MachineState parent;
97
+
98
+ IoTKit iotkit;
99
+ MemoryRegion psram;
100
+ MemoryRegion ssram1;
101
+ MemoryRegion ssram1_m;
102
+ MemoryRegion ssram23;
103
+ MPS2SCC scc;
104
+ MPS2FPGAIO fpgaio;
105
+ TZPPC ppc[5];
106
+ UnimplementedDeviceState ssram_mpc[3];
107
+ UnimplementedDeviceState spi[5];
108
+ UnimplementedDeviceState i2c[4];
109
+ UnimplementedDeviceState i2s_audio;
110
+ UnimplementedDeviceState gpio[5];
111
+ UnimplementedDeviceState dma[4];
112
+ UnimplementedDeviceState gfx;
113
+ CMSDKAPBUART uart[5];
114
+ SplitIRQ sec_resp_splitter;
115
+ qemu_or_irq uart_irq_orgate;
116
+} MPS2TZMachineState;
117
+
118
+#define TYPE_MPS2TZ_MACHINE "mps2tz"
119
+#define TYPE_MPS2TZ_AN505_MACHINE MACHINE_TYPE_NAME("mps2-an505")
120
+
121
+#define MPS2TZ_MACHINE(obj) \
122
+ OBJECT_CHECK(MPS2TZMachineState, obj, TYPE_MPS2TZ_MACHINE)
123
+#define MPS2TZ_MACHINE_GET_CLASS(obj) \
124
+ OBJECT_GET_CLASS(MPS2TZMachineClass, obj, TYPE_MPS2TZ_MACHINE)
125
+#define MPS2TZ_MACHINE_CLASS(klass) \
126
+ OBJECT_CLASS_CHECK(MPS2TZMachineClass, klass, TYPE_MPS2TZ_MACHINE)
127
+
128
+/* Main SYSCLK frequency in Hz */
129
+#define SYSCLK_FRQ 20000000
130
+
131
+/* Initialize the auxiliary RAM region @mr and map it into
132
+ * the memory map at @base.
133
+ */
134
+static void make_ram(MemoryRegion *mr, const char *name,
135
+ hwaddr base, hwaddr size)
136
+{
137
+ memory_region_init_ram(mr, NULL, name, size, &error_fatal);
138
+ memory_region_add_subregion(get_system_memory(), base, mr);
139
+}
140
+
141
+/* Create an alias of an entire original MemoryRegion @orig
142
+ * located at @base in the memory map.
143
+ */
144
+static void make_ram_alias(MemoryRegion *mr, const char *name,
145
+ MemoryRegion *orig, hwaddr base)
146
+{
147
+ memory_region_init_alias(mr, NULL, name, orig, 0,
148
+ memory_region_size(orig));
149
+ memory_region_add_subregion(get_system_memory(), base, mr);
150
+}
151
+
152
+static void init_sysbus_child(Object *parent, const char *childname,
153
+ void *child, size_t childsize,
154
+ const char *childtype)
155
+{
156
+ object_initialize(child, childsize, childtype);
157
+ object_property_add_child(parent, childname, OBJECT(child), &error_abort);
158
+ qdev_set_parent_bus(DEVICE(child), sysbus_get_default());
159
+
160
+}
161
+
162
+/* Most of the devices in the AN505 FPGA image sit behind
163
+ * Peripheral Protection Controllers. These data structures
164
+ * define the layout of which devices sit behind which PPCs.
165
+ * The devfn for each port is a function which creates, configures
166
+ * and initializes the device, returning the MemoryRegion which
167
+ * needs to be plugged into the downstream end of the PPC port.
168
+ */
169
+typedef MemoryRegion *MakeDevFn(MPS2TZMachineState *mms, void *opaque,
170
+ const char *name, hwaddr size);
171
+
172
+typedef struct PPCPortInfo {
173
+ const char *name;
174
+ MakeDevFn *devfn;
175
+ void *opaque;
176
+ hwaddr addr;
177
+ hwaddr size;
178
+} PPCPortInfo;
179
+
180
+typedef struct PPCInfo {
181
+ const char *name;
182
+ PPCPortInfo ports[TZ_NUM_PORTS];
183
+} PPCInfo;
184
+
185
+static MemoryRegion *make_unimp_dev(MPS2TZMachineState *mms,
186
+ void *opaque,
187
+ const char *name, hwaddr size)
188
+{
189
+ /* Initialize, configure and realize a TYPE_UNIMPLEMENTED_DEVICE,
190
+ * and return a pointer to its MemoryRegion.
191
+ */
192
+ UnimplementedDeviceState *uds = opaque;
193
+
194
+ init_sysbus_child(OBJECT(mms), name, uds,
195
+ sizeof(UnimplementedDeviceState),
196
+ TYPE_UNIMPLEMENTED_DEVICE);
197
+ qdev_prop_set_string(DEVICE(uds), "name", name);
198
+ qdev_prop_set_uint64(DEVICE(uds), "size", size);
199
+ object_property_set_bool(OBJECT(uds), true, "realized", &error_fatal);
200
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(uds), 0);
201
+}
202
+
203
+static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
204
+ const char *name, hwaddr size)
205
+{
206
+ CMSDKAPBUART *uart = opaque;
207
+ int i = uart - &mms->uart[0];
208
+ Chardev *uartchr = i < MAX_SERIAL_PORTS ? serial_hds[i] : NULL;
209
+ int rxirqno = i * 2;
210
+ int txirqno = i * 2 + 1;
211
+ int combirqno = i + 10;
212
+ SysBusDevice *s;
213
+ DeviceState *iotkitdev = DEVICE(&mms->iotkit);
214
+ DeviceState *orgate_dev = DEVICE(&mms->uart_irq_orgate);
215
+
216
+ init_sysbus_child(OBJECT(mms), name, uart,
217
+ sizeof(mms->uart[0]), TYPE_CMSDK_APB_UART);
218
+ qdev_prop_set_chr(DEVICE(uart), "chardev", uartchr);
219
+ qdev_prop_set_uint32(DEVICE(uart), "pclk-frq", SYSCLK_FRQ);
220
+ object_property_set_bool(OBJECT(uart), true, "realized", &error_fatal);
221
+ s = SYS_BUS_DEVICE(uart);
222
+ sysbus_connect_irq(s, 0, qdev_get_gpio_in_named(iotkitdev,
223
+ "EXP_IRQ", txirqno));
224
+ sysbus_connect_irq(s, 1, qdev_get_gpio_in_named(iotkitdev,
225
+ "EXP_IRQ", rxirqno));
226
+ sysbus_connect_irq(s, 2, qdev_get_gpio_in(orgate_dev, i * 2));
227
+ sysbus_connect_irq(s, 3, qdev_get_gpio_in(orgate_dev, i * 2 + 1));
228
+ sysbus_connect_irq(s, 4, qdev_get_gpio_in_named(iotkitdev,
229
+ "EXP_IRQ", combirqno));
230
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(uart), 0);
231
+}
232
+
233
+static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque,
234
+ const char *name, hwaddr size)
235
+{
236
+ MPS2SCC *scc = opaque;
237
+ DeviceState *sccdev;
238
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
239
+
240
+ object_initialize(scc, sizeof(mms->scc), TYPE_MPS2_SCC);
241
+ sccdev = DEVICE(scc);
242
+ qdev_set_parent_bus(sccdev, sysbus_get_default());
243
+ qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2);
244
+ qdev_prop_set_uint32(sccdev, "scc-aid", 0x02000008);
245
+ qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id);
246
+ object_property_set_bool(OBJECT(scc), true, "realized", &error_fatal);
247
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(sccdev), 0);
248
+}
249
+
250
+static MemoryRegion *make_fpgaio(MPS2TZMachineState *mms, void *opaque,
251
+ const char *name, hwaddr size)
252
+{
253
+ MPS2FPGAIO *fpgaio = opaque;
254
+
255
+ object_initialize(fpgaio, sizeof(mms->fpgaio), TYPE_MPS2_FPGAIO);
256
+ qdev_set_parent_bus(DEVICE(fpgaio), sysbus_get_default());
257
+ object_property_set_bool(OBJECT(fpgaio), true, "realized", &error_fatal);
258
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(fpgaio), 0);
259
+}
260
+
261
+static void mps2tz_common_init(MachineState *machine)
262
+{
263
+ MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine);
264
+ MachineClass *mc = MACHINE_GET_CLASS(machine);
265
+ MemoryRegion *system_memory = get_system_memory();
266
+ DeviceState *iotkitdev;
267
+ DeviceState *dev_splitter;
268
+ int i;
269
+
270
+ if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
271
+ error_report("This board can only be used with CPU %s",
272
+ mc->default_cpu_type);
273
+ exit(1);
274
+ }
275
+
276
+ init_sysbus_child(OBJECT(machine), "iotkit", &mms->iotkit,
277
+ sizeof(mms->iotkit), TYPE_IOTKIT);
278
+ iotkitdev = DEVICE(&mms->iotkit);
279
+ object_property_set_link(OBJECT(&mms->iotkit), OBJECT(system_memory),
280
+ "memory", &error_abort);
281
+ qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", 92);
282
+ qdev_prop_set_uint32(iotkitdev, "MAINCLK", SYSCLK_FRQ);
283
+ object_property_set_bool(OBJECT(&mms->iotkit), true, "realized",
284
+ &error_fatal);
285
+
286
+ /* The sec_resp_cfg output from the IoTKit must be split into multiple
287
+ * lines, one for each of the PPCs we create here.
288
+ */
289
+ object_initialize(&mms->sec_resp_splitter, sizeof(mms->sec_resp_splitter),
290
+ TYPE_SPLIT_IRQ);
291
+ object_property_add_child(OBJECT(machine), "sec-resp-splitter",
292
+ OBJECT(&mms->sec_resp_splitter), &error_abort);
293
+ object_property_set_int(OBJECT(&mms->sec_resp_splitter), 5,
294
+ "num-lines", &error_fatal);
295
+ object_property_set_bool(OBJECT(&mms->sec_resp_splitter), true,
296
+ "realized", &error_fatal);
297
+ dev_splitter = DEVICE(&mms->sec_resp_splitter);
298
+ qdev_connect_gpio_out_named(iotkitdev, "sec_resp_cfg", 0,
299
+ qdev_get_gpio_in(dev_splitter, 0));
300
+
301
+ /* The IoTKit sets up much of the memory layout, including
302
+ * the aliases between secure and non-secure regions in the
303
+ * address space. The FPGA itself contains:
304
+ *
305
+ * 0x00000000..0x003fffff SSRAM1
306
+ * 0x00400000..0x007fffff alias of SSRAM1
307
+ * 0x28000000..0x283fffff 4MB SSRAM2 + SSRAM3
308
+ * 0x40100000..0x4fffffff AHB Master Expansion 1 interface devices
309
+ * 0x80000000..0x80ffffff 16MB PSRAM
310
+ */
311
+
312
+ /* The FPGA images have an odd combination of different RAMs,
313
+ * because in hardware they are different implementations and
314
+ * connected to different buses, giving varying performance/size
315
+ * tradeoffs. For QEMU they're all just RAM, though. We arbitrarily
316
+ * call the 16MB our "system memory", as it's the largest lump.
317
+ */
318
+ memory_region_allocate_system_memory(&mms->psram,
319
+ NULL, "mps.ram", 0x01000000);
320
+ memory_region_add_subregion(system_memory, 0x80000000, &mms->psram);
321
+
322
+ /* The SSRAM memories should all be behind Memory Protection Controllers,
323
+ * but we don't implement that yet.
324
+ */
325
+ make_ram(&mms->ssram1, "mps.ssram1", 0x00000000, 0x00400000);
326
+ make_ram_alias(&mms->ssram1_m, "mps.ssram1_m", &mms->ssram1, 0x00400000);
327
+
328
+ make_ram(&mms->ssram23, "mps.ssram23", 0x28000000, 0x00400000);
329
+
330
+ /* The overflow IRQs for all UARTs are ORed together.
331
+ * Tx, Rx and "combined" IRQs are sent to the NVIC separately.
332
+ * Create the OR gate for this.
333
+ */
334
+ object_initialize(&mms->uart_irq_orgate, sizeof(mms->uart_irq_orgate),
335
+ TYPE_OR_IRQ);
336
+ object_property_add_child(OBJECT(mms), "uart-irq-orgate",
337
+ OBJECT(&mms->uart_irq_orgate), &error_abort);
338
+ object_property_set_int(OBJECT(&mms->uart_irq_orgate), 10, "num-lines",
339
+ &error_fatal);
340
+ object_property_set_bool(OBJECT(&mms->uart_irq_orgate), true,
341
+ "realized", &error_fatal);
342
+ qdev_connect_gpio_out(DEVICE(&mms->uart_irq_orgate), 0,
343
+ qdev_get_gpio_in_named(iotkitdev, "EXP_IRQ", 15));
344
+
345
+ /* Most of the devices in the FPGA are behind Peripheral Protection
346
+ * Controllers. The required order for initializing things is:
347
+ * + initialize the PPC
348
+ * + initialize, configure and realize downstream devices
349
+ * + connect downstream device MemoryRegions to the PPC
350
+ * + realize the PPC
351
+ * + map the PPC's MemoryRegions to the places in the address map
352
+ * where the downstream devices should appear
353
+ * + wire up the PPC's control lines to the IoTKit object
354
+ */
355
+
356
+ const PPCInfo ppcs[] = { {
357
+ .name = "apb_ppcexp0",
358
+ .ports = {
359
+ { "ssram-mpc0", make_unimp_dev, &mms->ssram_mpc[0],
360
+ 0x58007000, 0x1000 },
361
+ { "ssram-mpc1", make_unimp_dev, &mms->ssram_mpc[1],
362
+ 0x58008000, 0x1000 },
363
+ { "ssram-mpc2", make_unimp_dev, &mms->ssram_mpc[2],
364
+ 0x58009000, 0x1000 },
365
+ },
366
+ }, {
367
+ .name = "apb_ppcexp1",
368
+ .ports = {
369
+ { "spi0", make_unimp_dev, &mms->spi[0], 0x40205000, 0x1000 },
370
+ { "spi1", make_unimp_dev, &mms->spi[1], 0x40206000, 0x1000 },
371
+ { "spi2", make_unimp_dev, &mms->spi[2], 0x40209000, 0x1000 },
372
+ { "spi3", make_unimp_dev, &mms->spi[3], 0x4020a000, 0x1000 },
373
+ { "spi4", make_unimp_dev, &mms->spi[4], 0x4020b000, 0x1000 },
374
+ { "uart0", make_uart, &mms->uart[0], 0x40200000, 0x1000 },
375
+ { "uart1", make_uart, &mms->uart[1], 0x40201000, 0x1000 },
376
+ { "uart2", make_uart, &mms->uart[2], 0x40202000, 0x1000 },
377
+ { "uart3", make_uart, &mms->uart[3], 0x40203000, 0x1000 },
378
+ { "uart4", make_uart, &mms->uart[4], 0x40204000, 0x1000 },
379
+ { "i2c0", make_unimp_dev, &mms->i2c[0], 0x40207000, 0x1000 },
380
+ { "i2c1", make_unimp_dev, &mms->i2c[1], 0x40208000, 0x1000 },
381
+ { "i2c2", make_unimp_dev, &mms->i2c[2], 0x4020c000, 0x1000 },
382
+ { "i2c3", make_unimp_dev, &mms->i2c[3], 0x4020d000, 0x1000 },
383
+ },
384
+ }, {
385
+ .name = "apb_ppcexp2",
386
+ .ports = {
387
+ { "scc", make_scc, &mms->scc, 0x40300000, 0x1000 },
388
+ { "i2s-audio", make_unimp_dev, &mms->i2s_audio,
389
+ 0x40301000, 0x1000 },
390
+ { "fpgaio", make_fpgaio, &mms->fpgaio, 0x40302000, 0x1000 },
391
+ },
392
+ }, {
393
+ .name = "ahb_ppcexp0",
394
+ .ports = {
395
+ { "gfx", make_unimp_dev, &mms->gfx, 0x41000000, 0x140000 },
396
+ { "gpio0", make_unimp_dev, &mms->gpio[0], 0x40100000, 0x1000 },
397
+ { "gpio1", make_unimp_dev, &mms->gpio[1], 0x40101000, 0x1000 },
398
+ { "gpio2", make_unimp_dev, &mms->gpio[2], 0x40102000, 0x1000 },
399
+ { "gpio3", make_unimp_dev, &mms->gpio[3], 0x40103000, 0x1000 },
400
+ { "gpio4", make_unimp_dev, &mms->gpio[4], 0x40104000, 0x1000 },
401
+ },
402
+ }, {
403
+ .name = "ahb_ppcexp1",
404
+ .ports = {
405
+ { "dma0", make_unimp_dev, &mms->dma[0], 0x40110000, 0x1000 },
406
+ { "dma1", make_unimp_dev, &mms->dma[1], 0x40111000, 0x1000 },
407
+ { "dma2", make_unimp_dev, &mms->dma[2], 0x40112000, 0x1000 },
408
+ { "dma3", make_unimp_dev, &mms->dma[3], 0x40113000, 0x1000 },
409
+ },
410
+ },
411
+ };
412
+
413
+ for (i = 0; i < ARRAY_SIZE(ppcs); i++) {
414
+ const PPCInfo *ppcinfo = &ppcs[i];
415
+ TZPPC *ppc = &mms->ppc[i];
416
+ DeviceState *ppcdev;
417
+ int port;
418
+ char *gpioname;
419
+
420
+ init_sysbus_child(OBJECT(machine), ppcinfo->name, ppc,
421
+ sizeof(TZPPC), TYPE_TZ_PPC);
422
+ ppcdev = DEVICE(ppc);
423
+
424
+ for (port = 0; port < TZ_NUM_PORTS; port++) {
425
+ const PPCPortInfo *pinfo = &ppcinfo->ports[port];
426
+ MemoryRegion *mr;
427
+ char *portname;
428
+
429
+ if (!pinfo->devfn) {
430
+ continue;
431
+ }
432
+
433
+ mr = pinfo->devfn(mms, pinfo->opaque, pinfo->name, pinfo->size);
434
+ portname = g_strdup_printf("port[%d]", port);
435
+ object_property_set_link(OBJECT(ppc), OBJECT(mr),
436
+ portname, &error_fatal);
437
+ g_free(portname);
438
+ }
439
+
440
+ object_property_set_bool(OBJECT(ppc), true, "realized", &error_fatal);
441
+
442
+ for (port = 0; port < TZ_NUM_PORTS; port++) {
443
+ const PPCPortInfo *pinfo = &ppcinfo->ports[port];
444
+
445
+ if (!pinfo->devfn) {
446
+ continue;
447
+ }
448
+ sysbus_mmio_map(SYS_BUS_DEVICE(ppc), port, pinfo->addr);
449
+
450
+ gpioname = g_strdup_printf("%s_nonsec", ppcinfo->name);
451
+ qdev_connect_gpio_out_named(iotkitdev, gpioname, port,
452
+ qdev_get_gpio_in_named(ppcdev,
453
+ "cfg_nonsec",
454
+ port));
455
+ g_free(gpioname);
456
+ gpioname = g_strdup_printf("%s_ap", ppcinfo->name);
457
+ qdev_connect_gpio_out_named(iotkitdev, gpioname, port,
458
+ qdev_get_gpio_in_named(ppcdev,
459
+ "cfg_ap", port));
460
+ g_free(gpioname);
461
+ }
462
+
463
+ gpioname = g_strdup_printf("%s_irq_enable", ppcinfo->name);
464
+ qdev_connect_gpio_out_named(iotkitdev, gpioname, 0,
465
+ qdev_get_gpio_in_named(ppcdev,
466
+ "irq_enable", 0));
467
+ g_free(gpioname);
468
+ gpioname = g_strdup_printf("%s_irq_clear", ppcinfo->name);
469
+ qdev_connect_gpio_out_named(iotkitdev, gpioname, 0,
470
+ qdev_get_gpio_in_named(ppcdev,
471
+ "irq_clear", 0));
472
+ g_free(gpioname);
473
+ gpioname = g_strdup_printf("%s_irq_status", ppcinfo->name);
474
+ qdev_connect_gpio_out_named(ppcdev, "irq", 0,
475
+ qdev_get_gpio_in_named(iotkitdev,
476
+ gpioname, 0));
477
+ g_free(gpioname);
478
+
479
+ qdev_connect_gpio_out(dev_splitter, i,
480
+ qdev_get_gpio_in_named(ppcdev,
481
+ "cfg_sec_resp", 0));
482
+ }
483
+
484
+ /* In hardware this is a LAN9220; the LAN9118 is software compatible
485
+ * except that it doesn't support the checksum-offload feature.
486
+ * The ethernet controller is not behind a PPC.
487
+ */
488
+ lan9118_init(&nd_table[0], 0x42000000,
489
+ qdev_get_gpio_in_named(iotkitdev, "EXP_IRQ", 16));
490
+
491
+ create_unimplemented_device("FPGA NS PC", 0x48007000, 0x1000);
492
+
493
+ armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x400000);
494
+}
495
+
496
+static void mps2tz_class_init(ObjectClass *oc, void *data)
497
+{
498
+ MachineClass *mc = MACHINE_CLASS(oc);
499
+
500
+ mc->init = mps2tz_common_init;
501
+ mc->max_cpus = 1;
502
+}
503
+
504
+static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
505
+{
506
+ MachineClass *mc = MACHINE_CLASS(oc);
507
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_CLASS(oc);
508
+
509
+ mc->desc = "ARM MPS2 with AN505 FPGA image for Cortex-M33";
510
+ mmc->fpga_type = FPGA_AN505;
511
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
512
+ mmc->scc_id = 0x41040000 | (505 << 4);
513
+}
514
+
515
+static const TypeInfo mps2tz_info = {
516
+ .name = TYPE_MPS2TZ_MACHINE,
517
+ .parent = TYPE_MACHINE,
518
+ .abstract = true,
519
+ .instance_size = sizeof(MPS2TZMachineState),
520
+ .class_size = sizeof(MPS2TZMachineClass),
521
+ .class_init = mps2tz_class_init,
522
+};
523
+
524
+static const TypeInfo mps2tz_an505_info = {
525
+ .name = TYPE_MPS2TZ_AN505_MACHINE,
526
+ .parent = TYPE_MPS2TZ_MACHINE,
527
+ .class_init = mps2tz_an505_class_init,
528
+};
529
+
530
+static void mps2tz_machine_init(void)
531
+{
532
+ type_register_static(&mps2tz_info);
533
+ type_register_static(&mps2tz_an505_info);
534
+}
535
+
536
+type_init(mps2tz_machine_init);
537
--
57
--
538
2.16.2
58
2.20.1
539
59
540
60
diff view generated by jsdifflib
1
Create an "idau" property on the armv7m container object which
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
we can forward to the CPU object. Annoyingly, we can't use
3
object_property_add_alias() because the CPU object we want to
4
forward to doesn't exist until the armv7m container is realized.
5
2
3
The SDRAM is incorrectly created in the SA1110 SoC.
4
Move its creation in the board code, this will later allow the
5
board to have the QOM ownership of the RAM.
6
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
Message-id: 20191021190653.9511-4-philmd@redhat.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180220180325.29818-6-peter.maydell@linaro.org
9
---
12
---
10
include/hw/arm/armv7m.h | 3 +++
13
hw/arm/strongarm.h | 4 +---
11
hw/arm/armv7m.c | 9 +++++++++
14
hw/arm/collie.c | 8 ++++++--
12
2 files changed, 12 insertions(+)
15
hw/arm/strongarm.c | 7 +------
16
3 files changed, 8 insertions(+), 11 deletions(-)
13
17
14
diff --git a/include/hw/arm/armv7m.h b/include/hw/arm/armv7m.h
18
diff --git a/hw/arm/strongarm.h b/hw/arm/strongarm.h
15
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
16
--- a/include/hw/arm/armv7m.h
20
--- a/hw/arm/strongarm.h
17
+++ b/include/hw/arm/armv7m.h
21
+++ b/hw/arm/strongarm.h
18
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@ enum {
19
23
20
#include "hw/sysbus.h"
24
typedef struct {
21
#include "hw/intc/armv7m_nvic.h"
25
ARMCPU *cpu;
22
+#include "target/arm/idau.h"
26
- MemoryRegion sdram;
23
27
DeviceState *pic;
24
#define TYPE_BITBAND "ARM,bitband-memory"
28
DeviceState *gpio;
25
#define BITBAND(obj) OBJECT_CHECK(BitBandState, (obj), TYPE_BITBAND)
29
DeviceState *ppc;
26
@@ -XXX,XX +XXX,XX @@ typedef struct {
30
@@ -XXX,XX +XXX,XX @@ typedef struct {
27
* + Property "memory": MemoryRegion defining the physical address space
31
SSIBus *ssp_bus;
28
* that CPU accesses see. (The NVIC, bitbanding and other CPU-internal
32
} StrongARMState;
29
* devices will be automatically layered on top of this view.)
33
30
+ * + Property "idau": IDAU interface (forwarded to CPU object)
34
-StrongARMState *sa1110_init(MemoryRegion *sysmem,
31
*/
35
- unsigned int sdram_size, const char *rev);
32
typedef struct ARMv7MState {
36
+StrongARMState *sa1110_init(const char *cpu_type);
33
/*< private >*/
34
@@ -XXX,XX +XXX,XX @@ typedef struct ARMv7MState {
35
char *cpu_type;
36
/* MemoryRegion the board provides to us (with its devices, RAM, etc) */
37
MemoryRegion *board_memory;
38
+ Object *idau;
39
} ARMv7MState;
40
37
41
#endif
38
#endif
42
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
39
diff --git a/hw/arm/collie.c b/hw/arm/collie.c
43
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
44
--- a/hw/arm/armv7m.c
41
--- a/hw/arm/collie.c
45
+++ b/hw/arm/armv7m.c
42
+++ b/hw/arm/collie.c
46
@@ -XXX,XX +XXX,XX @@
43
@@ -XXX,XX +XXX,XX @@ static void collie_init(MachineState *machine)
47
#include "sysemu/qtest.h"
44
{
48
#include "qemu/error-report.h"
45
StrongARMState *s;
49
#include "exec/address-spaces.h"
46
DriveInfo *dinfo;
50
+#include "target/arm/idau.h"
47
- MemoryRegion *sysmem = get_system_memory();
51
48
+ MemoryRegion *sdram = g_new(MemoryRegion, 1);
52
/* Bitbanded IO. Each word corresponds to a single bit. */
49
53
50
- s = sa1110_init(sysmem, collie_binfo.ram_size, machine->cpu_type);
54
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
51
+ s = sa1110_init(machine->cpu_type);
55
52
+
56
object_property_set_link(OBJECT(s->cpu), OBJECT(&s->container), "memory",
53
+ memory_region_allocate_system_memory(sdram, NULL, "strongarm.sdram",
57
&error_abort);
54
+ collie_binfo.ram_size);
58
+ if (object_property_find(OBJECT(s->cpu), "idau", NULL)) {
55
+ memory_region_add_subregion(get_system_memory(), SA_SDCS0, sdram);
59
+ object_property_set_link(OBJECT(s->cpu), s->idau, "idau", &err);
56
60
+ if (err != NULL) {
57
dinfo = drive_get(IF_PFLASH, 0, 0);
61
+ error_propagate(errp, err);
58
pflash_cfi01_register(SA_CS0, "collie.fl1", 0x02000000,
62
+ return;
59
diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c
63
+ }
60
index XXXXXXX..XXXXXXX 100644
64
+ }
61
--- a/hw/arm/strongarm.c
65
object_property_set_bool(OBJECT(s->cpu), true, "realized", &err);
62
+++ b/hw/arm/strongarm.c
66
if (err != NULL) {
63
@@ -XXX,XX +XXX,XX @@ static const TypeInfo strongarm_ssp_info = {
67
error_propagate(errp, err);
68
@@ -XXX,XX +XXX,XX @@ static Property armv7m_properties[] = {
69
DEFINE_PROP_STRING("cpu-type", ARMv7MState, cpu_type),
70
DEFINE_PROP_LINK("memory", ARMv7MState, board_memory, TYPE_MEMORY_REGION,
71
MemoryRegion *),
72
+ DEFINE_PROP_LINK("idau", ARMv7MState, idau, TYPE_IDAU_INTERFACE, Object *),
73
DEFINE_PROP_END_OF_LIST(),
74
};
64
};
75
65
66
/* Main CPU functions */
67
-StrongARMState *sa1110_init(MemoryRegion *sysmem,
68
- unsigned int sdram_size, const char *cpu_type)
69
+StrongARMState *sa1110_init(const char *cpu_type)
70
{
71
StrongARMState *s;
72
int i;
73
@@ -XXX,XX +XXX,XX @@ StrongARMState *sa1110_init(MemoryRegion *sysmem,
74
75
s->cpu = ARM_CPU(cpu_create(cpu_type));
76
77
- memory_region_allocate_system_memory(&s->sdram, NULL, "strongarm.sdram",
78
- sdram_size);
79
- memory_region_add_subregion(sysmem, SA_SDCS0, &s->sdram);
80
-
81
s->pic = sysbus_create_varargs("strongarm_pic", 0x90050000,
82
qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ),
83
qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_FIQ),
76
--
84
--
77
2.16.2
85
2.20.1
78
86
79
87
diff view generated by jsdifflib
1
Move the definition of the struct for the unimplemented-device
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
from unimp.c to unimp.h, so that users can embed the struct
3
in their own device structs if they prefer.
4
2
3
The SDRAM is incorrectly created in the OMAP2420 SoC.
4
Move its creation in the board code, this will later allow the
5
board to have the QOM ownership of the RAM.
6
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
Message-id: 20191021190653.9511-5-philmd@redhat.com
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20180220180325.29818-10-peter.maydell@linaro.org
9
---
12
---
10
include/hw/misc/unimp.h | 10 ++++++++++
13
include/hw/arm/omap.h | 4 +---
11
hw/misc/unimp.c | 10 ----------
14
hw/arm/nseries.c | 10 +++++++---
12
2 files changed, 10 insertions(+), 10 deletions(-)
15
hw/arm/omap2.c | 13 +++++--------
16
3 files changed, 13 insertions(+), 14 deletions(-)
13
17
14
diff --git a/include/hw/misc/unimp.h b/include/hw/misc/unimp.h
18
diff --git a/include/hw/arm/omap.h b/include/hw/arm/omap.h
15
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
16
--- a/include/hw/misc/unimp.h
20
--- a/include/hw/arm/omap.h
17
+++ b/include/hw/misc/unimp.h
21
+++ b/include/hw/arm/omap.h
22
@@ -XXX,XX +XXX,XX @@ struct omap_mpu_state_s {
23
MemoryRegion tap_iomem;
24
MemoryRegion imif_ram;
25
MemoryRegion emiff_ram;
26
- MemoryRegion sdram;
27
MemoryRegion sram;
28
29
struct omap_dma_port_if_s {
30
@@ -XXX,XX +XXX,XX @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
31
const char *core);
32
33
/* omap2.c */
34
-struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
35
- unsigned long sdram_size,
36
+struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sdram,
37
const char *core);
38
39
uint32_t omap_badwidth_read8(void *opaque, hwaddr addr);
40
diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/arm/nseries.c
43
+++ b/hw/arm/nseries.c
18
@@ -XXX,XX +XXX,XX @@
44
@@ -XXX,XX +XXX,XX @@
19
45
20
#define TYPE_UNIMPLEMENTED_DEVICE "unimplemented-device"
46
/* Nokia N8x0 support */
21
47
struct n800_s {
22
+#define UNIMPLEMENTED_DEVICE(obj) \
48
+ MemoryRegion sdram;
23
+ OBJECT_CHECK(UnimplementedDeviceState, (obj), TYPE_UNIMPLEMENTED_DEVICE)
49
struct omap_mpu_state_s *mpu;
50
51
struct rfbi_chip_s blizzard;
52
@@ -XXX,XX +XXX,XX @@ static int n810_atag_setup(const struct arm_boot_info *info, void *p)
53
static void n8x0_init(MachineState *machine,
54
struct arm_boot_info *binfo, int model)
55
{
56
- MemoryRegion *sysmem = get_system_memory();
57
struct n800_s *s = (struct n800_s *) g_malloc0(sizeof(*s));
58
- int sdram_size = binfo->ram_size;
59
+ uint64_t sdram_size = binfo->ram_size;
60
61
- s->mpu = omap2420_mpu_init(sysmem, sdram_size, machine->cpu_type);
62
+ memory_region_allocate_system_memory(&s->sdram, NULL, "omap2.dram",
63
+ sdram_size);
64
+ memory_region_add_subregion(get_system_memory(), OMAP2_Q2_BASE, &s->sdram);
24
+
65
+
25
+typedef struct {
66
+ s->mpu = omap2420_mpu_init(&s->sdram, machine->cpu_type);
26
+ SysBusDevice parent_obj;
67
27
+ MemoryRegion iomem;
68
/* Setup peripherals
28
+ char *name;
69
*
29
+ uint64_t size;
70
diff --git a/hw/arm/omap2.c b/hw/arm/omap2.c
30
+} UnimplementedDeviceState;
31
+
32
/**
33
* create_unimplemented_device: create and map a dummy device
34
* @name: name of the device for debug logging
35
diff --git a/hw/misc/unimp.c b/hw/misc/unimp.c
36
index XXXXXXX..XXXXXXX 100644
71
index XXXXXXX..XXXXXXX 100644
37
--- a/hw/misc/unimp.c
72
--- a/hw/arm/omap2.c
38
+++ b/hw/misc/unimp.c
73
+++ b/hw/arm/omap2.c
39
@@ -XXX,XX +XXX,XX @@
74
@@ -XXX,XX +XXX,XX @@
40
#include "qemu/log.h"
75
#include "qemu/error-report.h"
41
#include "qapi/error.h"
76
#include "qapi/error.h"
42
77
#include "cpu.h"
43
-#define UNIMPLEMENTED_DEVICE(obj) \
78
+#include "exec/address-spaces.h"
44
- OBJECT_CHECK(UnimplementedDeviceState, (obj), TYPE_UNIMPLEMENTED_DEVICE)
79
#include "sysemu/blockdev.h"
45
-
80
#include "sysemu/qtest.h"
46
-typedef struct {
81
#include "sysemu/reset.h"
47
- SysBusDevice parent_obj;
82
@@ -XXX,XX +XXX,XX @@ static const struct dma_irq_map omap2_dma_irq_map[] = {
48
- MemoryRegion iomem;
83
{ 0, OMAP_INT_24XX_SDMA_IRQ3 },
49
- char *name;
84
};
50
- uint64_t size;
85
51
-} UnimplementedDeviceState;
86
-struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
52
-
87
- unsigned long sdram_size,
53
static uint64_t unimp_read(void *opaque, hwaddr offset, unsigned size)
88
+struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sdram,
89
const char *cpu_type)
54
{
90
{
55
UnimplementedDeviceState *s = UNIMPLEMENTED_DEVICE(opaque);
91
struct omap_mpu_state_s *s = g_new0(struct omap_mpu_state_s, 1);
92
@@ -XXX,XX +XXX,XX @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
93
int i;
94
SysBusDevice *busdev;
95
struct omap_target_agent_s *ta;
96
+ MemoryRegion *sysmem = get_system_memory();
97
98
/* Core */
99
s->mpu_model = omap2420;
100
s->cpu = ARM_CPU(cpu_create(cpu_type));
101
- s->sdram_size = sdram_size;
102
s->sram_size = OMAP242X_SRAM_SIZE;
103
104
s->wakeup = qemu_allocate_irq(omap_mpu_wakeup, s, 0);
105
@@ -XXX,XX +XXX,XX @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
106
omap_clk_init(s);
107
108
/* Memory-mapped stuff */
109
- memory_region_allocate_system_memory(&s->sdram, NULL, "omap2.dram",
110
- s->sdram_size);
111
- memory_region_add_subregion(sysmem, OMAP2_Q2_BASE, &s->sdram);
112
memory_region_init_ram(&s->sram, NULL, "omap2.sram", s->sram_size,
113
&error_fatal);
114
memory_region_add_subregion(sysmem, OMAP2_SRAM_BASE, &s->sram);
115
@@ -XXX,XX +XXX,XX @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
116
s->port->addr_valid = omap2_validate_addr;
117
118
/* Register SDRAM and SRAM ports for fast DMA transfers. */
119
- soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->sdram),
120
- OMAP2_Q2_BASE, s->sdram_size);
121
+ soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(sdram),
122
+ OMAP2_Q2_BASE, memory_region_size(sdram));
123
soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->sram),
124
OMAP2_SRAM_BASE, s->sram_size);
125
56
--
126
--
57
2.16.2
127
2.20.1
58
128
59
129
diff view generated by jsdifflib
1
The function qdev_init_gpio_in_named() passes the DeviceState pointer
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
as the opaque data pointor for the irq handler function. Usually
3
this is what you want, but in some cases it would be helpful to use
4
some other data pointer.
5
2
6
Add a new function qdev_init_gpio_in_named_with_opaque() which allows
3
The SDRAM is incorrectly created in the OMAP310 SoC.
7
the caller to specify the data pointer they want.
4
Move its creation in the board code, this will later allow the
5
board to have the QOM ownership of the RAM.
8
6
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
Message-id: 20191021190653.9511-6-philmd@redhat.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20180220180325.29818-12-peter.maydell@linaro.org
13
---
12
---
14
include/hw/qdev-core.h | 30 ++++++++++++++++++++++++++++--
13
include/hw/arm/omap.h | 6 ++----
15
hw/core/qdev.c | 8 +++++---
14
hw/arm/omap1.c | 12 +++++-------
16
2 files changed, 33 insertions(+), 5 deletions(-)
15
hw/arm/omap_sx1.c | 8 ++++++--
16
hw/arm/palm.c | 8 ++++++--
17
4 files changed, 19 insertions(+), 15 deletions(-)
17
18
18
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
19
diff --git a/include/hw/arm/omap.h b/include/hw/arm/omap.h
19
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/qdev-core.h
21
--- a/include/hw/arm/omap.h
21
+++ b/include/hw/qdev-core.h
22
+++ b/include/hw/arm/omap.h
22
@@ -XXX,XX +XXX,XX @@ BusState *qdev_get_child_bus(DeviceState *dev, const char *name);
23
@@ -XXX,XX +XXX,XX @@ struct omap_mpu_state_s {
23
/* GPIO inputs also double as IRQ sinks. */
24
MemoryRegion mpui_io_iomem;
24
void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n);
25
MemoryRegion tap_iomem;
25
void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n);
26
MemoryRegion imif_ram;
26
-void qdev_init_gpio_in_named(DeviceState *dev, qemu_irq_handler handler,
27
- MemoryRegion emiff_ram;
27
- const char *name, int n);
28
MemoryRegion sram;
28
void qdev_init_gpio_out_named(DeviceState *dev, qemu_irq *pins,
29
29
const char *name, int n);
30
struct omap_dma_port_if_s {
30
+/**
31
@@ -XXX,XX +XXX,XX @@ struct omap_mpu_state_s {
31
+ * qdev_init_gpio_in_named_with_opaque: create an array of input GPIO lines
32
hwaddr addr);
32
+ * for the specified device
33
} port[__omap_dma_port_last];
33
+ *
34
34
+ * @dev: Device to create input GPIOs for
35
- unsigned long sdram_size;
35
+ * @handler: Function to call when GPIO line value is set
36
+ uint64_t sdram_size;
36
+ * @opaque: Opaque data pointer to pass to @handler
37
unsigned long sram_size;
37
+ * @name: Name of the GPIO input (must be unique for this device)
38
38
+ * @n: Number of GPIO lines in this input set
39
/* MPUI-TIPB peripherals */
39
+ */
40
@@ -XXX,XX +XXX,XX @@ struct omap_mpu_state_s {
40
+void qdev_init_gpio_in_named_with_opaque(DeviceState *dev,
41
};
41
+ qemu_irq_handler handler,
42
42
+ void *opaque,
43
/* omap1.c */
43
+ const char *name, int n);
44
-struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
44
+
45
- unsigned long sdram_size,
45
+/**
46
+struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *sdram,
46
+ * qdev_init_gpio_in_named: create an array of input GPIO lines
47
const char *core);
47
+ * for the specified device
48
48
+ *
49
/* omap2.c */
49
+ * Like qdev_init_gpio_in_named_with_opaque(), but the opaque pointer
50
diff --git a/hw/arm/omap1.c b/hw/arm/omap1.c
50
+ * passed to the handler is @dev (which is the most commonly desired behaviour).
51
+ */
52
+static inline void qdev_init_gpio_in_named(DeviceState *dev,
53
+ qemu_irq_handler handler,
54
+ const char *name, int n)
55
+{
56
+ qdev_init_gpio_in_named_with_opaque(dev, handler, dev, name, n);
57
+}
58
59
void qdev_pass_gpios(DeviceState *dev, DeviceState *container,
60
const char *name);
61
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
62
index XXXXXXX..XXXXXXX 100644
51
index XXXXXXX..XXXXXXX 100644
63
--- a/hw/core/qdev.c
52
--- a/hw/arm/omap1.c
64
+++ b/hw/core/qdev.c
53
+++ b/hw/arm/omap1.c
65
@@ -XXX,XX +XXX,XX @@ static NamedGPIOList *qdev_get_named_gpio_list(DeviceState *dev,
54
@@ -XXX,XX +XXX,XX @@
66
return ngl;
55
#include "qapi/error.h"
56
#include "qemu-common.h"
57
#include "cpu.h"
58
+#include "exec/address-spaces.h"
59
#include "hw/boards.h"
60
#include "hw/hw.h"
61
#include "hw/irq.h"
62
@@ -XXX,XX +XXX,XX @@ static int omap_validate_tipb_mpui_addr(struct omap_mpu_state_s *s,
63
return range_covers_byte(0xe1010000, 0xe1020004 - 0xe1010000, addr);
67
}
64
}
68
65
69
-void qdev_init_gpio_in_named(DeviceState *dev, qemu_irq_handler handler,
66
-struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
70
- const char *name, int n)
67
- unsigned long sdram_size,
71
+void qdev_init_gpio_in_named_with_opaque(DeviceState *dev,
68
+struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *dram,
72
+ qemu_irq_handler handler,
69
const char *cpu_type)
73
+ void *opaque,
74
+ const char *name, int n)
75
{
70
{
76
int i;
71
int i;
77
NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name);
72
@@ -XXX,XX +XXX,XX @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
78
73
qemu_irq dma_irqs[6];
79
assert(gpio_list->num_out == 0 || !name);
74
DriveInfo *dinfo;
80
gpio_list->in = qemu_extend_irqs(gpio_list->in, gpio_list->num_in, handler,
75
SysBusDevice *busdev;
81
- dev, n);
76
+ MemoryRegion *system_memory = get_system_memory();
82
+ opaque, n);
77
83
78
/* Core */
84
if (!name) {
79
s->mpu_model = omap310;
85
name = "unnamed-gpio-in";
80
s->cpu = ARM_CPU(cpu_create(cpu_type));
81
- s->sdram_size = sdram_size;
82
+ s->sdram_size = memory_region_size(dram);
83
s->sram_size = OMAP15XX_SRAM_SIZE;
84
85
s->wakeup = qemu_allocate_irq(omap_mpu_wakeup, s, 0);
86
@@ -XXX,XX +XXX,XX @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
87
omap_clk_init(s);
88
89
/* Memory-mapped stuff */
90
- memory_region_allocate_system_memory(&s->emiff_ram, NULL, "omap1.dram",
91
- s->sdram_size);
92
- memory_region_add_subregion(system_memory, OMAP_EMIFF_BASE, &s->emiff_ram);
93
memory_region_init_ram(&s->imif_ram, NULL, "omap1.sram", s->sram_size,
94
&error_fatal);
95
memory_region_add_subregion(system_memory, OMAP_IMIF_BASE, &s->imif_ram);
96
@@ -XXX,XX +XXX,XX @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
97
s->port[tipb_mpui].addr_valid = omap_validate_tipb_mpui_addr;
98
99
/* Register SDRAM and SRAM DMA ports for fast transfers. */
100
- soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->emiff_ram),
101
+ soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(dram),
102
OMAP_EMIFF_BASE, s->sdram_size);
103
soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->imif_ram),
104
OMAP_IMIF_BASE, s->sram_size);
105
diff --git a/hw/arm/omap_sx1.c b/hw/arm/omap_sx1.c
106
index XXXXXXX..XXXXXXX 100644
107
--- a/hw/arm/omap_sx1.c
108
+++ b/hw/arm/omap_sx1.c
109
@@ -XXX,XX +XXX,XX @@ static void sx1_init(MachineState *machine, const int version)
110
{
111
struct omap_mpu_state_s *mpu;
112
MemoryRegion *address_space = get_system_memory();
113
+ MemoryRegion *dram = g_new(MemoryRegion, 1);
114
MemoryRegion *flash = g_new(MemoryRegion, 1);
115
MemoryRegion *cs = g_new(MemoryRegion, 4);
116
static uint32_t cs0val = 0x00213090;
117
@@ -XXX,XX +XXX,XX @@ static void sx1_init(MachineState *machine, const int version)
118
flash_size = flash2_size;
119
}
120
121
- mpu = omap310_mpu_init(address_space, sx1_binfo.ram_size,
122
- machine->cpu_type);
123
+ memory_region_allocate_system_memory(dram, NULL, "omap1.dram",
124
+ sx1_binfo.ram_size);
125
+ memory_region_add_subregion(address_space, OMAP_EMIFF_BASE, dram);
126
+
127
+ mpu = omap310_mpu_init(dram, machine->cpu_type);
128
129
/* External Flash (EMIFS) */
130
memory_region_init_ram(flash, NULL, "omap_sx1.flash0-0", flash_size,
131
diff --git a/hw/arm/palm.c b/hw/arm/palm.c
132
index XXXXXXX..XXXXXXX 100644
133
--- a/hw/arm/palm.c
134
+++ b/hw/arm/palm.c
135
@@ -XXX,XX +XXX,XX @@ static void palmte_init(MachineState *machine)
136
MemoryRegion *address_space_mem = get_system_memory();
137
struct omap_mpu_state_s *mpu;
138
int flash_size = 0x00800000;
139
- int sdram_size = palmte_binfo.ram_size;
140
static uint32_t cs0val = 0xffffffff;
141
static uint32_t cs1val = 0x0000e1a0;
142
static uint32_t cs2val = 0x0000e1a0;
143
static uint32_t cs3val = 0xe1a0e1a0;
144
int rom_size, rom_loaded = 0;
145
+ MemoryRegion *dram = g_new(MemoryRegion, 1);
146
MemoryRegion *flash = g_new(MemoryRegion, 1);
147
MemoryRegion *cs = g_new(MemoryRegion, 4);
148
149
- mpu = omap310_mpu_init(address_space_mem, sdram_size, machine->cpu_type);
150
+ memory_region_allocate_system_memory(dram, NULL, "omap1.dram",
151
+ palmte_binfo.ram_size);
152
+ memory_region_add_subregion(address_space_mem, OMAP_EMIFF_BASE, dram);
153
+
154
+ mpu = omap310_mpu_init(dram, machine->cpu_type);
155
156
/* External Flash (EMIFS) */
157
memory_region_init_ram(flash, NULL, "palmte.flash", flash_size,
86
--
158
--
87
2.16.2
159
2.20.1
88
160
89
161
diff view generated by jsdifflib
1
Instead of loading guest images to the system address space, use the
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
CPU's address space. This is important if we're trying to load the
3
file to memory or via an alias memory region that is provided by an
4
SoC object and thus not mapped into the system address space.
5
2
3
Having the RAM creation code in a separate function is not
4
very helpful. Move this code directly inside the board_init()
5
function, this will later allow the board to have the QOM
6
ownership of the RAM.
7
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
11
Message-id: 20191021190653.9511-7-philmd@redhat.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20180220180325.29818-4-peter.maydell@linaro.org
10
---
13
---
11
hw/arm/armv7m.c | 17 ++++++++++++++---
14
hw/arm/digic_boards.c | 9 ++-------
12
1 file changed, 14 insertions(+), 3 deletions(-)
15
1 file changed, 2 insertions(+), 7 deletions(-)
13
16
14
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
17
diff --git a/hw/arm/digic_boards.c b/hw/arm/digic_boards.c
15
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/armv7m.c
19
--- a/hw/arm/digic_boards.c
17
+++ b/hw/arm/armv7m.c
20
+++ b/hw/arm/digic_boards.c
18
@@ -XXX,XX +XXX,XX @@ void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size)
21
@@ -XXX,XX +XXX,XX @@ typedef struct DigicBoard {
19
uint64_t entry;
22
const char *rom1_def_filename;
20
uint64_t lowaddr;
23
} DigicBoard;
21
int big_endian;
24
22
+ AddressSpace *as;
25
-static void digic4_board_setup_ram(DigicBoardState *s, hwaddr ram_size)
23
+ int asidx;
26
-{
24
+ CPUState *cs = CPU(cpu);
27
- memory_region_allocate_system_memory(&s->ram, NULL, "ram", ram_size);
25
28
- memory_region_add_subregion(get_system_memory(), 0, &s->ram);
26
#ifdef TARGET_WORDS_BIGENDIAN
29
-}
27
big_endian = 1;
30
-
28
@@ -XXX,XX +XXX,XX @@ void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size)
31
static void digic4_board_init(DigicBoard *board)
32
{
33
Error *err = NULL;
34
@@ -XXX,XX +XXX,XX @@ static void digic4_board_init(DigicBoard *board)
29
exit(1);
35
exit(1);
30
}
36
}
31
37
32
+ if (arm_feature(&cpu->env, ARM_FEATURE_EL3)) {
38
- digic4_board_setup_ram(s, board->ram_size);
33
+ asidx = ARMASIdx_S;
39
+ memory_region_allocate_system_memory(&s->ram, NULL, "ram", board->ram_size);
34
+ } else {
40
+ memory_region_add_subregion(get_system_memory(), 0, &s->ram);
35
+ asidx = ARMASIdx_NS;
41
36
+ }
42
if (board->add_rom0) {
37
+ as = cpu_get_address_space(cs, asidx);
43
board->add_rom0(s, DIGIC4_ROM0_BASE, board->rom0_def_filename);
38
+
39
if (kernel_filename) {
40
- image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr,
41
- NULL, big_endian, EM_ARM, 1, 0);
42
+ image_size = load_elf_as(kernel_filename, NULL, NULL, &entry, &lowaddr,
43
+ NULL, big_endian, EM_ARM, 1, 0, as);
44
if (image_size < 0) {
45
- image_size = load_image_targphys(kernel_filename, 0, mem_size);
46
+ image_size = load_image_targphys_as(kernel_filename, 0,
47
+ mem_size, as);
48
lowaddr = 0;
49
}
50
if (image_size < 0) {
51
--
44
--
52
2.16.2
45
2.20.1
53
46
54
47
diff view generated by jsdifflib