1
Arm queue -- mostly the first slice of my Musca patches.
1
This is a respin of my pull request from earlier this week:
2
* versal board compile failure fixed
3
* a few new patches:
4
- MAINTAINERS file fix
5
- use ARRAY_SIZE macro in xilinx_zynq
6
- avoid an array overrun in strongarm GPIO irq handling
7
- fix an assert running KVM on an aarch64-only host
2
8
3
thanks
9
The following changes since commit 69e2d03843412b9c076515b3aa9a71db161b6a1a:
4
-- PMM
5
10
6
The following changes since commit fc3dbb90f2eb069801bfb4cfe9cbc83cf9c5f4a9:
11
Merge remote-tracking branch 'remotes/riscv/tags/riscv-for-master-3.1-sf1' into staging (2018-11-02 13:16:13 +0000)
7
8
Merge remote-tracking branch 'remotes/jnsnow/tags/bitmaps-pull-request' into staging (2019-02-21 13:09:33 +0000)
9
12
10
are available in the Git repository at:
13
are available in the Git repository at:
11
14
12
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20190221
15
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20181102
13
16
14
for you to fetch changes up to 3733f80308d2a7f23f5e39b039e0547aba6c07f1:
17
for you to fetch changes up to 6f16da53ffe4567c0353f85055df04860eb4e6fc:
15
18
16
hw/arm/armsse: Make 0x5... alias region work for per-CPU devices (2019-02-21 18:17:48 +0000)
19
hw/arm: versal: Add a virtual Xilinx Versal board (2018-11-02 14:11:31 +0000)
17
20
18
----------------------------------------------------------------
21
----------------------------------------------------------------
19
target-arm queue:
22
target-arm queue:
20
* Model the Arm "Musca" development boards: "musca-a" and "musca-b1"
23
* microbit: Add the UART to our nRF51 SoC model
21
* Implement the ARMv8.3-JSConv extension
24
* Add a virtual Xilinx Versal board "xlnx-versal-virt"
22
* v8M MPU should use background region as default, not always
25
* hw/arm/virt: Set VIRT_COMPAT_3_0 compat
23
* Stop unintentional sign extension in pmu_init
26
* MAINTAINERS: Remove bouncing email in ARM ACPI
27
* strongarm: mask off high[31:28] bits from dir and state registers
28
* target/arm: Conditionalize some asserts on aarch32 support
29
* hw/arm/xilinx_zynq: Use the ARRAY_SIZE macro
24
30
25
----------------------------------------------------------------
31
----------------------------------------------------------------
26
Aaron Lindsay OS (1):
32
Edgar E. Iglesias (2):
27
target/arm: Stop unintentional sign extension in pmu_init
33
hw/arm: versal: Add a model of Xilinx Versal SoC
34
hw/arm: versal: Add a virtual Xilinx Versal board
28
35
29
Peter Maydell (16):
36
Eric Auger (1):
30
hw/arm/armsse: Fix memory leak in error-exit path
37
hw/arm/virt: Set VIRT_COMPAT_3_0 compat
31
target/arm: v8M MPU should use background region as default, not always
32
hw/misc/tz-ppc: Support having unused ports in the middle of the range
33
hw/timer/pl031: Allow use as an embedded-struct device
34
hw/timer/pl031: Convert to using trace events
35
hw/char/pl011: Allow use as an embedded-struct device
36
hw/char/pl011: Support all interrupt lines
37
hw/char/pl011: Use '0x' prefix when logging hex numbers
38
hw/arm/armsse: Document SRAM_ADDR_WIDTH property in header comment
39
hw/arm/armsse: Allow boards to specify init-svtor
40
hw/arm/musca.c: Implement models of the Musca-A and -B1 boards
41
hw/arm/musca: Add PPCs
42
hw/arm/musca: Add MPCs
43
hw/arm/musca: Wire up PL031 RTC
44
hw/arm/musca: Wire up PL011 UARTs
45
hw/arm/armsse: Make 0x5... alias region work for per-CPU devices
46
38
47
Richard Henderson (4):
39
Julia Suvorova (3):
48
target/arm: Restructure disas_fp_int_conv
40
hw/char: Implement nRF51 SoC UART
49
target/arm: Split out vfp_helper.c
41
hw/arm/nrf51_soc: Connect UART to nRF51 SoC
50
target/arm: Rearrange Floating-point data-processing (2 regs)
42
tests/boot-serial-test: Add microbit board testcase
51
target/arm: Implement ARMv8.3-JSConv
52
43
53
hw/arm/Makefile.objs | 1 +
44
Philippe Mathieu-Daudé (2):
54
target/arm/Makefile.objs | 2 +-
45
MAINTAINERS: Remove bouncing email in ARM ACPI
55
include/hw/arm/armsse.h | 7 +-
46
hw/arm/xilinx_zynq: Use the ARRAY_SIZE macro
56
include/hw/char/pl011.h | 34 ++
57
include/hw/misc/tz-ppc.h | 8 +-
58
include/hw/timer/pl031.h | 44 ++
59
target/arm/cpu.h | 10 +
60
target/arm/helper.h | 3 +
61
hw/arm/armsse.c | 44 +-
62
hw/arm/musca.c | 669 ++++++++++++++++++++++
63
hw/char/pl011.c | 81 +--
64
hw/misc/tz-ppc.c | 32 ++
65
hw/timer/pl031.c | 80 ++-
66
target/arm/cpu.c | 1 +
67
target/arm/cpu64.c | 2 +
68
target/arm/helper.c | 1072 +----------------------------------
69
target/arm/translate-a64.c | 120 ++--
70
target/arm/translate.c | 237 ++++----
71
target/arm/vfp_helper.c | 1176 +++++++++++++++++++++++++++++++++++++++
72
MAINTAINERS | 7 +
73
default-configs/arm-softmmu.mak | 1 +
74
hw/timer/trace-events | 6 +
75
22 files changed, 2307 insertions(+), 1330 deletions(-)
76
create mode 100644 include/hw/timer/pl031.h
77
create mode 100644 hw/arm/musca.c
78
create mode 100644 target/arm/vfp_helper.c
79
47
48
Prasad J Pandit (1):
49
strongarm: mask off high[31:28] bits from dir and state registers
50
51
Richard Henderson (1):
52
target/arm: Conditionalize some asserts on aarch32 support
53
54
hw/arm/Makefile.objs | 1 +
55
hw/char/Makefile.objs | 1 +
56
include/hw/arm/nrf51_soc.h | 3 +
57
include/hw/arm/xlnx-versal.h | 122 +++++++++
58
include/hw/char/nrf51_uart.h | 78 ++++++
59
target/arm/cpu.h | 5 +
60
hw/arm/microbit.c | 2 +
61
hw/arm/nrf51_soc.c | 20 ++
62
hw/arm/strongarm.c | 4 +-
63
hw/arm/virt.c | 4 +
64
hw/arm/xilinx_zynq.c | 2 +-
65
hw/arm/xlnx-versal-virt.c | 494 ++++++++++++++++++++++++++++++++++++
66
hw/arm/xlnx-versal.c | 323 +++++++++++++++++++++++
67
hw/char/nrf51_uart.c | 330 ++++++++++++++++++++++++
68
target/arm/cpu.c | 15 +-
69
tests/boot-serial-test.c | 19 ++
70
MAINTAINERS | 1 -
71
default-configs/aarch64-softmmu.mak | 1 +
72
hw/char/trace-events | 4 +
73
19 files changed, 1423 insertions(+), 6 deletions(-)
74
create mode 100644 include/hw/arm/xlnx-versal.h
75
create mode 100644 include/hw/char/nrf51_uart.h
76
create mode 100644 hw/arm/xlnx-versal-virt.c
77
create mode 100644 hw/arm/xlnx-versal.c
78
create mode 100644 hw/char/nrf51_uart.c
79
diff view generated by jsdifflib
Deleted patch
1
Coverity points out (CID 1398632, CID 1398650) that we
2
leak a couple of allocated strings in the error-exit
3
code path for setting up the MHUs in the ARMSSE.
4
Fix this bug by moving the allocate-and-free of each
5
string to be closer to the use, so we do the free before
6
doing the error-exit check.
7
1
8
Fixes: f8574705f62b38a ("hw/arm/armsse: Add unimplemented-device stubs for MHUs")
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
Message-id: 20190215113707.24553-1-peter.maydell@linaro.org
12
---
13
hw/arm/armsse.c | 10 ++++++----
14
1 file changed, 6 insertions(+), 4 deletions(-)
15
16
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/armsse.c
19
+++ b/hw/arm/armsse.c
20
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
21
22
if (info->has_mhus) {
23
for (i = 0; i < ARRAY_SIZE(s->mhu); i++) {
24
- char *name = g_strdup_printf("MHU%d", i);
25
- char *port = g_strdup_printf("port[%d]", i + 3);
26
+ char *name;
27
+ char *port;
28
29
+ name = g_strdup_printf("MHU%d", i);
30
qdev_prop_set_string(DEVICE(&s->mhu[i]), "name", name);
31
qdev_prop_set_uint64(DEVICE(&s->mhu[i]), "size", 0x1000);
32
object_property_set_bool(OBJECT(&s->mhu[i]), true,
33
"realized", &err);
34
+ g_free(name);
35
if (err) {
36
error_propagate(errp, err);
37
return;
38
}
39
+ port = g_strdup_printf("port[%d]", i + 3);
40
mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mhu[i]), 0);
41
object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr),
42
port, &err);
43
+ g_free(port);
44
if (err) {
45
error_propagate(errp, err);
46
return;
47
}
48
- g_free(name);
49
- g_free(port);
50
}
51
}
52
53
--
54
2.20.1
55
56
diff view generated by jsdifflib
Deleted patch
1
The "background region" for a v8M MPU is a default which will be used
2
(if enabled, and if the access is privileged) if the access does
3
not match any specific MPU region. We were incorrectly using it
4
always (by putting the condition at the wrong nesting level). This
5
meant that we would always return the default background permissions
6
rather than the correct permissions for a specific region, and also
7
that we would not return the right information in response to a
8
TT instruction.
9
1
10
Move the check for the background region to the same place in the
11
logic as the equivalent v8M MPUCheck() pseudocode puts it.
12
This in turn means we must adjust the condition we use to detect
13
matches in multiple regions to avoid false-positives.
14
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20190214113408.10214-1-peter.maydell@linaro.org
18
---
19
target/arm/helper.c | 8 +++++---
20
1 file changed, 5 insertions(+), 3 deletions(-)
21
22
diff --git a/target/arm/helper.c b/target/arm/helper.c
23
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/helper.c
25
+++ b/target/arm/helper.c
26
@@ -XXX,XX +XXX,XX @@ static bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
27
hit = true;
28
} else if (m_is_ppb_region(env, address)) {
29
hit = true;
30
- } else if (pmsav7_use_background_region(cpu, mmu_idx, is_user)) {
31
- hit = true;
32
} else {
33
+ if (pmsav7_use_background_region(cpu, mmu_idx, is_user)) {
34
+ hit = true;
35
+ }
36
+
37
for (n = (int)cpu->pmsav7_dregion - 1; n >= 0; n--) {
38
/* region search */
39
/* Note that the base address is bits [31:5] from the register
40
@@ -XXX,XX +XXX,XX @@ static bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
41
*is_subpage = true;
42
}
43
44
- if (hit) {
45
+ if (matchregion != -1) {
46
/* Multiple regions match -- always a failure (unlike
47
* PMSAv7 where highest-numbered-region wins)
48
*/
49
--
50
2.20.1
51
52
diff view generated by jsdifflib
1
Many of the devices on the Musca board live behind TrustZone
1
From: Eric Auger <eric.auger@redhat.com>
2
Peripheral Protection Controllers (PPCs); add models of the
3
PPCs, using a similar scheme to the MPS2 board models.
4
This commit wires up the PPCs with "unimplemented device"
5
stubs behind them in the correct places in the address map.
6
2
3
We are missing the VIRT_COMPAT_3_0 definition and setting.
4
Let's add them.
5
6
Signed-off-by: Eric Auger <eric.auger@redhat.com>
7
Reviewed-by: Andrew Jones <drjones@redhat.com>
8
Message-id: 20181024085602.16611-1-eric.auger@redhat.com
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
---
10
---
10
hw/arm/musca.c | 289 +++++++++++++++++++++++++++++++++++++++++++++++++
11
hw/arm/virt.c | 4 ++++
11
1 file changed, 289 insertions(+)
12
1 file changed, 4 insertions(+)
12
13
13
diff --git a/hw/arm/musca.c b/hw/arm/musca.c
14
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/musca.c
16
--- a/hw/arm/virt.c
16
+++ b/hw/arm/musca.c
17
+++ b/hw/arm/virt.c
17
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ static void virt_machine_3_1_options(MachineClass *mc)
18
#include "hw/arm/armsse.h"
19
}
19
#include "hw/boards.h"
20
DEFINE_VIRT_MACHINE_AS_LATEST(3, 1)
20
#include "hw/core/split-irq.h"
21
21
+#include "hw/misc/tz-ppc.h"
22
+#define VIRT_COMPAT_3_0 \
22
+#include "hw/misc/unimp.h"
23
+ HW_COMPAT_3_0
23
24
#define MUSCA_NUMIRQ_MAX 96
25
+#define MUSCA_PPC_MAX 3
26
27
typedef enum MuscaType {
28
MUSCA_A,
29
@@ -XXX,XX +XXX,XX @@ typedef struct {
30
31
ARMSSE sse;
32
SplitIRQ cpu_irq_splitter[MUSCA_NUMIRQ_MAX];
33
+ SplitIRQ sec_resp_splitter;
34
+ TZPPC ppc[MUSCA_PPC_MAX];
35
+ MemoryRegion container;
36
+ UnimplementedDeviceState eflash[2];
37
+ UnimplementedDeviceState qspi;
38
+ UnimplementedDeviceState mpc[5];
39
+ UnimplementedDeviceState mhu[2];
40
+ UnimplementedDeviceState pwm[3];
41
+ UnimplementedDeviceState i2s;
42
+ UnimplementedDeviceState uart[2];
43
+ UnimplementedDeviceState i2c[2];
44
+ UnimplementedDeviceState spi;
45
+ UnimplementedDeviceState scc;
46
+ UnimplementedDeviceState timer;
47
+ UnimplementedDeviceState rtc;
48
+ UnimplementedDeviceState pvt;
49
+ UnimplementedDeviceState sdio;
50
+ UnimplementedDeviceState gpio;
51
} MuscaMachineState;
52
53
#define TYPE_MUSCA_MACHINE "musca"
54
@@ -XXX,XX +XXX,XX @@ typedef struct {
55
*/
56
#define SYSCLK_FRQ 40000000
57
58
+/*
59
+ * Most of the devices in the Musca board sit behind Peripheral Protection
60
+ * Controllers. These data structures define the layout of which devices
61
+ * sit behind which PPCs.
62
+ * The devfn for each port is a function which creates, configures
63
+ * and initializes the device, returning the MemoryRegion which
64
+ * needs to be plugged into the downstream end of the PPC port.
65
+ */
66
+typedef MemoryRegion *MakeDevFn(MuscaMachineState *mms, void *opaque,
67
+ const char *name, hwaddr size);
68
+
24
+
69
+typedef struct PPCPortInfo {
25
static void virt_3_0_instance_init(Object *obj)
70
+ const char *name;
71
+ MakeDevFn *devfn;
72
+ void *opaque;
73
+ hwaddr addr;
74
+ hwaddr size;
75
+} PPCPortInfo;
76
+
77
+typedef struct PPCInfo {
78
+ const char *name;
79
+ PPCPortInfo ports[TZ_NUM_PORTS];
80
+} PPCInfo;
81
+
82
+static MemoryRegion *make_unimp_dev(MuscaMachineState *mms,
83
+ void *opaque, const char *name, hwaddr size)
84
+{
85
+ /*
86
+ * Initialize, configure and realize a TYPE_UNIMPLEMENTED_DEVICE,
87
+ * and return a pointer to its MemoryRegion.
88
+ */
89
+ UnimplementedDeviceState *uds = opaque;
90
+
91
+ sysbus_init_child_obj(OBJECT(mms), name, uds,
92
+ sizeof(UnimplementedDeviceState),
93
+ TYPE_UNIMPLEMENTED_DEVICE);
94
+ qdev_prop_set_string(DEVICE(uds), "name", name);
95
+ qdev_prop_set_uint64(DEVICE(uds), "size", size);
96
+ object_property_set_bool(OBJECT(uds), true, "realized", &error_fatal);
97
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(uds), 0);
98
+}
99
+
100
+static MemoryRegion *make_musca_a_devs(MuscaMachineState *mms, void *opaque,
101
+ const char *name, hwaddr size)
102
+{
103
+ /*
104
+ * Create the container MemoryRegion for all the devices that live
105
+ * behind the Musca-A PPC's single port. These devices don't have a PPC
106
+ * port each, but we use the PPCPortInfo struct as a convenient way
107
+ * to describe them. Note that addresses here are relative to the base
108
+ * address of the PPC port region: 0x40100000, and devices appear both
109
+ * at the 0x4... NS region and the 0x5... S region.
110
+ */
111
+ int i;
112
+ MemoryRegion *container = &mms->container;
113
+
114
+ const PPCPortInfo devices[] = {
115
+ { "uart0", make_unimp_dev, &mms->uart[0], 0x1000, 0x1000 },
116
+ { "uart1", make_unimp_dev, &mms->uart[1], 0x2000, 0x1000 },
117
+ { "spi", make_unimp_dev, &mms->spi, 0x3000, 0x1000 },
118
+ { "i2c0", make_unimp_dev, &mms->i2c[0], 0x4000, 0x1000 },
119
+ { "i2c1", make_unimp_dev, &mms->i2c[1], 0x5000, 0x1000 },
120
+ { "i2s", make_unimp_dev, &mms->i2s, 0x6000, 0x1000 },
121
+ { "pwm0", make_unimp_dev, &mms->pwm[0], 0x7000, 0x1000 },
122
+ { "rtc", make_unimp_dev, &mms->rtc, 0x8000, 0x1000 },
123
+ { "qspi", make_unimp_dev, &mms->qspi, 0xa000, 0x1000 },
124
+ { "timer", make_unimp_dev, &mms->timer, 0xb000, 0x1000 },
125
+ { "scc", make_unimp_dev, &mms->scc, 0xc000, 0x1000 },
126
+ { "pwm1", make_unimp_dev, &mms->pwm[1], 0xe000, 0x1000 },
127
+ { "pwm2", make_unimp_dev, &mms->pwm[2], 0xf000, 0x1000 },
128
+ { "gpio", make_unimp_dev, &mms->gpio, 0x10000, 0x1000 },
129
+ { "mpc0", make_unimp_dev, &mms->mpc[0], 0x12000, 0x1000 },
130
+ { "mpc1", make_unimp_dev, &mms->mpc[1], 0x13000, 0x1000 },
131
+ };
132
+
133
+ memory_region_init(container, OBJECT(mms), "musca-device-container", size);
134
+
135
+ for (i = 0; i < ARRAY_SIZE(devices); i++) {
136
+ const PPCPortInfo *pinfo = &devices[i];
137
+ MemoryRegion *mr;
138
+
139
+ mr = pinfo->devfn(mms, pinfo->opaque, pinfo->name, pinfo->size);
140
+ memory_region_add_subregion(container, pinfo->addr, mr);
141
+ }
142
+
143
+ return &mms->container;
144
+}
145
+
146
static void musca_init(MachineState *machine)
147
{
26
{
148
MuscaMachineState *mms = MUSCA_MACHINE(machine);
27
virt_3_1_instance_init(obj);
149
@@ -XXX,XX +XXX,XX @@ static void musca_init(MachineState *machine)
28
@@ -XXX,XX +XXX,XX @@ static void virt_3_0_instance_init(Object *obj)
150
MachineClass *mc = MACHINE_GET_CLASS(machine);
29
static void virt_machine_3_0_options(MachineClass *mc)
151
MemoryRegion *system_memory = get_system_memory();
30
{
152
DeviceState *ssedev;
31
virt_machine_3_1_options(mc);
153
+ DeviceState *dev_splitter;
32
+ SET_MACHINE_COMPAT(mc, VIRT_COMPAT_3_0);
154
+ const PPCInfo *ppcs;
155
+ int num_ppcs;
156
int i;
157
158
assert(mmc->num_irqs <= MUSCA_NUMIRQ_MAX);
159
@@ -XXX,XX +XXX,XX @@ static void musca_init(MachineState *machine)
160
"EXP_CPU1_IRQ", i));
161
}
162
163
+ /*
164
+ * The sec_resp_cfg output from the SSE-200 must be split into multiple
165
+ * lines, one for each of the PPCs we create here.
166
+ */
167
+ object_initialize(&mms->sec_resp_splitter, sizeof(mms->sec_resp_splitter),
168
+ TYPE_SPLIT_IRQ);
169
+ object_property_add_child(OBJECT(machine), "sec-resp-splitter",
170
+ OBJECT(&mms->sec_resp_splitter), &error_fatal);
171
+ object_property_set_int(OBJECT(&mms->sec_resp_splitter),
172
+ ARRAY_SIZE(mms->ppc), "num-lines", &error_fatal);
173
+ object_property_set_bool(OBJECT(&mms->sec_resp_splitter), true,
174
+ "realized", &error_fatal);
175
+ dev_splitter = DEVICE(&mms->sec_resp_splitter);
176
+ qdev_connect_gpio_out_named(ssedev, "sec_resp_cfg", 0,
177
+ qdev_get_gpio_in(dev_splitter, 0));
178
+
179
+ /*
180
+ * Most of the devices in the board are behind Peripheral Protection
181
+ * Controllers. The required order for initializing things is:
182
+ * + initialize the PPC
183
+ * + initialize, configure and realize downstream devices
184
+ * + connect downstream device MemoryRegions to the PPC
185
+ * + realize the PPC
186
+ * + map the PPC's MemoryRegions to the places in the address map
187
+ * where the downstream devices should appear
188
+ * + wire up the PPC's control lines to the SSE object
189
+ *
190
+ * The PPC mapping differs for the -A and -B1 variants; the -A version
191
+ * is much simpler, using only a single port of a single PPC and putting
192
+ * all the devices behind that.
193
+ */
194
+ const PPCInfo a_ppcs[] = { {
195
+ .name = "ahb_ppcexp0",
196
+ .ports = {
197
+ { "musca-devices", make_musca_a_devs, 0, 0x40100000, 0x100000 },
198
+ },
199
+ },
200
+ };
201
+
202
+ /*
203
+ * Devices listed with an 0x4.. address appear in both the NS 0x4.. region
204
+ * and the 0x5.. S region. Devices listed with an 0x5.. address appear
205
+ * only in the S region.
206
+ */
207
+ const PPCInfo b1_ppcs[] = { {
208
+ .name = "apb_ppcexp0",
209
+ .ports = {
210
+ { "eflash0", make_unimp_dev, &mms->eflash[0],
211
+ 0x52400000, 0x1000 },
212
+ { "eflash1", make_unimp_dev, &mms->eflash[1],
213
+ 0x52500000, 0x1000 },
214
+ { "qspi", make_unimp_dev, &mms->qspi, 0x42800000, 0x100000 },
215
+ { "mpc0", make_unimp_dev, &mms->mpc[0], 0x52000000, 0x1000 },
216
+ { "mpc1", make_unimp_dev, &mms->mpc[1], 0x52100000, 0x1000 },
217
+ { "mpc2", make_unimp_dev, &mms->mpc[2], 0x52200000, 0x1000 },
218
+ { "mpc3", make_unimp_dev, &mms->mpc[3], 0x52300000, 0x1000 },
219
+ { "mhu0", make_unimp_dev, &mms->mhu[0], 0x42600000, 0x100000 },
220
+ { "mhu1", make_unimp_dev, &mms->mhu[1], 0x42700000, 0x100000 },
221
+ { }, /* port 9: unused */
222
+ { }, /* port 10: unused */
223
+ { }, /* port 11: unused */
224
+ { }, /* port 12: unused */
225
+ { }, /* port 13: unused */
226
+ { "mpc4", make_unimp_dev, &mms->mpc[4], 0x52e00000, 0x1000 },
227
+ },
228
+ }, {
229
+ .name = "apb_ppcexp1",
230
+ .ports = {
231
+ { "pwm0", make_unimp_dev, &mms->pwm[0], 0x40101000, 0x1000 },
232
+ { "pwm1", make_unimp_dev, &mms->pwm[1], 0x40102000, 0x1000 },
233
+ { "pwm2", make_unimp_dev, &mms->pwm[2], 0x40103000, 0x1000 },
234
+ { "i2s", make_unimp_dev, &mms->i2s, 0x40104000, 0x1000 },
235
+ { "uart0", make_unimp_dev, &mms->uart[0], 0x40105000, 0x1000 },
236
+ { "uart1", make_unimp_dev, &mms->uart[1], 0x40106000, 0x1000 },
237
+ { "i2c0", make_unimp_dev, &mms->i2c[0], 0x40108000, 0x1000 },
238
+ { "i2c1", make_unimp_dev, &mms->i2c[1], 0x40109000, 0x1000 },
239
+ { "spi", make_unimp_dev, &mms->spi, 0x4010a000, 0x1000 },
240
+ { "scc", make_unimp_dev, &mms->scc, 0x5010b000, 0x1000 },
241
+ { "timer", make_unimp_dev, &mms->timer, 0x4010c000, 0x1000 },
242
+ { "rtc", make_unimp_dev, &mms->rtc, 0x4010d000, 0x1000 },
243
+ { "pvt", make_unimp_dev, &mms->pvt, 0x4010e000, 0x1000 },
244
+ { "sdio", make_unimp_dev, &mms->sdio, 0x4010f000, 0x1000 },
245
+ },
246
+ }, {
247
+ .name = "ahb_ppcexp0",
248
+ .ports = {
249
+ { }, /* port 0: unused */
250
+ { "gpio", make_unimp_dev, &mms->gpio, 0x41000000, 0x1000 },
251
+ },
252
+ },
253
+ };
254
+
255
+ switch (mmc->type) {
256
+ case MUSCA_A:
257
+ ppcs = a_ppcs;
258
+ num_ppcs = ARRAY_SIZE(a_ppcs);
259
+ break;
260
+ case MUSCA_B1:
261
+ ppcs = b1_ppcs;
262
+ num_ppcs = ARRAY_SIZE(b1_ppcs);
263
+ break;
264
+ default:
265
+ g_assert_not_reached();
266
+ }
267
+ assert(num_ppcs <= MUSCA_PPC_MAX);
268
+
269
+ for (i = 0; i < num_ppcs; i++) {
270
+ const PPCInfo *ppcinfo = &ppcs[i];
271
+ TZPPC *ppc = &mms->ppc[i];
272
+ DeviceState *ppcdev;
273
+ int port;
274
+ char *gpioname;
275
+
276
+ sysbus_init_child_obj(OBJECT(machine), ppcinfo->name, ppc,
277
+ sizeof(TZPPC), TYPE_TZ_PPC);
278
+ ppcdev = DEVICE(ppc);
279
+
280
+ for (port = 0; port < TZ_NUM_PORTS; port++) {
281
+ const PPCPortInfo *pinfo = &ppcinfo->ports[port];
282
+ MemoryRegion *mr;
283
+ char *portname;
284
+
285
+ if (!pinfo->devfn) {
286
+ continue;
287
+ }
288
+
289
+ mr = pinfo->devfn(mms, pinfo->opaque, pinfo->name, pinfo->size);
290
+ portname = g_strdup_printf("port[%d]", port);
291
+ object_property_set_link(OBJECT(ppc), OBJECT(mr),
292
+ portname, &error_fatal);
293
+ g_free(portname);
294
+ }
295
+
296
+ object_property_set_bool(OBJECT(ppc), true, "realized", &error_fatal);
297
+
298
+ for (port = 0; port < TZ_NUM_PORTS; port++) {
299
+ const PPCPortInfo *pinfo = &ppcinfo->ports[port];
300
+
301
+ if (!pinfo->devfn) {
302
+ continue;
303
+ }
304
+ sysbus_mmio_map(SYS_BUS_DEVICE(ppc), port, pinfo->addr);
305
+
306
+ gpioname = g_strdup_printf("%s_nonsec", ppcinfo->name);
307
+ qdev_connect_gpio_out_named(ssedev, gpioname, port,
308
+ qdev_get_gpio_in_named(ppcdev,
309
+ "cfg_nonsec",
310
+ port));
311
+ g_free(gpioname);
312
+ gpioname = g_strdup_printf("%s_ap", ppcinfo->name);
313
+ qdev_connect_gpio_out_named(ssedev, gpioname, port,
314
+ qdev_get_gpio_in_named(ppcdev,
315
+ "cfg_ap", port));
316
+ g_free(gpioname);
317
+ }
318
+
319
+ gpioname = g_strdup_printf("%s_irq_enable", ppcinfo->name);
320
+ qdev_connect_gpio_out_named(ssedev, gpioname, 0,
321
+ qdev_get_gpio_in_named(ppcdev,
322
+ "irq_enable", 0));
323
+ g_free(gpioname);
324
+ gpioname = g_strdup_printf("%s_irq_clear", ppcinfo->name);
325
+ qdev_connect_gpio_out_named(ssedev, gpioname, 0,
326
+ qdev_get_gpio_in_named(ppcdev,
327
+ "irq_clear", 0));
328
+ g_free(gpioname);
329
+ gpioname = g_strdup_printf("%s_irq_status", ppcinfo->name);
330
+ qdev_connect_gpio_out_named(ppcdev, "irq", 0,
331
+ qdev_get_gpio_in_named(ssedev,
332
+ gpioname, 0));
333
+ g_free(gpioname);
334
+
335
+ qdev_connect_gpio_out(dev_splitter, i,
336
+ qdev_get_gpio_in_named(ppcdev,
337
+ "cfg_sec_resp", 0));
338
+ }
339
+
340
armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x2000000);
341
}
33
}
34
DEFINE_VIRT_MACHINE(3, 0)
342
35
343
--
36
--
344
2.20.1
37
2.19.1
345
38
346
39
diff view generated by jsdifflib
1
The Musca board puts its SRAM and flash behind TrustZone
1
From: Julia Suvorova <jusual@mail.ru>
2
Memory Protection Controllers (MPCs). Each MPC sits between
3
the CPU and the RAM/flash, and also has a set of memory mapped
4
control registers. Wire up the MPCs, and the memory behind them.
5
For the moment we implement the flash as simple ROM, which
6
cannot be reprogrammed by the guest.
7
2
3
Not implemented: CTS/NCTS, PSEL*.
4
5
Signed-off-by: Julia Suvorova <jusual@mail.ru>
6
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
---
8
---
11
hw/arm/musca.c | 155 ++++++++++++++++++++++++++++++++++++++++++++++---
9
hw/char/Makefile.objs | 1 +
12
1 file changed, 147 insertions(+), 8 deletions(-)
10
include/hw/char/nrf51_uart.h | 78 +++++++++
11
hw/char/nrf51_uart.c | 330 +++++++++++++++++++++++++++++++++++
12
hw/char/trace-events | 4 +
13
4 files changed, 413 insertions(+)
14
create mode 100644 include/hw/char/nrf51_uart.h
15
create mode 100644 hw/char/nrf51_uart.c
13
16
14
diff --git a/hw/arm/musca.c b/hw/arm/musca.c
17
diff --git a/hw/char/Makefile.objs b/hw/char/Makefile.objs
15
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/musca.c
19
--- a/hw/char/Makefile.objs
17
+++ b/hw/arm/musca.c
20
+++ b/hw/char/Makefile.objs
18
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@
19
#include "hw/arm/armsse.h"
22
common-obj-$(CONFIG_IPACK) += ipoctal232.o
20
#include "hw/boards.h"
23
common-obj-$(CONFIG_ESCC) += escc.o
21
#include "hw/core/split-irq.h"
24
+common-obj-$(CONFIG_NRF51_SOC) += nrf51_uart.o
22
+#include "hw/misc/tz-mpc.h"
25
common-obj-$(CONFIG_PARALLEL) += parallel.o
23
#include "hw/misc/tz-ppc.h"
26
common-obj-$(CONFIG_PARALLEL) += parallel-isa.o
24
#include "hw/misc/unimp.h"
27
common-obj-$(CONFIG_PL011) += pl011.o
25
28
diff --git a/include/hw/char/nrf51_uart.h b/include/hw/char/nrf51_uart.h
26
#define MUSCA_NUMIRQ_MAX 96
29
new file mode 100644
27
#define MUSCA_PPC_MAX 3
30
index XXXXXXX..XXXXXXX
28
+#define MUSCA_MPC_MAX 5
31
--- /dev/null
29
+
32
+++ b/include/hw/char/nrf51_uart.h
30
+typedef struct MPCInfo MPCInfo;
33
@@ -XXX,XX +XXX,XX @@
31
34
+/*
32
typedef enum MuscaType {
35
+ * nRF51 SoC UART emulation
33
MUSCA_A,
36
+ *
34
@@ -XXX,XX +XXX,XX @@ typedef struct {
37
+ * Copyright (c) 2018 Julia Suvorova <jusual@mail.ru>
35
uint32_t init_svtor;
38
+ *
36
int sram_addr_width;
39
+ * This program is free software; you can redistribute it and/or modify
37
int num_irqs;
40
+ * it under the terms of the GNU General Public License version 2 or
38
+ const MPCInfo *mpc_info;
41
+ * (at your option) any later version.
39
+ int num_mpcs;
42
+ */
40
} MuscaMachineClass;
43
+
41
44
+#ifndef NRF51_UART_H
42
typedef struct {
45
+#define NRF51_UART_H
43
MachineState parent;
46
+
44
47
+#include "hw/sysbus.h"
45
ARMSSE sse;
48
+#include "chardev/char-fe.h"
46
+ /* RAM and flash */
49
+#include "hw/registerfields.h"
47
+ MemoryRegion ram[MUSCA_MPC_MAX];
50
+
48
SplitIRQ cpu_irq_splitter[MUSCA_NUMIRQ_MAX];
51
+#define UART_FIFO_LENGTH 6
49
SplitIRQ sec_resp_splitter;
52
+#define UART_BASE 0x40002000
50
TZPPC ppc[MUSCA_PPC_MAX];
53
+#define UART_SIZE 0x1000
51
MemoryRegion container;
54
+
52
UnimplementedDeviceState eflash[2];
55
+#define TYPE_NRF51_UART "nrf51_soc.uart"
53
UnimplementedDeviceState qspi;
56
+#define NRF51_UART(obj) OBJECT_CHECK(NRF51UARTState, (obj), TYPE_NRF51_UART)
54
- UnimplementedDeviceState mpc[5];
57
+
55
+ TZMPC mpc[MUSCA_MPC_MAX];
58
+REG32(UART_STARTRX, 0x000)
56
UnimplementedDeviceState mhu[2];
59
+REG32(UART_STOPRX, 0x004)
57
UnimplementedDeviceState pwm[3];
60
+REG32(UART_STARTTX, 0x008)
58
UnimplementedDeviceState i2s;
61
+REG32(UART_STOPTX, 0x00C)
59
@@ -XXX,XX +XXX,XX @@ typedef struct {
62
+REG32(UART_SUSPEND, 0x01C)
60
UnimplementedDeviceState pvt;
63
+
61
UnimplementedDeviceState sdio;
64
+REG32(UART_CTS, 0x100)
62
UnimplementedDeviceState gpio;
65
+REG32(UART_NCTS, 0x104)
63
+ UnimplementedDeviceState cryptoisland;
66
+REG32(UART_RXDRDY, 0x108)
64
} MuscaMachineState;
67
+REG32(UART_TXDRDY, 0x11C)
65
68
+REG32(UART_ERROR, 0x124)
66
#define TYPE_MUSCA_MACHINE "musca"
69
+REG32(UART_RXTO, 0x144)
67
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_unimp_dev(MuscaMachineState *mms,
70
+
68
return sysbus_mmio_get_region(SYS_BUS_DEVICE(uds), 0);
71
+REG32(UART_INTEN, 0x300)
69
}
72
+ FIELD(UART_INTEN, CTS, 0, 1)
70
73
+ FIELD(UART_INTEN, NCTS, 1, 1)
71
+typedef enum MPCInfoType {
74
+ FIELD(UART_INTEN, RXDRDY, 2, 1)
72
+ MPC_RAM,
75
+ FIELD(UART_INTEN, TXDRDY, 7, 1)
73
+ MPC_ROM,
76
+ FIELD(UART_INTEN, ERROR, 9, 1)
74
+ MPC_CRYPTOISLAND,
77
+ FIELD(UART_INTEN, RXTO, 17, 1)
75
+} MPCInfoType;
78
+REG32(UART_INTENSET, 0x304)
76
+
79
+REG32(UART_INTENCLR, 0x308)
77
+struct MPCInfo {
80
+REG32(UART_ERRORSRC, 0x480)
78
+ const char *name;
81
+REG32(UART_ENABLE, 0x500)
79
+ hwaddr addr;
82
+REG32(UART_PSELRTS, 0x508)
80
+ hwaddr size;
83
+REG32(UART_PSELTXD, 0x50C)
81
+ MPCInfoType type;
84
+REG32(UART_PSELCTS, 0x510)
85
+REG32(UART_PSELRXD, 0x514)
86
+REG32(UART_RXD, 0x518)
87
+REG32(UART_TXD, 0x51C)
88
+REG32(UART_BAUDRATE, 0x524)
89
+REG32(UART_CONFIG, 0x56C)
90
+
91
+typedef struct NRF51UARTState {
92
+ SysBusDevice parent_obj;
93
+
94
+ MemoryRegion iomem;
95
+ CharBackend chr;
96
+ qemu_irq irq;
97
+ guint watch_tag;
98
+
99
+ uint8_t rx_fifo[UART_FIFO_LENGTH];
100
+ unsigned int rx_fifo_pos;
101
+ unsigned int rx_fifo_len;
102
+
103
+ uint32_t reg[0x56C];
104
+
105
+ bool rx_started;
106
+ bool tx_started;
107
+ bool pending_tx_byte;
108
+ bool enabled;
109
+} NRF51UARTState;
110
+
111
+#endif
112
diff --git a/hw/char/nrf51_uart.c b/hw/char/nrf51_uart.c
113
new file mode 100644
114
index XXXXXXX..XXXXXXX
115
--- /dev/null
116
+++ b/hw/char/nrf51_uart.c
117
@@ -XXX,XX +XXX,XX @@
118
+/*
119
+ * nRF51 SoC UART emulation
120
+ *
121
+ * See nRF51 Series Reference Manual, "29 Universal Asynchronous
122
+ * Receiver/Transmitter" for hardware specifications:
123
+ * http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.pdf
124
+ *
125
+ * Copyright (c) 2018 Julia Suvorova <jusual@mail.ru>
126
+ *
127
+ * This program is free software; you can redistribute it and/or modify
128
+ * it under the terms of the GNU General Public License version 2 or
129
+ * (at your option) any later version.
130
+ */
131
+
132
+#include "qemu/osdep.h"
133
+#include "qemu/log.h"
134
+#include "hw/char/nrf51_uart.h"
135
+#include "trace.h"
136
+
137
+static void nrf51_uart_update_irq(NRF51UARTState *s)
138
+{
139
+ bool irq = false;
140
+
141
+ irq |= (s->reg[R_UART_RXDRDY] &&
142
+ (s->reg[R_UART_INTEN] & R_UART_INTEN_RXDRDY_MASK));
143
+ irq |= (s->reg[R_UART_TXDRDY] &&
144
+ (s->reg[R_UART_INTEN] & R_UART_INTEN_TXDRDY_MASK));
145
+ irq |= (s->reg[R_UART_ERROR] &&
146
+ (s->reg[R_UART_INTEN] & R_UART_INTEN_ERROR_MASK));
147
+ irq |= (s->reg[R_UART_RXTO] &&
148
+ (s->reg[R_UART_INTEN] & R_UART_INTEN_RXTO_MASK));
149
+
150
+ qemu_set_irq(s->irq, irq);
151
+}
152
+
153
+static uint64_t uart_read(void *opaque, hwaddr addr, unsigned int size)
154
+{
155
+ NRF51UARTState *s = NRF51_UART(opaque);
156
+ uint64_t r;
157
+
158
+ if (!s->enabled) {
159
+ return 0;
160
+ }
161
+
162
+ switch (addr) {
163
+ case A_UART_RXD:
164
+ r = s->rx_fifo[s->rx_fifo_pos];
165
+ if (s->rx_started && s->rx_fifo_len) {
166
+ s->rx_fifo_pos = (s->rx_fifo_pos + 1) % UART_FIFO_LENGTH;
167
+ s->rx_fifo_len--;
168
+ if (s->rx_fifo_len) {
169
+ s->reg[R_UART_RXDRDY] = 1;
170
+ nrf51_uart_update_irq(s);
171
+ }
172
+ qemu_chr_fe_accept_input(&s->chr);
173
+ }
174
+ break;
175
+ case A_UART_INTENSET:
176
+ case A_UART_INTENCLR:
177
+ case A_UART_INTEN:
178
+ r = s->reg[R_UART_INTEN];
179
+ break;
180
+ default:
181
+ r = s->reg[addr / 4];
182
+ break;
183
+ }
184
+
185
+ trace_nrf51_uart_read(addr, r, size);
186
+
187
+ return r;
188
+}
189
+
190
+static gboolean uart_transmit(GIOChannel *chan, GIOCondition cond, void *opaque)
191
+{
192
+ NRF51UARTState *s = NRF51_UART(opaque);
193
+ int r;
194
+ uint8_t c = s->reg[R_UART_TXD];
195
+
196
+ s->watch_tag = 0;
197
+
198
+ r = qemu_chr_fe_write(&s->chr, &c, 1);
199
+ if (r <= 0) {
200
+ s->watch_tag = qemu_chr_fe_add_watch(&s->chr, G_IO_OUT | G_IO_HUP,
201
+ uart_transmit, s);
202
+ if (!s->watch_tag) {
203
+ /* The hardware has no transmit error reporting,
204
+ * so silently drop the byte
205
+ */
206
+ goto buffer_drained;
207
+ }
208
+ return FALSE;
209
+ }
210
+
211
+buffer_drained:
212
+ s->reg[R_UART_TXDRDY] = 1;
213
+ s->pending_tx_byte = false;
214
+ return FALSE;
215
+}
216
+
217
+static void uart_cancel_transmit(NRF51UARTState *s)
218
+{
219
+ if (s->watch_tag) {
220
+ g_source_remove(s->watch_tag);
221
+ s->watch_tag = 0;
222
+ }
223
+}
224
+
225
+static void uart_write(void *opaque, hwaddr addr,
226
+ uint64_t value, unsigned int size)
227
+{
228
+ NRF51UARTState *s = NRF51_UART(opaque);
229
+
230
+ trace_nrf51_uart_write(addr, value, size);
231
+
232
+ if (!s->enabled && (addr != A_UART_ENABLE)) {
233
+ return;
234
+ }
235
+
236
+ switch (addr) {
237
+ case A_UART_TXD:
238
+ if (!s->pending_tx_byte && s->tx_started) {
239
+ s->reg[R_UART_TXD] = value;
240
+ s->pending_tx_byte = true;
241
+ uart_transmit(NULL, G_IO_OUT, s);
242
+ }
243
+ break;
244
+ case A_UART_INTEN:
245
+ s->reg[R_UART_INTEN] = value;
246
+ break;
247
+ case A_UART_INTENSET:
248
+ s->reg[R_UART_INTEN] |= value;
249
+ break;
250
+ case A_UART_INTENCLR:
251
+ s->reg[R_UART_INTEN] &= ~value;
252
+ break;
253
+ case A_UART_TXDRDY ... A_UART_RXTO:
254
+ s->reg[addr / 4] = value;
255
+ break;
256
+ case A_UART_ERRORSRC:
257
+ s->reg[addr / 4] &= ~value;
258
+ break;
259
+ case A_UART_RXD:
260
+ break;
261
+ case A_UART_RXDRDY:
262
+ if (value == 0) {
263
+ s->reg[R_UART_RXDRDY] = 0;
264
+ }
265
+ break;
266
+ case A_UART_STARTTX:
267
+ if (value == 1) {
268
+ s->tx_started = true;
269
+ }
270
+ break;
271
+ case A_UART_STARTRX:
272
+ if (value == 1) {
273
+ s->rx_started = true;
274
+ }
275
+ break;
276
+ case A_UART_ENABLE:
277
+ if (value) {
278
+ if (value == 4) {
279
+ s->enabled = true;
280
+ }
281
+ break;
282
+ }
283
+ s->enabled = false;
284
+ value = 1;
285
+ /* fall through */
286
+ case A_UART_SUSPEND:
287
+ case A_UART_STOPTX:
288
+ if (value == 1) {
289
+ s->tx_started = false;
290
+ }
291
+ /* fall through */
292
+ case A_UART_STOPRX:
293
+ if (addr != A_UART_STOPTX && value == 1) {
294
+ s->rx_started = false;
295
+ s->reg[R_UART_RXTO] = 1;
296
+ }
297
+ break;
298
+ default:
299
+ s->reg[addr / 4] = value;
300
+ break;
301
+ }
302
+ nrf51_uart_update_irq(s);
303
+}
304
+
305
+static const MemoryRegionOps uart_ops = {
306
+ .read = uart_read,
307
+ .write = uart_write,
308
+ .endianness = DEVICE_LITTLE_ENDIAN,
82
+};
309
+};
83
+
310
+
84
+/* Order of the MPCs here must match the order of the bits in SECMPCINTSTATUS */
311
+static void nrf51_uart_reset(DeviceState *dev)
85
+static const MPCInfo a_mpc_info[] = { {
312
+{
86
+ .name = "qspi",
313
+ NRF51UARTState *s = NRF51_UART(dev);
87
+ .type = MPC_ROM,
314
+
88
+ .addr = 0x00200000,
315
+ s->pending_tx_byte = 0;
89
+ .size = 0x00800000,
316
+
90
+ }, {
317
+ uart_cancel_transmit(s);
91
+ .name = "sram",
318
+
92
+ .type = MPC_RAM,
319
+ memset(s->reg, 0, sizeof(s->reg));
93
+ .addr = 0x00000000,
320
+
94
+ .size = 0x00200000,
321
+ s->reg[R_UART_PSELRTS] = 0xFFFFFFFF;
322
+ s->reg[R_UART_PSELTXD] = 0xFFFFFFFF;
323
+ s->reg[R_UART_PSELCTS] = 0xFFFFFFFF;
324
+ s->reg[R_UART_PSELRXD] = 0xFFFFFFFF;
325
+ s->reg[R_UART_BAUDRATE] = 0x4000000;
326
+
327
+ s->rx_fifo_len = 0;
328
+ s->rx_fifo_pos = 0;
329
+ s->rx_started = false;
330
+ s->tx_started = false;
331
+ s->enabled = false;
332
+}
333
+
334
+static void uart_receive(void *opaque, const uint8_t *buf, int size)
335
+{
336
+
337
+ NRF51UARTState *s = NRF51_UART(opaque);
338
+ int i;
339
+
340
+ if (size == 0 || s->rx_fifo_len >= UART_FIFO_LENGTH) {
341
+ return;
342
+ }
343
+
344
+ for (i = 0; i < size; i++) {
345
+ uint32_t pos = (s->rx_fifo_pos + s->rx_fifo_len) % UART_FIFO_LENGTH;
346
+ s->rx_fifo[pos] = buf[i];
347
+ s->rx_fifo_len++;
348
+ }
349
+
350
+ s->reg[R_UART_RXDRDY] = 1;
351
+ nrf51_uart_update_irq(s);
352
+}
353
+
354
+static int uart_can_receive(void *opaque)
355
+{
356
+ NRF51UARTState *s = NRF51_UART(opaque);
357
+
358
+ return s->rx_started ? (UART_FIFO_LENGTH - s->rx_fifo_len) : 0;
359
+}
360
+
361
+static void uart_event(void *opaque, int event)
362
+{
363
+ NRF51UARTState *s = NRF51_UART(opaque);
364
+
365
+ if (event == CHR_EVENT_BREAK) {
366
+ s->reg[R_UART_ERRORSRC] |= 3;
367
+ s->reg[R_UART_ERROR] = 1;
368
+ nrf51_uart_update_irq(s);
369
+ }
370
+}
371
+
372
+static void nrf51_uart_realize(DeviceState *dev, Error **errp)
373
+{
374
+ NRF51UARTState *s = NRF51_UART(dev);
375
+
376
+ qemu_chr_fe_set_handlers(&s->chr, uart_can_receive, uart_receive,
377
+ uart_event, NULL, s, NULL, true);
378
+}
379
+
380
+static void nrf51_uart_init(Object *obj)
381
+{
382
+ NRF51UARTState *s = NRF51_UART(obj);
383
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
384
+
385
+ memory_region_init_io(&s->iomem, obj, &uart_ops, s,
386
+ "nrf51_soc.uart", UART_SIZE);
387
+ sysbus_init_mmio(sbd, &s->iomem);
388
+ sysbus_init_irq(sbd, &s->irq);
389
+}
390
+
391
+static int nrf51_uart_post_load(void *opaque, int version_id)
392
+{
393
+ NRF51UARTState *s = NRF51_UART(opaque);
394
+
395
+ if (s->pending_tx_byte) {
396
+ s->watch_tag = qemu_chr_fe_add_watch(&s->chr, G_IO_OUT | G_IO_HUP,
397
+ uart_transmit, s);
398
+ }
399
+
400
+ return 0;
401
+}
402
+
403
+static const VMStateDescription nrf51_uart_vmstate = {
404
+ .name = "nrf51_soc.uart",
405
+ .post_load = nrf51_uart_post_load,
406
+ .fields = (VMStateField[]) {
407
+ VMSTATE_UINT32_ARRAY(reg, NRF51UARTState, 0x56C),
408
+ VMSTATE_UINT8_ARRAY(rx_fifo, NRF51UARTState, UART_FIFO_LENGTH),
409
+ VMSTATE_UINT32(rx_fifo_pos, NRF51UARTState),
410
+ VMSTATE_UINT32(rx_fifo_len, NRF51UARTState),
411
+ VMSTATE_BOOL(rx_started, NRF51UARTState),
412
+ VMSTATE_BOOL(tx_started, NRF51UARTState),
413
+ VMSTATE_BOOL(pending_tx_byte, NRF51UARTState),
414
+ VMSTATE_BOOL(enabled, NRF51UARTState),
415
+ VMSTATE_END_OF_LIST()
95
+ }
416
+ }
96
+};
417
+};
97
+
418
+
98
+static const MPCInfo b1_mpc_info[] = { {
419
+static Property nrf51_uart_properties[] = {
99
+ .name = "qspi",
420
+ DEFINE_PROP_CHR("chardev", NRF51UARTState, chr),
100
+ .type = MPC_ROM,
421
+ DEFINE_PROP_END_OF_LIST(),
101
+ .addr = 0x00000000,
102
+ .size = 0x02000000,
103
+ }, {
104
+ .name = "sram",
105
+ .type = MPC_RAM,
106
+ .addr = 0x0a400000,
107
+ .size = 0x00080000,
108
+ }, {
109
+ .name = "eflash0",
110
+ .type = MPC_ROM,
111
+ .addr = 0x0a000000,
112
+ .size = 0x00200000,
113
+ }, {
114
+ .name = "eflash1",
115
+ .type = MPC_ROM,
116
+ .addr = 0x0a200000,
117
+ .size = 0x00200000,
118
+ }, {
119
+ .name = "cryptoisland",
120
+ .type = MPC_CRYPTOISLAND,
121
+ .addr = 0x0a000000,
122
+ .size = 0x00200000,
123
+ }
124
+};
422
+};
125
+
423
+
126
+static MemoryRegion *make_mpc(MuscaMachineState *mms, void *opaque,
424
+static void nrf51_uart_class_init(ObjectClass *klass, void *data)
127
+ const char *name, hwaddr size)
425
+{
128
+{
426
+ DeviceClass *dc = DEVICE_CLASS(klass);
129
+ /*
427
+
130
+ * Create an MPC and the RAM or flash behind it.
428
+ dc->reset = nrf51_uart_reset;
131
+ * MPC 0: eFlash 0
429
+ dc->realize = nrf51_uart_realize;
132
+ * MPC 1: eFlash 1
430
+ dc->props = nrf51_uart_properties;
133
+ * MPC 2: SRAM
431
+ dc->vmsd = &nrf51_uart_vmstate;
134
+ * MPC 3: QSPI flash
432
+}
135
+ * MPC 4: CryptoIsland
433
+
136
+ * For now we implement the flash regions as ROM (ie not programmable)
434
+static const TypeInfo nrf51_uart_info = {
137
+ * (with their control interface memory regions being unimplemented
435
+ .name = TYPE_NRF51_UART,
138
+ * stubs behind the PPCs).
436
+ .parent = TYPE_SYS_BUS_DEVICE,
139
+ * The whole CryptoIsland region behind its MPC is an unimplemented stub.
437
+ .instance_size = sizeof(NRF51UARTState),
140
+ */
438
+ .instance_init = nrf51_uart_init,
141
+ MuscaMachineClass *mmc = MUSCA_MACHINE_GET_CLASS(mms);
439
+ .class_init = nrf51_uart_class_init
142
+ TZMPC *mpc = opaque;
440
+};
143
+ int i = mpc - &mms->mpc[0];
441
+
144
+ MemoryRegion *downstream;
442
+static void nrf51_uart_register_types(void)
145
+ MemoryRegion *upstream;
443
+{
146
+ UnimplementedDeviceState *uds;
444
+ type_register_static(&nrf51_uart_info);
147
+ char *mpcname;
445
+}
148
+ const MPCInfo *mpcinfo = mmc->mpc_info;
446
+
149
+
447
+type_init(nrf51_uart_register_types)
150
+ mpcname = g_strdup_printf("%s-mpc", mpcinfo[i].name);
448
diff --git a/hw/char/trace-events b/hw/char/trace-events
151
+
449
index XXXXXXX..XXXXXXX 100644
152
+ switch (mpcinfo[i].type) {
450
--- a/hw/char/trace-events
153
+ case MPC_ROM:
451
+++ b/hw/char/trace-events
154
+ downstream = &mms->ram[i];
452
@@ -XXX,XX +XXX,XX @@ cmsdk_apb_uart_receive(uint8_t c) "CMSDK APB UART: got character 0x%x from backe
155
+ memory_region_init_rom(downstream, NULL, mpcinfo[i].name,
453
cmsdk_apb_uart_tx_pending(void) "CMSDK APB UART: character send to backend pending"
156
+ mpcinfo[i].size, &error_fatal);
454
cmsdk_apb_uart_tx(uint8_t c) "CMSDK APB UART: character 0x%x sent to backend"
157
+ break;
455
cmsdk_apb_uart_set_params(int speed) "CMSDK APB UART: params set to %d 8N1"
158
+ case MPC_RAM:
456
+
159
+ downstream = &mms->ram[i];
457
+# hw/char/nrf51_uart.c
160
+ memory_region_init_ram(downstream, NULL, mpcinfo[i].name,
458
+nrf51_uart_read(uint64_t addr, uint64_t r, unsigned int size) "addr 0x%" PRIx64 " value 0x%" PRIx64 " size %u"
161
+ mpcinfo[i].size, &error_fatal);
459
+nrf51_uart_write(uint64_t addr, uint64_t value, unsigned int size) "addr 0x%" PRIx64 " value 0x%" PRIx64 " size %u"
162
+ break;
163
+ case MPC_CRYPTOISLAND:
164
+ /* We don't implement the CryptoIsland yet */
165
+ uds = &mms->cryptoisland;
166
+ sysbus_init_child_obj(OBJECT(mms), name, uds,
167
+ sizeof(UnimplementedDeviceState),
168
+ TYPE_UNIMPLEMENTED_DEVICE);
169
+ qdev_prop_set_string(DEVICE(uds), "name", mpcinfo[i].name);
170
+ qdev_prop_set_uint64(DEVICE(uds), "size", mpcinfo[i].size);
171
+ object_property_set_bool(OBJECT(uds), true, "realized", &error_fatal);
172
+ downstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(uds), 0);
173
+ break;
174
+ default:
175
+ g_assert_not_reached();
176
+ }
177
+
178
+ sysbus_init_child_obj(OBJECT(mms), mpcname, mpc, sizeof(mms->mpc[0]),
179
+ TYPE_TZ_MPC);
180
+ object_property_set_link(OBJECT(mpc), OBJECT(downstream),
181
+ "downstream", &error_fatal);
182
+ object_property_set_bool(OBJECT(mpc), true, "realized", &error_fatal);
183
+ /* Map the upstream end of the MPC into system memory */
184
+ upstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 1);
185
+ memory_region_add_subregion(get_system_memory(), mpcinfo[i].addr, upstream);
186
+ /* and connect its interrupt to the SSE-200 */
187
+ qdev_connect_gpio_out_named(DEVICE(mpc), "irq", 0,
188
+ qdev_get_gpio_in_named(DEVICE(&mms->sse),
189
+ "mpcexp_status", i));
190
+
191
+ g_free(mpcname);
192
+ /* Return the register interface MR for our caller to map behind the PPC */
193
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 0);
194
+}
195
+
196
static MemoryRegion *make_musca_a_devs(MuscaMachineState *mms, void *opaque,
197
const char *name, hwaddr size)
198
{
199
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_musca_a_devs(MuscaMachineState *mms, void *opaque,
200
{ "pwm1", make_unimp_dev, &mms->pwm[1], 0xe000, 0x1000 },
201
{ "pwm2", make_unimp_dev, &mms->pwm[2], 0xf000, 0x1000 },
202
{ "gpio", make_unimp_dev, &mms->gpio, 0x10000, 0x1000 },
203
- { "mpc0", make_unimp_dev, &mms->mpc[0], 0x12000, 0x1000 },
204
- { "mpc1", make_unimp_dev, &mms->mpc[1], 0x13000, 0x1000 },
205
+ { "mpc0", make_mpc, &mms->mpc[0], 0x12000, 0x1000 },
206
+ { "mpc1", make_mpc, &mms->mpc[1], 0x13000, 0x1000 },
207
};
208
209
memory_region_init(container, OBJECT(mms), "musca-device-container", size);
210
@@ -XXX,XX +XXX,XX @@ static void musca_init(MachineState *machine)
211
int i;
212
213
assert(mmc->num_irqs <= MUSCA_NUMIRQ_MAX);
214
+ assert(mmc->num_mpcs <= MUSCA_MPC_MAX);
215
216
if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
217
error_report("This board can only be used with CPU %s",
218
@@ -XXX,XX +XXX,XX @@ static void musca_init(MachineState *machine)
219
{ "eflash1", make_unimp_dev, &mms->eflash[1],
220
0x52500000, 0x1000 },
221
{ "qspi", make_unimp_dev, &mms->qspi, 0x42800000, 0x100000 },
222
- { "mpc0", make_unimp_dev, &mms->mpc[0], 0x52000000, 0x1000 },
223
- { "mpc1", make_unimp_dev, &mms->mpc[1], 0x52100000, 0x1000 },
224
- { "mpc2", make_unimp_dev, &mms->mpc[2], 0x52200000, 0x1000 },
225
- { "mpc3", make_unimp_dev, &mms->mpc[3], 0x52300000, 0x1000 },
226
+ { "mpc0", make_mpc, &mms->mpc[0], 0x52000000, 0x1000 },
227
+ { "mpc1", make_mpc, &mms->mpc[1], 0x52100000, 0x1000 },
228
+ { "mpc2", make_mpc, &mms->mpc[2], 0x52200000, 0x1000 },
229
+ { "mpc3", make_mpc, &mms->mpc[3], 0x52300000, 0x1000 },
230
{ "mhu0", make_unimp_dev, &mms->mhu[0], 0x42600000, 0x100000 },
231
{ "mhu1", make_unimp_dev, &mms->mhu[1], 0x42700000, 0x100000 },
232
{ }, /* port 9: unused */
233
@@ -XXX,XX +XXX,XX @@ static void musca_init(MachineState *machine)
234
{ }, /* port 11: unused */
235
{ }, /* port 12: unused */
236
{ }, /* port 13: unused */
237
- { "mpc4", make_unimp_dev, &mms->mpc[4], 0x52e00000, 0x1000 },
238
+ { "mpc4", make_mpc, &mms->mpc[4], 0x52e00000, 0x1000 },
239
},
240
}, {
241
.name = "apb_ppcexp1",
242
@@ -XXX,XX +XXX,XX @@ static void musca_a_class_init(ObjectClass *oc, void *data)
243
mmc->init_svtor = 0x10200000;
244
mmc->sram_addr_width = 15;
245
mmc->num_irqs = 64;
246
+ mmc->mpc_info = a_mpc_info;
247
+ mmc->num_mpcs = ARRAY_SIZE(a_mpc_info);
248
}
249
250
static void musca_b1_class_init(ObjectClass *oc, void *data)
251
@@ -XXX,XX +XXX,XX @@ static void musca_b1_class_init(ObjectClass *oc, void *data)
252
mmc->init_svtor = 0x10000000;
253
mmc->sram_addr_width = 17;
254
mmc->num_irqs = 96;
255
+ mmc->mpc_info = b1_mpc_info;
256
+ mmc->num_mpcs = ARRAY_SIZE(b1_mpc_info);
257
}
258
259
static const TypeInfo musca_info = {
260
--
460
--
261
2.20.1
461
2.19.1
262
462
263
463
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Julia Suvorova <jusual@mail.ru>
2
2
3
For opcodes 0-5, move some if conditions into the structure
3
Wire up nRF51 UART in the corresponding SoC.
4
of a switch statement. For opcodes 6 & 7, decode everything
5
at once with a second switch.
6
4
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Julia Suvorova <jusual@mail.ru>
8
Message-id: 20190215192302.27855-2-richard.henderson@linaro.org
6
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
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
target/arm/translate-a64.c | 94 ++++++++++++++++++++------------------
11
include/hw/arm/nrf51_soc.h | 3 +++
13
1 file changed, 49 insertions(+), 45 deletions(-)
12
hw/arm/microbit.c | 2 ++
13
hw/arm/nrf51_soc.c | 20 ++++++++++++++++++++
14
3 files changed, 25 insertions(+)
14
15
15
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
16
diff --git a/include/hw/arm/nrf51_soc.h b/include/hw/arm/nrf51_soc.h
16
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate-a64.c
18
--- a/include/hw/arm/nrf51_soc.h
18
+++ b/target/arm/translate-a64.c
19
+++ b/include/hw/arm/nrf51_soc.h
19
@@ -XXX,XX +XXX,XX @@ static void disas_fp_int_conv(DisasContext *s, uint32_t insn)
20
@@ -XXX,XX +XXX,XX @@
20
int type = extract32(insn, 22, 2);
21
21
bool sbit = extract32(insn, 29, 1);
22
#include "hw/sysbus.h"
22
bool sf = extract32(insn, 31, 1);
23
#include "hw/arm/armv7m.h"
23
+ bool itof = false;
24
+#include "hw/char/nrf51_uart.h"
24
25
25
if (sbit) {
26
#define TYPE_NRF51_SOC "nrf51-soc"
26
- unallocated_encoding(s);
27
#define NRF51_SOC(obj) \
27
- return;
28
@@ -XXX,XX +XXX,XX @@ typedef struct NRF51State {
28
+ goto do_unallocated;
29
/*< public >*/
30
ARMv7MState cpu;
31
32
+ NRF51UARTState uart;
33
+
34
MemoryRegion iomem;
35
MemoryRegion sram;
36
MemoryRegion flash;
37
diff --git a/hw/arm/microbit.c b/hw/arm/microbit.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/hw/arm/microbit.c
40
+++ b/hw/arm/microbit.c
41
@@ -XXX,XX +XXX,XX @@
42
#include "qapi/error.h"
43
#include "hw/boards.h"
44
#include "hw/arm/arm.h"
45
+#include "sysemu/sysemu.h"
46
#include "exec/address-spaces.h"
47
48
#include "hw/arm/nrf51_soc.h"
49
@@ -XXX,XX +XXX,XX @@ static void microbit_init(MachineState *machine)
50
51
sysbus_init_child_obj(OBJECT(machine), "nrf51", soc, sizeof(s->nrf51),
52
TYPE_NRF51_SOC);
53
+ qdev_prop_set_chr(DEVICE(&s->nrf51), "serial0", serial_hd(0));
54
object_property_set_link(soc, OBJECT(system_memory), "memory",
55
&error_fatal);
56
object_property_set_bool(soc, true, "realized", &error_fatal);
57
diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c
58
index XXXXXXX..XXXXXXX 100644
59
--- a/hw/arm/nrf51_soc.c
60
+++ b/hw/arm/nrf51_soc.c
61
@@ -XXX,XX +XXX,XX @@
62
#define NRF51822_FLASH_SIZE (256 * 1024)
63
#define NRF51822_SRAM_SIZE (16 * 1024)
64
65
+#define BASE_TO_IRQ(base) ((base >> 12) & 0x1F)
66
+
67
static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
68
{
69
NRF51State *s = NRF51_SOC(dev_soc);
70
+ MemoryRegion *mr;
71
Error *err = NULL;
72
73
if (!s->board_memory) {
74
@@ -XXX,XX +XXX,XX @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
29
}
75
}
30
76
memory_region_add_subregion(&s->container, SRAM_BASE, &s->sram);
31
- if (opcode > 5) {
77
32
- /* FMOV */
78
+ /* UART */
33
- bool itof = opcode & 1;
79
+ object_property_set_bool(OBJECT(&s->uart), true, "realized", &err);
34
-
80
+ if (err) {
35
- if (rmode >= 2) {
81
+ error_propagate(errp, err);
36
- unallocated_encoding(s);
82
+ return;
37
- return;
83
+ }
38
- }
84
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->uart), 0);
39
-
85
+ memory_region_add_subregion_overlap(&s->container, UART_BASE, mr, 0);
40
- switch (sf << 3 | type << 1 | rmode) {
86
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart), 0,
41
- case 0x0: /* 32 bit */
87
+ qdev_get_gpio_in(DEVICE(&s->cpu),
42
- case 0xa: /* 64 bit */
88
+ BASE_TO_IRQ(UART_BASE)));
43
- case 0xd: /* 64 bit to top half of quad */
44
- break;
45
- case 0x6: /* 16-bit float, 32-bit int */
46
- case 0xe: /* 16-bit float, 64-bit int */
47
- if (dc_isar_feature(aa64_fp16, s)) {
48
- break;
49
- }
50
- /* fallthru */
51
- default:
52
- /* all other sf/type/rmode combinations are invalid */
53
- unallocated_encoding(s);
54
- return;
55
- }
56
-
57
- if (!fp_access_check(s)) {
58
- return;
59
- }
60
- handle_fmov(s, rd, rn, type, itof);
61
- } else {
62
- /* actual FP conversions */
63
- bool itof = extract32(opcode, 1, 1);
64
-
65
- if (rmode != 0 && opcode > 1) {
66
- unallocated_encoding(s);
67
- return;
68
+ switch (opcode) {
69
+ case 2: /* SCVTF */
70
+ case 3: /* UCVTF */
71
+ itof = true;
72
+ /* fallthru */
73
+ case 4: /* FCVTAS */
74
+ case 5: /* FCVTAU */
75
+ if (rmode != 0) {
76
+ goto do_unallocated;
77
}
78
+ /* fallthru */
79
+ case 0: /* FCVT[NPMZ]S */
80
+ case 1: /* FCVT[NPMZ]U */
81
switch (type) {
82
case 0: /* float32 */
83
case 1: /* float64 */
84
break;
85
case 3: /* float16 */
86
- if (dc_isar_feature(aa64_fp16, s)) {
87
- break;
88
+ if (!dc_isar_feature(aa64_fp16, s)) {
89
+ goto do_unallocated;
90
}
91
- /* fallthru */
92
+ break;
93
default:
94
- unallocated_encoding(s);
95
- return;
96
+ goto do_unallocated;
97
}
98
-
99
if (!fp_access_check(s)) {
100
return;
101
}
102
handle_fpfpcvt(s, rd, rn, opcode, itof, rmode, 64, sf, type);
103
+ break;
104
+
89
+
105
+ default:
90
create_unimplemented_device("nrf51_soc.io", IOMEM_BASE, IOMEM_SIZE);
106
+ switch (sf << 7 | type << 5 | rmode << 3 | opcode) {
91
create_unimplemented_device("nrf51_soc.ficr", FICR_BASE, FICR_SIZE);
107
+ case 0b01100110: /* FMOV half <-> 32-bit int */
92
create_unimplemented_device("nrf51_soc.private",
108
+ case 0b01100111:
93
@@ -XXX,XX +XXX,XX @@ static void nrf51_soc_init(Object *obj)
109
+ case 0b11100110: /* FMOV half <-> 64-bit int */
94
qdev_prop_set_string(DEVICE(&s->cpu), "cpu-type",
110
+ case 0b11100111:
95
ARM_CPU_TYPE_NAME("cortex-m0"));
111
+ if (!dc_isar_feature(aa64_fp16, s)) {
96
qdev_prop_set_uint32(DEVICE(&s->cpu), "num-irq", 32);
112
+ goto do_unallocated;
113
+ }
114
+ /* fallthru */
115
+ case 0b00000110: /* FMOV 32-bit */
116
+ case 0b00000111:
117
+ case 0b10100110: /* FMOV 64-bit */
118
+ case 0b10100111:
119
+ case 0b11001110: /* FMOV top half of 128-bit */
120
+ case 0b11001111:
121
+ if (!fp_access_check(s)) {
122
+ return;
123
+ }
124
+ itof = opcode & 1;
125
+ handle_fmov(s, rd, rn, type, itof);
126
+ break;
127
+
97
+
128
+ default:
98
+ sysbus_init_child_obj(obj, "uart", &s->uart, sizeof(s->uart),
129
+ do_unallocated:
99
+ TYPE_NRF51_UART);
130
+ unallocated_encoding(s);
100
+ object_property_add_alias(obj, "serial0", OBJECT(&s->uart), "chardev",
131
+ return;
101
+ &error_abort);
132
+ }
133
+ break;
134
}
135
}
102
}
136
103
104
static Property nrf51_soc_properties[] = {
137
--
105
--
138
2.20.1
106
2.19.1
139
107
140
108
diff view generated by jsdifflib
1
The Peripheral Protection Controller's handling of unused ports
1
From: Julia Suvorova <jusual@mail.ru>
2
is that if there is nothing connected to the port's downstream
3
then it does not create the sysbus MMIO region for the upstream
4
end of the port. This results in odd behaviour when there is
5
an unused port in the middle of the range: since sysbus MMIO
6
regions are implicitly consecutively allocated, any used ports
7
above the unused ones end up with sysbus MMIO region numbers
8
that don't match the port number.
9
2
10
Avoid this numbering mismatch by creating dummy MMIO regions
3
New mini-kernel test for nRF51 SoC UART.
11
for the unused ports. This doesn't change anything for our
12
existing boards, which don't have any gaps in the middle of
13
the port ranges they use; but it will be needed for the Musca
14
board.
15
4
5
Signed-off-by: Julia Suvorova <jusual@mail.ru>
6
Acked-by: Thomas Huth <thuth@redhat.com>
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
---
9
---
19
include/hw/misc/tz-ppc.h | 8 +++++++-
10
tests/boot-serial-test.c | 19 +++++++++++++++++++
20
hw/misc/tz-ppc.c | 32 ++++++++++++++++++++++++++++++++
11
1 file changed, 19 insertions(+)
21
2 files changed, 39 insertions(+), 1 deletion(-)
22
12
23
diff --git a/include/hw/misc/tz-ppc.h b/include/hw/misc/tz-ppc.h
13
diff --git a/tests/boot-serial-test.c b/tests/boot-serial-test.c
24
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/misc/tz-ppc.h
15
--- a/tests/boot-serial-test.c
26
+++ b/include/hw/misc/tz-ppc.h
16
+++ b/tests/boot-serial-test.c
27
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@ static const uint8_t kernel_aarch64[] = {
28
*
18
0xfd, 0xff, 0xff, 0x17, /* b -12 (loop) */
29
* QEMU interface:
30
* + sysbus MMIO regions 0..15: MemoryRegions defining the upstream end
31
- * of each of the 16 ports of the PPC
32
+ * of each of the 16 ports of the PPC. When a port is unused (i.e. no
33
+ * downstream MemoryRegion is connected to it) at the end of the 0..15
34
+ * range then no sysbus MMIO region is created for its upstream. When an
35
+ * unused port lies in the middle of the range with other used ports at
36
+ * higher port numbers, a dummy MMIO region is created to ensure that
37
+ * port N's upstream is always sysbus MMIO region N. Dummy regions should
38
+ * not be mapped, and will assert if any access is made to them.
39
* + Property "port[0..15]": MemoryRegion defining the downstream device(s)
40
* for each of the 16 ports of the PPC
41
* + Named GPIO inputs "cfg_nonsec[0..15]": set to 1 if the port should be
42
diff --git a/hw/misc/tz-ppc.c b/hw/misc/tz-ppc.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/hw/misc/tz-ppc.c
45
+++ b/hw/misc/tz-ppc.c
46
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps tz_ppc_ops = {
47
.endianness = DEVICE_LITTLE_ENDIAN,
48
};
19
};
49
20
50
+static bool tz_ppc_dummy_accepts(void *opaque, hwaddr addr,
21
+static const uint8_t kernel_nrf51[] = {
51
+ unsigned size, bool is_write,
22
+ 0x00, 0x00, 0x00, 0x00, /* Stack top address */
52
+ MemTxAttrs attrs)
23
+ 0x09, 0x00, 0x00, 0x00, /* Reset handler address */
53
+{
24
+ 0x04, 0x4a, /* ldr r2, [pc, #16] Get ENABLE */
54
+ /*
25
+ 0x04, 0x21, /* movs r1, #4 */
55
+ * Board code should never map the upstream end of an unused port,
26
+ 0x11, 0x60, /* str r1, [r2] */
56
+ * so we should never try to make a memory access to it.
27
+ 0x04, 0x4a, /* ldr r2, [pc, #16] Get STARTTX */
57
+ */
28
+ 0x01, 0x21, /* movs r1, #1 */
58
+ g_assert_not_reached();
29
+ 0x11, 0x60, /* str r1, [r2] */
59
+}
30
+ 0x03, 0x4a, /* ldr r2, [pc, #12] Get TXD */
60
+
31
+ 0x54, 0x21, /* movs r1, 'T' */
61
+static const MemoryRegionOps tz_ppc_dummy_ops = {
32
+ 0x11, 0x60, /* str r1, [r2] */
62
+ .valid.accepts = tz_ppc_dummy_accepts,
33
+ 0xfe, 0xe7, /* b . */
34
+ 0x00, 0x25, 0x00, 0x40, /* 0x40002500 = UART ENABLE */
35
+ 0x08, 0x20, 0x00, 0x40, /* 0x40002008 = UART STARTTX */
36
+ 0x1c, 0x25, 0x00, 0x40 /* 0x4000251c = UART TXD */
63
+};
37
+};
64
+
38
+
65
static void tz_ppc_reset(DeviceState *dev)
39
typedef struct testdef {
66
{
40
const char *arch; /* Target architecture */
67
TZPPC *s = TZ_PPC(dev);
41
const char *machine; /* Name of the machine */
68
@@ -XXX,XX +XXX,XX @@ static void tz_ppc_realize(DeviceState *dev, Error **errp)
42
@@ -XXX,XX +XXX,XX @@ static testdef_t tests[] = {
69
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
43
{ "hppa", "hppa", "", "SeaBIOS wants SYSTEM HALT" },
70
TZPPC *s = TZ_PPC(dev);
44
{ "aarch64", "virt", "-cpu cortex-a57", "TT", sizeof(kernel_aarch64),
71
int i;
45
kernel_aarch64 },
72
+ int max_port = 0;
46
+ { "arm", "microbit", "", "T", sizeof(kernel_nrf51), kernel_nrf51 },
73
47
74
/* We can't create the upstream end of the port until realize,
48
{ NULL }
75
* as we don't know the size of the MR used as the downstream until then.
49
};
76
*/
77
for (i = 0; i < TZ_NUM_PORTS; i++) {
78
+ if (s->port[i].downstream) {
79
+ max_port = i;
80
+ }
81
+ }
82
+
83
+ for (i = 0; i <= max_port; i++) {
84
TZPPCPort *port = &s->port[i];
85
char *name;
86
uint64_t size;
87
88
if (!port->downstream) {
89
+ /*
90
+ * Create dummy sysbus MMIO region so the sysbus region
91
+ * numbering doesn't get out of sync with the port numbers.
92
+ * The size is entirely arbitrary.
93
+ */
94
+ name = g_strdup_printf("tz-ppc-dummy-port[%d]", i);
95
+ memory_region_init_io(&port->upstream, obj, &tz_ppc_dummy_ops,
96
+ port, name, 0x10000);
97
+ sysbus_init_mmio(sbd, &port->upstream);
98
+ g_free(name);
99
continue;
100
}
101
102
--
50
--
103
2.20.1
51
2.19.1
104
52
105
53
diff view generated by jsdifflib
1
Create a new include file for the pl031's device struct,
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
type macros, etc, so that it can be instantiated using
3
the "embedded struct" coding style.
4
2
3
Shannon Zhao's email at Huawei is bouncing: remove it.
4
5
X-Failed-Recipients: zhaoshenglong@huawei.com
6
** Address not found **
7
Your message wasn't delivered to zhaoshenglong@huawei.com because the address couldn't be found, or is unable to receive mail.
8
9
Note that the section still contains his personal email (see e59f13d76bb).
10
11
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
12
Acked-by: Shannon Zhao <shannon.zhaosl@gmail.com>
13
Message-id: 20181029195931.8747-1-philmd@redhat.com
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
---
15
---
9
include/hw/timer/pl031.h | 44 ++++++++++++++++++++++++++++++++++++++++
16
MAINTAINERS | 1 -
10
hw/timer/pl031.c | 25 +----------------------
17
1 file changed, 1 deletion(-)
11
MAINTAINERS | 1 +
12
3 files changed, 46 insertions(+), 24 deletions(-)
13
create mode 100644 include/hw/timer/pl031.h
14
18
15
diff --git a/include/hw/timer/pl031.h b/include/hw/timer/pl031.h
16
new file mode 100644
17
index XXXXXXX..XXXXXXX
18
--- /dev/null
19
+++ b/include/hw/timer/pl031.h
20
@@ -XXX,XX +XXX,XX @@
21
+/*
22
+ * ARM AMBA PrimeCell PL031 RTC
23
+ *
24
+ * Copyright (c) 2007 CodeSourcery
25
+ *
26
+ * This file is free software; you can redistribute it and/or modify
27
+ * it under the terms of the GNU General Public License version 2 as
28
+ * published by the Free Software Foundation.
29
+ *
30
+ * Contributions after 2012-01-13 are licensed under the terms of the
31
+ * GNU GPL, version 2 or (at your option) any later version.
32
+ */
33
+
34
+#ifndef HW_TIMER_PL031
35
+#define HW_TIMER_PL031
36
+
37
+#include "hw/sysbus.h"
38
+
39
+#define TYPE_PL031 "pl031"
40
+#define PL031(obj) OBJECT_CHECK(PL031State, (obj), TYPE_PL031)
41
+
42
+typedef struct PL031State {
43
+ SysBusDevice parent_obj;
44
+
45
+ MemoryRegion iomem;
46
+ QEMUTimer *timer;
47
+ qemu_irq irq;
48
+
49
+ /*
50
+ * Needed to preserve the tick_count across migration, even if the
51
+ * absolute value of the rtc_clock is different on the source and
52
+ * destination.
53
+ */
54
+ uint32_t tick_offset_vmstate;
55
+ uint32_t tick_offset;
56
+
57
+ uint32_t mr;
58
+ uint32_t lr;
59
+ uint32_t cr;
60
+ uint32_t im;
61
+ uint32_t is;
62
+} PL031State;
63
+
64
+#endif
65
diff --git a/hw/timer/pl031.c b/hw/timer/pl031.c
66
index XXXXXXX..XXXXXXX 100644
67
--- a/hw/timer/pl031.c
68
+++ b/hw/timer/pl031.c
69
@@ -XXX,XX +XXX,XX @@
70
*/
71
72
#include "qemu/osdep.h"
73
+#include "hw/timer/pl031.h"
74
#include "hw/sysbus.h"
75
#include "qemu/timer.h"
76
#include "sysemu/sysemu.h"
77
@@ -XXX,XX +XXX,XX @@ do { printf("pl031: " fmt , ## __VA_ARGS__); } while (0)
78
#define RTC_MIS 0x18 /* Masked interrupt status register */
79
#define RTC_ICR 0x1c /* Interrupt clear register */
80
81
-#define TYPE_PL031 "pl031"
82
-#define PL031(obj) OBJECT_CHECK(PL031State, (obj), TYPE_PL031)
83
-
84
-typedef struct PL031State {
85
- SysBusDevice parent_obj;
86
-
87
- MemoryRegion iomem;
88
- QEMUTimer *timer;
89
- qemu_irq irq;
90
-
91
- /* Needed to preserve the tick_count across migration, even if the
92
- * absolute value of the rtc_clock is different on the source and
93
- * destination.
94
- */
95
- uint32_t tick_offset_vmstate;
96
- uint32_t tick_offset;
97
-
98
- uint32_t mr;
99
- uint32_t lr;
100
- uint32_t cr;
101
- uint32_t im;
102
- uint32_t is;
103
-} PL031State;
104
-
105
static const unsigned char pl031_id[] = {
106
0x31, 0x10, 0x14, 0x00, /* Device ID */
107
0x0d, 0xf0, 0x05, 0xb1 /* Cell ID */
108
diff --git a/MAINTAINERS b/MAINTAINERS
19
diff --git a/MAINTAINERS b/MAINTAINERS
109
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
110
--- a/MAINTAINERS
21
--- a/MAINTAINERS
111
+++ b/MAINTAINERS
22
+++ b/MAINTAINERS
112
@@ -XXX,XX +XXX,XX @@ F: hw/sd/pl181.c
23
@@ -XXX,XX +XXX,XX @@ F: hw/*/xlnx*.c
113
F: hw/ssi/pl022.c
24
F: include/hw/*/xlnx*.h
114
F: include/hw/ssi/pl022.h
25
115
F: hw/timer/pl031.c
26
ARM ACPI Subsystem
116
+F: include/hw/timer/pl031.h
27
-M: Shannon Zhao <zhaoshenglong@huawei.com>
117
F: include/hw/arm/primecell.h
28
M: Shannon Zhao <shannon.zhaosl@gmail.com>
118
F: hw/timer/cmsdk-apb-timer.c
29
L: qemu-arm@nongnu.org
119
F: include/hw/timer/cmsdk-apb-timer.h
30
S: Maintained
120
--
31
--
121
2.20.1
32
2.19.1
122
33
123
34
diff view generated by jsdifflib
1
The pl011 logs when the guest makes a bad access. It prints
1
From: Prasad J Pandit <pjp@fedoraproject.org>
2
the address offset in hex but confusingly omits the '0x'
3
prefix; add it.
4
2
3
The high[31:28] bits of 'direction' and 'state' registers of
4
SA-1100/SA-1110 device are reserved. Setting them may lead to
5
OOB 's->handler[]' array access issue. Mask off [31:28] bits to
6
avoid it.
7
8
Reported-by: Moguofang <moguofang@huawei.com>
9
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
10
Message-id: 20181030114635.31232-1-ppandit@redhat.com
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
---
13
---
9
hw/char/pl011.c | 4 ++--
14
hw/arm/strongarm.c | 4 ++--
10
1 file changed, 2 insertions(+), 2 deletions(-)
15
1 file changed, 2 insertions(+), 2 deletions(-)
11
16
12
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
17
diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c
13
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/char/pl011.c
19
--- a/hw/arm/strongarm.c
15
+++ b/hw/char/pl011.c
20
+++ b/hw/arm/strongarm.c
16
@@ -XXX,XX +XXX,XX @@ static uint64_t pl011_read(void *opaque, hwaddr offset,
21
@@ -XXX,XX +XXX,XX @@ static void strongarm_gpio_write(void *opaque, hwaddr offset,
22
23
switch (offset) {
24
case GPDR: /* GPIO Pin-Direction registers */
25
- s->dir = value;
26
+ s->dir = value & 0x0fffffff;
27
strongarm_gpio_handler_update(s);
17
break;
28
break;
18
default:
29
19
qemu_log_mask(LOG_GUEST_ERROR,
30
case GPSR: /* GPIO Pin-Output Set registers */
20
- "pl011_read: Bad offset %x\n", (int)offset);
31
- s->olevel |= value;
21
+ "pl011_read: Bad offset 0x%x\n", (int)offset);
32
+ s->olevel |= value & 0x0fffffff;
22
r = 0;
33
strongarm_gpio_handler_update(s);
23
break;
34
break;
24
}
25
@@ -XXX,XX +XXX,XX @@ static void pl011_write(void *opaque, hwaddr offset,
26
break;
27
default:
28
qemu_log_mask(LOG_GUEST_ERROR,
29
- "pl011_write: Bad offset %x\n", (int)offset);
30
+ "pl011_write: Bad offset 0x%x\n", (int)offset);
31
}
32
}
33
35
34
--
36
--
35
2.20.1
37
2.19.1
36
38
37
39
diff view generated by jsdifflib
1
From: Aaron Lindsay OS <aaron@os.amperecomputing.com>
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
2
3
This was introduced by
3
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
4
commit bf8d09694ccc07487cd73d7562081fdaec3370c8
4
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
5
target/arm: Don't clear supported PMU events when initializing PMCEID1
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
and identified by Coverity (CID 1398645).
7
8
Signed-off-by: Aaron Lindsay <aaron@os.amperecomputing.com>
9
Reported-by: Peter Maydell <peter.maydell@linaro.org>
10
Message-id: 20190219144621.450-1-aaron@os.amperecomputing.com
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
8
---
14
target/arm/helper.c | 2 +-
9
hw/arm/xilinx_zynq.c | 2 +-
15
1 file changed, 1 insertion(+), 1 deletion(-)
10
1 file changed, 1 insertion(+), 1 deletion(-)
16
11
17
diff --git a/target/arm/helper.c b/target/arm/helper.c
12
diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
18
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper.c
14
--- a/hw/arm/xilinx_zynq.c
20
+++ b/target/arm/helper.c
15
+++ b/hw/arm/xilinx_zynq.c
21
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu)
16
@@ -XXX,XX +XXX,XX @@ static void zynq_init(MachineState *machine)
22
17
busdev = SYS_BUS_DEVICE(dev);
23
if (cnt->supported(&cpu->env)) {
18
sysbus_mmio_map(busdev, 0, 0xF8003000);
24
supported_event_map[cnt->number] = i;
19
sysbus_connect_irq(busdev, 0, pic[45-IRQ_OFFSET]); /* abort irq line */
25
- uint64_t event_mask = 1 << (cnt->number & 0x1f);
20
- for (n = 0; n < 8; ++n) { /* event irqs */
26
+ uint64_t event_mask = 1ULL << (cnt->number & 0x1f);
21
+ for (n = 0; n < ARRAY_SIZE(dma_irqs); ++n) { /* event irqs */
27
if (cnt->number & 0x20) {
22
sysbus_connect_irq(busdev, n + 1, pic[dma_irqs[n] - IRQ_OFFSET]);
28
cpu->pmceid1 |= event_mask;
23
}
29
} else {
24
30
--
25
--
31
2.20.1
26
2.19.1
32
27
33
28
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
When populating id registers from kvm, on a host that doesn't support
4
aarch32 mode at all, neither arm_div nor jazelle will be supported either.
5
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Message-id: 20190215192302.27855-5-richard.henderson@linaro.org
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Tested-by: Alex Bennée <alex.bennee@linaro.org>
9
Message-id: 20181102102025.3546-1-richard.henderson@linaro.org
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
[PMM: fixed a couple of comment typos]
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
12
---
9
target/arm/cpu.h | 10 +++++
13
target/arm/cpu.h | 5 +++++
10
target/arm/helper.h | 3 ++
14
target/arm/cpu.c | 15 +++++++++++++--
11
target/arm/cpu.c | 1 +
15
2 files changed, 18 insertions(+), 2 deletions(-)
12
target/arm/cpu64.c | 2 +
13
target/arm/translate-a64.c | 26 +++++++++++
14
target/arm/translate.c | 10 +++++
15
target/arm/vfp_helper.c | 88 ++++++++++++++++++++++++++++++++++++++
16
7 files changed, 140 insertions(+)
17
16
18
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
19
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/cpu.h
19
--- a/target/arm/cpu.h
21
+++ b/target/arm/cpu.h
20
+++ b/target/arm/cpu.h
22
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_vcma(const ARMISARegisters *id)
21
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_fp16(const ARMISARegisters *id)
23
return FIELD_EX32(id->id_isar5, ID_ISAR5, VCMA) != 0;
22
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, FP) == 1;
24
}
23
}
25
24
26
+static inline bool isar_feature_aa32_jscvt(const ARMISARegisters *id)
25
+static inline bool isar_feature_aa64_aa32(const ARMISARegisters *id)
27
+{
26
+{
28
+ return FIELD_EX32(id->id_isar6, ID_ISAR6, JSCVT) != 0;
27
+ return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL0) >= 2;
29
+}
28
+}
30
+
29
+
31
static inline bool isar_feature_aa32_dp(const ARMISARegisters *id)
30
static inline bool isar_feature_aa64_sve(const ARMISARegisters *id)
32
{
31
{
33
return FIELD_EX32(id->id_isar6, ID_ISAR6, DP) != 0;
32
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, SVE) != 0;
34
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_dp(const ARMISARegisters *id)
35
return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, DP) != 0;
36
}
37
38
+static inline bool isar_feature_aa64_jscvt(const ARMISARegisters *id)
39
+{
40
+ return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, JSCVT) != 0;
41
+}
42
+
43
static inline bool isar_feature_aa64_fcma(const ARMISARegisters *id)
44
{
45
return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, FCMA) != 0;
46
diff --git a/target/arm/helper.h b/target/arm/helper.h
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/helper.h
49
+++ b/target/arm/helper.h
50
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_2(rintd_exact, TCG_CALL_NO_RWG, f64, f64, ptr)
51
DEF_HELPER_FLAGS_2(rints, TCG_CALL_NO_RWG, f32, f32, ptr)
52
DEF_HELPER_FLAGS_2(rintd, TCG_CALL_NO_RWG, f64, f64, ptr)
53
54
+DEF_HELPER_FLAGS_2(vjcvt, TCG_CALL_NO_RWG, i32, f64, env)
55
+DEF_HELPER_FLAGS_2(fjcvtzs, TCG_CALL_NO_RWG, i64, f64, ptr)
56
+
57
/* neon_helper.c */
58
DEF_HELPER_FLAGS_3(neon_qadd_u8, TCG_CALL_NO_RWG, i32, env, i32, i32)
59
DEF_HELPER_FLAGS_3(neon_qadd_s8, TCG_CALL_NO_RWG, i32, env, i32, i32)
60
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
33
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
61
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
62
--- a/target/arm/cpu.c
35
--- a/target/arm/cpu.c
63
+++ b/target/arm/cpu.c
36
+++ b/target/arm/cpu.c
64
@@ -XXX,XX +XXX,XX @@ static void arm_max_initfn(Object *obj)
37
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
65
cpu->isar.id_isar5 = t;
38
CPUARMState *env = &cpu->env;
66
39
int pagebits;
67
t = cpu->isar.id_isar6;
40
Error *local_err = NULL;
68
+ t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1);
41
+ bool no_aa32 = false;
69
t = FIELD_DP32(t, ID_ISAR6, DP, 1);
42
70
cpu->isar.id_isar6 = t;
43
/* If we needed to query the host kernel for the CPU features
71
44
* then it's possible that might have failed in the initfn, but
72
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
45
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
73
index XXXXXXX..XXXXXXX 100644
46
set_feature(env, ARM_FEATURE_V7VE);
74
--- a/target/arm/cpu64.c
47
}
75
+++ b/target/arm/cpu64.c
76
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
77
cpu->isar.id_aa64isar0 = t;
78
79
t = cpu->isar.id_aa64isar1;
80
+ t = FIELD_DP64(t, ID_AA64ISAR1, JSCVT, 1);
81
t = FIELD_DP64(t, ID_AA64ISAR1, FCMA, 1);
82
t = FIELD_DP64(t, ID_AA64ISAR1, APA, 1); /* PAuth, architected only */
83
t = FIELD_DP64(t, ID_AA64ISAR1, API, 0);
84
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
85
cpu->isar.id_isar5 = u;
86
87
u = cpu->isar.id_isar6;
88
+ u = FIELD_DP32(u, ID_ISAR6, JSCVT, 1);
89
u = FIELD_DP32(u, ID_ISAR6, DP, 1);
90
cpu->isar.id_isar6 = u;
91
92
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
93
index XXXXXXX..XXXXXXX 100644
94
--- a/target/arm/translate-a64.c
95
+++ b/target/arm/translate-a64.c
96
@@ -XXX,XX +XXX,XX @@ static void handle_fmov(DisasContext *s, int rd, int rn, int type, bool itof)
97
}
48
}
98
}
99
100
+static void handle_fjcvtzs(DisasContext *s, int rd, int rn)
101
+{
102
+ TCGv_i64 t = read_fp_dreg(s, rn);
103
+ TCGv_ptr fpstatus = get_fpstatus_ptr(false);
104
+
49
+
105
+ gen_helper_fjcvtzs(t, t, fpstatus);
50
+ /*
106
+
51
+ * There exist AArch64 cpus without AArch32 support. When KVM
107
+ tcg_temp_free_ptr(fpstatus);
52
+ * queries ID_ISAR0_EL1 on such a host, the value is UNKNOWN.
108
+
53
+ * Similarly, we cannot check ID_AA64PFR0 without AArch64 support.
109
+ tcg_gen_ext32u_i64(cpu_reg(s, rd), t);
54
+ */
110
+ tcg_gen_extrh_i64_i32(cpu_ZF, t);
55
+ if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
111
+ tcg_gen_movi_i32(cpu_CF, 0);
56
+ no_aa32 = !cpu_isar_feature(aa64_aa32, cpu);
112
+ tcg_gen_movi_i32(cpu_NF, 0);
113
+ tcg_gen_movi_i32(cpu_VF, 0);
114
+
115
+ tcg_temp_free_i64(t);
116
+}
117
+
118
/* Floating point <-> integer conversions
119
* 31 30 29 28 24 23 22 21 20 19 18 16 15 10 9 5 4 0
120
* +----+---+---+-----------+------+---+-------+-----+-------------+----+----+
121
@@ -XXX,XX +XXX,XX @@ static void disas_fp_int_conv(DisasContext *s, uint32_t insn)
122
handle_fmov(s, rd, rn, type, itof);
123
break;
124
125
+ case 0b00111110: /* FJCVTZS */
126
+ if (!dc_isar_feature(aa64_jscvt, s)) {
127
+ goto do_unallocated;
128
+ } else if (fp_access_check(s)) {
129
+ handle_fjcvtzs(s, rd, rn);
130
+ }
131
+ break;
132
+
133
default:
134
do_unallocated:
135
unallocated_encoding(s);
136
diff --git a/target/arm/translate.c b/target/arm/translate.c
137
index XXXXXXX..XXXXXXX 100644
138
--- a/target/arm/translate.c
139
+++ b/target/arm/translate.c
140
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
141
rm_is_dp = false;
142
break;
143
144
+ case 0x13: /* vjcvt */
145
+ if (!dp || !dc_isar_feature(aa32_jscvt, s)) {
146
+ return 1;
147
+ }
148
+ rd_is_dp = false;
149
+ break;
150
+
151
default:
152
return 1;
153
}
154
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
155
case 17: /* fsito */
156
gen_vfp_sito(dp, 0);
157
break;
158
+ case 19: /* vjcvt */
159
+ gen_helper_vjcvt(cpu_F0s, cpu_F0d, cpu_env);
160
+ break;
161
case 20: /* fshto */
162
gen_vfp_shto(dp, 16 - rm, 0);
163
break;
164
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
165
index XXXXXXX..XXXXXXX 100644
166
--- a/target/arm/vfp_helper.c
167
+++ b/target/arm/vfp_helper.c
168
@@ -XXX,XX +XXX,XX @@ int arm_rmode_to_sf(int rmode)
169
}
170
return rmode;
171
}
172
+
173
+/*
174
+ * Implement float64 to int32_t conversion without saturation;
175
+ * the result is supplied modulo 2^32.
176
+ */
177
+uint64_t HELPER(fjcvtzs)(float64 value, void *vstatus)
178
+{
179
+ float_status *status = vstatus;
180
+ uint32_t exp, sign;
181
+ uint64_t frac;
182
+ uint32_t inexact = 1; /* !Z */
183
+
184
+ sign = extract64(value, 63, 1);
185
+ exp = extract64(value, 52, 11);
186
+ frac = extract64(value, 0, 52);
187
+
188
+ if (exp == 0) {
189
+ /* While not inexact for IEEE FP, -0.0 is inexact for JavaScript. */
190
+ inexact = sign;
191
+ if (frac != 0) {
192
+ if (status->flush_inputs_to_zero) {
193
+ float_raise(float_flag_input_denormal, status);
194
+ } else {
195
+ float_raise(float_flag_inexact, status);
196
+ inexact = 1;
197
+ }
198
+ }
199
+ frac = 0;
200
+ } else if (exp == 0x7ff) {
201
+ /* This operation raises Invalid for both NaN and overflow (Inf). */
202
+ float_raise(float_flag_invalid, status);
203
+ frac = 0;
204
+ } else {
205
+ int true_exp = exp - 1023;
206
+ int shift = true_exp - 52;
207
+
208
+ /* Restore implicit bit. */
209
+ frac |= 1ull << 52;
210
+
211
+ /* Shift the fraction into place. */
212
+ if (shift >= 0) {
213
+ /* The number is so large we must shift the fraction left. */
214
+ if (shift >= 64) {
215
+ /* The fraction is shifted out entirely. */
216
+ frac = 0;
217
+ } else {
218
+ frac <<= shift;
219
+ }
220
+ } else if (shift > -64) {
221
+ /* Normal case -- shift right and notice if bits shift out. */
222
+ inexact = (frac << (64 + shift)) != 0;
223
+ frac >>= -shift;
224
+ } else {
225
+ /* The fraction is shifted out entirely. */
226
+ frac = 0;
227
+ }
228
+
229
+ /* Notice overflow or inexact exceptions. */
230
+ if (true_exp > 31 || frac > (sign ? 0x80000000ull : 0x7fffffff)) {
231
+ /* Overflow, for which this operation raises invalid. */
232
+ float_raise(float_flag_invalid, status);
233
+ inexact = 1;
234
+ } else if (inexact) {
235
+ float_raise(float_flag_inexact, status);
236
+ }
237
+
238
+ /* Honor the sign. */
239
+ if (sign) {
240
+ frac = -frac;
241
+ }
242
+ }
57
+ }
243
+
58
+
244
+ /* Pack the result and the env->ZF representation of Z together. */
59
if (arm_feature(env, ARM_FEATURE_V7VE)) {
245
+ return deposit64(frac, 32, 32, inexact);
60
/* v7 Virtualization Extensions. In real hardware this implies
246
+}
61
* EL2 and also the presence of the Security Extensions.
247
+
62
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
248
+uint32_t HELPER(vjcvt)(float64 value, CPUARMState *env)
63
* Presence of EL2 itself is ARM_FEATURE_EL2, and of the
249
+{
64
* Security Extensions is ARM_FEATURE_EL3.
250
+ uint64_t pair = HELPER(fjcvtzs)(value, &env->vfp.fp_status);
65
*/
251
+ uint32_t result = pair;
66
- assert(cpu_isar_feature(arm_div, cpu));
252
+ uint32_t z = (pair >> 32) == 0;
67
+ assert(no_aa32 || cpu_isar_feature(arm_div, cpu));
253
+
68
set_feature(env, ARM_FEATURE_LPAE);
254
+ /* Store Z, clear NCV, in FPSCR.NZCV. */
69
set_feature(env, ARM_FEATURE_V7);
255
+ env->vfp.xregs[ARM_VFP_FPSCR]
70
}
256
+ = (env->vfp.xregs[ARM_VFP_FPSCR] & ~CPSR_NZCV) | (z * CPSR_Z);
71
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
257
+
72
if (arm_feature(env, ARM_FEATURE_V6)) {
258
+ return result;
73
set_feature(env, ARM_FEATURE_V5);
259
+}
74
if (!arm_feature(env, ARM_FEATURE_M)) {
75
- assert(cpu_isar_feature(jazelle, cpu));
76
+ assert(no_aa32 || cpu_isar_feature(jazelle, cpu));
77
set_feature(env, ARM_FEATURE_AUXCR);
78
}
79
}
260
--
80
--
261
2.20.1
81
2.19.1
262
82
263
83
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
2
2
3
Move all of the fp helpers out of helper.c into a new file.
3
Add a model of Xilinx Versal SoC.
4
This is code movement only. Since helper.c has no copyright
5
header, take the one from cpu.h for the new file.
6
4
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Message-id: 20190215192302.27855-3-richard.henderson@linaro.org
6
Message-id: 20181102131913.1535-2-edgar.iglesias@xilinx.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
9
---
12
target/arm/Makefile.objs | 2 +-
10
hw/arm/Makefile.objs | 1 +
13
target/arm/helper.c | 1062 -------------------------------------
11
include/hw/arm/xlnx-versal.h | 122 +++++++++++
14
target/arm/vfp_helper.c | 1088 ++++++++++++++++++++++++++++++++++++++
12
hw/arm/xlnx-versal.c | 323 ++++++++++++++++++++++++++++
15
3 files changed, 1089 insertions(+), 1063 deletions(-)
13
default-configs/aarch64-softmmu.mak | 1 +
16
create mode 100644 target/arm/vfp_helper.c
14
4 files changed, 447 insertions(+)
15
create mode 100644 include/hw/arm/xlnx-versal.h
16
create mode 100644 hw/arm/xlnx-versal.c
17
17
18
diff --git a/target/arm/Makefile.objs b/target/arm/Makefile.objs
18
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
19
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/Makefile.objs
20
--- a/hw/arm/Makefile.objs
21
+++ b/target/arm/Makefile.objs
21
+++ b/hw/arm/Makefile.objs
22
@@ -XXX,XX +XXX,XX @@ obj-$(call land,$(CONFIG_KVM),$(call lnot,$(TARGET_AARCH64))) += kvm32.o
22
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o
23
obj-$(call land,$(CONFIG_KVM),$(TARGET_AARCH64)) += kvm64.o
23
obj-$(CONFIG_RASPI) += bcm2835_peripherals.o bcm2836.o raspi.o
24
obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o
24
obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o
25
obj-y += translate.o op_helper.o helper.o cpu.o
25
obj-$(CONFIG_XLNX_ZYNQMP_ARM) += xlnx-zynqmp.o xlnx-zcu102.o
26
-obj-y += neon_helper.o iwmmxt_helper.o vec_helper.o
26
+obj-$(CONFIG_XLNX_VERSAL) += xlnx-versal.o
27
+obj-y += neon_helper.o iwmmxt_helper.o vec_helper.o vfp_helper.o
27
obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o
28
obj-y += gdbstub.o
28
obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o
29
obj-$(TARGET_AARCH64) += cpu64.o translate-a64.o helper-a64.o gdbstub64.o
29
obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o
30
obj-$(TARGET_AARCH64) += pauth_helper.o
30
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
31
diff --git a/target/arm/helper.c b/target/arm/helper.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/helper.c
34
+++ b/target/arm/helper.c
35
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(sel_flags)(uint32_t flags, uint32_t a, uint32_t b)
36
return (a & mask) | (b & ~mask);
37
}
38
39
-/* VFP support. We follow the convention used for VFP instructions:
40
- Single precision routines have a "s" suffix, double precision a
41
- "d" suffix. */
42
-
43
-/* Convert host exception flags to vfp form. */
44
-static inline int vfp_exceptbits_from_host(int host_bits)
45
-{
46
- int target_bits = 0;
47
-
48
- if (host_bits & float_flag_invalid)
49
- target_bits |= 1;
50
- if (host_bits & float_flag_divbyzero)
51
- target_bits |= 2;
52
- if (host_bits & float_flag_overflow)
53
- target_bits |= 4;
54
- if (host_bits & (float_flag_underflow | float_flag_output_denormal))
55
- target_bits |= 8;
56
- if (host_bits & float_flag_inexact)
57
- target_bits |= 0x10;
58
- if (host_bits & float_flag_input_denormal)
59
- target_bits |= 0x80;
60
- return target_bits;
61
-}
62
-
63
-uint32_t HELPER(vfp_get_fpscr)(CPUARMState *env)
64
-{
65
- uint32_t i, fpscr;
66
-
67
- fpscr = env->vfp.xregs[ARM_VFP_FPSCR]
68
- | (env->vfp.vec_len << 16)
69
- | (env->vfp.vec_stride << 20);
70
-
71
- i = get_float_exception_flags(&env->vfp.fp_status);
72
- i |= get_float_exception_flags(&env->vfp.standard_fp_status);
73
- /* FZ16 does not generate an input denormal exception. */
74
- i |= (get_float_exception_flags(&env->vfp.fp_status_f16)
75
- & ~float_flag_input_denormal);
76
- fpscr |= vfp_exceptbits_from_host(i);
77
-
78
- i = env->vfp.qc[0] | env->vfp.qc[1] | env->vfp.qc[2] | env->vfp.qc[3];
79
- fpscr |= i ? FPCR_QC : 0;
80
-
81
- return fpscr;
82
-}
83
-
84
-uint32_t vfp_get_fpscr(CPUARMState *env)
85
-{
86
- return HELPER(vfp_get_fpscr)(env);
87
-}
88
-
89
-/* Convert vfp exception flags to target form. */
90
-static inline int vfp_exceptbits_to_host(int target_bits)
91
-{
92
- int host_bits = 0;
93
-
94
- if (target_bits & 1)
95
- host_bits |= float_flag_invalid;
96
- if (target_bits & 2)
97
- host_bits |= float_flag_divbyzero;
98
- if (target_bits & 4)
99
- host_bits |= float_flag_overflow;
100
- if (target_bits & 8)
101
- host_bits |= float_flag_underflow;
102
- if (target_bits & 0x10)
103
- host_bits |= float_flag_inexact;
104
- if (target_bits & 0x80)
105
- host_bits |= float_flag_input_denormal;
106
- return host_bits;
107
-}
108
-
109
-void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
110
-{
111
- int i;
112
- uint32_t changed = env->vfp.xregs[ARM_VFP_FPSCR];
113
-
114
- /* When ARMv8.2-FP16 is not supported, FZ16 is RES0. */
115
- if (!cpu_isar_feature(aa64_fp16, arm_env_get_cpu(env))) {
116
- val &= ~FPCR_FZ16;
117
- }
118
-
119
- /*
120
- * We don't implement trapped exception handling, so the
121
- * trap enable bits, IDE|IXE|UFE|OFE|DZE|IOE are all RAZ/WI (not RES0!)
122
- *
123
- * If we exclude the exception flags, IOC|DZC|OFC|UFC|IXC|IDC
124
- * (which are stored in fp_status), and the other RES0 bits
125
- * in between, then we clear all of the low 16 bits.
126
- */
127
- env->vfp.xregs[ARM_VFP_FPSCR] = val & 0xf7c80000;
128
- env->vfp.vec_len = (val >> 16) & 7;
129
- env->vfp.vec_stride = (val >> 20) & 3;
130
-
131
- /*
132
- * The bit we set within fpscr_q is arbitrary; the register as a
133
- * whole being zero/non-zero is what counts.
134
- */
135
- env->vfp.qc[0] = val & FPCR_QC;
136
- env->vfp.qc[1] = 0;
137
- env->vfp.qc[2] = 0;
138
- env->vfp.qc[3] = 0;
139
-
140
- changed ^= val;
141
- if (changed & (3 << 22)) {
142
- i = (val >> 22) & 3;
143
- switch (i) {
144
- case FPROUNDING_TIEEVEN:
145
- i = float_round_nearest_even;
146
- break;
147
- case FPROUNDING_POSINF:
148
- i = float_round_up;
149
- break;
150
- case FPROUNDING_NEGINF:
151
- i = float_round_down;
152
- break;
153
- case FPROUNDING_ZERO:
154
- i = float_round_to_zero;
155
- break;
156
- }
157
- set_float_rounding_mode(i, &env->vfp.fp_status);
158
- set_float_rounding_mode(i, &env->vfp.fp_status_f16);
159
- }
160
- if (changed & FPCR_FZ16) {
161
- bool ftz_enabled = val & FPCR_FZ16;
162
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status_f16);
163
- set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status_f16);
164
- }
165
- if (changed & FPCR_FZ) {
166
- bool ftz_enabled = val & FPCR_FZ;
167
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status);
168
- set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status);
169
- }
170
- if (changed & FPCR_DN) {
171
- bool dnan_enabled = val & FPCR_DN;
172
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status);
173
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status_f16);
174
- }
175
-
176
- /* The exception flags are ORed together when we read fpscr so we
177
- * only need to preserve the current state in one of our
178
- * float_status values.
179
- */
180
- i = vfp_exceptbits_to_host(val);
181
- set_float_exception_flags(i, &env->vfp.fp_status);
182
- set_float_exception_flags(0, &env->vfp.fp_status_f16);
183
- set_float_exception_flags(0, &env->vfp.standard_fp_status);
184
-}
185
-
186
-void vfp_set_fpscr(CPUARMState *env, uint32_t val)
187
-{
188
- HELPER(vfp_set_fpscr)(env, val);
189
-}
190
-
191
-#define VFP_HELPER(name, p) HELPER(glue(glue(vfp_,name),p))
192
-
193
-#define VFP_BINOP(name) \
194
-float32 VFP_HELPER(name, s)(float32 a, float32 b, void *fpstp) \
195
-{ \
196
- float_status *fpst = fpstp; \
197
- return float32_ ## name(a, b, fpst); \
198
-} \
199
-float64 VFP_HELPER(name, d)(float64 a, float64 b, void *fpstp) \
200
-{ \
201
- float_status *fpst = fpstp; \
202
- return float64_ ## name(a, b, fpst); \
203
-}
204
-VFP_BINOP(add)
205
-VFP_BINOP(sub)
206
-VFP_BINOP(mul)
207
-VFP_BINOP(div)
208
-VFP_BINOP(min)
209
-VFP_BINOP(max)
210
-VFP_BINOP(minnum)
211
-VFP_BINOP(maxnum)
212
-#undef VFP_BINOP
213
-
214
-float32 VFP_HELPER(neg, s)(float32 a)
215
-{
216
- return float32_chs(a);
217
-}
218
-
219
-float64 VFP_HELPER(neg, d)(float64 a)
220
-{
221
- return float64_chs(a);
222
-}
223
-
224
-float32 VFP_HELPER(abs, s)(float32 a)
225
-{
226
- return float32_abs(a);
227
-}
228
-
229
-float64 VFP_HELPER(abs, d)(float64 a)
230
-{
231
- return float64_abs(a);
232
-}
233
-
234
-float32 VFP_HELPER(sqrt, s)(float32 a, CPUARMState *env)
235
-{
236
- return float32_sqrt(a, &env->vfp.fp_status);
237
-}
238
-
239
-float64 VFP_HELPER(sqrt, d)(float64 a, CPUARMState *env)
240
-{
241
- return float64_sqrt(a, &env->vfp.fp_status);
242
-}
243
-
244
-static void softfloat_to_vfp_compare(CPUARMState *env, int cmp)
245
-{
246
- uint32_t flags;
247
- switch (cmp) {
248
- case float_relation_equal:
249
- flags = 0x6;
250
- break;
251
- case float_relation_less:
252
- flags = 0x8;
253
- break;
254
- case float_relation_greater:
255
- flags = 0x2;
256
- break;
257
- case float_relation_unordered:
258
- flags = 0x3;
259
- break;
260
- default:
261
- g_assert_not_reached();
262
- }
263
- env->vfp.xregs[ARM_VFP_FPSCR] =
264
- deposit32(env->vfp.xregs[ARM_VFP_FPSCR], 28, 4, flags);
265
-}
266
-
267
-/* XXX: check quiet/signaling case */
268
-#define DO_VFP_cmp(p, type) \
269
-void VFP_HELPER(cmp, p)(type a, type b, CPUARMState *env) \
270
-{ \
271
- softfloat_to_vfp_compare(env, \
272
- type ## _compare_quiet(a, b, &env->vfp.fp_status)); \
273
-} \
274
-void VFP_HELPER(cmpe, p)(type a, type b, CPUARMState *env) \
275
-{ \
276
- softfloat_to_vfp_compare(env, \
277
- type ## _compare(a, b, &env->vfp.fp_status)); \
278
-}
279
-DO_VFP_cmp(s, float32)
280
-DO_VFP_cmp(d, float64)
281
-#undef DO_VFP_cmp
282
-
283
-/* Integer to float and float to integer conversions */
284
-
285
-#define CONV_ITOF(name, ftype, fsz, sign) \
286
-ftype HELPER(name)(uint32_t x, void *fpstp) \
287
-{ \
288
- float_status *fpst = fpstp; \
289
- return sign##int32_to_##float##fsz((sign##int32_t)x, fpst); \
290
-}
291
-
292
-#define CONV_FTOI(name, ftype, fsz, sign, round) \
293
-sign##int32_t HELPER(name)(ftype x, void *fpstp) \
294
-{ \
295
- float_status *fpst = fpstp; \
296
- if (float##fsz##_is_any_nan(x)) { \
297
- float_raise(float_flag_invalid, fpst); \
298
- return 0; \
299
- } \
300
- return float##fsz##_to_##sign##int32##round(x, fpst); \
301
-}
302
-
303
-#define FLOAT_CONVS(name, p, ftype, fsz, sign) \
304
- CONV_ITOF(vfp_##name##to##p, ftype, fsz, sign) \
305
- CONV_FTOI(vfp_to##name##p, ftype, fsz, sign, ) \
306
- CONV_FTOI(vfp_to##name##z##p, ftype, fsz, sign, _round_to_zero)
307
-
308
-FLOAT_CONVS(si, h, uint32_t, 16, )
309
-FLOAT_CONVS(si, s, float32, 32, )
310
-FLOAT_CONVS(si, d, float64, 64, )
311
-FLOAT_CONVS(ui, h, uint32_t, 16, u)
312
-FLOAT_CONVS(ui, s, float32, 32, u)
313
-FLOAT_CONVS(ui, d, float64, 64, u)
314
-
315
-#undef CONV_ITOF
316
-#undef CONV_FTOI
317
-#undef FLOAT_CONVS
318
-
319
-/* floating point conversion */
320
-float64 VFP_HELPER(fcvtd, s)(float32 x, CPUARMState *env)
321
-{
322
- return float32_to_float64(x, &env->vfp.fp_status);
323
-}
324
-
325
-float32 VFP_HELPER(fcvts, d)(float64 x, CPUARMState *env)
326
-{
327
- return float64_to_float32(x, &env->vfp.fp_status);
328
-}
329
-
330
-/* VFP3 fixed point conversion. */
331
-#define VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
332
-float##fsz HELPER(vfp_##name##to##p)(uint##isz##_t x, uint32_t shift, \
333
- void *fpstp) \
334
-{ return itype##_to_##float##fsz##_scalbn(x, -shift, fpstp); }
335
-
336
-#define VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, ROUND, suff) \
337
-uint##isz##_t HELPER(vfp_to##name##p##suff)(float##fsz x, uint32_t shift, \
338
- void *fpst) \
339
-{ \
340
- if (unlikely(float##fsz##_is_any_nan(x))) { \
341
- float_raise(float_flag_invalid, fpst); \
342
- return 0; \
343
- } \
344
- return float##fsz##_to_##itype##_scalbn(x, ROUND, shift, fpst); \
345
-}
346
-
347
-#define VFP_CONV_FIX(name, p, fsz, isz, itype) \
348
-VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
349
-VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \
350
- float_round_to_zero, _round_to_zero) \
351
-VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \
352
- get_float_rounding_mode(fpst), )
353
-
354
-#define VFP_CONV_FIX_A64(name, p, fsz, isz, itype) \
355
-VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
356
-VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \
357
- get_float_rounding_mode(fpst), )
358
-
359
-VFP_CONV_FIX(sh, d, 64, 64, int16)
360
-VFP_CONV_FIX(sl, d, 64, 64, int32)
361
-VFP_CONV_FIX_A64(sq, d, 64, 64, int64)
362
-VFP_CONV_FIX(uh, d, 64, 64, uint16)
363
-VFP_CONV_FIX(ul, d, 64, 64, uint32)
364
-VFP_CONV_FIX_A64(uq, d, 64, 64, uint64)
365
-VFP_CONV_FIX(sh, s, 32, 32, int16)
366
-VFP_CONV_FIX(sl, s, 32, 32, int32)
367
-VFP_CONV_FIX_A64(sq, s, 32, 64, int64)
368
-VFP_CONV_FIX(uh, s, 32, 32, uint16)
369
-VFP_CONV_FIX(ul, s, 32, 32, uint32)
370
-VFP_CONV_FIX_A64(uq, s, 32, 64, uint64)
371
-
372
-#undef VFP_CONV_FIX
373
-#undef VFP_CONV_FIX_FLOAT
374
-#undef VFP_CONV_FLOAT_FIX_ROUND
375
-#undef VFP_CONV_FIX_A64
376
-
377
-uint32_t HELPER(vfp_sltoh)(uint32_t x, uint32_t shift, void *fpst)
378
-{
379
- return int32_to_float16_scalbn(x, -shift, fpst);
380
-}
381
-
382
-uint32_t HELPER(vfp_ultoh)(uint32_t x, uint32_t shift, void *fpst)
383
-{
384
- return uint32_to_float16_scalbn(x, -shift, fpst);
385
-}
386
-
387
-uint32_t HELPER(vfp_sqtoh)(uint64_t x, uint32_t shift, void *fpst)
388
-{
389
- return int64_to_float16_scalbn(x, -shift, fpst);
390
-}
391
-
392
-uint32_t HELPER(vfp_uqtoh)(uint64_t x, uint32_t shift, void *fpst)
393
-{
394
- return uint64_to_float16_scalbn(x, -shift, fpst);
395
-}
396
-
397
-uint32_t HELPER(vfp_toshh)(uint32_t x, uint32_t shift, void *fpst)
398
-{
399
- if (unlikely(float16_is_any_nan(x))) {
400
- float_raise(float_flag_invalid, fpst);
401
- return 0;
402
- }
403
- return float16_to_int16_scalbn(x, get_float_rounding_mode(fpst),
404
- shift, fpst);
405
-}
406
-
407
-uint32_t HELPER(vfp_touhh)(uint32_t x, uint32_t shift, void *fpst)
408
-{
409
- if (unlikely(float16_is_any_nan(x))) {
410
- float_raise(float_flag_invalid, fpst);
411
- return 0;
412
- }
413
- return float16_to_uint16_scalbn(x, get_float_rounding_mode(fpst),
414
- shift, fpst);
415
-}
416
-
417
-uint32_t HELPER(vfp_toslh)(uint32_t x, uint32_t shift, void *fpst)
418
-{
419
- if (unlikely(float16_is_any_nan(x))) {
420
- float_raise(float_flag_invalid, fpst);
421
- return 0;
422
- }
423
- return float16_to_int32_scalbn(x, get_float_rounding_mode(fpst),
424
- shift, fpst);
425
-}
426
-
427
-uint32_t HELPER(vfp_toulh)(uint32_t x, uint32_t shift, void *fpst)
428
-{
429
- if (unlikely(float16_is_any_nan(x))) {
430
- float_raise(float_flag_invalid, fpst);
431
- return 0;
432
- }
433
- return float16_to_uint32_scalbn(x, get_float_rounding_mode(fpst),
434
- shift, fpst);
435
-}
436
-
437
-uint64_t HELPER(vfp_tosqh)(uint32_t x, uint32_t shift, void *fpst)
438
-{
439
- if (unlikely(float16_is_any_nan(x))) {
440
- float_raise(float_flag_invalid, fpst);
441
- return 0;
442
- }
443
- return float16_to_int64_scalbn(x, get_float_rounding_mode(fpst),
444
- shift, fpst);
445
-}
446
-
447
-uint64_t HELPER(vfp_touqh)(uint32_t x, uint32_t shift, void *fpst)
448
-{
449
- if (unlikely(float16_is_any_nan(x))) {
450
- float_raise(float_flag_invalid, fpst);
451
- return 0;
452
- }
453
- return float16_to_uint64_scalbn(x, get_float_rounding_mode(fpst),
454
- shift, fpst);
455
-}
456
-
457
-/* Set the current fp rounding mode and return the old one.
458
- * The argument is a softfloat float_round_ value.
459
- */
460
-uint32_t HELPER(set_rmode)(uint32_t rmode, void *fpstp)
461
-{
462
- float_status *fp_status = fpstp;
463
-
464
- uint32_t prev_rmode = get_float_rounding_mode(fp_status);
465
- set_float_rounding_mode(rmode, fp_status);
466
-
467
- return prev_rmode;
468
-}
469
-
470
-/* Set the current fp rounding mode in the standard fp status and return
471
- * the old one. This is for NEON instructions that need to change the
472
- * rounding mode but wish to use the standard FPSCR values for everything
473
- * else. Always set the rounding mode back to the correct value after
474
- * modifying it.
475
- * The argument is a softfloat float_round_ value.
476
- */
477
-uint32_t HELPER(set_neon_rmode)(uint32_t rmode, CPUARMState *env)
478
-{
479
- float_status *fp_status = &env->vfp.standard_fp_status;
480
-
481
- uint32_t prev_rmode = get_float_rounding_mode(fp_status);
482
- set_float_rounding_mode(rmode, fp_status);
483
-
484
- return prev_rmode;
485
-}
486
-
487
-/* Half precision conversions. */
488
-float32 HELPER(vfp_fcvt_f16_to_f32)(uint32_t a, void *fpstp, uint32_t ahp_mode)
489
-{
490
- /* Squash FZ16 to 0 for the duration of conversion. In this case,
491
- * it would affect flushing input denormals.
492
- */
493
- float_status *fpst = fpstp;
494
- flag save = get_flush_inputs_to_zero(fpst);
495
- set_flush_inputs_to_zero(false, fpst);
496
- float32 r = float16_to_float32(a, !ahp_mode, fpst);
497
- set_flush_inputs_to_zero(save, fpst);
498
- return r;
499
-}
500
-
501
-uint32_t HELPER(vfp_fcvt_f32_to_f16)(float32 a, void *fpstp, uint32_t ahp_mode)
502
-{
503
- /* Squash FZ16 to 0 for the duration of conversion. In this case,
504
- * it would affect flushing output denormals.
505
- */
506
- float_status *fpst = fpstp;
507
- flag save = get_flush_to_zero(fpst);
508
- set_flush_to_zero(false, fpst);
509
- float16 r = float32_to_float16(a, !ahp_mode, fpst);
510
- set_flush_to_zero(save, fpst);
511
- return r;
512
-}
513
-
514
-float64 HELPER(vfp_fcvt_f16_to_f64)(uint32_t a, void *fpstp, uint32_t ahp_mode)
515
-{
516
- /* Squash FZ16 to 0 for the duration of conversion. In this case,
517
- * it would affect flushing input denormals.
518
- */
519
- float_status *fpst = fpstp;
520
- flag save = get_flush_inputs_to_zero(fpst);
521
- set_flush_inputs_to_zero(false, fpst);
522
- float64 r = float16_to_float64(a, !ahp_mode, fpst);
523
- set_flush_inputs_to_zero(save, fpst);
524
- return r;
525
-}
526
-
527
-uint32_t HELPER(vfp_fcvt_f64_to_f16)(float64 a, void *fpstp, uint32_t ahp_mode)
528
-{
529
- /* Squash FZ16 to 0 for the duration of conversion. In this case,
530
- * it would affect flushing output denormals.
531
- */
532
- float_status *fpst = fpstp;
533
- flag save = get_flush_to_zero(fpst);
534
- set_flush_to_zero(false, fpst);
535
- float16 r = float64_to_float16(a, !ahp_mode, fpst);
536
- set_flush_to_zero(save, fpst);
537
- return r;
538
-}
539
-
540
-#define float32_two make_float32(0x40000000)
541
-#define float32_three make_float32(0x40400000)
542
-#define float32_one_point_five make_float32(0x3fc00000)
543
-
544
-float32 HELPER(recps_f32)(float32 a, float32 b, CPUARMState *env)
545
-{
546
- float_status *s = &env->vfp.standard_fp_status;
547
- if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) ||
548
- (float32_is_infinity(b) && float32_is_zero_or_denormal(a))) {
549
- if (!(float32_is_zero(a) || float32_is_zero(b))) {
550
- float_raise(float_flag_input_denormal, s);
551
- }
552
- return float32_two;
553
- }
554
- return float32_sub(float32_two, float32_mul(a, b, s), s);
555
-}
556
-
557
-float32 HELPER(rsqrts_f32)(float32 a, float32 b, CPUARMState *env)
558
-{
559
- float_status *s = &env->vfp.standard_fp_status;
560
- float32 product;
561
- if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) ||
562
- (float32_is_infinity(b) && float32_is_zero_or_denormal(a))) {
563
- if (!(float32_is_zero(a) || float32_is_zero(b))) {
564
- float_raise(float_flag_input_denormal, s);
565
- }
566
- return float32_one_point_five;
567
- }
568
- product = float32_mul(a, b, s);
569
- return float32_div(float32_sub(float32_three, product, s), float32_two, s);
570
-}
571
-
572
-/* NEON helpers. */
573
-
574
-/* Constants 256 and 512 are used in some helpers; we avoid relying on
575
- * int->float conversions at run-time. */
576
-#define float64_256 make_float64(0x4070000000000000LL)
577
-#define float64_512 make_float64(0x4080000000000000LL)
578
-#define float16_maxnorm make_float16(0x7bff)
579
-#define float32_maxnorm make_float32(0x7f7fffff)
580
-#define float64_maxnorm make_float64(0x7fefffffffffffffLL)
581
-
582
-/* Reciprocal functions
583
- *
584
- * The algorithm that must be used to calculate the estimate
585
- * is specified by the ARM ARM, see FPRecipEstimate()/RecipEstimate
586
- */
587
-
588
-/* See RecipEstimate()
589
- *
590
- * input is a 9 bit fixed point number
591
- * input range 256 .. 511 for a number from 0.5 <= x < 1.0.
592
- * result range 256 .. 511 for a number from 1.0 to 511/256.
593
- */
594
-
595
-static int recip_estimate(int input)
596
-{
597
- int a, b, r;
598
- assert(256 <= input && input < 512);
599
- a = (input * 2) + 1;
600
- b = (1 << 19) / a;
601
- r = (b + 1) >> 1;
602
- assert(256 <= r && r < 512);
603
- return r;
604
-}
605
-
606
-/*
607
- * Common wrapper to call recip_estimate
608
- *
609
- * The parameters are exponent and 64 bit fraction (without implicit
610
- * bit) where the binary point is nominally at bit 52. Returns a
611
- * float64 which can then be rounded to the appropriate size by the
612
- * callee.
613
- */
614
-
615
-static uint64_t call_recip_estimate(int *exp, int exp_off, uint64_t frac)
616
-{
617
- uint32_t scaled, estimate;
618
- uint64_t result_frac;
619
- int result_exp;
620
-
621
- /* Handle sub-normals */
622
- if (*exp == 0) {
623
- if (extract64(frac, 51, 1) == 0) {
624
- *exp = -1;
625
- frac <<= 2;
626
- } else {
627
- frac <<= 1;
628
- }
629
- }
630
-
631
- /* scaled = UInt('1':fraction<51:44>) */
632
- scaled = deposit32(1 << 8, 0, 8, extract64(frac, 44, 8));
633
- estimate = recip_estimate(scaled);
634
-
635
- result_exp = exp_off - *exp;
636
- result_frac = deposit64(0, 44, 8, estimate);
637
- if (result_exp == 0) {
638
- result_frac = deposit64(result_frac >> 1, 51, 1, 1);
639
- } else if (result_exp == -1) {
640
- result_frac = deposit64(result_frac >> 2, 50, 2, 1);
641
- result_exp = 0;
642
- }
643
-
644
- *exp = result_exp;
645
-
646
- return result_frac;
647
-}
648
-
649
-static bool round_to_inf(float_status *fpst, bool sign_bit)
650
-{
651
- switch (fpst->float_rounding_mode) {
652
- case float_round_nearest_even: /* Round to Nearest */
653
- return true;
654
- case float_round_up: /* Round to +Inf */
655
- return !sign_bit;
656
- case float_round_down: /* Round to -Inf */
657
- return sign_bit;
658
- case float_round_to_zero: /* Round to Zero */
659
- return false;
660
- }
661
-
662
- g_assert_not_reached();
663
-}
664
-
665
-uint32_t HELPER(recpe_f16)(uint32_t input, void *fpstp)
666
-{
667
- float_status *fpst = fpstp;
668
- float16 f16 = float16_squash_input_denormal(input, fpst);
669
- uint32_t f16_val = float16_val(f16);
670
- uint32_t f16_sign = float16_is_neg(f16);
671
- int f16_exp = extract32(f16_val, 10, 5);
672
- uint32_t f16_frac = extract32(f16_val, 0, 10);
673
- uint64_t f64_frac;
674
-
675
- if (float16_is_any_nan(f16)) {
676
- float16 nan = f16;
677
- if (float16_is_signaling_nan(f16, fpst)) {
678
- float_raise(float_flag_invalid, fpst);
679
- nan = float16_silence_nan(f16, fpst);
680
- }
681
- if (fpst->default_nan_mode) {
682
- nan = float16_default_nan(fpst);
683
- }
684
- return nan;
685
- } else if (float16_is_infinity(f16)) {
686
- return float16_set_sign(float16_zero, float16_is_neg(f16));
687
- } else if (float16_is_zero(f16)) {
688
- float_raise(float_flag_divbyzero, fpst);
689
- return float16_set_sign(float16_infinity, float16_is_neg(f16));
690
- } else if (float16_abs(f16) < (1 << 8)) {
691
- /* Abs(value) < 2.0^-16 */
692
- float_raise(float_flag_overflow | float_flag_inexact, fpst);
693
- if (round_to_inf(fpst, f16_sign)) {
694
- return float16_set_sign(float16_infinity, f16_sign);
695
- } else {
696
- return float16_set_sign(float16_maxnorm, f16_sign);
697
- }
698
- } else if (f16_exp >= 29 && fpst->flush_to_zero) {
699
- float_raise(float_flag_underflow, fpst);
700
- return float16_set_sign(float16_zero, float16_is_neg(f16));
701
- }
702
-
703
- f64_frac = call_recip_estimate(&f16_exp, 29,
704
- ((uint64_t) f16_frac) << (52 - 10));
705
-
706
- /* result = sign : result_exp<4:0> : fraction<51:42> */
707
- f16_val = deposit32(0, 15, 1, f16_sign);
708
- f16_val = deposit32(f16_val, 10, 5, f16_exp);
709
- f16_val = deposit32(f16_val, 0, 10, extract64(f64_frac, 52 - 10, 10));
710
- return make_float16(f16_val);
711
-}
712
-
713
-float32 HELPER(recpe_f32)(float32 input, void *fpstp)
714
-{
715
- float_status *fpst = fpstp;
716
- float32 f32 = float32_squash_input_denormal(input, fpst);
717
- uint32_t f32_val = float32_val(f32);
718
- bool f32_sign = float32_is_neg(f32);
719
- int f32_exp = extract32(f32_val, 23, 8);
720
- uint32_t f32_frac = extract32(f32_val, 0, 23);
721
- uint64_t f64_frac;
722
-
723
- if (float32_is_any_nan(f32)) {
724
- float32 nan = f32;
725
- if (float32_is_signaling_nan(f32, fpst)) {
726
- float_raise(float_flag_invalid, fpst);
727
- nan = float32_silence_nan(f32, fpst);
728
- }
729
- if (fpst->default_nan_mode) {
730
- nan = float32_default_nan(fpst);
731
- }
732
- return nan;
733
- } else if (float32_is_infinity(f32)) {
734
- return float32_set_sign(float32_zero, float32_is_neg(f32));
735
- } else if (float32_is_zero(f32)) {
736
- float_raise(float_flag_divbyzero, fpst);
737
- return float32_set_sign(float32_infinity, float32_is_neg(f32));
738
- } else if (float32_abs(f32) < (1ULL << 21)) {
739
- /* Abs(value) < 2.0^-128 */
740
- float_raise(float_flag_overflow | float_flag_inexact, fpst);
741
- if (round_to_inf(fpst, f32_sign)) {
742
- return float32_set_sign(float32_infinity, f32_sign);
743
- } else {
744
- return float32_set_sign(float32_maxnorm, f32_sign);
745
- }
746
- } else if (f32_exp >= 253 && fpst->flush_to_zero) {
747
- float_raise(float_flag_underflow, fpst);
748
- return float32_set_sign(float32_zero, float32_is_neg(f32));
749
- }
750
-
751
- f64_frac = call_recip_estimate(&f32_exp, 253,
752
- ((uint64_t) f32_frac) << (52 - 23));
753
-
754
- /* result = sign : result_exp<7:0> : fraction<51:29> */
755
- f32_val = deposit32(0, 31, 1, f32_sign);
756
- f32_val = deposit32(f32_val, 23, 8, f32_exp);
757
- f32_val = deposit32(f32_val, 0, 23, extract64(f64_frac, 52 - 23, 23));
758
- return make_float32(f32_val);
759
-}
760
-
761
-float64 HELPER(recpe_f64)(float64 input, void *fpstp)
762
-{
763
- float_status *fpst = fpstp;
764
- float64 f64 = float64_squash_input_denormal(input, fpst);
765
- uint64_t f64_val = float64_val(f64);
766
- bool f64_sign = float64_is_neg(f64);
767
- int f64_exp = extract64(f64_val, 52, 11);
768
- uint64_t f64_frac = extract64(f64_val, 0, 52);
769
-
770
- /* Deal with any special cases */
771
- if (float64_is_any_nan(f64)) {
772
- float64 nan = f64;
773
- if (float64_is_signaling_nan(f64, fpst)) {
774
- float_raise(float_flag_invalid, fpst);
775
- nan = float64_silence_nan(f64, fpst);
776
- }
777
- if (fpst->default_nan_mode) {
778
- nan = float64_default_nan(fpst);
779
- }
780
- return nan;
781
- } else if (float64_is_infinity(f64)) {
782
- return float64_set_sign(float64_zero, float64_is_neg(f64));
783
- } else if (float64_is_zero(f64)) {
784
- float_raise(float_flag_divbyzero, fpst);
785
- return float64_set_sign(float64_infinity, float64_is_neg(f64));
786
- } else if ((f64_val & ~(1ULL << 63)) < (1ULL << 50)) {
787
- /* Abs(value) < 2.0^-1024 */
788
- float_raise(float_flag_overflow | float_flag_inexact, fpst);
789
- if (round_to_inf(fpst, f64_sign)) {
790
- return float64_set_sign(float64_infinity, f64_sign);
791
- } else {
792
- return float64_set_sign(float64_maxnorm, f64_sign);
793
- }
794
- } else if (f64_exp >= 2045 && fpst->flush_to_zero) {
795
- float_raise(float_flag_underflow, fpst);
796
- return float64_set_sign(float64_zero, float64_is_neg(f64));
797
- }
798
-
799
- f64_frac = call_recip_estimate(&f64_exp, 2045, f64_frac);
800
-
801
- /* result = sign : result_exp<10:0> : fraction<51:0>; */
802
- f64_val = deposit64(0, 63, 1, f64_sign);
803
- f64_val = deposit64(f64_val, 52, 11, f64_exp);
804
- f64_val = deposit64(f64_val, 0, 52, f64_frac);
805
- return make_float64(f64_val);
806
-}
807
-
808
-/* The algorithm that must be used to calculate the estimate
809
- * is specified by the ARM ARM.
810
- */
811
-
812
-static int do_recip_sqrt_estimate(int a)
813
-{
814
- int b, estimate;
815
-
816
- assert(128 <= a && a < 512);
817
- if (a < 256) {
818
- a = a * 2 + 1;
819
- } else {
820
- a = (a >> 1) << 1;
821
- a = (a + 1) * 2;
822
- }
823
- b = 512;
824
- while (a * (b + 1) * (b + 1) < (1 << 28)) {
825
- b += 1;
826
- }
827
- estimate = (b + 1) / 2;
828
- assert(256 <= estimate && estimate < 512);
829
-
830
- return estimate;
831
-}
832
-
833
-
834
-static uint64_t recip_sqrt_estimate(int *exp , int exp_off, uint64_t frac)
835
-{
836
- int estimate;
837
- uint32_t scaled;
838
-
839
- if (*exp == 0) {
840
- while (extract64(frac, 51, 1) == 0) {
841
- frac = frac << 1;
842
- *exp -= 1;
843
- }
844
- frac = extract64(frac, 0, 51) << 1;
845
- }
846
-
847
- if (*exp & 1) {
848
- /* scaled = UInt('01':fraction<51:45>) */
849
- scaled = deposit32(1 << 7, 0, 7, extract64(frac, 45, 7));
850
- } else {
851
- /* scaled = UInt('1':fraction<51:44>) */
852
- scaled = deposit32(1 << 8, 0, 8, extract64(frac, 44, 8));
853
- }
854
- estimate = do_recip_sqrt_estimate(scaled);
855
-
856
- *exp = (exp_off - *exp) / 2;
857
- return extract64(estimate, 0, 8) << 44;
858
-}
859
-
860
-uint32_t HELPER(rsqrte_f16)(uint32_t input, void *fpstp)
861
-{
862
- float_status *s = fpstp;
863
- float16 f16 = float16_squash_input_denormal(input, s);
864
- uint16_t val = float16_val(f16);
865
- bool f16_sign = float16_is_neg(f16);
866
- int f16_exp = extract32(val, 10, 5);
867
- uint16_t f16_frac = extract32(val, 0, 10);
868
- uint64_t f64_frac;
869
-
870
- if (float16_is_any_nan(f16)) {
871
- float16 nan = f16;
872
- if (float16_is_signaling_nan(f16, s)) {
873
- float_raise(float_flag_invalid, s);
874
- nan = float16_silence_nan(f16, s);
875
- }
876
- if (s->default_nan_mode) {
877
- nan = float16_default_nan(s);
878
- }
879
- return nan;
880
- } else if (float16_is_zero(f16)) {
881
- float_raise(float_flag_divbyzero, s);
882
- return float16_set_sign(float16_infinity, f16_sign);
883
- } else if (f16_sign) {
884
- float_raise(float_flag_invalid, s);
885
- return float16_default_nan(s);
886
- } else if (float16_is_infinity(f16)) {
887
- return float16_zero;
888
- }
889
-
890
- /* Scale and normalize to a double-precision value between 0.25 and 1.0,
891
- * preserving the parity of the exponent. */
892
-
893
- f64_frac = ((uint64_t) f16_frac) << (52 - 10);
894
-
895
- f64_frac = recip_sqrt_estimate(&f16_exp, 44, f64_frac);
896
-
897
- /* result = sign : result_exp<4:0> : estimate<7:0> : Zeros(2) */
898
- val = deposit32(0, 15, 1, f16_sign);
899
- val = deposit32(val, 10, 5, f16_exp);
900
- val = deposit32(val, 2, 8, extract64(f64_frac, 52 - 8, 8));
901
- return make_float16(val);
902
-}
903
-
904
-float32 HELPER(rsqrte_f32)(float32 input, void *fpstp)
905
-{
906
- float_status *s = fpstp;
907
- float32 f32 = float32_squash_input_denormal(input, s);
908
- uint32_t val = float32_val(f32);
909
- uint32_t f32_sign = float32_is_neg(f32);
910
- int f32_exp = extract32(val, 23, 8);
911
- uint32_t f32_frac = extract32(val, 0, 23);
912
- uint64_t f64_frac;
913
-
914
- if (float32_is_any_nan(f32)) {
915
- float32 nan = f32;
916
- if (float32_is_signaling_nan(f32, s)) {
917
- float_raise(float_flag_invalid, s);
918
- nan = float32_silence_nan(f32, s);
919
- }
920
- if (s->default_nan_mode) {
921
- nan = float32_default_nan(s);
922
- }
923
- return nan;
924
- } else if (float32_is_zero(f32)) {
925
- float_raise(float_flag_divbyzero, s);
926
- return float32_set_sign(float32_infinity, float32_is_neg(f32));
927
- } else if (float32_is_neg(f32)) {
928
- float_raise(float_flag_invalid, s);
929
- return float32_default_nan(s);
930
- } else if (float32_is_infinity(f32)) {
931
- return float32_zero;
932
- }
933
-
934
- /* Scale and normalize to a double-precision value between 0.25 and 1.0,
935
- * preserving the parity of the exponent. */
936
-
937
- f64_frac = ((uint64_t) f32_frac) << 29;
938
-
939
- f64_frac = recip_sqrt_estimate(&f32_exp, 380, f64_frac);
940
-
941
- /* result = sign : result_exp<4:0> : estimate<7:0> : Zeros(15) */
942
- val = deposit32(0, 31, 1, f32_sign);
943
- val = deposit32(val, 23, 8, f32_exp);
944
- val = deposit32(val, 15, 8, extract64(f64_frac, 52 - 8, 8));
945
- return make_float32(val);
946
-}
947
-
948
-float64 HELPER(rsqrte_f64)(float64 input, void *fpstp)
949
-{
950
- float_status *s = fpstp;
951
- float64 f64 = float64_squash_input_denormal(input, s);
952
- uint64_t val = float64_val(f64);
953
- bool f64_sign = float64_is_neg(f64);
954
- int f64_exp = extract64(val, 52, 11);
955
- uint64_t f64_frac = extract64(val, 0, 52);
956
-
957
- if (float64_is_any_nan(f64)) {
958
- float64 nan = f64;
959
- if (float64_is_signaling_nan(f64, s)) {
960
- float_raise(float_flag_invalid, s);
961
- nan = float64_silence_nan(f64, s);
962
- }
963
- if (s->default_nan_mode) {
964
- nan = float64_default_nan(s);
965
- }
966
- return nan;
967
- } else if (float64_is_zero(f64)) {
968
- float_raise(float_flag_divbyzero, s);
969
- return float64_set_sign(float64_infinity, float64_is_neg(f64));
970
- } else if (float64_is_neg(f64)) {
971
- float_raise(float_flag_invalid, s);
972
- return float64_default_nan(s);
973
- } else if (float64_is_infinity(f64)) {
974
- return float64_zero;
975
- }
976
-
977
- f64_frac = recip_sqrt_estimate(&f64_exp, 3068, f64_frac);
978
-
979
- /* result = sign : result_exp<4:0> : estimate<7:0> : Zeros(44) */
980
- val = deposit64(0, 61, 1, f64_sign);
981
- val = deposit64(val, 52, 11, f64_exp);
982
- val = deposit64(val, 44, 8, extract64(f64_frac, 52 - 8, 8));
983
- return make_float64(val);
984
-}
985
-
986
-uint32_t HELPER(recpe_u32)(uint32_t a, void *fpstp)
987
-{
988
- /* float_status *s = fpstp; */
989
- int input, estimate;
990
-
991
- if ((a & 0x80000000) == 0) {
992
- return 0xffffffff;
993
- }
994
-
995
- input = extract32(a, 23, 9);
996
- estimate = recip_estimate(input);
997
-
998
- return deposit32(0, (32 - 9), 9, estimate);
999
-}
1000
-
1001
-uint32_t HELPER(rsqrte_u32)(uint32_t a, void *fpstp)
1002
-{
1003
- int estimate;
1004
-
1005
- if ((a & 0xc0000000) == 0) {
1006
- return 0xffffffff;
1007
- }
1008
-
1009
- estimate = do_recip_sqrt_estimate(extract32(a, 23, 9));
1010
-
1011
- return deposit32(0, 23, 9, estimate);
1012
-}
1013
-
1014
-/* VFPv4 fused multiply-accumulate */
1015
-float32 VFP_HELPER(muladd, s)(float32 a, float32 b, float32 c, void *fpstp)
1016
-{
1017
- float_status *fpst = fpstp;
1018
- return float32_muladd(a, b, c, 0, fpst);
1019
-}
1020
-
1021
-float64 VFP_HELPER(muladd, d)(float64 a, float64 b, float64 c, void *fpstp)
1022
-{
1023
- float_status *fpst = fpstp;
1024
- return float64_muladd(a, b, c, 0, fpst);
1025
-}
1026
-
1027
-/* ARMv8 round to integral */
1028
-float32 HELPER(rints_exact)(float32 x, void *fp_status)
1029
-{
1030
- return float32_round_to_int(x, fp_status);
1031
-}
1032
-
1033
-float64 HELPER(rintd_exact)(float64 x, void *fp_status)
1034
-{
1035
- return float64_round_to_int(x, fp_status);
1036
-}
1037
-
1038
-float32 HELPER(rints)(float32 x, void *fp_status)
1039
-{
1040
- int old_flags = get_float_exception_flags(fp_status), new_flags;
1041
- float32 ret;
1042
-
1043
- ret = float32_round_to_int(x, fp_status);
1044
-
1045
- /* Suppress any inexact exceptions the conversion produced */
1046
- if (!(old_flags & float_flag_inexact)) {
1047
- new_flags = get_float_exception_flags(fp_status);
1048
- set_float_exception_flags(new_flags & ~float_flag_inexact, fp_status);
1049
- }
1050
-
1051
- return ret;
1052
-}
1053
-
1054
-float64 HELPER(rintd)(float64 x, void *fp_status)
1055
-{
1056
- int old_flags = get_float_exception_flags(fp_status), new_flags;
1057
- float64 ret;
1058
-
1059
- ret = float64_round_to_int(x, fp_status);
1060
-
1061
- new_flags = get_float_exception_flags(fp_status);
1062
-
1063
- /* Suppress any inexact exceptions the conversion produced */
1064
- if (!(old_flags & float_flag_inexact)) {
1065
- new_flags = get_float_exception_flags(fp_status);
1066
- set_float_exception_flags(new_flags & ~float_flag_inexact, fp_status);
1067
- }
1068
-
1069
- return ret;
1070
-}
1071
-
1072
-/* Convert ARM rounding mode to softfloat */
1073
-int arm_rmode_to_sf(int rmode)
1074
-{
1075
- switch (rmode) {
1076
- case FPROUNDING_TIEAWAY:
1077
- rmode = float_round_ties_away;
1078
- break;
1079
- case FPROUNDING_ODD:
1080
- /* FIXME: add support for TIEAWAY and ODD */
1081
- qemu_log_mask(LOG_UNIMP, "arm: unimplemented rounding mode: %d\n",
1082
- rmode);
1083
- /* fall through for now */
1084
- case FPROUNDING_TIEEVEN:
1085
- default:
1086
- rmode = float_round_nearest_even;
1087
- break;
1088
- case FPROUNDING_POSINF:
1089
- rmode = float_round_up;
1090
- break;
1091
- case FPROUNDING_NEGINF:
1092
- rmode = float_round_down;
1093
- break;
1094
- case FPROUNDING_ZERO:
1095
- rmode = float_round_to_zero;
1096
- break;
1097
- }
1098
- return rmode;
1099
-}
1100
-
1101
/* CRC helpers.
1102
* The upper bytes of val (above the number specified by 'bytes') must have
1103
* been zeroed out by the caller.
1104
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
1105
new file mode 100644
31
new file mode 100644
1106
index XXXXXXX..XXXXXXX
32
index XXXXXXX..XXXXXXX
1107
--- /dev/null
33
--- /dev/null
1108
+++ b/target/arm/vfp_helper.c
34
+++ b/include/hw/arm/xlnx-versal.h
1109
@@ -XXX,XX +XXX,XX @@
35
@@ -XXX,XX +XXX,XX @@
1110
+/*
36
+/*
1111
+ * ARM VFP floating-point operations
37
+ * Model of the Xilinx Versal
1112
+ *
38
+ *
1113
+ * Copyright (c) 2003 Fabrice Bellard
39
+ * Copyright (c) 2018 Xilinx Inc.
40
+ * Written by Edgar E. Iglesias
1114
+ *
41
+ *
1115
+ * This library is free software; you can redistribute it and/or
42
+ * This program is free software; you can redistribute it and/or modify
1116
+ * modify it under the terms of the GNU Lesser General Public
43
+ * it under the terms of the GNU General Public License version 2 or
1117
+ * License as published by the Free Software Foundation; either
44
+ * (at your option) any later version.
1118
+ * version 2.1 of the License, or (at your option) any later version.
45
+ */
46
+
47
+#ifndef XLNX_VERSAL_H
48
+#define XLNX_VERSAL_H
49
+
50
+#include "hw/sysbus.h"
51
+#include "hw/arm/arm.h"
52
+#include "hw/intc/arm_gicv3.h"
53
+
54
+#define TYPE_XLNX_VERSAL "xlnx-versal"
55
+#define XLNX_VERSAL(obj) OBJECT_CHECK(Versal, (obj), TYPE_XLNX_VERSAL)
56
+
57
+#define XLNX_VERSAL_NR_ACPUS 2
58
+#define XLNX_VERSAL_NR_UARTS 2
59
+#define XLNX_VERSAL_NR_GEMS 2
60
+#define XLNX_VERSAL_NR_IRQS 256
61
+
62
+typedef struct Versal {
63
+ /*< private >*/
64
+ SysBusDevice parent_obj;
65
+
66
+ /*< public >*/
67
+ struct {
68
+ struct {
69
+ MemoryRegion mr;
70
+ ARMCPU *cpu[XLNX_VERSAL_NR_ACPUS];
71
+ GICv3State gic;
72
+ } apu;
73
+ } fpd;
74
+
75
+ MemoryRegion mr_ps;
76
+
77
+ struct {
78
+ /* 4 ranges to access DDR. */
79
+ MemoryRegion mr_ddr_ranges[4];
80
+ } noc;
81
+
82
+ struct {
83
+ MemoryRegion mr_ocm;
84
+
85
+ struct {
86
+ SysBusDevice *uart[XLNX_VERSAL_NR_UARTS];
87
+ SysBusDevice *gem[XLNX_VERSAL_NR_GEMS];
88
+ } iou;
89
+ } lpd;
90
+
91
+ struct {
92
+ MemoryRegion *mr_ddr;
93
+ uint32_t psci_conduit;
94
+ } cfg;
95
+} Versal;
96
+
97
+/* Memory-map and IRQ definitions. Copied a subset from
98
+ * auto-generated files. */
99
+
100
+#define VERSAL_GIC_MAINT_IRQ 9
101
+#define VERSAL_TIMER_VIRT_IRQ 11
102
+#define VERSAL_TIMER_S_EL1_IRQ 13
103
+#define VERSAL_TIMER_NS_EL1_IRQ 14
104
+#define VERSAL_TIMER_NS_EL2_IRQ 10
105
+
106
+#define VERSAL_UART0_IRQ_0 18
107
+#define VERSAL_UART1_IRQ_0 19
108
+#define VERSAL_GEM0_IRQ_0 56
109
+#define VERSAL_GEM0_WAKE_IRQ_0 57
110
+#define VERSAL_GEM1_IRQ_0 58
111
+#define VERSAL_GEM1_WAKE_IRQ_0 59
112
+
113
+/* Architecturally eserved IRQs suitable for virtualization. */
114
+#define VERSAL_RSVD_HIGH_IRQ_FIRST 160
115
+#define VERSAL_RSVD_HIGH_IRQ_LAST 255
116
+
117
+#define MM_TOP_RSVD 0xa0000000U
118
+#define MM_TOP_RSVD_SIZE 0x4000000
119
+#define MM_GIC_APU_DIST_MAIN 0xf9000000U
120
+#define MM_GIC_APU_DIST_MAIN_SIZE 0x10000
121
+#define MM_GIC_APU_REDIST_0 0xf9080000U
122
+#define MM_GIC_APU_REDIST_0_SIZE 0x80000
123
+
124
+#define MM_UART0 0xff000000U
125
+#define MM_UART0_SIZE 0x10000
126
+#define MM_UART1 0xff010000U
127
+#define MM_UART1_SIZE 0x10000
128
+
129
+#define MM_GEM0 0xff0c0000U
130
+#define MM_GEM0_SIZE 0x10000
131
+#define MM_GEM1 0xff0d0000U
132
+#define MM_GEM1_SIZE 0x10000
133
+
134
+#define MM_OCM 0xfffc0000U
135
+#define MM_OCM_SIZE 0x40000
136
+
137
+#define MM_TOP_DDR 0x0
138
+#define MM_TOP_DDR_SIZE 0x80000000U
139
+#define MM_TOP_DDR_2 0x800000000ULL
140
+#define MM_TOP_DDR_2_SIZE 0x800000000ULL
141
+#define MM_TOP_DDR_3 0xc000000000ULL
142
+#define MM_TOP_DDR_3_SIZE 0x4000000000ULL
143
+#define MM_TOP_DDR_4 0x10000000000ULL
144
+#define MM_TOP_DDR_4_SIZE 0xb780000000ULL
145
+
146
+#define MM_PSM_START 0xffc80000U
147
+#define MM_PSM_END 0xffcf0000U
148
+
149
+#define MM_CRL 0xff5e0000U
150
+#define MM_CRL_SIZE 0x300000
151
+#define MM_IOU_SCNTR 0xff130000U
152
+#define MM_IOU_SCNTR_SIZE 0x10000
153
+#define MM_IOU_SCNTRS 0xff140000U
154
+#define MM_IOU_SCNTRS_SIZE 0x10000
155
+#define MM_FPD_CRF 0xfd1a0000U
156
+#define MM_FPD_CRF_SIZE 0x140000
157
+#endif
158
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
159
new file mode 100644
160
index XXXXXXX..XXXXXXX
161
--- /dev/null
162
+++ b/hw/arm/xlnx-versal.c
163
@@ -XXX,XX +XXX,XX @@
164
+/*
165
+ * Xilinx Versal SoC model.
1119
+ *
166
+ *
1120
+ * This library is distributed in the hope that it will be useful,
167
+ * Copyright (c) 2018 Xilinx Inc.
1121
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
168
+ * Written by Edgar E. Iglesias
1122
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1123
+ * Lesser General Public License for more details.
1124
+ *
169
+ *
1125
+ * You should have received a copy of the GNU Lesser General Public
170
+ * This program is free software; you can redistribute it and/or modify
1126
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
171
+ * it under the terms of the GNU General Public License version 2 or
172
+ * (at your option) any later version.
1127
+ */
173
+ */
1128
+
174
+
1129
+#include "qemu/osdep.h"
175
+#include "qemu/osdep.h"
176
+#include "qapi/error.h"
177
+#include "qemu-common.h"
1130
+#include "qemu/log.h"
178
+#include "qemu/log.h"
1131
+#include "cpu.h"
179
+#include "hw/sysbus.h"
1132
+#include "exec/helper-proto.h"
180
+#include "net/net.h"
1133
+#include "fpu/softfloat.h"
181
+#include "sysemu/sysemu.h"
1134
+#include "internals.h"
182
+#include "sysemu/kvm.h"
1135
+
183
+#include "hw/arm/arm.h"
1136
+
184
+#include "kvm_arm.h"
1137
+/* VFP support. We follow the convention used for VFP instructions:
185
+#include "hw/misc/unimp.h"
1138
+ Single precision routines have a "s" suffix, double precision a
186
+#include "hw/intc/arm_gicv3_common.h"
1139
+ "d" suffix. */
187
+#include "hw/arm/xlnx-versal.h"
1140
+
188
+
1141
+/* Convert host exception flags to vfp form. */
189
+#define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
1142
+static inline int vfp_exceptbits_from_host(int host_bits)
190
+#define GEM_REVISION 0x40070106
1143
+{
191
+
1144
+ int target_bits = 0;
192
+static void versal_create_apu_cpus(Versal *s)
1145
+
1146
+ if (host_bits & float_flag_invalid)
1147
+ target_bits |= 1;
1148
+ if (host_bits & float_flag_divbyzero)
1149
+ target_bits |= 2;
1150
+ if (host_bits & float_flag_overflow)
1151
+ target_bits |= 4;
1152
+ if (host_bits & (float_flag_underflow | float_flag_output_denormal))
1153
+ target_bits |= 8;
1154
+ if (host_bits & float_flag_inexact)
1155
+ target_bits |= 0x10;
1156
+ if (host_bits & float_flag_input_denormal)
1157
+ target_bits |= 0x80;
1158
+ return target_bits;
1159
+}
1160
+
1161
+uint32_t HELPER(vfp_get_fpscr)(CPUARMState *env)
1162
+{
1163
+ uint32_t i, fpscr;
1164
+
1165
+ fpscr = env->vfp.xregs[ARM_VFP_FPSCR]
1166
+ | (env->vfp.vec_len << 16)
1167
+ | (env->vfp.vec_stride << 20);
1168
+
1169
+ i = get_float_exception_flags(&env->vfp.fp_status);
1170
+ i |= get_float_exception_flags(&env->vfp.standard_fp_status);
1171
+ /* FZ16 does not generate an input denormal exception. */
1172
+ i |= (get_float_exception_flags(&env->vfp.fp_status_f16)
1173
+ & ~float_flag_input_denormal);
1174
+ fpscr |= vfp_exceptbits_from_host(i);
1175
+
1176
+ i = env->vfp.qc[0] | env->vfp.qc[1] | env->vfp.qc[2] | env->vfp.qc[3];
1177
+ fpscr |= i ? FPCR_QC : 0;
1178
+
1179
+ return fpscr;
1180
+}
1181
+
1182
+uint32_t vfp_get_fpscr(CPUARMState *env)
1183
+{
1184
+ return HELPER(vfp_get_fpscr)(env);
1185
+}
1186
+
1187
+/* Convert vfp exception flags to target form. */
1188
+static inline int vfp_exceptbits_to_host(int target_bits)
1189
+{
1190
+ int host_bits = 0;
1191
+
1192
+ if (target_bits & 1)
1193
+ host_bits |= float_flag_invalid;
1194
+ if (target_bits & 2)
1195
+ host_bits |= float_flag_divbyzero;
1196
+ if (target_bits & 4)
1197
+ host_bits |= float_flag_overflow;
1198
+ if (target_bits & 8)
1199
+ host_bits |= float_flag_underflow;
1200
+ if (target_bits & 0x10)
1201
+ host_bits |= float_flag_inexact;
1202
+ if (target_bits & 0x80)
1203
+ host_bits |= float_flag_input_denormal;
1204
+ return host_bits;
1205
+}
1206
+
1207
+void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
1208
+{
193
+{
1209
+ int i;
194
+ int i;
1210
+ uint32_t changed = env->vfp.xregs[ARM_VFP_FPSCR];
195
+
1211
+
196
+ for (i = 0; i < ARRAY_SIZE(s->fpd.apu.cpu); i++) {
1212
+ /* When ARMv8.2-FP16 is not supported, FZ16 is RES0. */
197
+ Object *obj;
1213
+ if (!cpu_isar_feature(aa64_fp16, arm_env_get_cpu(env))) {
198
+ char *name;
1214
+ val &= ~FPCR_FZ16;
199
+
1215
+ }
200
+ obj = object_new(XLNX_VERSAL_ACPU_TYPE);
1216
+
201
+ if (!obj) {
1217
+ /*
202
+ /* Secondary CPUs start in PSCI powered-down state */
1218
+ * We don't implement trapped exception handling, so the
203
+ error_report("Unable to create apu.cpu[%d] of type %s",
1219
+ * trap enable bits, IDE|IXE|UFE|OFE|DZE|IOE are all RAZ/WI (not RES0!)
204
+ i, XLNX_VERSAL_ACPU_TYPE);
1220
+ *
205
+ exit(EXIT_FAILURE);
1221
+ * If we exclude the exception flags, IOC|DZC|OFC|UFC|IXC|IDC
1222
+ * (which are stored in fp_status), and the other RES0 bits
1223
+ * in between, then we clear all of the low 16 bits.
1224
+ */
1225
+ env->vfp.xregs[ARM_VFP_FPSCR] = val & 0xf7c80000;
1226
+ env->vfp.vec_len = (val >> 16) & 7;
1227
+ env->vfp.vec_stride = (val >> 20) & 3;
1228
+
1229
+ /*
1230
+ * The bit we set within fpscr_q is arbitrary; the register as a
1231
+ * whole being zero/non-zero is what counts.
1232
+ */
1233
+ env->vfp.qc[0] = val & FPCR_QC;
1234
+ env->vfp.qc[1] = 0;
1235
+ env->vfp.qc[2] = 0;
1236
+ env->vfp.qc[3] = 0;
1237
+
1238
+ changed ^= val;
1239
+ if (changed & (3 << 22)) {
1240
+ i = (val >> 22) & 3;
1241
+ switch (i) {
1242
+ case FPROUNDING_TIEEVEN:
1243
+ i = float_round_nearest_even;
1244
+ break;
1245
+ case FPROUNDING_POSINF:
1246
+ i = float_round_up;
1247
+ break;
1248
+ case FPROUNDING_NEGINF:
1249
+ i = float_round_down;
1250
+ break;
1251
+ case FPROUNDING_ZERO:
1252
+ i = float_round_to_zero;
1253
+ break;
1254
+ }
206
+ }
1255
+ set_float_rounding_mode(i, &env->vfp.fp_status);
207
+
1256
+ set_float_rounding_mode(i, &env->vfp.fp_status_f16);
208
+ name = g_strdup_printf("apu-cpu[%d]", i);
1257
+ }
209
+ object_property_add_child(OBJECT(s), name, obj, &error_fatal);
1258
+ if (changed & FPCR_FZ16) {
210
+ g_free(name);
1259
+ bool ftz_enabled = val & FPCR_FZ16;
211
+
1260
+ set_flush_to_zero(ftz_enabled, &env->vfp.fp_status_f16);
212
+ object_property_set_int(obj, s->cfg.psci_conduit,
1261
+ set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status_f16);
213
+ "psci-conduit", &error_abort);
1262
+ }
214
+ if (i) {
1263
+ if (changed & FPCR_FZ) {
215
+ object_property_set_bool(obj, true,
1264
+ bool ftz_enabled = val & FPCR_FZ;
216
+ "start-powered-off", &error_abort);
1265
+ set_flush_to_zero(ftz_enabled, &env->vfp.fp_status);
217
+ }
1266
+ set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status);
218
+
1267
+ }
219
+ object_property_set_int(obj, ARRAY_SIZE(s->fpd.apu.cpu),
1268
+ if (changed & FPCR_DN) {
220
+ "core-count", &error_abort);
1269
+ bool dnan_enabled = val & FPCR_DN;
221
+ object_property_set_link(obj, OBJECT(&s->fpd.apu.mr), "memory",
1270
+ set_default_nan_mode(dnan_enabled, &env->vfp.fp_status);
222
+ &error_abort);
1271
+ set_default_nan_mode(dnan_enabled, &env->vfp.fp_status_f16);
223
+ object_property_set_bool(obj, true, "realized", &error_fatal);
1272
+ }
224
+ s->fpd.apu.cpu[i] = ARM_CPU(obj);
1273
+
225
+ }
1274
+ /* The exception flags are ORed together when we read fpscr so we
226
+}
1275
+ * only need to preserve the current state in one of our
227
+
1276
+ * float_status values.
228
+static void versal_create_apu_gic(Versal *s, qemu_irq *pic)
1277
+ */
229
+{
1278
+ i = vfp_exceptbits_to_host(val);
230
+ static const uint64_t addrs[] = {
1279
+ set_float_exception_flags(i, &env->vfp.fp_status);
231
+ MM_GIC_APU_DIST_MAIN,
1280
+ set_float_exception_flags(0, &env->vfp.fp_status_f16);
232
+ MM_GIC_APU_REDIST_0
1281
+ set_float_exception_flags(0, &env->vfp.standard_fp_status);
233
+ };
1282
+}
234
+ SysBusDevice *gicbusdev;
1283
+
235
+ DeviceState *gicdev;
1284
+void vfp_set_fpscr(CPUARMState *env, uint32_t val)
236
+ int nr_apu_cpus = ARRAY_SIZE(s->fpd.apu.cpu);
1285
+{
237
+ int i;
1286
+ HELPER(vfp_set_fpscr)(env, val);
238
+
1287
+}
239
+ sysbus_init_child_obj(OBJECT(s), "apu-gic",
1288
+
240
+ &s->fpd.apu.gic, sizeof(s->fpd.apu.gic),
1289
+#define VFP_HELPER(name, p) HELPER(glue(glue(vfp_,name),p))
241
+ gicv3_class_name());
1290
+
242
+ gicbusdev = SYS_BUS_DEVICE(&s->fpd.apu.gic);
1291
+#define VFP_BINOP(name) \
243
+ gicdev = DEVICE(&s->fpd.apu.gic);
1292
+float32 VFP_HELPER(name, s)(float32 a, float32 b, void *fpstp) \
244
+ qdev_prop_set_uint32(gicdev, "revision", 3);
1293
+{ \
245
+ qdev_prop_set_uint32(gicdev, "num-cpu", 2);
1294
+ float_status *fpst = fpstp; \
246
+ qdev_prop_set_uint32(gicdev, "num-irq", XLNX_VERSAL_NR_IRQS + 32);
1295
+ return float32_ ## name(a, b, fpst); \
247
+ qdev_prop_set_uint32(gicdev, "len-redist-region-count", 1);
1296
+} \
248
+ qdev_prop_set_uint32(gicdev, "redist-region-count[0]", 2);
1297
+float64 VFP_HELPER(name, d)(float64 a, float64 b, void *fpstp) \
249
+ qdev_prop_set_bit(gicdev, "has-security-extensions", true);
1298
+{ \
250
+
1299
+ float_status *fpst = fpstp; \
251
+ object_property_set_bool(OBJECT(&s->fpd.apu.gic), true, "realized",
1300
+ return float64_ ## name(a, b, fpst); \
252
+ &error_fatal);
1301
+}
253
+
1302
+VFP_BINOP(add)
254
+ for (i = 0; i < ARRAY_SIZE(addrs); i++) {
1303
+VFP_BINOP(sub)
255
+ MemoryRegion *mr;
1304
+VFP_BINOP(mul)
256
+
1305
+VFP_BINOP(div)
257
+ mr = sysbus_mmio_get_region(gicbusdev, i);
1306
+VFP_BINOP(min)
258
+ memory_region_add_subregion(&s->fpd.apu.mr, addrs[i], mr);
1307
+VFP_BINOP(max)
259
+ }
1308
+VFP_BINOP(minnum)
260
+
1309
+VFP_BINOP(maxnum)
261
+ for (i = 0; i < nr_apu_cpus; i++) {
1310
+#undef VFP_BINOP
262
+ DeviceState *cpudev = DEVICE(s->fpd.apu.cpu[i]);
1311
+
263
+ int ppibase = XLNX_VERSAL_NR_IRQS + i * GIC_INTERNAL + GIC_NR_SGIS;
1312
+float32 VFP_HELPER(neg, s)(float32 a)
264
+ qemu_irq maint_irq;
1313
+{
265
+ int ti;
1314
+ return float32_chs(a);
266
+ /* Mapping from the output timer irq lines from the CPU to the
1315
+}
267
+ * GIC PPI inputs.
1316
+
268
+ */
1317
+float64 VFP_HELPER(neg, d)(float64 a)
269
+ const int timer_irq[] = {
1318
+{
270
+ [GTIMER_PHYS] = VERSAL_TIMER_NS_EL1_IRQ,
1319
+ return float64_chs(a);
271
+ [GTIMER_VIRT] = VERSAL_TIMER_VIRT_IRQ,
1320
+}
272
+ [GTIMER_HYP] = VERSAL_TIMER_NS_EL2_IRQ,
1321
+
273
+ [GTIMER_SEC] = VERSAL_TIMER_S_EL1_IRQ,
1322
+float32 VFP_HELPER(abs, s)(float32 a)
274
+ };
1323
+{
275
+
1324
+ return float32_abs(a);
276
+ for (ti = 0; ti < ARRAY_SIZE(timer_irq); ti++) {
1325
+}
277
+ qdev_connect_gpio_out(cpudev, ti,
1326
+
278
+ qdev_get_gpio_in(gicdev,
1327
+float64 VFP_HELPER(abs, d)(float64 a)
279
+ ppibase + timer_irq[ti]));
1328
+{
280
+ }
1329
+ return float64_abs(a);
281
+ maint_irq = qdev_get_gpio_in(gicdev,
1330
+}
282
+ ppibase + VERSAL_GIC_MAINT_IRQ);
1331
+
283
+ qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt",
1332
+float32 VFP_HELPER(sqrt, s)(float32 a, CPUARMState *env)
284
+ 0, maint_irq);
1333
+{
285
+ sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
1334
+ return float32_sqrt(a, &env->vfp.fp_status);
286
+ sysbus_connect_irq(gicbusdev, i + nr_apu_cpus,
1335
+}
287
+ qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
1336
+
288
+ sysbus_connect_irq(gicbusdev, i + 2 * nr_apu_cpus,
1337
+float64 VFP_HELPER(sqrt, d)(float64 a, CPUARMState *env)
289
+ qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
1338
+{
290
+ sysbus_connect_irq(gicbusdev, i + 3 * nr_apu_cpus,
1339
+ return float64_sqrt(a, &env->vfp.fp_status);
291
+ qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
1340
+}
292
+ }
1341
+
293
+
1342
+static void softfloat_to_vfp_compare(CPUARMState *env, int cmp)
294
+ for (i = 0; i < XLNX_VERSAL_NR_IRQS; i++) {
1343
+{
295
+ pic[i] = qdev_get_gpio_in(gicdev, i);
1344
+ uint32_t flags;
296
+ }
1345
+ switch (cmp) {
297
+}
1346
+ case float_relation_equal:
298
+
1347
+ flags = 0x6;
299
+static void versal_create_uarts(Versal *s, qemu_irq *pic)
1348
+ break;
300
+{
1349
+ case float_relation_less:
301
+ int i;
1350
+ flags = 0x8;
302
+
1351
+ break;
303
+ for (i = 0; i < ARRAY_SIZE(s->lpd.iou.uart); i++) {
1352
+ case float_relation_greater:
304
+ static const int irqs[] = { VERSAL_UART0_IRQ_0, VERSAL_UART1_IRQ_0};
1353
+ flags = 0x2;
305
+ static const uint64_t addrs[] = { MM_UART0, MM_UART1 };
1354
+ break;
306
+ char *name = g_strdup_printf("uart%d", i);
1355
+ case float_relation_unordered:
307
+ DeviceState *dev;
1356
+ flags = 0x3;
308
+ MemoryRegion *mr;
1357
+ break;
309
+
1358
+ default:
310
+ dev = qdev_create(NULL, "pl011");
1359
+ g_assert_not_reached();
311
+ s->lpd.iou.uart[i] = SYS_BUS_DEVICE(dev);
1360
+ }
312
+ qdev_prop_set_chr(dev, "chardev", serial_hd(i));
1361
+ env->vfp.xregs[ARM_VFP_FPSCR] =
313
+ object_property_add_child(OBJECT(s), name, OBJECT(dev), &error_fatal);
1362
+ deposit32(env->vfp.xregs[ARM_VFP_FPSCR], 28, 4, flags);
314
+ qdev_init_nofail(dev);
1363
+}
315
+
1364
+
316
+ mr = sysbus_mmio_get_region(s->lpd.iou.uart[i], 0);
1365
+/* XXX: check quiet/signaling case */
317
+ memory_region_add_subregion(&s->mr_ps, addrs[i], mr);
1366
+#define DO_VFP_cmp(p, type) \
318
+
1367
+void VFP_HELPER(cmp, p)(type a, type b, CPUARMState *env) \
319
+ sysbus_connect_irq(s->lpd.iou.uart[i], 0, pic[irqs[i]]);
1368
+{ \
320
+ g_free(name);
1369
+ softfloat_to_vfp_compare(env, \
321
+ }
1370
+ type ## _compare_quiet(a, b, &env->vfp.fp_status)); \
322
+}
1371
+} \
323
+
1372
+void VFP_HELPER(cmpe, p)(type a, type b, CPUARMState *env) \
324
+static void versal_create_gems(Versal *s, qemu_irq *pic)
1373
+{ \
325
+{
1374
+ softfloat_to_vfp_compare(env, \
326
+ int i;
1375
+ type ## _compare(a, b, &env->vfp.fp_status)); \
327
+
1376
+}
328
+ for (i = 0; i < ARRAY_SIZE(s->lpd.iou.gem); i++) {
1377
+DO_VFP_cmp(s, float32)
329
+ static const int irqs[] = { VERSAL_GEM0_IRQ_0, VERSAL_GEM1_IRQ_0};
1378
+DO_VFP_cmp(d, float64)
330
+ static const uint64_t addrs[] = { MM_GEM0, MM_GEM1 };
1379
+#undef DO_VFP_cmp
331
+ char *name = g_strdup_printf("gem%d", i);
1380
+
332
+ NICInfo *nd = &nd_table[i];
1381
+/* Integer to float and float to integer conversions */
333
+ DeviceState *dev;
1382
+
334
+ MemoryRegion *mr;
1383
+#define CONV_ITOF(name, ftype, fsz, sign) \
335
+
1384
+ftype HELPER(name)(uint32_t x, void *fpstp) \
336
+ dev = qdev_create(NULL, "cadence_gem");
1385
+{ \
337
+ s->lpd.iou.gem[i] = SYS_BUS_DEVICE(dev);
1386
+ float_status *fpst = fpstp; \
338
+ object_property_add_child(OBJECT(s), name, OBJECT(dev), &error_fatal);
1387
+ return sign##int32_to_##float##fsz((sign##int32_t)x, fpst); \
339
+ if (nd->used) {
1388
+}
340
+ qemu_check_nic_model(nd, "cadence_gem");
1389
+
341
+ qdev_set_nic_properties(dev, nd);
1390
+#define CONV_FTOI(name, ftype, fsz, sign, round) \
342
+ }
1391
+sign##int32_t HELPER(name)(ftype x, void *fpstp) \
343
+ object_property_set_int(OBJECT(s->lpd.iou.gem[i]),
1392
+{ \
344
+ 2, "num-priority-queues",
1393
+ float_status *fpst = fpstp; \
345
+ &error_abort);
1394
+ if (float##fsz##_is_any_nan(x)) { \
346
+ object_property_set_link(OBJECT(s->lpd.iou.gem[i]),
1395
+ float_raise(float_flag_invalid, fpst); \
347
+ OBJECT(&s->mr_ps), "dma",
1396
+ return 0; \
348
+ &error_abort);
1397
+ } \
349
+ qdev_init_nofail(dev);
1398
+ return float##fsz##_to_##sign##int32##round(x, fpst); \
350
+
1399
+}
351
+ mr = sysbus_mmio_get_region(s->lpd.iou.gem[i], 0);
1400
+
352
+ memory_region_add_subregion(&s->mr_ps, addrs[i], mr);
1401
+#define FLOAT_CONVS(name, p, ftype, fsz, sign) \
353
+
1402
+ CONV_ITOF(vfp_##name##to##p, ftype, fsz, sign) \
354
+ sysbus_connect_irq(s->lpd.iou.gem[i], 0, pic[irqs[i]]);
1403
+ CONV_FTOI(vfp_to##name##p, ftype, fsz, sign, ) \
355
+ g_free(name);
1404
+ CONV_FTOI(vfp_to##name##z##p, ftype, fsz, sign, _round_to_zero)
356
+ }
1405
+
357
+}
1406
+FLOAT_CONVS(si, h, uint32_t, 16, )
358
+
1407
+FLOAT_CONVS(si, s, float32, 32, )
359
+/* This takes the board allocated linear DDR memory and creates aliases
1408
+FLOAT_CONVS(si, d, float64, 64, )
360
+ * for each split DDR range/aperture on the Versal address map.
1409
+FLOAT_CONVS(ui, h, uint32_t, 16, u)
1410
+FLOAT_CONVS(ui, s, float32, 32, u)
1411
+FLOAT_CONVS(ui, d, float64, 64, u)
1412
+
1413
+#undef CONV_ITOF
1414
+#undef CONV_FTOI
1415
+#undef FLOAT_CONVS
1416
+
1417
+/* floating point conversion */
1418
+float64 VFP_HELPER(fcvtd, s)(float32 x, CPUARMState *env)
1419
+{
1420
+ return float32_to_float64(x, &env->vfp.fp_status);
1421
+}
1422
+
1423
+float32 VFP_HELPER(fcvts, d)(float64 x, CPUARMState *env)
1424
+{
1425
+ return float64_to_float32(x, &env->vfp.fp_status);
1426
+}
1427
+
1428
+/* VFP3 fixed point conversion. */
1429
+#define VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
1430
+float##fsz HELPER(vfp_##name##to##p)(uint##isz##_t x, uint32_t shift, \
1431
+ void *fpstp) \
1432
+{ return itype##_to_##float##fsz##_scalbn(x, -shift, fpstp); }
1433
+
1434
+#define VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, ROUND, suff) \
1435
+uint##isz##_t HELPER(vfp_to##name##p##suff)(float##fsz x, uint32_t shift, \
1436
+ void *fpst) \
1437
+{ \
1438
+ if (unlikely(float##fsz##_is_any_nan(x))) { \
1439
+ float_raise(float_flag_invalid, fpst); \
1440
+ return 0; \
1441
+ } \
1442
+ return float##fsz##_to_##itype##_scalbn(x, ROUND, shift, fpst); \
1443
+}
1444
+
1445
+#define VFP_CONV_FIX(name, p, fsz, isz, itype) \
1446
+VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
1447
+VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \
1448
+ float_round_to_zero, _round_to_zero) \
1449
+VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \
1450
+ get_float_rounding_mode(fpst), )
1451
+
1452
+#define VFP_CONV_FIX_A64(name, p, fsz, isz, itype) \
1453
+VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
1454
+VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, \
1455
+ get_float_rounding_mode(fpst), )
1456
+
1457
+VFP_CONV_FIX(sh, d, 64, 64, int16)
1458
+VFP_CONV_FIX(sl, d, 64, 64, int32)
1459
+VFP_CONV_FIX_A64(sq, d, 64, 64, int64)
1460
+VFP_CONV_FIX(uh, d, 64, 64, uint16)
1461
+VFP_CONV_FIX(ul, d, 64, 64, uint32)
1462
+VFP_CONV_FIX_A64(uq, d, 64, 64, uint64)
1463
+VFP_CONV_FIX(sh, s, 32, 32, int16)
1464
+VFP_CONV_FIX(sl, s, 32, 32, int32)
1465
+VFP_CONV_FIX_A64(sq, s, 32, 64, int64)
1466
+VFP_CONV_FIX(uh, s, 32, 32, uint16)
1467
+VFP_CONV_FIX(ul, s, 32, 32, uint32)
1468
+VFP_CONV_FIX_A64(uq, s, 32, 64, uint64)
1469
+
1470
+#undef VFP_CONV_FIX
1471
+#undef VFP_CONV_FIX_FLOAT
1472
+#undef VFP_CONV_FLOAT_FIX_ROUND
1473
+#undef VFP_CONV_FIX_A64
1474
+
1475
+uint32_t HELPER(vfp_sltoh)(uint32_t x, uint32_t shift, void *fpst)
1476
+{
1477
+ return int32_to_float16_scalbn(x, -shift, fpst);
1478
+}
1479
+
1480
+uint32_t HELPER(vfp_ultoh)(uint32_t x, uint32_t shift, void *fpst)
1481
+{
1482
+ return uint32_to_float16_scalbn(x, -shift, fpst);
1483
+}
1484
+
1485
+uint32_t HELPER(vfp_sqtoh)(uint64_t x, uint32_t shift, void *fpst)
1486
+{
1487
+ return int64_to_float16_scalbn(x, -shift, fpst);
1488
+}
1489
+
1490
+uint32_t HELPER(vfp_uqtoh)(uint64_t x, uint32_t shift, void *fpst)
1491
+{
1492
+ return uint64_to_float16_scalbn(x, -shift, fpst);
1493
+}
1494
+
1495
+uint32_t HELPER(vfp_toshh)(uint32_t x, uint32_t shift, void *fpst)
1496
+{
1497
+ if (unlikely(float16_is_any_nan(x))) {
1498
+ float_raise(float_flag_invalid, fpst);
1499
+ return 0;
1500
+ }
1501
+ return float16_to_int16_scalbn(x, get_float_rounding_mode(fpst),
1502
+ shift, fpst);
1503
+}
1504
+
1505
+uint32_t HELPER(vfp_touhh)(uint32_t x, uint32_t shift, void *fpst)
1506
+{
1507
+ if (unlikely(float16_is_any_nan(x))) {
1508
+ float_raise(float_flag_invalid, fpst);
1509
+ return 0;
1510
+ }
1511
+ return float16_to_uint16_scalbn(x, get_float_rounding_mode(fpst),
1512
+ shift, fpst);
1513
+}
1514
+
1515
+uint32_t HELPER(vfp_toslh)(uint32_t x, uint32_t shift, void *fpst)
1516
+{
1517
+ if (unlikely(float16_is_any_nan(x))) {
1518
+ float_raise(float_flag_invalid, fpst);
1519
+ return 0;
1520
+ }
1521
+ return float16_to_int32_scalbn(x, get_float_rounding_mode(fpst),
1522
+ shift, fpst);
1523
+}
1524
+
1525
+uint32_t HELPER(vfp_toulh)(uint32_t x, uint32_t shift, void *fpst)
1526
+{
1527
+ if (unlikely(float16_is_any_nan(x))) {
1528
+ float_raise(float_flag_invalid, fpst);
1529
+ return 0;
1530
+ }
1531
+ return float16_to_uint32_scalbn(x, get_float_rounding_mode(fpst),
1532
+ shift, fpst);
1533
+}
1534
+
1535
+uint64_t HELPER(vfp_tosqh)(uint32_t x, uint32_t shift, void *fpst)
1536
+{
1537
+ if (unlikely(float16_is_any_nan(x))) {
1538
+ float_raise(float_flag_invalid, fpst);
1539
+ return 0;
1540
+ }
1541
+ return float16_to_int64_scalbn(x, get_float_rounding_mode(fpst),
1542
+ shift, fpst);
1543
+}
1544
+
1545
+uint64_t HELPER(vfp_touqh)(uint32_t x, uint32_t shift, void *fpst)
1546
+{
1547
+ if (unlikely(float16_is_any_nan(x))) {
1548
+ float_raise(float_flag_invalid, fpst);
1549
+ return 0;
1550
+ }
1551
+ return float16_to_uint64_scalbn(x, get_float_rounding_mode(fpst),
1552
+ shift, fpst);
1553
+}
1554
+
1555
+/* Set the current fp rounding mode and return the old one.
1556
+ * The argument is a softfloat float_round_ value.
1557
+ */
361
+ */
1558
+uint32_t HELPER(set_rmode)(uint32_t rmode, void *fpstp)
362
+static void versal_map_ddr(Versal *s)
1559
+{
363
+{
1560
+ float_status *fp_status = fpstp;
364
+ uint64_t size = memory_region_size(s->cfg.mr_ddr);
1561
+
365
+ /* Describes the various split DDR access regions. */
1562
+ uint32_t prev_rmode = get_float_rounding_mode(fp_status);
366
+ static const struct {
1563
+ set_float_rounding_mode(rmode, fp_status);
367
+ uint64_t base;
1564
+
368
+ uint64_t size;
1565
+ return prev_rmode;
369
+ } addr_ranges[] = {
1566
+}
370
+ { MM_TOP_DDR, MM_TOP_DDR_SIZE },
1567
+
371
+ { MM_TOP_DDR_2, MM_TOP_DDR_2_SIZE },
1568
+/* Set the current fp rounding mode in the standard fp status and return
372
+ { MM_TOP_DDR_3, MM_TOP_DDR_3_SIZE },
1569
+ * the old one. This is for NEON instructions that need to change the
373
+ { MM_TOP_DDR_4, MM_TOP_DDR_4_SIZE }
1570
+ * rounding mode but wish to use the standard FPSCR values for everything
374
+ };
1571
+ * else. Always set the rounding mode back to the correct value after
375
+ uint64_t offset = 0;
1572
+ * modifying it.
376
+ int i;
1573
+ * The argument is a softfloat float_round_ value.
377
+
1574
+ */
378
+ assert(ARRAY_SIZE(addr_ranges) == ARRAY_SIZE(s->noc.mr_ddr_ranges));
1575
+uint32_t HELPER(set_neon_rmode)(uint32_t rmode, CPUARMState *env)
379
+ for (i = 0; i < ARRAY_SIZE(addr_ranges) && size; i++) {
1576
+{
380
+ char *name;
1577
+ float_status *fp_status = &env->vfp.standard_fp_status;
381
+ uint64_t mapsize;
1578
+
382
+
1579
+ uint32_t prev_rmode = get_float_rounding_mode(fp_status);
383
+ mapsize = size < addr_ranges[i].size ? size : addr_ranges[i].size;
1580
+ set_float_rounding_mode(rmode, fp_status);
384
+ name = g_strdup_printf("noc-ddr-range%d", i);
1581
+
385
+ /* Create the MR alias. */
1582
+ return prev_rmode;
386
+ memory_region_init_alias(&s->noc.mr_ddr_ranges[i], OBJECT(s),
1583
+}
387
+ name, s->cfg.mr_ddr,
1584
+
388
+ offset, mapsize);
1585
+/* Half precision conversions. */
389
+
1586
+float32 HELPER(vfp_fcvt_f16_to_f32)(uint32_t a, void *fpstp, uint32_t ahp_mode)
390
+ /* Map it onto the NoC MR. */
1587
+{
391
+ memory_region_add_subregion(&s->mr_ps, addr_ranges[i].base,
1588
+ /* Squash FZ16 to 0 for the duration of conversion. In this case,
392
+ &s->noc.mr_ddr_ranges[i]);
1589
+ * it would affect flushing input denormals.
393
+ offset += mapsize;
1590
+ */
394
+ size -= mapsize;
1591
+ float_status *fpst = fpstp;
395
+ g_free(name);
1592
+ flag save = get_flush_inputs_to_zero(fpst);
396
+ }
1593
+ set_flush_inputs_to_zero(false, fpst);
397
+}
1594
+ float32 r = float16_to_float32(a, !ahp_mode, fpst);
398
+
1595
+ set_flush_inputs_to_zero(save, fpst);
399
+static void versal_unimp_area(Versal *s, const char *name,
1596
+ return r;
400
+ MemoryRegion *mr,
1597
+}
401
+ hwaddr base, hwaddr size)
1598
+
402
+{
1599
+uint32_t HELPER(vfp_fcvt_f32_to_f16)(float32 a, void *fpstp, uint32_t ahp_mode)
403
+ DeviceState *dev = qdev_create(NULL, TYPE_UNIMPLEMENTED_DEVICE);
1600
+{
404
+ MemoryRegion *mr_dev;
1601
+ /* Squash FZ16 to 0 for the duration of conversion. In this case,
405
+
1602
+ * it would affect flushing output denormals.
406
+ qdev_prop_set_string(dev, "name", name);
1603
+ */
407
+ qdev_prop_set_uint64(dev, "size", size);
1604
+ float_status *fpst = fpstp;
408
+ object_property_add_child(OBJECT(s), name, OBJECT(dev), &error_fatal);
1605
+ flag save = get_flush_to_zero(fpst);
409
+ qdev_init_nofail(dev);
1606
+ set_flush_to_zero(false, fpst);
410
+
1607
+ float16 r = float32_to_float16(a, !ahp_mode, fpst);
411
+ mr_dev = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
1608
+ set_flush_to_zero(save, fpst);
412
+ memory_region_add_subregion(mr, base, mr_dev);
1609
+ return r;
413
+}
1610
+}
414
+
1611
+
415
+static void versal_unimp(Versal *s)
1612
+float64 HELPER(vfp_fcvt_f16_to_f64)(uint32_t a, void *fpstp, uint32_t ahp_mode)
416
+{
1613
+{
417
+ versal_unimp_area(s, "psm", &s->mr_ps,
1614
+ /* Squash FZ16 to 0 for the duration of conversion. In this case,
418
+ MM_PSM_START, MM_PSM_END - MM_PSM_START);
1615
+ * it would affect flushing input denormals.
419
+ versal_unimp_area(s, "crl", &s->mr_ps,
1616
+ */
420
+ MM_CRL, MM_CRL_SIZE);
1617
+ float_status *fpst = fpstp;
421
+ versal_unimp_area(s, "crf", &s->mr_ps,
1618
+ flag save = get_flush_inputs_to_zero(fpst);
422
+ MM_FPD_CRF, MM_FPD_CRF_SIZE);
1619
+ set_flush_inputs_to_zero(false, fpst);
423
+ versal_unimp_area(s, "iou-scntr", &s->mr_ps,
1620
+ float64 r = float16_to_float64(a, !ahp_mode, fpst);
424
+ MM_IOU_SCNTR, MM_IOU_SCNTR_SIZE);
1621
+ set_flush_inputs_to_zero(save, fpst);
425
+ versal_unimp_area(s, "iou-scntr-seucre", &s->mr_ps,
1622
+ return r;
426
+ MM_IOU_SCNTRS, MM_IOU_SCNTRS_SIZE);
1623
+}
427
+}
1624
+
428
+
1625
+uint32_t HELPER(vfp_fcvt_f64_to_f16)(float64 a, void *fpstp, uint32_t ahp_mode)
429
+static void versal_realize(DeviceState *dev, Error **errp)
1626
+{
430
+{
1627
+ /* Squash FZ16 to 0 for the duration of conversion. In this case,
431
+ Versal *s = XLNX_VERSAL(dev);
1628
+ * it would affect flushing output denormals.
432
+ qemu_irq pic[XLNX_VERSAL_NR_IRQS];
1629
+ */
433
+
1630
+ float_status *fpst = fpstp;
434
+ versal_create_apu_cpus(s);
1631
+ flag save = get_flush_to_zero(fpst);
435
+ versal_create_apu_gic(s, pic);
1632
+ set_flush_to_zero(false, fpst);
436
+ versal_create_uarts(s, pic);
1633
+ float16 r = float64_to_float16(a, !ahp_mode, fpst);
437
+ versal_create_gems(s, pic);
1634
+ set_flush_to_zero(save, fpst);
438
+ versal_map_ddr(s);
1635
+ return r;
439
+ versal_unimp(s);
1636
+}
440
+
1637
+
441
+ /* Create the On Chip Memory (OCM). */
1638
+#define float32_two make_float32(0x40000000)
442
+ memory_region_init_ram(&s->lpd.mr_ocm, OBJECT(s), "ocm",
1639
+#define float32_three make_float32(0x40400000)
443
+ MM_OCM_SIZE, &error_fatal);
1640
+#define float32_one_point_five make_float32(0x3fc00000)
444
+
1641
+
445
+ memory_region_add_subregion_overlap(&s->mr_ps, MM_OCM, &s->lpd.mr_ocm, 0);
1642
+float32 HELPER(recps_f32)(float32 a, float32 b, CPUARMState *env)
446
+ memory_region_add_subregion_overlap(&s->fpd.apu.mr, 0, &s->mr_ps, 0);
1643
+{
447
+}
1644
+ float_status *s = &env->vfp.standard_fp_status;
448
+
1645
+ if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) ||
449
+static void versal_init(Object *obj)
1646
+ (float32_is_infinity(b) && float32_is_zero_or_denormal(a))) {
450
+{
1647
+ if (!(float32_is_zero(a) || float32_is_zero(b))) {
451
+ Versal *s = XLNX_VERSAL(obj);
1648
+ float_raise(float_flag_input_denormal, s);
452
+
1649
+ }
453
+ memory_region_init(&s->fpd.apu.mr, obj, "mr-apu", UINT64_MAX);
1650
+ return float32_two;
454
+ memory_region_init(&s->mr_ps, obj, "mr-ps-switch", UINT64_MAX);
1651
+ }
455
+}
1652
+ return float32_sub(float32_two, float32_mul(a, b, s), s);
456
+
1653
+}
457
+static Property versal_properties[] = {
1654
+
458
+ DEFINE_PROP_LINK("ddr", Versal, cfg.mr_ddr, TYPE_MEMORY_REGION,
1655
+float32 HELPER(rsqrts_f32)(float32 a, float32 b, CPUARMState *env)
459
+ MemoryRegion *),
1656
+{
460
+ DEFINE_PROP_UINT32("psci-conduit", Versal, cfg.psci_conduit, 0),
1657
+ float_status *s = &env->vfp.standard_fp_status;
461
+ DEFINE_PROP_END_OF_LIST()
1658
+ float32 product;
462
+};
1659
+ if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) ||
463
+
1660
+ (float32_is_infinity(b) && float32_is_zero_or_denormal(a))) {
464
+static void versal_class_init(ObjectClass *klass, void *data)
1661
+ if (!(float32_is_zero(a) || float32_is_zero(b))) {
465
+{
1662
+ float_raise(float_flag_input_denormal, s);
466
+ DeviceClass *dc = DEVICE_CLASS(klass);
1663
+ }
467
+
1664
+ return float32_one_point_five;
468
+ dc->realize = versal_realize;
1665
+ }
469
+ dc->props = versal_properties;
1666
+ product = float32_mul(a, b, s);
470
+ /* No VMSD since we haven't got any top-level SoC state to save. */
1667
+ return float32_div(float32_sub(float32_three, product, s), float32_two, s);
471
+}
1668
+}
472
+
1669
+
473
+static const TypeInfo versal_info = {
1670
+/* NEON helpers. */
474
+ .name = TYPE_XLNX_VERSAL,
1671
+
475
+ .parent = TYPE_SYS_BUS_DEVICE,
1672
+/* Constants 256 and 512 are used in some helpers; we avoid relying on
476
+ .instance_size = sizeof(Versal),
1673
+ * int->float conversions at run-time. */
477
+ .instance_init = versal_init,
1674
+#define float64_256 make_float64(0x4070000000000000LL)
478
+ .class_init = versal_class_init,
1675
+#define float64_512 make_float64(0x4080000000000000LL)
479
+};
1676
+#define float16_maxnorm make_float16(0x7bff)
480
+
1677
+#define float32_maxnorm make_float32(0x7f7fffff)
481
+static void versal_register_types(void)
1678
+#define float64_maxnorm make_float64(0x7fefffffffffffffLL)
482
+{
1679
+
483
+ type_register_static(&versal_info);
1680
+/* Reciprocal functions
484
+}
1681
+ *
485
+
1682
+ * The algorithm that must be used to calculate the estimate
486
+type_init(versal_register_types);
1683
+ * is specified by the ARM ARM, see FPRecipEstimate()/RecipEstimate
487
diff --git a/default-configs/aarch64-softmmu.mak b/default-configs/aarch64-softmmu.mak
1684
+ */
488
index XXXXXXX..XXXXXXX 100644
1685
+
489
--- a/default-configs/aarch64-softmmu.mak
1686
+/* See RecipEstimate()
490
+++ b/default-configs/aarch64-softmmu.mak
1687
+ *
491
@@ -XXX,XX +XXX,XX @@ CONFIG_DDC=y
1688
+ * input is a 9 bit fixed point number
492
CONFIG_DPCD=y
1689
+ * input range 256 .. 511 for a number from 0.5 <= x < 1.0.
493
CONFIG_XLNX_ZYNQMP=y
1690
+ * result range 256 .. 511 for a number from 1.0 to 511/256.
494
CONFIG_XLNX_ZYNQMP_ARM=y
1691
+ */
495
+CONFIG_XLNX_VERSAL=y
1692
+
496
CONFIG_ARM_SMMUV3=y
1693
+static int recip_estimate(int input)
1694
+{
1695
+ int a, b, r;
1696
+ assert(256 <= input && input < 512);
1697
+ a = (input * 2) + 1;
1698
+ b = (1 << 19) / a;
1699
+ r = (b + 1) >> 1;
1700
+ assert(256 <= r && r < 512);
1701
+ return r;
1702
+}
1703
+
1704
+/*
1705
+ * Common wrapper to call recip_estimate
1706
+ *
1707
+ * The parameters are exponent and 64 bit fraction (without implicit
1708
+ * bit) where the binary point is nominally at bit 52. Returns a
1709
+ * float64 which can then be rounded to the appropriate size by the
1710
+ * callee.
1711
+ */
1712
+
1713
+static uint64_t call_recip_estimate(int *exp, int exp_off, uint64_t frac)
1714
+{
1715
+ uint32_t scaled, estimate;
1716
+ uint64_t result_frac;
1717
+ int result_exp;
1718
+
1719
+ /* Handle sub-normals */
1720
+ if (*exp == 0) {
1721
+ if (extract64(frac, 51, 1) == 0) {
1722
+ *exp = -1;
1723
+ frac <<= 2;
1724
+ } else {
1725
+ frac <<= 1;
1726
+ }
1727
+ }
1728
+
1729
+ /* scaled = UInt('1':fraction<51:44>) */
1730
+ scaled = deposit32(1 << 8, 0, 8, extract64(frac, 44, 8));
1731
+ estimate = recip_estimate(scaled);
1732
+
1733
+ result_exp = exp_off - *exp;
1734
+ result_frac = deposit64(0, 44, 8, estimate);
1735
+ if (result_exp == 0) {
1736
+ result_frac = deposit64(result_frac >> 1, 51, 1, 1);
1737
+ } else if (result_exp == -1) {
1738
+ result_frac = deposit64(result_frac >> 2, 50, 2, 1);
1739
+ result_exp = 0;
1740
+ }
1741
+
1742
+ *exp = result_exp;
1743
+
1744
+ return result_frac;
1745
+}
1746
+
1747
+static bool round_to_inf(float_status *fpst, bool sign_bit)
1748
+{
1749
+ switch (fpst->float_rounding_mode) {
1750
+ case float_round_nearest_even: /* Round to Nearest */
1751
+ return true;
1752
+ case float_round_up: /* Round to +Inf */
1753
+ return !sign_bit;
1754
+ case float_round_down: /* Round to -Inf */
1755
+ return sign_bit;
1756
+ case float_round_to_zero: /* Round to Zero */
1757
+ return false;
1758
+ }
1759
+
1760
+ g_assert_not_reached();
1761
+}
1762
+
1763
+uint32_t HELPER(recpe_f16)(uint32_t input, void *fpstp)
1764
+{
1765
+ float_status *fpst = fpstp;
1766
+ float16 f16 = float16_squash_input_denormal(input, fpst);
1767
+ uint32_t f16_val = float16_val(f16);
1768
+ uint32_t f16_sign = float16_is_neg(f16);
1769
+ int f16_exp = extract32(f16_val, 10, 5);
1770
+ uint32_t f16_frac = extract32(f16_val, 0, 10);
1771
+ uint64_t f64_frac;
1772
+
1773
+ if (float16_is_any_nan(f16)) {
1774
+ float16 nan = f16;
1775
+ if (float16_is_signaling_nan(f16, fpst)) {
1776
+ float_raise(float_flag_invalid, fpst);
1777
+ nan = float16_silence_nan(f16, fpst);
1778
+ }
1779
+ if (fpst->default_nan_mode) {
1780
+ nan = float16_default_nan(fpst);
1781
+ }
1782
+ return nan;
1783
+ } else if (float16_is_infinity(f16)) {
1784
+ return float16_set_sign(float16_zero, float16_is_neg(f16));
1785
+ } else if (float16_is_zero(f16)) {
1786
+ float_raise(float_flag_divbyzero, fpst);
1787
+ return float16_set_sign(float16_infinity, float16_is_neg(f16));
1788
+ } else if (float16_abs(f16) < (1 << 8)) {
1789
+ /* Abs(value) < 2.0^-16 */
1790
+ float_raise(float_flag_overflow | float_flag_inexact, fpst);
1791
+ if (round_to_inf(fpst, f16_sign)) {
1792
+ return float16_set_sign(float16_infinity, f16_sign);
1793
+ } else {
1794
+ return float16_set_sign(float16_maxnorm, f16_sign);
1795
+ }
1796
+ } else if (f16_exp >= 29 && fpst->flush_to_zero) {
1797
+ float_raise(float_flag_underflow, fpst);
1798
+ return float16_set_sign(float16_zero, float16_is_neg(f16));
1799
+ }
1800
+
1801
+ f64_frac = call_recip_estimate(&f16_exp, 29,
1802
+ ((uint64_t) f16_frac) << (52 - 10));
1803
+
1804
+ /* result = sign : result_exp<4:0> : fraction<51:42> */
1805
+ f16_val = deposit32(0, 15, 1, f16_sign);
1806
+ f16_val = deposit32(f16_val, 10, 5, f16_exp);
1807
+ f16_val = deposit32(f16_val, 0, 10, extract64(f64_frac, 52 - 10, 10));
1808
+ return make_float16(f16_val);
1809
+}
1810
+
1811
+float32 HELPER(recpe_f32)(float32 input, void *fpstp)
1812
+{
1813
+ float_status *fpst = fpstp;
1814
+ float32 f32 = float32_squash_input_denormal(input, fpst);
1815
+ uint32_t f32_val = float32_val(f32);
1816
+ bool f32_sign = float32_is_neg(f32);
1817
+ int f32_exp = extract32(f32_val, 23, 8);
1818
+ uint32_t f32_frac = extract32(f32_val, 0, 23);
1819
+ uint64_t f64_frac;
1820
+
1821
+ if (float32_is_any_nan(f32)) {
1822
+ float32 nan = f32;
1823
+ if (float32_is_signaling_nan(f32, fpst)) {
1824
+ float_raise(float_flag_invalid, fpst);
1825
+ nan = float32_silence_nan(f32, fpst);
1826
+ }
1827
+ if (fpst->default_nan_mode) {
1828
+ nan = float32_default_nan(fpst);
1829
+ }
1830
+ return nan;
1831
+ } else if (float32_is_infinity(f32)) {
1832
+ return float32_set_sign(float32_zero, float32_is_neg(f32));
1833
+ } else if (float32_is_zero(f32)) {
1834
+ float_raise(float_flag_divbyzero, fpst);
1835
+ return float32_set_sign(float32_infinity, float32_is_neg(f32));
1836
+ } else if (float32_abs(f32) < (1ULL << 21)) {
1837
+ /* Abs(value) < 2.0^-128 */
1838
+ float_raise(float_flag_overflow | float_flag_inexact, fpst);
1839
+ if (round_to_inf(fpst, f32_sign)) {
1840
+ return float32_set_sign(float32_infinity, f32_sign);
1841
+ } else {
1842
+ return float32_set_sign(float32_maxnorm, f32_sign);
1843
+ }
1844
+ } else if (f32_exp >= 253 && fpst->flush_to_zero) {
1845
+ float_raise(float_flag_underflow, fpst);
1846
+ return float32_set_sign(float32_zero, float32_is_neg(f32));
1847
+ }
1848
+
1849
+ f64_frac = call_recip_estimate(&f32_exp, 253,
1850
+ ((uint64_t) f32_frac) << (52 - 23));
1851
+
1852
+ /* result = sign : result_exp<7:0> : fraction<51:29> */
1853
+ f32_val = deposit32(0, 31, 1, f32_sign);
1854
+ f32_val = deposit32(f32_val, 23, 8, f32_exp);
1855
+ f32_val = deposit32(f32_val, 0, 23, extract64(f64_frac, 52 - 23, 23));
1856
+ return make_float32(f32_val);
1857
+}
1858
+
1859
+float64 HELPER(recpe_f64)(float64 input, void *fpstp)
1860
+{
1861
+ float_status *fpst = fpstp;
1862
+ float64 f64 = float64_squash_input_denormal(input, fpst);
1863
+ uint64_t f64_val = float64_val(f64);
1864
+ bool f64_sign = float64_is_neg(f64);
1865
+ int f64_exp = extract64(f64_val, 52, 11);
1866
+ uint64_t f64_frac = extract64(f64_val, 0, 52);
1867
+
1868
+ /* Deal with any special cases */
1869
+ if (float64_is_any_nan(f64)) {
1870
+ float64 nan = f64;
1871
+ if (float64_is_signaling_nan(f64, fpst)) {
1872
+ float_raise(float_flag_invalid, fpst);
1873
+ nan = float64_silence_nan(f64, fpst);
1874
+ }
1875
+ if (fpst->default_nan_mode) {
1876
+ nan = float64_default_nan(fpst);
1877
+ }
1878
+ return nan;
1879
+ } else if (float64_is_infinity(f64)) {
1880
+ return float64_set_sign(float64_zero, float64_is_neg(f64));
1881
+ } else if (float64_is_zero(f64)) {
1882
+ float_raise(float_flag_divbyzero, fpst);
1883
+ return float64_set_sign(float64_infinity, float64_is_neg(f64));
1884
+ } else if ((f64_val & ~(1ULL << 63)) < (1ULL << 50)) {
1885
+ /* Abs(value) < 2.0^-1024 */
1886
+ float_raise(float_flag_overflow | float_flag_inexact, fpst);
1887
+ if (round_to_inf(fpst, f64_sign)) {
1888
+ return float64_set_sign(float64_infinity, f64_sign);
1889
+ } else {
1890
+ return float64_set_sign(float64_maxnorm, f64_sign);
1891
+ }
1892
+ } else if (f64_exp >= 2045 && fpst->flush_to_zero) {
1893
+ float_raise(float_flag_underflow, fpst);
1894
+ return float64_set_sign(float64_zero, float64_is_neg(f64));
1895
+ }
1896
+
1897
+ f64_frac = call_recip_estimate(&f64_exp, 2045, f64_frac);
1898
+
1899
+ /* result = sign : result_exp<10:0> : fraction<51:0>; */
1900
+ f64_val = deposit64(0, 63, 1, f64_sign);
1901
+ f64_val = deposit64(f64_val, 52, 11, f64_exp);
1902
+ f64_val = deposit64(f64_val, 0, 52, f64_frac);
1903
+ return make_float64(f64_val);
1904
+}
1905
+
1906
+/* The algorithm that must be used to calculate the estimate
1907
+ * is specified by the ARM ARM.
1908
+ */
1909
+
1910
+static int do_recip_sqrt_estimate(int a)
1911
+{
1912
+ int b, estimate;
1913
+
1914
+ assert(128 <= a && a < 512);
1915
+ if (a < 256) {
1916
+ a = a * 2 + 1;
1917
+ } else {
1918
+ a = (a >> 1) << 1;
1919
+ a = (a + 1) * 2;
1920
+ }
1921
+ b = 512;
1922
+ while (a * (b + 1) * (b + 1) < (1 << 28)) {
1923
+ b += 1;
1924
+ }
1925
+ estimate = (b + 1) / 2;
1926
+ assert(256 <= estimate && estimate < 512);
1927
+
1928
+ return estimate;
1929
+}
1930
+
1931
+
1932
+static uint64_t recip_sqrt_estimate(int *exp , int exp_off, uint64_t frac)
1933
+{
1934
+ int estimate;
1935
+ uint32_t scaled;
1936
+
1937
+ if (*exp == 0) {
1938
+ while (extract64(frac, 51, 1) == 0) {
1939
+ frac = frac << 1;
1940
+ *exp -= 1;
1941
+ }
1942
+ frac = extract64(frac, 0, 51) << 1;
1943
+ }
1944
+
1945
+ if (*exp & 1) {
1946
+ /* scaled = UInt('01':fraction<51:45>) */
1947
+ scaled = deposit32(1 << 7, 0, 7, extract64(frac, 45, 7));
1948
+ } else {
1949
+ /* scaled = UInt('1':fraction<51:44>) */
1950
+ scaled = deposit32(1 << 8, 0, 8, extract64(frac, 44, 8));
1951
+ }
1952
+ estimate = do_recip_sqrt_estimate(scaled);
1953
+
1954
+ *exp = (exp_off - *exp) / 2;
1955
+ return extract64(estimate, 0, 8) << 44;
1956
+}
1957
+
1958
+uint32_t HELPER(rsqrte_f16)(uint32_t input, void *fpstp)
1959
+{
1960
+ float_status *s = fpstp;
1961
+ float16 f16 = float16_squash_input_denormal(input, s);
1962
+ uint16_t val = float16_val(f16);
1963
+ bool f16_sign = float16_is_neg(f16);
1964
+ int f16_exp = extract32(val, 10, 5);
1965
+ uint16_t f16_frac = extract32(val, 0, 10);
1966
+ uint64_t f64_frac;
1967
+
1968
+ if (float16_is_any_nan(f16)) {
1969
+ float16 nan = f16;
1970
+ if (float16_is_signaling_nan(f16, s)) {
1971
+ float_raise(float_flag_invalid, s);
1972
+ nan = float16_silence_nan(f16, s);
1973
+ }
1974
+ if (s->default_nan_mode) {
1975
+ nan = float16_default_nan(s);
1976
+ }
1977
+ return nan;
1978
+ } else if (float16_is_zero(f16)) {
1979
+ float_raise(float_flag_divbyzero, s);
1980
+ return float16_set_sign(float16_infinity, f16_sign);
1981
+ } else if (f16_sign) {
1982
+ float_raise(float_flag_invalid, s);
1983
+ return float16_default_nan(s);
1984
+ } else if (float16_is_infinity(f16)) {
1985
+ return float16_zero;
1986
+ }
1987
+
1988
+ /* Scale and normalize to a double-precision value between 0.25 and 1.0,
1989
+ * preserving the parity of the exponent. */
1990
+
1991
+ f64_frac = ((uint64_t) f16_frac) << (52 - 10);
1992
+
1993
+ f64_frac = recip_sqrt_estimate(&f16_exp, 44, f64_frac);
1994
+
1995
+ /* result = sign : result_exp<4:0> : estimate<7:0> : Zeros(2) */
1996
+ val = deposit32(0, 15, 1, f16_sign);
1997
+ val = deposit32(val, 10, 5, f16_exp);
1998
+ val = deposit32(val, 2, 8, extract64(f64_frac, 52 - 8, 8));
1999
+ return make_float16(val);
2000
+}
2001
+
2002
+float32 HELPER(rsqrte_f32)(float32 input, void *fpstp)
2003
+{
2004
+ float_status *s = fpstp;
2005
+ float32 f32 = float32_squash_input_denormal(input, s);
2006
+ uint32_t val = float32_val(f32);
2007
+ uint32_t f32_sign = float32_is_neg(f32);
2008
+ int f32_exp = extract32(val, 23, 8);
2009
+ uint32_t f32_frac = extract32(val, 0, 23);
2010
+ uint64_t f64_frac;
2011
+
2012
+ if (float32_is_any_nan(f32)) {
2013
+ float32 nan = f32;
2014
+ if (float32_is_signaling_nan(f32, s)) {
2015
+ float_raise(float_flag_invalid, s);
2016
+ nan = float32_silence_nan(f32, s);
2017
+ }
2018
+ if (s->default_nan_mode) {
2019
+ nan = float32_default_nan(s);
2020
+ }
2021
+ return nan;
2022
+ } else if (float32_is_zero(f32)) {
2023
+ float_raise(float_flag_divbyzero, s);
2024
+ return float32_set_sign(float32_infinity, float32_is_neg(f32));
2025
+ } else if (float32_is_neg(f32)) {
2026
+ float_raise(float_flag_invalid, s);
2027
+ return float32_default_nan(s);
2028
+ } else if (float32_is_infinity(f32)) {
2029
+ return float32_zero;
2030
+ }
2031
+
2032
+ /* Scale and normalize to a double-precision value between 0.25 and 1.0,
2033
+ * preserving the parity of the exponent. */
2034
+
2035
+ f64_frac = ((uint64_t) f32_frac) << 29;
2036
+
2037
+ f64_frac = recip_sqrt_estimate(&f32_exp, 380, f64_frac);
2038
+
2039
+ /* result = sign : result_exp<4:0> : estimate<7:0> : Zeros(15) */
2040
+ val = deposit32(0, 31, 1, f32_sign);
2041
+ val = deposit32(val, 23, 8, f32_exp);
2042
+ val = deposit32(val, 15, 8, extract64(f64_frac, 52 - 8, 8));
2043
+ return make_float32(val);
2044
+}
2045
+
2046
+float64 HELPER(rsqrte_f64)(float64 input, void *fpstp)
2047
+{
2048
+ float_status *s = fpstp;
2049
+ float64 f64 = float64_squash_input_denormal(input, s);
2050
+ uint64_t val = float64_val(f64);
2051
+ bool f64_sign = float64_is_neg(f64);
2052
+ int f64_exp = extract64(val, 52, 11);
2053
+ uint64_t f64_frac = extract64(val, 0, 52);
2054
+
2055
+ if (float64_is_any_nan(f64)) {
2056
+ float64 nan = f64;
2057
+ if (float64_is_signaling_nan(f64, s)) {
2058
+ float_raise(float_flag_invalid, s);
2059
+ nan = float64_silence_nan(f64, s);
2060
+ }
2061
+ if (s->default_nan_mode) {
2062
+ nan = float64_default_nan(s);
2063
+ }
2064
+ return nan;
2065
+ } else if (float64_is_zero(f64)) {
2066
+ float_raise(float_flag_divbyzero, s);
2067
+ return float64_set_sign(float64_infinity, float64_is_neg(f64));
2068
+ } else if (float64_is_neg(f64)) {
2069
+ float_raise(float_flag_invalid, s);
2070
+ return float64_default_nan(s);
2071
+ } else if (float64_is_infinity(f64)) {
2072
+ return float64_zero;
2073
+ }
2074
+
2075
+ f64_frac = recip_sqrt_estimate(&f64_exp, 3068, f64_frac);
2076
+
2077
+ /* result = sign : result_exp<4:0> : estimate<7:0> : Zeros(44) */
2078
+ val = deposit64(0, 61, 1, f64_sign);
2079
+ val = deposit64(val, 52, 11, f64_exp);
2080
+ val = deposit64(val, 44, 8, extract64(f64_frac, 52 - 8, 8));
2081
+ return make_float64(val);
2082
+}
2083
+
2084
+uint32_t HELPER(recpe_u32)(uint32_t a, void *fpstp)
2085
+{
2086
+ /* float_status *s = fpstp; */
2087
+ int input, estimate;
2088
+
2089
+ if ((a & 0x80000000) == 0) {
2090
+ return 0xffffffff;
2091
+ }
2092
+
2093
+ input = extract32(a, 23, 9);
2094
+ estimate = recip_estimate(input);
2095
+
2096
+ return deposit32(0, (32 - 9), 9, estimate);
2097
+}
2098
+
2099
+uint32_t HELPER(rsqrte_u32)(uint32_t a, void *fpstp)
2100
+{
2101
+ int estimate;
2102
+
2103
+ if ((a & 0xc0000000) == 0) {
2104
+ return 0xffffffff;
2105
+ }
2106
+
2107
+ estimate = do_recip_sqrt_estimate(extract32(a, 23, 9));
2108
+
2109
+ return deposit32(0, 23, 9, estimate);
2110
+}
2111
+
2112
+/* VFPv4 fused multiply-accumulate */
2113
+float32 VFP_HELPER(muladd, s)(float32 a, float32 b, float32 c, void *fpstp)
2114
+{
2115
+ float_status *fpst = fpstp;
2116
+ return float32_muladd(a, b, c, 0, fpst);
2117
+}
2118
+
2119
+float64 VFP_HELPER(muladd, d)(float64 a, float64 b, float64 c, void *fpstp)
2120
+{
2121
+ float_status *fpst = fpstp;
2122
+ return float64_muladd(a, b, c, 0, fpst);
2123
+}
2124
+
2125
+/* ARMv8 round to integral */
2126
+float32 HELPER(rints_exact)(float32 x, void *fp_status)
2127
+{
2128
+ return float32_round_to_int(x, fp_status);
2129
+}
2130
+
2131
+float64 HELPER(rintd_exact)(float64 x, void *fp_status)
2132
+{
2133
+ return float64_round_to_int(x, fp_status);
2134
+}
2135
+
2136
+float32 HELPER(rints)(float32 x, void *fp_status)
2137
+{
2138
+ int old_flags = get_float_exception_flags(fp_status), new_flags;
2139
+ float32 ret;
2140
+
2141
+ ret = float32_round_to_int(x, fp_status);
2142
+
2143
+ /* Suppress any inexact exceptions the conversion produced */
2144
+ if (!(old_flags & float_flag_inexact)) {
2145
+ new_flags = get_float_exception_flags(fp_status);
2146
+ set_float_exception_flags(new_flags & ~float_flag_inexact, fp_status);
2147
+ }
2148
+
2149
+ return ret;
2150
+}
2151
+
2152
+float64 HELPER(rintd)(float64 x, void *fp_status)
2153
+{
2154
+ int old_flags = get_float_exception_flags(fp_status), new_flags;
2155
+ float64 ret;
2156
+
2157
+ ret = float64_round_to_int(x, fp_status);
2158
+
2159
+ new_flags = get_float_exception_flags(fp_status);
2160
+
2161
+ /* Suppress any inexact exceptions the conversion produced */
2162
+ if (!(old_flags & float_flag_inexact)) {
2163
+ new_flags = get_float_exception_flags(fp_status);
2164
+ set_float_exception_flags(new_flags & ~float_flag_inexact, fp_status);
2165
+ }
2166
+
2167
+ return ret;
2168
+}
2169
+
2170
+/* Convert ARM rounding mode to softfloat */
2171
+int arm_rmode_to_sf(int rmode)
2172
+{
2173
+ switch (rmode) {
2174
+ case FPROUNDING_TIEAWAY:
2175
+ rmode = float_round_ties_away;
2176
+ break;
2177
+ case FPROUNDING_ODD:
2178
+ /* FIXME: add support for TIEAWAY and ODD */
2179
+ qemu_log_mask(LOG_UNIMP, "arm: unimplemented rounding mode: %d\n",
2180
+ rmode);
2181
+ /* fall through for now */
2182
+ case FPROUNDING_TIEEVEN:
2183
+ default:
2184
+ rmode = float_round_nearest_even;
2185
+ break;
2186
+ case FPROUNDING_POSINF:
2187
+ rmode = float_round_up;
2188
+ break;
2189
+ case FPROUNDING_NEGINF:
2190
+ rmode = float_round_down;
2191
+ break;
2192
+ case FPROUNDING_ZERO:
2193
+ rmode = float_round_to_zero;
2194
+ break;
2195
+ }
2196
+ return rmode;
2197
+}
2198
--
497
--
2199
2.20.1
498
2.19.1
2200
499
2201
500
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
There are lots of special cases within these insns. Split the
4
major argument decode/loading/saving into no_output (compares),
5
rd_is_dp, and rm_is_dp.
6
7
We still need to special case argument load for compare (rd as
8
input, rm as zero) and vcvt fixed (rd as input+output), but lots
9
of special cases do disappear.
10
11
Now that we have a full switch at the beginning, hoist the ISA
12
checks from the code generation.
13
14
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20190215192302.27855-4-richard.henderson@linaro.org
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
19
target/arm/translate.c | 227 ++++++++++++++++++++---------------------
20
1 file changed, 111 insertions(+), 116 deletions(-)
21
22
diff --git a/target/arm/translate.c b/target/arm/translate.c
23
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/translate.c
25
+++ b/target/arm/translate.c
26
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
27
}
28
} else {
29
/* data processing */
30
+ bool rd_is_dp = dp;
31
+ bool rm_is_dp = dp;
32
+ bool no_output = false;
33
+
34
/* The opcode is in bits 23, 21, 20 and 6. */
35
op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
36
- if (dp) {
37
- if (op == 15) {
38
- /* rn is opcode */
39
- rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
40
- } else {
41
- /* rn is register number */
42
- VFP_DREG_N(rn, insn);
43
- }
44
+ rn = VFP_SREG_N(insn);
45
46
- if (op == 15 && (rn == 15 || ((rn & 0x1c) == 0x18) ||
47
- ((rn & 0x1e) == 0x6))) {
48
- /* Integer or single/half precision destination. */
49
- rd = VFP_SREG_D(insn);
50
- } else {
51
- VFP_DREG_D(rd, insn);
52
- }
53
- if (op == 15 &&
54
- (((rn & 0x1c) == 0x10) || ((rn & 0x14) == 0x14) ||
55
- ((rn & 0x1e) == 0x4))) {
56
- /* VCVT from int or half precision is always from S reg
57
- * regardless of dp bit. VCVT with immediate frac_bits
58
- * has same format as SREG_M.
59
+ if (op == 15) {
60
+ /* rn is opcode, encoded as per VFP_SREG_N. */
61
+ switch (rn) {
62
+ case 0x00: /* vmov */
63
+ case 0x01: /* vabs */
64
+ case 0x02: /* vneg */
65
+ case 0x03: /* vsqrt */
66
+ break;
67
+
68
+ case 0x04: /* vcvtb.f64.f16, vcvtb.f32.f16 */
69
+ case 0x05: /* vcvtt.f64.f16, vcvtt.f32.f16 */
70
+ /*
71
+ * VCVTB, VCVTT: only present with the halfprec extension
72
+ * UNPREDICTABLE if bit 8 is set prior to ARMv8
73
+ * (we choose to UNDEF)
74
*/
75
- rm = VFP_SREG_M(insn);
76
- } else {
77
- VFP_DREG_M(rm, insn);
78
+ if ((dp && !arm_dc_feature(s, ARM_FEATURE_V8)) ||
79
+ !arm_dc_feature(s, ARM_FEATURE_VFP_FP16)) {
80
+ return 1;
81
+ }
82
+ rm_is_dp = false;
83
+ break;
84
+ case 0x06: /* vcvtb.f16.f32, vcvtb.f16.f64 */
85
+ case 0x07: /* vcvtt.f16.f32, vcvtt.f16.f64 */
86
+ if ((dp && !arm_dc_feature(s, ARM_FEATURE_V8)) ||
87
+ !arm_dc_feature(s, ARM_FEATURE_VFP_FP16)) {
88
+ return 1;
89
+ }
90
+ rd_is_dp = false;
91
+ break;
92
+
93
+ case 0x08: case 0x0a: /* vcmp, vcmpz */
94
+ case 0x09: case 0x0b: /* vcmpe, vcmpez */
95
+ no_output = true;
96
+ break;
97
+
98
+ case 0x0c: /* vrintr */
99
+ case 0x0d: /* vrintz */
100
+ case 0x0e: /* vrintx */
101
+ break;
102
+
103
+ case 0x0f: /* vcvt double<->single */
104
+ rd_is_dp = !dp;
105
+ break;
106
+
107
+ case 0x10: /* vcvt.fxx.u32 */
108
+ case 0x11: /* vcvt.fxx.s32 */
109
+ rm_is_dp = false;
110
+ break;
111
+ case 0x18: /* vcvtr.u32.fxx */
112
+ case 0x19: /* vcvtz.u32.fxx */
113
+ case 0x1a: /* vcvtr.s32.fxx */
114
+ case 0x1b: /* vcvtz.s32.fxx */
115
+ rd_is_dp = false;
116
+ break;
117
+
118
+ case 0x14: /* vcvt fp <-> fixed */
119
+ case 0x15:
120
+ case 0x16:
121
+ case 0x17:
122
+ case 0x1c:
123
+ case 0x1d:
124
+ case 0x1e:
125
+ case 0x1f:
126
+ if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
127
+ return 1;
128
+ }
129
+ /* Immediate frac_bits has same format as SREG_M. */
130
+ rm_is_dp = false;
131
+ break;
132
+
133
+ default:
134
+ return 1;
135
}
136
+ } else if (dp) {
137
+ /* rn is register number */
138
+ VFP_DREG_N(rn, insn);
139
+ }
140
+
141
+ if (rd_is_dp) {
142
+ VFP_DREG_D(rd, insn);
143
+ } else {
144
+ rd = VFP_SREG_D(insn);
145
+ }
146
+ if (rm_is_dp) {
147
+ VFP_DREG_M(rm, insn);
148
} else {
149
- rn = VFP_SREG_N(insn);
150
- if (op == 15 && rn == 15) {
151
- /* Double precision destination. */
152
- VFP_DREG_D(rd, insn);
153
- } else {
154
- rd = VFP_SREG_D(insn);
155
- }
156
- /* NB that we implicitly rely on the encoding for the frac_bits
157
- * in VCVT of fixed to float being the same as that of an SREG_M
158
- */
159
rm = VFP_SREG_M(insn);
160
}
161
162
veclen = s->vec_len;
163
- if (op == 15 && rn > 3)
164
+ if (op == 15 && rn > 3) {
165
veclen = 0;
166
+ }
167
168
/* Shut up compiler warnings. */
169
delta_m = 0;
170
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
171
/* Load the initial operands. */
172
if (op == 15) {
173
switch (rn) {
174
- case 16:
175
- case 17:
176
- /* Integer source */
177
- gen_mov_F0_vreg(0, rm);
178
- break;
179
- case 8:
180
- case 9:
181
- /* Compare */
182
+ case 0x08: case 0x09: /* Compare */
183
gen_mov_F0_vreg(dp, rd);
184
gen_mov_F1_vreg(dp, rm);
185
break;
186
- case 10:
187
- case 11:
188
- /* Compare with zero */
189
+ case 0x0a: case 0x0b: /* Compare with zero */
190
gen_mov_F0_vreg(dp, rd);
191
gen_vfp_F1_ld0(dp);
192
break;
193
- case 20:
194
- case 21:
195
- case 22:
196
- case 23:
197
- case 28:
198
- case 29:
199
- case 30:
200
- case 31:
201
+ case 0x14: /* vcvt fp <-> fixed */
202
+ case 0x15:
203
+ case 0x16:
204
+ case 0x17:
205
+ case 0x1c:
206
+ case 0x1d:
207
+ case 0x1e:
208
+ case 0x1f:
209
/* Source and destination the same. */
210
gen_mov_F0_vreg(dp, rd);
211
break;
212
- case 4:
213
- case 5:
214
- case 6:
215
- case 7:
216
- /* VCVTB, VCVTT: only present with the halfprec extension
217
- * UNPREDICTABLE if bit 8 is set prior to ARMv8
218
- * (we choose to UNDEF)
219
- */
220
- if ((dp && !arm_dc_feature(s, ARM_FEATURE_V8)) ||
221
- !arm_dc_feature(s, ARM_FEATURE_VFP_FP16)) {
222
- return 1;
223
- }
224
- if (!extract32(rn, 1, 1)) {
225
- /* Half precision source. */
226
- gen_mov_F0_vreg(0, rm);
227
- break;
228
- }
229
- /* Otherwise fall through */
230
default:
231
/* One source operand. */
232
- gen_mov_F0_vreg(dp, rm);
233
+ gen_mov_F0_vreg(rm_is_dp, rm);
234
break;
235
}
236
} else {
237
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
238
break;
239
}
240
case 15: /* single<->double conversion */
241
- if (dp)
242
+ if (dp) {
243
gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
244
- else
245
+ } else {
246
gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
247
+ }
248
break;
249
case 16: /* fuito */
250
gen_vfp_uito(dp, 0);
251
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
252
gen_vfp_sito(dp, 0);
253
break;
254
case 20: /* fshto */
255
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
256
- return 1;
257
- }
258
gen_vfp_shto(dp, 16 - rm, 0);
259
break;
260
case 21: /* fslto */
261
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
262
- return 1;
263
- }
264
gen_vfp_slto(dp, 32 - rm, 0);
265
break;
266
case 22: /* fuhto */
267
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
268
- return 1;
269
- }
270
gen_vfp_uhto(dp, 16 - rm, 0);
271
break;
272
case 23: /* fulto */
273
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
274
- return 1;
275
- }
276
gen_vfp_ulto(dp, 32 - rm, 0);
277
break;
278
case 24: /* ftoui */
279
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
280
gen_vfp_tosiz(dp, 0);
281
break;
282
case 28: /* ftosh */
283
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
284
- return 1;
285
- }
286
gen_vfp_tosh(dp, 16 - rm, 0);
287
break;
288
case 29: /* ftosl */
289
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
290
- return 1;
291
- }
292
gen_vfp_tosl(dp, 32 - rm, 0);
293
break;
294
case 30: /* ftouh */
295
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
296
- return 1;
297
- }
298
gen_vfp_touh(dp, 16 - rm, 0);
299
break;
300
case 31: /* ftoul */
301
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
302
- return 1;
303
- }
304
gen_vfp_toul(dp, 32 - rm, 0);
305
break;
306
default: /* undefined */
307
- return 1;
308
+ g_assert_not_reached();
309
}
310
break;
311
default: /* undefined */
312
return 1;
313
}
314
315
- /* Write back the result. */
316
- if (op == 15 && (rn >= 8 && rn <= 11)) {
317
- /* Comparison, do nothing. */
318
- } else if (op == 15 && dp && ((rn & 0x1c) == 0x18 ||
319
- (rn & 0x1e) == 0x6)) {
320
- /* VCVT double to int: always integer result.
321
- * VCVT double to half precision is always a single
322
- * precision result.
323
- */
324
- gen_mov_vreg_F0(0, rd);
325
- } else if (op == 15 && rn == 15) {
326
- /* conversion */
327
- gen_mov_vreg_F0(!dp, rd);
328
- } else {
329
- gen_mov_vreg_F0(dp, rd);
330
+ /* Write back the result, if any. */
331
+ if (!no_output) {
332
+ gen_mov_vreg_F0(rd_is_dp, rd);
333
}
334
335
/* break out of the loop if we have finished */
336
- if (veclen == 0)
337
+ if (veclen == 0) {
338
break;
339
+ }
340
341
if (op == 15 && delta_m == 0) {
342
/* single source one-many */
343
--
344
2.20.1
345
346
diff view generated by jsdifflib
Deleted patch
1
Convert the debug printing in the PL031 device to use trace events,
2
and augment it to cover the interesting parts of device operation.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
---
8
hw/timer/pl031.c | 55 +++++++++++++++++++++++--------------------
9
hw/timer/trace-events | 6 +++++
10
2 files changed, 36 insertions(+), 25 deletions(-)
11
12
diff --git a/hw/timer/pl031.c b/hw/timer/pl031.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/timer/pl031.c
15
+++ b/hw/timer/pl031.c
16
@@ -XXX,XX +XXX,XX @@
17
#include "sysemu/sysemu.h"
18
#include "qemu/cutils.h"
19
#include "qemu/log.h"
20
-
21
-//#define DEBUG_PL031
22
-
23
-#ifdef DEBUG_PL031
24
-#define DPRINTF(fmt, ...) \
25
-do { printf("pl031: " fmt , ## __VA_ARGS__); } while (0)
26
-#else
27
-#define DPRINTF(fmt, ...) do {} while(0)
28
-#endif
29
+#include "trace.h"
30
31
#define RTC_DR 0x00 /* Data read register */
32
#define RTC_MR 0x04 /* Match register */
33
@@ -XXX,XX +XXX,XX @@ static const unsigned char pl031_id[] = {
34
35
static void pl031_update(PL031State *s)
36
{
37
- qemu_set_irq(s->irq, s->is & s->im);
38
+ uint32_t flags = s->is & s->im;
39
+
40
+ trace_pl031_irq_state(flags);
41
+ qemu_set_irq(s->irq, flags);
42
}
43
44
static void pl031_interrupt(void * opaque)
45
@@ -XXX,XX +XXX,XX @@ static void pl031_interrupt(void * opaque)
46
PL031State *s = (PL031State *)opaque;
47
48
s->is = 1;
49
- DPRINTF("Alarm raised\n");
50
+ trace_pl031_alarm_raised();
51
pl031_update(s);
52
}
53
54
@@ -XXX,XX +XXX,XX @@ static void pl031_set_alarm(PL031State *s)
55
/* The timer wraps around. This subtraction also wraps in the same way,
56
and gives correct results when alarm < now_ticks. */
57
ticks = s->mr - pl031_get_count(s);
58
- DPRINTF("Alarm set in %ud ticks\n", ticks);
59
+ trace_pl031_set_alarm(ticks);
60
if (ticks == 0) {
61
timer_del(s->timer);
62
pl031_interrupt(s);
63
@@ -XXX,XX +XXX,XX @@ static uint64_t pl031_read(void *opaque, hwaddr offset,
64
unsigned size)
65
{
66
PL031State *s = (PL031State *)opaque;
67
-
68
- if (offset >= 0xfe0 && offset < 0x1000)
69
- return pl031_id[(offset - 0xfe0) >> 2];
70
+ uint64_t r;
71
72
switch (offset) {
73
case RTC_DR:
74
- return pl031_get_count(s);
75
+ r = pl031_get_count(s);
76
+ break;
77
case RTC_MR:
78
- return s->mr;
79
+ r = s->mr;
80
+ break;
81
case RTC_IMSC:
82
- return s->im;
83
+ r = s->im;
84
+ break;
85
case RTC_RIS:
86
- return s->is;
87
+ r = s->is;
88
+ break;
89
case RTC_LR:
90
- return s->lr;
91
+ r = s->lr;
92
+ break;
93
case RTC_CR:
94
/* RTC is permanently enabled. */
95
- return 1;
96
+ r = 1;
97
+ break;
98
case RTC_MIS:
99
- return s->is & s->im;
100
+ r = s->is & s->im;
101
+ break;
102
+ case 0xfe0 ... 0xfff:
103
+ r = pl031_id[(offset - 0xfe0) >> 2];
104
+ break;
105
case RTC_ICR:
106
qemu_log_mask(LOG_GUEST_ERROR,
107
"pl031: read of write-only register at offset 0x%x\n",
108
(int)offset);
109
+ r = 0;
110
break;
111
default:
112
qemu_log_mask(LOG_GUEST_ERROR,
113
"pl031_read: Bad offset 0x%x\n", (int)offset);
114
+ r = 0;
115
break;
116
}
117
118
- return 0;
119
+ trace_pl031_read(offset, r);
120
+ return r;
121
}
122
123
static void pl031_write(void * opaque, hwaddr offset,
124
@@ -XXX,XX +XXX,XX @@ static void pl031_write(void * opaque, hwaddr offset,
125
{
126
PL031State *s = (PL031State *)opaque;
127
128
+ trace_pl031_write(offset, value);
129
130
switch (offset) {
131
case RTC_LR:
132
@@ -XXX,XX +XXX,XX @@ static void pl031_write(void * opaque, hwaddr offset,
133
break;
134
case RTC_IMSC:
135
s->im = value & 1;
136
- DPRINTF("Interrupt mask %d\n", s->im);
137
pl031_update(s);
138
break;
139
case RTC_ICR:
140
@@ -XXX,XX +XXX,XX @@ static void pl031_write(void * opaque, hwaddr offset,
141
cleared when bit 0 of the written value is set. However the
142
arm926e documentation (DDI0287B) states that the interrupt is
143
cleared when any value is written. */
144
- DPRINTF("Interrupt cleared");
145
s->is = 0;
146
pl031_update(s);
147
break;
148
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
149
index XXXXXXX..XXXXXXX 100644
150
--- a/hw/timer/trace-events
151
+++ b/hw/timer/trace-events
152
@@ -XXX,XX +XXX,XX @@ xlnx_zynqmp_rtc_gettime(int year, int month, int day, int hour, int min, int sec
153
nrf51_timer_read(uint64_t addr, uint32_t value, unsigned size) "read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
154
nrf51_timer_write(uint64_t addr, uint32_t value, unsigned size) "write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
155
156
+# hw/timer/pl031.c
157
+pl031_irq_state(int level) "irq state %d"
158
+pl031_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
159
+pl031_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
160
+pl031_alarm_raised(void) "alarm raised"
161
+pl031_set_alarm(uint32_t ticks) "alarm set for %u ticks"
162
--
163
2.20.1
164
165
diff view generated by jsdifflib
Deleted patch
1
Create a new include file for the pl011's device struct,
2
type macros, etc, so that it can be instantiated using
3
the "embedded struct" coding style.
4
1
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
---
9
include/hw/char/pl011.h | 34 ++++++++++++++++++++++++++++++++++
10
hw/char/pl011.c | 31 ++-----------------------------
11
2 files changed, 36 insertions(+), 29 deletions(-)
12
13
diff --git a/include/hw/char/pl011.h b/include/hw/char/pl011.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/char/pl011.h
16
+++ b/include/hw/char/pl011.h
17
@@ -XXX,XX +XXX,XX @@
18
#ifndef HW_PL011_H
19
#define HW_PL011_H
20
21
+#include "hw/sysbus.h"
22
+#include "chardev/char-fe.h"
23
+
24
+#define TYPE_PL011 "pl011"
25
+#define PL011(obj) OBJECT_CHECK(PL011State, (obj), TYPE_PL011)
26
+
27
+/* This shares the same struct (and cast macro) as the base pl011 device */
28
+#define TYPE_PL011_LUMINARY "pl011_luminary"
29
+
30
+typedef struct PL011State {
31
+ SysBusDevice parent_obj;
32
+
33
+ MemoryRegion iomem;
34
+ uint32_t readbuff;
35
+ uint32_t flags;
36
+ uint32_t lcr;
37
+ uint32_t rsr;
38
+ uint32_t cr;
39
+ uint32_t dmacr;
40
+ uint32_t int_enabled;
41
+ uint32_t int_level;
42
+ uint32_t read_fifo[16];
43
+ uint32_t ilpr;
44
+ uint32_t ibrd;
45
+ uint32_t fbrd;
46
+ uint32_t ifl;
47
+ int read_pos;
48
+ int read_count;
49
+ int read_trigger;
50
+ CharBackend chr;
51
+ qemu_irq irq;
52
+ const unsigned char *id;
53
+} PL011State;
54
+
55
static inline DeviceState *pl011_create(hwaddr addr,
56
qemu_irq irq,
57
Chardev *chr)
58
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
59
index XXXXXXX..XXXXXXX 100644
60
--- a/hw/char/pl011.c
61
+++ b/hw/char/pl011.c
62
@@ -XXX,XX +XXX,XX @@
63
*/
64
65
#include "qemu/osdep.h"
66
+#include "hw/char/pl011.h"
67
#include "hw/sysbus.h"
68
#include "chardev/char-fe.h"
69
#include "qemu/log.h"
70
#include "trace.h"
71
72
-#define TYPE_PL011 "pl011"
73
-#define PL011(obj) OBJECT_CHECK(PL011State, (obj), TYPE_PL011)
74
-
75
-typedef struct PL011State {
76
- SysBusDevice parent_obj;
77
-
78
- MemoryRegion iomem;
79
- uint32_t readbuff;
80
- uint32_t flags;
81
- uint32_t lcr;
82
- uint32_t rsr;
83
- uint32_t cr;
84
- uint32_t dmacr;
85
- uint32_t int_enabled;
86
- uint32_t int_level;
87
- uint32_t read_fifo[16];
88
- uint32_t ilpr;
89
- uint32_t ibrd;
90
- uint32_t fbrd;
91
- uint32_t ifl;
92
- int read_pos;
93
- int read_count;
94
- int read_trigger;
95
- CharBackend chr;
96
- qemu_irq irq;
97
- const unsigned char *id;
98
-} PL011State;
99
-
100
#define PL011_INT_TX 0x20
101
#define PL011_INT_RX 0x10
102
103
@@ -XXX,XX +XXX,XX @@ static void pl011_luminary_init(Object *obj)
104
}
105
106
static const TypeInfo pl011_luminary_info = {
107
- .name = "pl011_luminary",
108
+ .name = TYPE_PL011_LUMINARY,
109
.parent = TYPE_PL011,
110
.instance_init = pl011_luminary_init,
111
};
112
--
113
2.20.1
114
115
diff view generated by jsdifflib
Deleted patch
1
The PL011 UART has six interrupt lines:
2
* RX (receive data)
3
* TX (transmit data)
4
* RT (receive timeout)
5
* MS (modem status)
6
* E (errors)
7
* combined (logical OR of all the above)
8
1
9
So far we have only emulated the combined interrupt line;
10
add support for the others, so that boards that wire them
11
up to different interrupt controller inputs can do so.
12
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
---
16
include/hw/char/pl011.h | 2 +-
17
hw/char/pl011.c | 46 +++++++++++++++++++++++++++++++++++++++--
18
2 files changed, 45 insertions(+), 3 deletions(-)
19
20
diff --git a/include/hw/char/pl011.h b/include/hw/char/pl011.h
21
index XXXXXXX..XXXXXXX 100644
22
--- a/include/hw/char/pl011.h
23
+++ b/include/hw/char/pl011.h
24
@@ -XXX,XX +XXX,XX @@ typedef struct PL011State {
25
int read_count;
26
int read_trigger;
27
CharBackend chr;
28
- qemu_irq irq;
29
+ qemu_irq irq[6];
30
const unsigned char *id;
31
} PL011State;
32
33
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/hw/char/pl011.c
36
+++ b/hw/char/pl011.c
37
@@ -XXX,XX +XXX,XX @@
38
* This code is licensed under the GPL.
39
*/
40
41
+/*
42
+ * QEMU interface:
43
+ * + sysbus MMIO region 0: device registers
44
+ * + sysbus IRQ 0: UARTINTR (combined interrupt line)
45
+ * + sysbus IRQ 1: UARTRXINTR (receive FIFO interrupt line)
46
+ * + sysbus IRQ 2: UARTTXINTR (transmit FIFO interrupt line)
47
+ * + sysbus IRQ 3: UARTRTINTR (receive timeout interrupt line)
48
+ * + sysbus IRQ 4: UARTMSINTR (momem status interrupt line)
49
+ * + sysbus IRQ 5: UARTEINTR (error interrupt line)
50
+ */
51
+
52
#include "qemu/osdep.h"
53
#include "hw/char/pl011.h"
54
#include "hw/sysbus.h"
55
@@ -XXX,XX +XXX,XX @@
56
#define PL011_FLAG_TXFF 0x20
57
#define PL011_FLAG_RXFE 0x10
58
59
+/* Interrupt status bits in UARTRIS, UARTMIS, UARTIMSC */
60
+#define INT_OE (1 << 10)
61
+#define INT_BE (1 << 9)
62
+#define INT_PE (1 << 8)
63
+#define INT_FE (1 << 7)
64
+#define INT_RT (1 << 6)
65
+#define INT_TX (1 << 5)
66
+#define INT_RX (1 << 4)
67
+#define INT_DSR (1 << 3)
68
+#define INT_DCD (1 << 2)
69
+#define INT_CTS (1 << 1)
70
+#define INT_RI (1 << 0)
71
+#define INT_E (INT_OE | INT_BE | INT_PE | INT_FE)
72
+#define INT_MS (INT_RI | INT_DSR | INT_DCD | INT_CTS)
73
+
74
static const unsigned char pl011_id_arm[8] =
75
{ 0x11, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
76
static const unsigned char pl011_id_luminary[8] =
77
{ 0x11, 0x00, 0x18, 0x01, 0x0d, 0xf0, 0x05, 0xb1 };
78
79
+/* Which bits in the interrupt status matter for each outbound IRQ line ? */
80
+static const uint32_t irqmask[] = {
81
+ INT_E | INT_MS | INT_RT | INT_TX | INT_RX, /* combined IRQ */
82
+ INT_RX,
83
+ INT_TX,
84
+ INT_RT,
85
+ INT_MS,
86
+ INT_E,
87
+};
88
+
89
static void pl011_update(PL011State *s)
90
{
91
uint32_t flags;
92
+ int i;
93
94
flags = s->int_level & s->int_enabled;
95
trace_pl011_irq_state(flags != 0);
96
- qemu_set_irq(s->irq, flags != 0);
97
+ for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
98
+ qemu_set_irq(s->irq[i], (flags & irqmask[i]) != 0);
99
+ }
100
}
101
102
static uint64_t pl011_read(void *opaque, hwaddr offset,
103
@@ -XXX,XX +XXX,XX @@ static void pl011_init(Object *obj)
104
{
105
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
106
PL011State *s = PL011(obj);
107
+ int i;
108
109
memory_region_init_io(&s->iomem, OBJECT(s), &pl011_ops, s, "pl011", 0x1000);
110
sysbus_init_mmio(sbd, &s->iomem);
111
- sysbus_init_irq(sbd, &s->irq);
112
+ for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
113
+ sysbus_init_irq(sbd, &s->irq[i]);
114
+ }
115
116
s->read_trigger = 1;
117
s->ifl = 0x12;
118
--
119
2.20.1
120
121
diff view generated by jsdifflib
Deleted patch
1
In commit 4b635cf7a95e501211 we added a QOM property to the ARMSSE
2
object, but forgot to add it to the documentation comment in the
3
header. Correct the omission.
4
1
5
Fixes: 4b635cf7a95e501211 ("hw/arm/armsse: Make SRAM bank size configurable")
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
---
9
include/hw/arm/armsse.h | 2 ++
10
1 file changed, 2 insertions(+)
11
12
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
13
index XXXXXXX..XXXXXXX 100644
14
--- a/include/hw/arm/armsse.h
15
+++ b/include/hw/arm/armsse.h
16
@@ -XXX,XX +XXX,XX @@
17
* being the same for both, to avoid having to have separate Property
18
* lists for different variants. This restriction can be relaxed later
19
* if necessary.)
20
+ * + QOM property "SRAM_ADDR_WIDTH" sets the number of bits used for the
21
+ * address of each SRAM bank (and thus the total amount of internal SRAM)
22
* + Named GPIO inputs "EXP_IRQ" 0..n are the expansion interrupts for CPU 0,
23
* which are wired to its NVIC lines 32 .. n+32
24
* + Named GPIO inputs "EXP_CPU1_IRQ" 0..n are the expansion interrupts for
25
--
26
2.20.1
27
28
diff view generated by jsdifflib
Deleted patch
1
The Musca boards have DAPLink firmware that sets the initial
2
secure VTOR value (the location of the vector table) differently
3
depending on the boot mode (from flash, from RAM, etc). Export
4
the init-svtor as a QOM property of the ARMSSE object so that
5
the board can change it.
6
1
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
---
11
include/hw/arm/armsse.h | 3 +++
12
hw/arm/armsse.c | 8 ++++----
13
2 files changed, 7 insertions(+), 4 deletions(-)
14
15
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/arm/armsse.h
18
+++ b/include/hw/arm/armsse.h
19
@@ -XXX,XX +XXX,XX @@
20
* if necessary.)
21
* + QOM property "SRAM_ADDR_WIDTH" sets the number of bits used for the
22
* address of each SRAM bank (and thus the total amount of internal SRAM)
23
+ * + QOM property "init-svtor" sets the initial value of the CPU SVTOR register
24
+ * (where it expects to load the PC and SP from the vector table on reset)
25
* + Named GPIO inputs "EXP_IRQ" 0..n are the expansion interrupts for CPU 0,
26
* which are wired to its NVIC lines 32 .. n+32
27
* + Named GPIO inputs "EXP_CPU1_IRQ" 0..n are the expansion interrupts for
28
@@ -XXX,XX +XXX,XX @@ typedef struct ARMSSE {
29
uint32_t exp_numirq;
30
uint32_t mainclk_frq;
31
uint32_t sram_addr_width;
32
+ uint32_t init_svtor;
33
} ARMSSE;
34
35
typedef struct ARMSSEInfo ARMSSEInfo;
36
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/hw/arm/armsse.c
39
+++ b/hw/arm/armsse.c
40
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
41
* the INITSVTOR* registers before powering up the CPUs in any case,
42
* so the hardware's default value doesn't matter. QEMU doesn't emulate
43
* the control processor, so instead we behave in the way that the
44
- * firmware does. All boards currently known about have firmware that
45
- * sets the INITSVTOR0 and INITSVTOR1 registers to 0x10000000, like the
46
- * IoTKit default. We can make this more configurable if necessary.
47
+ * firmware does. The initial value is configurable by the board code
48
+ * to match whatever its firmware does.
49
*/
50
- qdev_prop_set_uint32(cpudev, "init-svtor", 0x10000000);
51
+ qdev_prop_set_uint32(cpudev, "init-svtor", s->init_svtor);
52
/*
53
* Start all CPUs except CPU0 powered down. In real hardware it is
54
* a configurable property of the SSE-200 which CPUs start powered up
55
@@ -XXX,XX +XXX,XX @@ static Property armsse_properties[] = {
56
DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
57
DEFINE_PROP_UINT32("MAINCLK", ARMSSE, mainclk_frq, 0),
58
DEFINE_PROP_UINT32("SRAM_ADDR_WIDTH", ARMSSE, sram_addr_width, 15),
59
+ DEFINE_PROP_UINT32("init-svtor", ARMSSE, init_svtor, 0x10000000),
60
DEFINE_PROP_END_OF_LIST()
61
};
62
63
--
64
2.20.1
65
66
diff view generated by jsdifflib
1
The Musca-A and Musca-B1 development boards are based on the
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
2
SSE-200 subsystem for embedded. Implement an initial skeleton
3
model of these boards, which are similar but not identical.
4
2
5
This commit creates the board model with the SSE and the IRQ
3
Add a virtual Xilinx Versal board.
6
splitters to wire IRQs up to its two CPUs. As yet there
7
are no devices and no memory: these will be added later.
8
4
5
This board is based on the Xilinx Versal SoC. The exact
6
details of what peripherals are attached to this board
7
will remain in control of QEMU. QEMU will generate an
8
FDT on the fly for Linux and other software to auto-discover
9
peripherals.
10
11
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
12
Message-id: 20181102131913.1535-3-edgar.iglesias@xilinx.com
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
---
15
---
12
hw/arm/Makefile.objs | 1 +
16
hw/arm/Makefile.objs | 2 +-
13
hw/arm/musca.c | 197 ++++++++++++++++++++++++++++++++
17
hw/arm/xlnx-versal-virt.c | 494 ++++++++++++++++++++++++++++++++++++++
14
MAINTAINERS | 6 +
18
2 files changed, 495 insertions(+), 1 deletion(-)
15
default-configs/arm-softmmu.mak | 1 +
19
create mode 100644 hw/arm/xlnx-versal-virt.c
16
4 files changed, 205 insertions(+)
17
create mode 100644 hw/arm/musca.c
18
20
19
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
21
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
20
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/arm/Makefile.objs
23
--- a/hw/arm/Makefile.objs
22
+++ b/hw/arm/Makefile.objs
24
+++ b/hw/arm/Makefile.objs
23
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_ASPEED_SOC) += aspeed_soc.o aspeed.o
25
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o
24
obj-$(CONFIG_MPS2) += mps2.o
26
obj-$(CONFIG_RASPI) += bcm2835_peripherals.o bcm2836.o raspi.o
25
obj-$(CONFIG_MPS2) += mps2-tz.o
27
obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o
26
obj-$(CONFIG_MSF2) += msf2-soc.o msf2-som.o
28
obj-$(CONFIG_XLNX_ZYNQMP_ARM) += xlnx-zynqmp.o xlnx-zcu102.o
27
+obj-$(CONFIG_MUSCA) += musca.o
29
-obj-$(CONFIG_XLNX_VERSAL) += xlnx-versal.o
28
obj-$(CONFIG_ARMSSE) += armsse.o
30
+obj-$(CONFIG_XLNX_VERSAL) += xlnx-versal.o xlnx-versal-virt.o
29
obj-$(CONFIG_FSL_IMX7) += fsl-imx7.o mcimx7d-sabre.o
31
obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o
30
obj-$(CONFIG_ARM_SMMUV3) += smmu-common.o smmuv3.o
32
obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o
31
diff --git a/hw/arm/musca.c b/hw/arm/musca.c
33
obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o
34
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
32
new file mode 100644
35
new file mode 100644
33
index XXXXXXX..XXXXXXX
36
index XXXXXXX..XXXXXXX
34
--- /dev/null
37
--- /dev/null
35
+++ b/hw/arm/musca.c
38
+++ b/hw/arm/xlnx-versal-virt.c
36
@@ -XXX,XX +XXX,XX @@
39
@@ -XXX,XX +XXX,XX @@
37
+/*
40
+/*
38
+ * Arm Musca-B1 test chip board emulation
41
+ * Xilinx Versal Virtual board.
39
+ *
42
+ *
40
+ * Copyright (c) 2019 Linaro Limited
43
+ * Copyright (c) 2018 Xilinx Inc.
41
+ * Written by Peter Maydell
44
+ * Written by Edgar E. Iglesias
42
+ *
45
+ *
43
+ * This program is free software; you can redistribute it and/or modify
46
+ * This program is free software; you can redistribute it and/or modify
44
+ * it under the terms of the GNU General Public License version 2 or
47
+ * it under the terms of the GNU General Public License version 2 or
45
+ * (at your option) any later version.
48
+ * (at your option) any later version.
46
+ */
49
+ */
47
+
50
+
48
+/*
49
+ * The Musca boards are a reference implementation of a system using
50
+ * the SSE-200 subsystem for embedded:
51
+ * https://developer.arm.com/products/system-design/development-boards/iot-test-chips-and-boards/musca-a-test-chip-board
52
+ * https://developer.arm.com/products/system-design/development-boards/iot-test-chips-and-boards/musca-b-test-chip-board
53
+ * We model the A and B1 variants of this board, as described in the TRMs:
54
+ * http://infocenter.arm.com/help/topic/com.arm.doc.101107_0000_00_en/index.html
55
+ * http://infocenter.arm.com/help/topic/com.arm.doc.101312_0000_00_en/index.html
56
+ */
57
+
58
+#include "qemu/osdep.h"
51
+#include "qemu/osdep.h"
52
+#include "qemu/log.h"
59
+#include "qemu/error-report.h"
53
+#include "qemu/error-report.h"
60
+#include "qapi/error.h"
54
+#include "qapi/error.h"
55
+#include "sysemu/device_tree.h"
61
+#include "exec/address-spaces.h"
56
+#include "exec/address-spaces.h"
62
+#include "hw/arm/arm.h"
63
+#include "hw/arm/armsse.h"
64
+#include "hw/boards.h"
57
+#include "hw/boards.h"
65
+#include "hw/core/split-irq.h"
58
+#include "hw/sysbus.h"
66
+
59
+#include "hw/arm/sysbus-fdt.h"
67
+#define MUSCA_NUMIRQ_MAX 96
60
+#include "hw/arm/fdt.h"
68
+
61
+#include "cpu.h"
69
+typedef enum MuscaType {
62
+#include "hw/arm/xlnx-versal.h"
70
+ MUSCA_A,
63
+
71
+ MUSCA_B1,
64
+#define TYPE_XLNX_VERSAL_VIRT_MACHINE MACHINE_TYPE_NAME("xlnx-versal-virt")
72
+} MuscaType;
65
+#define XLNX_VERSAL_VIRT_MACHINE(obj) \
73
+
66
+ OBJECT_CHECK(VersalVirt, (obj), TYPE_XLNX_VERSAL_VIRT_MACHINE)
74
+typedef struct {
67
+
75
+ MachineClass parent;
68
+typedef struct VersalVirt {
76
+ MuscaType type;
69
+ MachineState parent_obj;
77
+ uint32_t init_svtor;
70
+
78
+ int sram_addr_width;
71
+ Versal soc;
79
+ int num_irqs;
72
+ MemoryRegion mr_ddr;
80
+} MuscaMachineClass;
73
+
81
+
74
+ void *fdt;
82
+typedef struct {
75
+ int fdt_size;
83
+ MachineState parent;
76
+ struct {
84
+
77
+ uint32_t gic;
85
+ ARMSSE sse;
78
+ uint32_t ethernet_phy[2];
86
+ SplitIRQ cpu_irq_splitter[MUSCA_NUMIRQ_MAX];
79
+ uint32_t clk_125Mhz;
87
+} MuscaMachineState;
80
+ uint32_t clk_25Mhz;
88
+
81
+ } phandle;
89
+#define TYPE_MUSCA_MACHINE "musca"
82
+ struct arm_boot_info binfo;
90
+#define TYPE_MUSCA_A_MACHINE MACHINE_TYPE_NAME("musca-a")
83
+
91
+#define TYPE_MUSCA_B1_MACHINE MACHINE_TYPE_NAME("musca-b1")
84
+ struct {
92
+
85
+ bool secure;
93
+#define MUSCA_MACHINE(obj) \
86
+ } cfg;
94
+ OBJECT_CHECK(MuscaMachineState, obj, TYPE_MUSCA_MACHINE)
87
+} VersalVirt;
95
+#define MUSCA_MACHINE_GET_CLASS(obj) \
88
+
96
+ OBJECT_GET_CLASS(MuscaMachineClass, obj, TYPE_MUSCA_MACHINE)
89
+static void fdt_create(VersalVirt *s)
97
+#define MUSCA_MACHINE_CLASS(klass) \
90
+{
98
+ OBJECT_CLASS_CHECK(MuscaMachineClass, klass, TYPE_MUSCA_MACHINE)
91
+ MachineClass *mc = MACHINE_GET_CLASS(s);
99
+
100
+/*
101
+ * Main SYSCLK frequency in Hz
102
+ * TODO this should really be different for the two cores, but we
103
+ * don't model that in our SSE-200 model yet.
104
+ */
105
+#define SYSCLK_FRQ 40000000
106
+
107
+static void musca_init(MachineState *machine)
108
+{
109
+ MuscaMachineState *mms = MUSCA_MACHINE(machine);
110
+ MuscaMachineClass *mmc = MUSCA_MACHINE_GET_CLASS(mms);
111
+ MachineClass *mc = MACHINE_GET_CLASS(machine);
112
+ MemoryRegion *system_memory = get_system_memory();
113
+ DeviceState *ssedev;
114
+ int i;
92
+ int i;
115
+
93
+
116
+ assert(mmc->num_irqs <= MUSCA_NUMIRQ_MAX);
94
+ s->fdt = create_device_tree(&s->fdt_size);
117
+
95
+ if (!s->fdt) {
118
+ if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
96
+ error_report("create_device_tree() failed");
119
+ error_report("This board can only be used with CPU %s",
120
+ mc->default_cpu_type);
121
+ exit(1);
97
+ exit(1);
122
+ }
98
+ }
123
+
99
+
124
+ sysbus_init_child_obj(OBJECT(machine), "sse-200", &mms->sse,
100
+ /* Allocate all phandles. */
125
+ sizeof(mms->sse), TYPE_SSE200);
101
+ s->phandle.gic = qemu_fdt_alloc_phandle(s->fdt);
126
+ ssedev = DEVICE(&mms->sse);
102
+ for (i = 0; i < ARRAY_SIZE(s->phandle.ethernet_phy); i++) {
127
+ object_property_set_link(OBJECT(&mms->sse), OBJECT(system_memory),
103
+ s->phandle.ethernet_phy[i] = qemu_fdt_alloc_phandle(s->fdt);
128
+ "memory", &error_fatal);
104
+ }
129
+ qdev_prop_set_uint32(ssedev, "EXP_NUMIRQ", mmc->num_irqs);
105
+ s->phandle.clk_25Mhz = qemu_fdt_alloc_phandle(s->fdt);
130
+ qdev_prop_set_uint32(ssedev, "init-svtor", mmc->init_svtor);
106
+ s->phandle.clk_125Mhz = qemu_fdt_alloc_phandle(s->fdt);
131
+ qdev_prop_set_uint32(ssedev, "SRAM_ADDR_WIDTH", mmc->sram_addr_width);
107
+
132
+ qdev_prop_set_uint32(ssedev, "MAINCLK", SYSCLK_FRQ);
108
+ /* Create /chosen node for load_dtb. */
133
+ object_property_set_bool(OBJECT(&mms->sse), true, "realized",
109
+ qemu_fdt_add_subnode(s->fdt, "/chosen");
134
+ &error_fatal);
110
+
111
+ /* Header */
112
+ qemu_fdt_setprop_cell(s->fdt, "/", "interrupt-parent", s->phandle.gic);
113
+ qemu_fdt_setprop_cell(s->fdt, "/", "#size-cells", 0x2);
114
+ qemu_fdt_setprop_cell(s->fdt, "/", "#address-cells", 0x2);
115
+ qemu_fdt_setprop_string(s->fdt, "/", "model", mc->desc);
116
+ qemu_fdt_setprop_string(s->fdt, "/", "compatible", "xlnx-versal-virt");
117
+}
118
+
119
+static void fdt_add_clk_node(VersalVirt *s, const char *name,
120
+ unsigned int freq_hz, uint32_t phandle)
121
+{
122
+ qemu_fdt_add_subnode(s->fdt, name);
123
+ qemu_fdt_setprop_cell(s->fdt, name, "phandle", phandle);
124
+ qemu_fdt_setprop_cell(s->fdt, name, "clock-frequency", freq_hz);
125
+ qemu_fdt_setprop_cell(s->fdt, name, "#clock-cells", 0x0);
126
+ qemu_fdt_setprop_string(s->fdt, name, "compatible", "fixed-clock");
127
+ qemu_fdt_setprop(s->fdt, name, "u-boot,dm-pre-reloc", NULL, 0);
128
+}
129
+
130
+static void fdt_add_cpu_nodes(VersalVirt *s, uint32_t psci_conduit)
131
+{
132
+ int i;
133
+
134
+ qemu_fdt_add_subnode(s->fdt, "/cpus");
135
+ qemu_fdt_setprop_cell(s->fdt, "/cpus", "#size-cells", 0x0);
136
+ qemu_fdt_setprop_cell(s->fdt, "/cpus", "#address-cells", 1);
137
+
138
+ for (i = XLNX_VERSAL_NR_ACPUS - 1; i >= 0; i--) {
139
+ char *name = g_strdup_printf("/cpus/cpu@%d", i);
140
+ ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(i));
141
+
142
+ qemu_fdt_add_subnode(s->fdt, name);
143
+ qemu_fdt_setprop_cell(s->fdt, name, "reg", armcpu->mp_affinity);
144
+ if (psci_conduit != QEMU_PSCI_CONDUIT_DISABLED) {
145
+ qemu_fdt_setprop_string(s->fdt, name, "enable-method", "psci");
146
+ }
147
+ qemu_fdt_setprop_string(s->fdt, name, "device_type", "cpu");
148
+ qemu_fdt_setprop_string(s->fdt, name, "compatible",
149
+ armcpu->dtb_compatible);
150
+ g_free(name);
151
+ }
152
+}
153
+
154
+static void fdt_add_gic_nodes(VersalVirt *s)
155
+{
156
+ char *nodename;
157
+
158
+ nodename = g_strdup_printf("/gic@%x", MM_GIC_APU_DIST_MAIN);
159
+ qemu_fdt_add_subnode(s->fdt, nodename);
160
+ qemu_fdt_setprop_cell(s->fdt, nodename, "phandle", s->phandle.gic);
161
+ qemu_fdt_setprop_cells(s->fdt, nodename, "interrupts",
162
+ GIC_FDT_IRQ_TYPE_PPI, VERSAL_GIC_MAINT_IRQ,
163
+ GIC_FDT_IRQ_FLAGS_LEVEL_HI);
164
+ qemu_fdt_setprop(s->fdt, nodename, "interrupt-controller", NULL, 0);
165
+ qemu_fdt_setprop_sized_cells(s->fdt, nodename, "reg",
166
+ 2, MM_GIC_APU_DIST_MAIN,
167
+ 2, MM_GIC_APU_DIST_MAIN_SIZE,
168
+ 2, MM_GIC_APU_REDIST_0,
169
+ 2, MM_GIC_APU_REDIST_0_SIZE);
170
+ qemu_fdt_setprop_cell(s->fdt, nodename, "#interrupt-cells", 3);
171
+ qemu_fdt_setprop_string(s->fdt, nodename, "compatible", "arm,gic-v3");
172
+}
173
+
174
+static void fdt_add_timer_nodes(VersalVirt *s)
175
+{
176
+ const char compat[] = "arm,armv8-timer";
177
+ uint32_t irqflags = GIC_FDT_IRQ_FLAGS_LEVEL_HI;
178
+
179
+ qemu_fdt_add_subnode(s->fdt, "/timer");
180
+ qemu_fdt_setprop_cells(s->fdt, "/timer", "interrupts",
181
+ GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_S_EL1_IRQ, irqflags,
182
+ GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_NS_EL1_IRQ, irqflags,
183
+ GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_VIRT_IRQ, irqflags,
184
+ GIC_FDT_IRQ_TYPE_PPI, VERSAL_TIMER_NS_EL2_IRQ, irqflags);
185
+ qemu_fdt_setprop(s->fdt, "/timer", "compatible",
186
+ compat, sizeof(compat));
187
+}
188
+
189
+static void fdt_add_uart_nodes(VersalVirt *s)
190
+{
191
+ uint64_t addrs[] = { MM_UART1, MM_UART0 };
192
+ unsigned int irqs[] = { VERSAL_UART1_IRQ_0, VERSAL_UART0_IRQ_0 };
193
+ const char compat[] = "arm,pl011\0arm,sbsa-uart";
194
+ const char clocknames[] = "uartclk\0apb_pclk";
195
+ int i;
196
+
197
+ for (i = 0; i < ARRAY_SIZE(addrs); i++) {
198
+ char *name = g_strdup_printf("/uart@%" PRIx64, addrs[i]);
199
+ qemu_fdt_add_subnode(s->fdt, name);
200
+ qemu_fdt_setprop_cell(s->fdt, name, "current-speed", 115200);
201
+ qemu_fdt_setprop_cells(s->fdt, name, "clocks",
202
+ s->phandle.clk_125Mhz, s->phandle.clk_125Mhz);
203
+ qemu_fdt_setprop(s->fdt, name, "clock-names",
204
+ clocknames, sizeof(clocknames));
205
+
206
+ qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
207
+ GIC_FDT_IRQ_TYPE_SPI, irqs[i],
208
+ GIC_FDT_IRQ_FLAGS_LEVEL_HI);
209
+ qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
210
+ 2, addrs[i], 2, 0x1000);
211
+ qemu_fdt_setprop(s->fdt, name, "compatible",
212
+ compat, sizeof(compat));
213
+ qemu_fdt_setprop(s->fdt, name, "u-boot,dm-pre-reloc", NULL, 0);
214
+
215
+ if (addrs[i] == MM_UART0) {
216
+ /* Select UART0. */
217
+ qemu_fdt_setprop_string(s->fdt, "/chosen", "stdout-path", name);
218
+ }
219
+ g_free(name);
220
+ }
221
+}
222
+
223
+static void fdt_add_fixed_link_nodes(VersalVirt *s, char *gemname,
224
+ uint32_t phandle)
225
+{
226
+ char *name = g_strdup_printf("%s/fixed-link", gemname);
227
+
228
+ qemu_fdt_add_subnode(s->fdt, name);
229
+ qemu_fdt_setprop_cell(s->fdt, name, "phandle", phandle);
230
+ qemu_fdt_setprop(s->fdt, name, "full-duplex", NULL, 0);
231
+ qemu_fdt_setprop_cell(s->fdt, name, "speed", 1000);
232
+ g_free(name);
233
+}
234
+
235
+static void fdt_add_gem_nodes(VersalVirt *s)
236
+{
237
+ uint64_t addrs[] = { MM_GEM1, MM_GEM0 };
238
+ unsigned int irqs[] = { VERSAL_GEM1_IRQ_0, VERSAL_GEM0_IRQ_0 };
239
+ const char clocknames[] = "pclk\0hclk\0tx_clk\0rx_clk";
240
+ const char compat_gem[] = "cdns,zynqmp-gem\0cdns,gem";
241
+ int i;
242
+
243
+ for (i = 0; i < ARRAY_SIZE(addrs); i++) {
244
+ char *name = g_strdup_printf("/ethernet@%" PRIx64, addrs[i]);
245
+ qemu_fdt_add_subnode(s->fdt, name);
246
+
247
+ fdt_add_fixed_link_nodes(s, name, s->phandle.ethernet_phy[i]);
248
+ qemu_fdt_setprop_string(s->fdt, name, "phy-mode", "rgmii-id");
249
+ qemu_fdt_setprop_cell(s->fdt, name, "phy-handle",
250
+ s->phandle.ethernet_phy[i]);
251
+ qemu_fdt_setprop_cells(s->fdt, name, "clocks",
252
+ s->phandle.clk_25Mhz, s->phandle.clk_25Mhz,
253
+ s->phandle.clk_25Mhz, s->phandle.clk_25Mhz);
254
+ qemu_fdt_setprop(s->fdt, name, "clock-names",
255
+ clocknames, sizeof(clocknames));
256
+ qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
257
+ GIC_FDT_IRQ_TYPE_SPI, irqs[i],
258
+ GIC_FDT_IRQ_FLAGS_LEVEL_HI,
259
+ GIC_FDT_IRQ_TYPE_SPI, irqs[i],
260
+ GIC_FDT_IRQ_FLAGS_LEVEL_HI);
261
+ qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
262
+ 2, addrs[i], 2, 0x1000);
263
+ qemu_fdt_setprop(s->fdt, name, "compatible",
264
+ compat_gem, sizeof(compat_gem));
265
+ qemu_fdt_setprop_cell(s->fdt, name, "#address-cells", 1);
266
+ qemu_fdt_setprop_cell(s->fdt, name, "#size-cells", 0);
267
+ g_free(name);
268
+ }
269
+}
270
+
271
+static void fdt_nop_memory_nodes(void *fdt, Error **errp)
272
+{
273
+ Error *err = NULL;
274
+ char **node_path;
275
+ int n = 0;
276
+
277
+ node_path = qemu_fdt_node_unit_path(fdt, "memory", &err);
278
+ if (err) {
279
+ error_propagate(errp, err);
280
+ return;
281
+ }
282
+ while (node_path[n]) {
283
+ if (g_str_has_prefix(node_path[n], "/memory")) {
284
+ qemu_fdt_nop_node(fdt, node_path[n]);
285
+ }
286
+ n++;
287
+ }
288
+ g_strfreev(node_path);
289
+}
290
+
291
+static void fdt_add_memory_nodes(VersalVirt *s, void *fdt, uint64_t ram_size)
292
+{
293
+ /* Describes the various split DDR access regions. */
294
+ static const struct {
295
+ uint64_t base;
296
+ uint64_t size;
297
+ } addr_ranges[] = {
298
+ { MM_TOP_DDR, MM_TOP_DDR_SIZE },
299
+ { MM_TOP_DDR_2, MM_TOP_DDR_2_SIZE },
300
+ { MM_TOP_DDR_3, MM_TOP_DDR_3_SIZE },
301
+ { MM_TOP_DDR_4, MM_TOP_DDR_4_SIZE }
302
+ };
303
+ uint64_t mem_reg_prop[8] = {0};
304
+ uint64_t size = ram_size;
305
+ Error *err = NULL;
306
+ char *name;
307
+ int i;
308
+
309
+ fdt_nop_memory_nodes(fdt, &err);
310
+ if (err) {
311
+ error_report_err(err);
312
+ return;
313
+ }
314
+
315
+ name = g_strdup_printf("/memory@%x", MM_TOP_DDR);
316
+ for (i = 0; i < ARRAY_SIZE(addr_ranges) && size; i++) {
317
+ uint64_t mapsize;
318
+
319
+ mapsize = size < addr_ranges[i].size ? size : addr_ranges[i].size;
320
+
321
+ mem_reg_prop[i * 2] = addr_ranges[i].base;
322
+ mem_reg_prop[i * 2 + 1] = mapsize;
323
+ size -= mapsize;
324
+ }
325
+ qemu_fdt_add_subnode(fdt, name);
326
+ qemu_fdt_setprop_string(fdt, name, "device_type", "memory");
327
+
328
+ switch (i) {
329
+ case 1:
330
+ qemu_fdt_setprop_sized_cells(fdt, name, "reg",
331
+ 2, mem_reg_prop[0],
332
+ 2, mem_reg_prop[1]);
333
+ break;
334
+ case 2:
335
+ qemu_fdt_setprop_sized_cells(fdt, name, "reg",
336
+ 2, mem_reg_prop[0],
337
+ 2, mem_reg_prop[1],
338
+ 2, mem_reg_prop[2],
339
+ 2, mem_reg_prop[3]);
340
+ break;
341
+ case 3:
342
+ qemu_fdt_setprop_sized_cells(fdt, name, "reg",
343
+ 2, mem_reg_prop[0],
344
+ 2, mem_reg_prop[1],
345
+ 2, mem_reg_prop[2],
346
+ 2, mem_reg_prop[3],
347
+ 2, mem_reg_prop[4],
348
+ 2, mem_reg_prop[5]);
349
+ break;
350
+ case 4:
351
+ qemu_fdt_setprop_sized_cells(fdt, name, "reg",
352
+ 2, mem_reg_prop[0],
353
+ 2, mem_reg_prop[1],
354
+ 2, mem_reg_prop[2],
355
+ 2, mem_reg_prop[3],
356
+ 2, mem_reg_prop[4],
357
+ 2, mem_reg_prop[5],
358
+ 2, mem_reg_prop[6],
359
+ 2, mem_reg_prop[7]);
360
+ break;
361
+ default:
362
+ g_assert_not_reached();
363
+ }
364
+ g_free(name);
365
+}
366
+
367
+static void versal_virt_modify_dtb(const struct arm_boot_info *binfo,
368
+ void *fdt)
369
+{
370
+ VersalVirt *s = container_of(binfo, VersalVirt, binfo);
371
+
372
+ fdt_add_memory_nodes(s, fdt, binfo->ram_size);
373
+}
374
+
375
+static void *versal_virt_get_dtb(const struct arm_boot_info *binfo,
376
+ int *fdt_size)
377
+{
378
+ const VersalVirt *board = container_of(binfo, VersalVirt, binfo);
379
+
380
+ *fdt_size = board->fdt_size;
381
+ return board->fdt;
382
+}
383
+
384
+#define NUM_VIRTIO_TRANSPORT 32
385
+static void create_virtio_regions(VersalVirt *s)
386
+{
387
+ int virtio_mmio_size = 0x200;
388
+ int i;
389
+
390
+ for (i = 0; i < NUM_VIRTIO_TRANSPORT; i++) {
391
+ char *name = g_strdup_printf("virtio%d", i);;
392
+ hwaddr base = MM_TOP_RSVD + i * virtio_mmio_size;
393
+ int irq = VERSAL_RSVD_HIGH_IRQ_FIRST + i;
394
+ MemoryRegion *mr;
395
+ DeviceState *dev;
396
+ qemu_irq pic_irq;
397
+
398
+ pic_irq = qdev_get_gpio_in(DEVICE(&s->soc.fpd.apu.gic), irq);
399
+ dev = qdev_create(NULL, "virtio-mmio");
400
+ object_property_add_child(OBJECT(&s->soc), name, OBJECT(dev),
401
+ &error_fatal);
402
+ qdev_init_nofail(dev);
403
+ sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic_irq);
404
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
405
+ memory_region_add_subregion(&s->soc.mr_ps, base, mr);
406
+ sysbus_create_simple("virtio-mmio", base, pic_irq);
407
+ }
408
+
409
+ for (i = 0; i < NUM_VIRTIO_TRANSPORT; i++) {
410
+ hwaddr base = MM_TOP_RSVD + i * virtio_mmio_size;
411
+ int irq = VERSAL_RSVD_HIGH_IRQ_FIRST + i;
412
+ char *name = g_strdup_printf("/virtio_mmio@%" PRIx64, base);
413
+
414
+ qemu_fdt_add_subnode(s->fdt, name);
415
+ qemu_fdt_setprop(s->fdt, name, "dma-coherent", NULL, 0);
416
+ qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
417
+ GIC_FDT_IRQ_TYPE_SPI, irq,
418
+ GIC_FDT_IRQ_FLAGS_EDGE_LO_HI);
419
+ qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
420
+ 2, base, 2, virtio_mmio_size);
421
+ qemu_fdt_setprop_string(s->fdt, name, "compatible", "virtio,mmio");
422
+ g_free(name);
423
+ }
424
+}
425
+
426
+static void versal_virt_init(MachineState *machine)
427
+{
428
+ VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(machine);
429
+ int psci_conduit = QEMU_PSCI_CONDUIT_DISABLED;
135
+
430
+
136
+ /*
431
+ /*
137
+ * We need to create splitters to feed the IRQ inputs
432
+ * If the user provides an Operating System to be loaded, we expect them
138
+ * for each CPU in the SSE-200 from each device in the board.
433
+ * to use the -kernel command line option.
434
+ *
435
+ * Users can load firmware or boot-loaders with the -device loader options.
436
+ *
437
+ * When loading an OS, we generate a dtb and let arm_load_kernel() select
438
+ * where it gets loaded. This dtb will be passed to the kernel in x0.
439
+ *
440
+ * If there's no -kernel option, we generate a DTB and place it at 0x1000
441
+ * for the bootloaders or firmware to pick up.
442
+ *
443
+ * If users want to provide their own DTB, they can use the -dtb option.
444
+ * These dtb's will have their memory nodes modified to match QEMU's
445
+ * selected ram_size option before they get passed to the kernel or fw.
446
+ *
447
+ * When loading an OS, we turn on QEMU's PSCI implementation with SMC
448
+ * as the PSCI conduit. When there's no -kernel, we assume the user
449
+ * provides EL3 firmware to handle PSCI.
139
+ */
450
+ */
140
+ for (i = 0; i < mmc->num_irqs; i++) {
451
+ if (machine->kernel_filename) {
141
+ char *name = g_strdup_printf("musca-irq-splitter%d", i);
452
+ psci_conduit = QEMU_PSCI_CONDUIT_SMC;
142
+ SplitIRQ *splitter = &mms->cpu_irq_splitter[i];
453
+ }
143
+
454
+
144
+ object_initialize_child(OBJECT(machine), name,
455
+ memory_region_allocate_system_memory(&s->mr_ddr, NULL, "ddr",
145
+ splitter, sizeof(*splitter),
456
+ machine->ram_size);
146
+ TYPE_SPLIT_IRQ, &error_fatal, NULL);
457
+
147
+ g_free(name);
458
+ sysbus_init_child_obj(OBJECT(machine), "xlnx-ve", &s->soc,
148
+
459
+ sizeof(s->soc), TYPE_XLNX_VERSAL);
149
+ object_property_set_int(OBJECT(splitter), 2, "num-lines",
460
+ object_property_set_link(OBJECT(&s->soc), OBJECT(&s->mr_ddr),
150
+ &error_fatal);
461
+ "ddr", &error_abort);
151
+ object_property_set_bool(OBJECT(splitter), true, "realized",
462
+ object_property_set_int(OBJECT(&s->soc), psci_conduit,
152
+ &error_fatal);
463
+ "psci-conduit", &error_abort);
153
+ qdev_connect_gpio_out(DEVICE(splitter), 0,
464
+ object_property_set_bool(OBJECT(&s->soc), true, "realized", &error_fatal);
154
+ qdev_get_gpio_in_named(ssedev, "EXP_IRQ", i));
465
+
155
+ qdev_connect_gpio_out(DEVICE(splitter), 1,
466
+ fdt_create(s);
156
+ qdev_get_gpio_in_named(ssedev,
467
+ create_virtio_regions(s);
157
+ "EXP_CPU1_IRQ", i));
468
+ fdt_add_gem_nodes(s);
158
+ }
469
+ fdt_add_uart_nodes(s);
159
+
470
+ fdt_add_gic_nodes(s);
160
+ armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x2000000);
471
+ fdt_add_timer_nodes(s);
161
+}
472
+ fdt_add_cpu_nodes(s, psci_conduit);
162
+
473
+ fdt_add_clk_node(s, "/clk125", 125000000, s->phandle.clk_125Mhz);
163
+static void musca_class_init(ObjectClass *oc, void *data)
474
+ fdt_add_clk_node(s, "/clk25", 25000000, s->phandle.clk_25Mhz);
475
+
476
+ /* Make the APU cpu address space visible to virtio and other
477
+ * modules unaware of muliple address-spaces. */
478
+ memory_region_add_subregion_overlap(get_system_memory(),
479
+ 0, &s->soc.fpd.apu.mr, 0);
480
+
481
+ s->binfo.ram_size = machine->ram_size;
482
+ s->binfo.kernel_filename = machine->kernel_filename;
483
+ s->binfo.kernel_cmdline = machine->kernel_cmdline;
484
+ s->binfo.initrd_filename = machine->initrd_filename;
485
+ s->binfo.loader_start = 0x0;
486
+ s->binfo.get_dtb = versal_virt_get_dtb;
487
+ s->binfo.modify_dtb = versal_virt_modify_dtb;
488
+ if (machine->kernel_filename) {
489
+ arm_load_kernel(s->soc.fpd.apu.cpu[0], &s->binfo);
490
+ } else {
491
+ AddressSpace *as = arm_boot_address_space(s->soc.fpd.apu.cpu[0],
492
+ &s->binfo);
493
+ /* Some boot-loaders (e.g u-boot) don't like blobs at address 0 (NULL).
494
+ * Offset things by 4K. */
495
+ s->binfo.loader_start = 0x1000;
496
+ s->binfo.dtb_limit = 0x1000000;
497
+ if (arm_load_dtb(s->binfo.loader_start,
498
+ &s->binfo, s->binfo.dtb_limit, as) < 0) {
499
+ exit(EXIT_FAILURE);
500
+ }
501
+ }
502
+}
503
+
504
+static void versal_virt_machine_instance_init(Object *obj)
505
+{
506
+}
507
+
508
+static void versal_virt_machine_class_init(ObjectClass *oc, void *data)
164
+{
509
+{
165
+ MachineClass *mc = MACHINE_CLASS(oc);
510
+ MachineClass *mc = MACHINE_CLASS(oc);
166
+
511
+
167
+ mc->default_cpus = 2;
512
+ mc->desc = "Xilinx Versal Virtual development board";
168
+ mc->min_cpus = mc->default_cpus;
513
+ mc->init = versal_virt_init;
169
+ mc->max_cpus = mc->default_cpus;
514
+ mc->max_cpus = XLNX_VERSAL_NR_ACPUS;
170
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
515
+ mc->default_cpus = XLNX_VERSAL_NR_ACPUS;
171
+ mc->init = musca_init;
516
+ mc->no_cdrom = true;
172
+}
517
+}
173
+
518
+
174
+static void musca_a_class_init(ObjectClass *oc, void *data)
519
+static const TypeInfo versal_virt_machine_init_typeinfo = {
175
+{
520
+ .name = TYPE_XLNX_VERSAL_VIRT_MACHINE,
176
+ MachineClass *mc = MACHINE_CLASS(oc);
521
+ .parent = TYPE_MACHINE,
177
+ MuscaMachineClass *mmc = MUSCA_MACHINE_CLASS(oc);
522
+ .class_init = versal_virt_machine_class_init,
178
+
523
+ .instance_init = versal_virt_machine_instance_init,
179
+ mc->desc = "ARM Musca-A board (dual Cortex-M33)";
524
+ .instance_size = sizeof(VersalVirt),
180
+ mmc->type = MUSCA_A;
181
+ mmc->init_svtor = 0x10200000;
182
+ mmc->sram_addr_width = 15;
183
+ mmc->num_irqs = 64;
184
+}
185
+
186
+static void musca_b1_class_init(ObjectClass *oc, void *data)
187
+{
188
+ MachineClass *mc = MACHINE_CLASS(oc);
189
+ MuscaMachineClass *mmc = MUSCA_MACHINE_CLASS(oc);
190
+
191
+ mc->desc = "ARM Musca-B1 board (dual Cortex-M33)";
192
+ mmc->type = MUSCA_B1;
193
+ /*
194
+ * This matches the DAPlink firmware which boots from QSPI. There
195
+ * is also a firmware blob which boots from the eFlash, which
196
+ * uses init_svtor = 0x1A000000. QEMU doesn't currently support that,
197
+ * though we could in theory expose a machine property on the command
198
+ * line to allow the user to request eFlash boot.
199
+ */
200
+ mmc->init_svtor = 0x10000000;
201
+ mmc->sram_addr_width = 17;
202
+ mmc->num_irqs = 96;
203
+}
204
+
205
+static const TypeInfo musca_info = {
206
+ .name = TYPE_MUSCA_MACHINE,
207
+ .parent = TYPE_MACHINE,
208
+ .abstract = true,
209
+ .instance_size = sizeof(MuscaMachineState),
210
+ .class_size = sizeof(MuscaMachineClass),
211
+ .class_init = musca_class_init,
212
+};
525
+};
213
+
526
+
214
+static const TypeInfo musca_a_info = {
527
+static void versal_virt_machine_init_register_types(void)
215
+ .name = TYPE_MUSCA_A_MACHINE,
528
+{
216
+ .parent = TYPE_MUSCA_MACHINE,
529
+ type_register_static(&versal_virt_machine_init_typeinfo);
217
+ .class_init = musca_a_class_init,
530
+}
218
+};
531
+
219
+
532
+type_init(versal_virt_machine_init_register_types)
220
+static const TypeInfo musca_b1_info = {
533
+
221
+ .name = TYPE_MUSCA_B1_MACHINE,
222
+ .parent = TYPE_MUSCA_MACHINE,
223
+ .class_init = musca_b1_class_init,
224
+};
225
+
226
+static void musca_machine_init(void)
227
+{
228
+ type_register_static(&musca_info);
229
+ type_register_static(&musca_a_info);
230
+ type_register_static(&musca_b1_info);
231
+}
232
+
233
+type_init(musca_machine_init);
234
diff --git a/MAINTAINERS b/MAINTAINERS
235
index XXXXXXX..XXXXXXX 100644
236
--- a/MAINTAINERS
237
+++ b/MAINTAINERS
238
@@ -XXX,XX +XXX,XX @@ F: include/hw/misc/iotkit-sysinfo.h
239
F: hw/misc/armsse-cpuid.c
240
F: include/hw/misc/armsse-cpuid.h
241
242
+Musca
243
+M: Peter Maydell <peter.maydell@linaro.org>
244
+L: qemu-arm@nongnu.org
245
+S: Maintained
246
+F: hw/arm/musca.c
247
+
248
Musicpal
249
M: Jan Kiszka <jan.kiszka@web.de>
250
M: Peter Maydell <peter.maydell@linaro.org>
251
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
252
index XXXXXXX..XXXXXXX 100644
253
--- a/default-configs/arm-softmmu.mak
254
+++ b/default-configs/arm-softmmu.mak
255
@@ -XXX,XX +XXX,XX @@ CONFIG_TUSB6010=y
256
CONFIG_IMX=y
257
CONFIG_MAINSTONE=y
258
CONFIG_MPS2=y
259
+CONFIG_MUSCA=y
260
CONFIG_NSERIES=y
261
CONFIG_RASPI=y
262
CONFIG_REALVIEW=y
263
--
534
--
264
2.20.1
535
2.19.1
265
536
266
537
diff view generated by jsdifflib
Deleted patch
1
Wire up the PL031 RTC for the Musca board.
2
1
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
---
6
hw/arm/musca.c | 26 +++++++++++++++++++++++---
7
1 file changed, 23 insertions(+), 3 deletions(-)
8
9
diff --git a/hw/arm/musca.c b/hw/arm/musca.c
10
index XXXXXXX..XXXXXXX 100644
11
--- a/hw/arm/musca.c
12
+++ b/hw/arm/musca.c
13
@@ -XXX,XX +XXX,XX @@
14
#include "hw/misc/tz-mpc.h"
15
#include "hw/misc/tz-ppc.h"
16
#include "hw/misc/unimp.h"
17
+#include "hw/timer/pl031.h"
18
19
#define MUSCA_NUMIRQ_MAX 96
20
#define MUSCA_PPC_MAX 3
21
@@ -XXX,XX +XXX,XX @@ typedef struct {
22
UnimplementedDeviceState spi;
23
UnimplementedDeviceState scc;
24
UnimplementedDeviceState timer;
25
- UnimplementedDeviceState rtc;
26
+ PL031State rtc;
27
UnimplementedDeviceState pvt;
28
UnimplementedDeviceState sdio;
29
UnimplementedDeviceState gpio;
30
@@ -XXX,XX +XXX,XX @@ typedef struct {
31
*/
32
#define SYSCLK_FRQ 40000000
33
34
+static qemu_irq get_sse_irq_in(MuscaMachineState *mms, int irqno)
35
+{
36
+ /* Return a qemu_irq which will signal IRQ n to all CPUs in the SSE. */
37
+ assert(irqno < MUSCA_NUMIRQ_MAX);
38
+
39
+ return qdev_get_gpio_in(DEVICE(&mms->cpu_irq_splitter[irqno]), 0);
40
+}
41
+
42
/*
43
* Most of the devices in the Musca board sit behind Peripheral Protection
44
* Controllers. These data structures define the layout of which devices
45
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_mpc(MuscaMachineState *mms, void *opaque,
46
return sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 0);
47
}
48
49
+static MemoryRegion *make_rtc(MuscaMachineState *mms, void *opaque,
50
+ const char *name, hwaddr size)
51
+{
52
+ PL031State *rtc = opaque;
53
+
54
+ sysbus_init_child_obj(OBJECT(mms), name, rtc, sizeof(mms->rtc), TYPE_PL031);
55
+ object_property_set_bool(OBJECT(rtc), true, "realized", &error_fatal);
56
+ sysbus_connect_irq(SYS_BUS_DEVICE(rtc), 0, get_sse_irq_in(mms, 39));
57
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(rtc), 0);
58
+}
59
+
60
static MemoryRegion *make_musca_a_devs(MuscaMachineState *mms, void *opaque,
61
const char *name, hwaddr size)
62
{
63
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_musca_a_devs(MuscaMachineState *mms, void *opaque,
64
{ "i2c1", make_unimp_dev, &mms->i2c[1], 0x5000, 0x1000 },
65
{ "i2s", make_unimp_dev, &mms->i2s, 0x6000, 0x1000 },
66
{ "pwm0", make_unimp_dev, &mms->pwm[0], 0x7000, 0x1000 },
67
- { "rtc", make_unimp_dev, &mms->rtc, 0x8000, 0x1000 },
68
+ { "rtc", make_rtc, &mms->rtc, 0x8000, 0x1000 },
69
{ "qspi", make_unimp_dev, &mms->qspi, 0xa000, 0x1000 },
70
{ "timer", make_unimp_dev, &mms->timer, 0xb000, 0x1000 },
71
{ "scc", make_unimp_dev, &mms->scc, 0xc000, 0x1000 },
72
@@ -XXX,XX +XXX,XX @@ static void musca_init(MachineState *machine)
73
{ "spi", make_unimp_dev, &mms->spi, 0x4010a000, 0x1000 },
74
{ "scc", make_unimp_dev, &mms->scc, 0x5010b000, 0x1000 },
75
{ "timer", make_unimp_dev, &mms->timer, 0x4010c000, 0x1000 },
76
- { "rtc", make_unimp_dev, &mms->rtc, 0x4010d000, 0x1000 },
77
+ { "rtc", make_rtc, &mms->rtc, 0x4010d000, 0x1000 },
78
{ "pvt", make_unimp_dev, &mms->pvt, 0x4010e000, 0x1000 },
79
{ "sdio", make_unimp_dev, &mms->sdio, 0x4010f000, 0x1000 },
80
},
81
--
82
2.20.1
83
84
diff view generated by jsdifflib
Deleted patch
1
Wire up the two PL011 UARTs in the Musca board.
2
1
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
---
6
hw/arm/musca.c | 34 +++++++++++++++++++++++++++++-----
7
1 file changed, 29 insertions(+), 5 deletions(-)
8
9
diff --git a/hw/arm/musca.c b/hw/arm/musca.c
10
index XXXXXXX..XXXXXXX 100644
11
--- a/hw/arm/musca.c
12
+++ b/hw/arm/musca.c
13
@@ -XXX,XX +XXX,XX @@
14
#include "qemu/error-report.h"
15
#include "qapi/error.h"
16
#include "exec/address-spaces.h"
17
+#include "sysemu/sysemu.h"
18
#include "hw/arm/arm.h"
19
#include "hw/arm/armsse.h"
20
#include "hw/boards.h"
21
+#include "hw/char/pl011.h"
22
#include "hw/core/split-irq.h"
23
#include "hw/misc/tz-mpc.h"
24
#include "hw/misc/tz-ppc.h"
25
@@ -XXX,XX +XXX,XX @@ typedef struct {
26
UnimplementedDeviceState mhu[2];
27
UnimplementedDeviceState pwm[3];
28
UnimplementedDeviceState i2s;
29
- UnimplementedDeviceState uart[2];
30
+ PL011State uart[2];
31
UnimplementedDeviceState i2c[2];
32
UnimplementedDeviceState spi;
33
UnimplementedDeviceState scc;
34
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_rtc(MuscaMachineState *mms, void *opaque,
35
return sysbus_mmio_get_region(SYS_BUS_DEVICE(rtc), 0);
36
}
37
38
+static MemoryRegion *make_uart(MuscaMachineState *mms, void *opaque,
39
+ const char *name, hwaddr size)
40
+{
41
+ PL011State *uart = opaque;
42
+ int i = uart - &mms->uart[0];
43
+ int irqbase = 7 + i * 6;
44
+ SysBusDevice *s;
45
+
46
+ sysbus_init_child_obj(OBJECT(mms), name, uart, sizeof(mms->uart[0]),
47
+ TYPE_PL011);
48
+ qdev_prop_set_chr(DEVICE(uart), "chardev", serial_hd(i));
49
+ object_property_set_bool(OBJECT(uart), true, "realized", &error_fatal);
50
+ s = SYS_BUS_DEVICE(uart);
51
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqbase + 5)); /* combined */
52
+ sysbus_connect_irq(s, 1, get_sse_irq_in(mms, irqbase + 0)); /* RX */
53
+ sysbus_connect_irq(s, 2, get_sse_irq_in(mms, irqbase + 1)); /* TX */
54
+ sysbus_connect_irq(s, 3, get_sse_irq_in(mms, irqbase + 2)); /* RT */
55
+ sysbus_connect_irq(s, 4, get_sse_irq_in(mms, irqbase + 3)); /* MS */
56
+ sysbus_connect_irq(s, 5, get_sse_irq_in(mms, irqbase + 4)); /* E */
57
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(uart), 0);
58
+}
59
+
60
static MemoryRegion *make_musca_a_devs(MuscaMachineState *mms, void *opaque,
61
const char *name, hwaddr size)
62
{
63
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_musca_a_devs(MuscaMachineState *mms, void *opaque,
64
MemoryRegion *container = &mms->container;
65
66
const PPCPortInfo devices[] = {
67
- { "uart0", make_unimp_dev, &mms->uart[0], 0x1000, 0x1000 },
68
- { "uart1", make_unimp_dev, &mms->uart[1], 0x2000, 0x1000 },
69
+ { "uart0", make_uart, &mms->uart[0], 0x1000, 0x1000 },
70
+ { "uart1", make_uart, &mms->uart[1], 0x2000, 0x1000 },
71
{ "spi", make_unimp_dev, &mms->spi, 0x3000, 0x1000 },
72
{ "i2c0", make_unimp_dev, &mms->i2c[0], 0x4000, 0x1000 },
73
{ "i2c1", make_unimp_dev, &mms->i2c[1], 0x5000, 0x1000 },
74
@@ -XXX,XX +XXX,XX @@ static void musca_init(MachineState *machine)
75
{ "pwm1", make_unimp_dev, &mms->pwm[1], 0x40102000, 0x1000 },
76
{ "pwm2", make_unimp_dev, &mms->pwm[2], 0x40103000, 0x1000 },
77
{ "i2s", make_unimp_dev, &mms->i2s, 0x40104000, 0x1000 },
78
- { "uart0", make_unimp_dev, &mms->uart[0], 0x40105000, 0x1000 },
79
- { "uart1", make_unimp_dev, &mms->uart[1], 0x40106000, 0x1000 },
80
+ { "uart0", make_uart, &mms->uart[0], 0x40105000, 0x1000 },
81
+ { "uart1", make_uart, &mms->uart[1], 0x40106000, 0x1000 },
82
{ "i2c0", make_unimp_dev, &mms->i2c[0], 0x40108000, 0x1000 },
83
{ "i2c1", make_unimp_dev, &mms->i2c[1], 0x40109000, 0x1000 },
84
{ "spi", make_unimp_dev, &mms->spi, 0x4010a000, 0x1000 },
85
--
86
2.20.1
87
88
diff view generated by jsdifflib
Deleted patch
1
The region 0x40010000 .. 0x4001ffff and its secure-only alias
2
at 0x50010000... are for per-CPU devices. We implement this by
3
giving each CPU its own container memory region, where the
4
per-CPU devices live. Unfortunately, the alias region which
5
makes devices mapped at 0x4... addresses also appear at 0x5...
6
is only implemented in the overall "all CPUs" container. The
7
effect of this bug is that the CPU_IDENTITY register block appears
8
only at 0x4001f000, but not at the 0x5001f000 alias where it should
9
also appear. Guests (like very recent Arm Trusted Firmware-M)
10
which try to access it at 0x5001f000 will crash.
11
1
12
Fix this by moving the handling for this alias from the "all CPUs"
13
container to the per-CPU container. (We leave the aliases for
14
0x1... and 0x3... in the overall container, because there are
15
no per-CPU devices there.)
16
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Message-id: 20190215180500.6906-1-peter.maydell@linaro.org
19
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
20
---
21
include/hw/arm/armsse.h | 2 +-
22
hw/arm/armsse.c | 26 ++++++++++++++++----------
23
2 files changed, 17 insertions(+), 11 deletions(-)
24
25
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
26
index XXXXXXX..XXXXXXX 100644
27
--- a/include/hw/arm/armsse.h
28
+++ b/include/hw/arm/armsse.h
29
@@ -XXX,XX +XXX,XX @@ typedef struct ARMSSE {
30
MemoryRegion cpu_container[SSE_MAX_CPUS];
31
MemoryRegion alias1;
32
MemoryRegion alias2;
33
- MemoryRegion alias3;
34
+ MemoryRegion alias3[SSE_MAX_CPUS];
35
MemoryRegion sram[MAX_SRAM_BANKS];
36
37
qemu_irq *exp_irqs[SSE_MAX_CPUS];
38
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/hw/arm/armsse.c
41
+++ b/hw/arm/armsse.c
42
@@ -XXX,XX +XXX,XX @@ static bool irq_is_common[32] = {
43
/* 30, 31: reserved */
44
};
45
46
-/* Create an alias region of @size bytes starting at @base
47
+/*
48
+ * Create an alias region in @container of @size bytes starting at @base
49
* which mirrors the memory starting at @orig.
50
*/
51
-static void make_alias(ARMSSE *s, MemoryRegion *mr, const char *name,
52
- hwaddr base, hwaddr size, hwaddr orig)
53
+static void make_alias(ARMSSE *s, MemoryRegion *mr, MemoryRegion *container,
54
+ const char *name, hwaddr base, hwaddr size, hwaddr orig)
55
{
56
- memory_region_init_alias(mr, NULL, name, &s->container, orig, size);
57
+ memory_region_init_alias(mr, NULL, name, container, orig, size);
58
/* The alias is even lower priority than unimplemented_device regions */
59
- memory_region_add_subregion_overlap(&s->container, base, mr, -1500);
60
+ memory_region_add_subregion_overlap(container, base, mr, -1500);
61
}
62
63
static void irq_status_forwarder(void *opaque, int n, int level)
64
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
65
}
66
67
/* Set up the big aliases first */
68
- make_alias(s, &s->alias1, "alias 1", 0x10000000, 0x10000000, 0x00000000);
69
- make_alias(s, &s->alias2, "alias 2", 0x30000000, 0x10000000, 0x20000000);
70
+ make_alias(s, &s->alias1, &s->container, "alias 1",
71
+ 0x10000000, 0x10000000, 0x00000000);
72
+ make_alias(s, &s->alias2, &s->container,
73
+ "alias 2", 0x30000000, 0x10000000, 0x20000000);
74
/* The 0x50000000..0x5fffffff region is not a pure alias: it has
75
* a few extra devices that only appear there (generally the
76
* control interfaces for the protection controllers).
77
* We implement this by mapping those devices over the top of this
78
- * alias MR at a higher priority.
79
+ * alias MR at a higher priority. Some of the devices in this range
80
+ * are per-CPU, so we must put this alias in the per-cpu containers.
81
*/
82
- make_alias(s, &s->alias3, "alias 3", 0x50000000, 0x10000000, 0x40000000);
83
-
84
+ for (i = 0; i < info->num_cpus; i++) {
85
+ make_alias(s, &s->alias3[i], &s->cpu_container[i],
86
+ "alias 3", 0x50000000, 0x10000000, 0x40000000);
87
+ }
88
89
/* Security controller */
90
object_property_set_bool(OBJECT(&s->secctl), true, "realized", &err);
91
--
92
2.20.1
93
94
diff view generated by jsdifflib