1
Last lot of patches for arm before softfreeze tomorrow...
1
One last arm pullreq before I stop work for the end of the year...
2
2
3
thanks
4
-- PMM
3
-- PMM
5
4
6
The following changes since commit ef3a6af5e789ff078d1fef880f9dfb6adf18e8f1:
5
The following changes since commit 8e5943260a8f765216674ee87ce8588cc4e7463e:
7
6
8
Merge remote-tracking branch 'remotes/kraxel/tags/vga-20181029-pull-request' into staging (2018-10-29 12:59:15 +0000)
7
Merge remote-tracking branch 'remotes/vivier2/tags/trivial-branch-pull-request' into staging (2019-12-20 12:46:10 +0000)
9
8
10
are available in the Git repository at:
9
are available in the Git repository at:
11
10
12
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20181029
11
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20191220
13
12
14
for you to fetch changes up to 20cf5663734310a282e27b7389bc9f53ffe227e6:
13
for you to fetch changes up to c8fa6079eb35888587f1be27c1590da4edcc5098:
15
14
16
tests/boot-serial-test: Add microbit board testcase (2018-10-29 15:19:48 +0000)
15
arm/arm-powerctl: rebuild hflags after setting CP15 bits in arm_set_cpu_on() (2019-12-20 14:03:00 +0000)
17
16
18
----------------------------------------------------------------
17
----------------------------------------------------------------
19
target-arm queue:
18
target-arm queue:
20
* microbit: Add the UART to our nRF51 SoC model
19
* Support emulating the generic timers at frequencies other than 62.5MHz
21
* Add a virtual Xilinx Versal board "xlnx-versal-virt"
20
* Various fixes for SMMUv3 emulation bugs
22
* hw/arm/virt: Set VIRT_COMPAT_3_0 compat
21
* Improve assert error message for hflags mismatches
22
* arm-powerctl: rebuild hflags after setting CP15 bits in arm_set_cpu_on()
23
23
24
----------------------------------------------------------------
24
----------------------------------------------------------------
25
Edgar E. Iglesias (2):
25
Andrew Jeffery (4):
26
hw/arm: versal: Add a model of Xilinx Versal SoC
26
target/arm: Remove redundant scaling of nexttick
27
hw/arm: versal: Add a virtual Xilinx Versal board
27
target/arm: Abstract the generic timer frequency
28
target/arm: Prepare generic timer for per-platform CNTFRQ
29
ast2600: Configure CNTFRQ at 1125MHz
28
30
29
Eric Auger (1):
31
Niek Linnenbank (1):
30
hw/arm/virt: Set VIRT_COMPAT_3_0 compat
32
arm/arm-powerctl: rebuild hflags after setting CP15 bits in arm_set_cpu_on()
31
33
32
Julia Suvorova (3):
34
Philippe Mathieu-Daudé (1):
33
hw/char: Implement nRF51 SoC UART
35
target/arm: Display helpful message when hflags mismatch
34
hw/arm/nrf51_soc: Connect UART to nRF51 SoC
35
tests/boot-serial-test: Add microbit board testcase
36
36
37
hw/arm/Makefile.objs | 1 +
37
Simon Veith (6):
38
hw/char/Makefile.objs | 1 +
38
hw/arm/smmuv3: Apply address mask to linear strtab base address
39
include/hw/arm/nrf51_soc.h | 3 +
39
hw/arm/smmuv3: Correct SMMU_BASE_ADDR_MASK value
40
include/hw/arm/xlnx-versal.h | 122 +++++++++
40
hw/arm/smmuv3: Check stream IDs against actual table LOG2SIZE
41
include/hw/char/nrf51_uart.h | 78 ++++++
41
hw/arm/smmuv3: Align stream table base address to table size
42
hw/arm/microbit.c | 2 +
42
hw/arm/smmuv3: Use correct bit positions in EVT_SET_ADDR2 macro
43
hw/arm/nrf51_soc.c | 20 ++
43
hw/arm/smmuv3: Report F_STE_FETCH fault address in correct word position
44
hw/arm/virt.c | 4 +
45
hw/arm/xlnx-versal-virt.c | 493 ++++++++++++++++++++++++++++++++++++
46
hw/arm/xlnx-versal.c | 323 +++++++++++++++++++++++
47
hw/char/nrf51_uart.c | 330 ++++++++++++++++++++++++
48
tests/boot-serial-test.c | 19 ++
49
default-configs/aarch64-softmmu.mak | 1 +
50
hw/char/trace-events | 4 +
51
14 files changed, 1401 insertions(+)
52
create mode 100644 include/hw/arm/xlnx-versal.h
53
create mode 100644 include/hw/char/nrf51_uart.h
54
create mode 100644 hw/arm/xlnx-versal-virt.c
55
create mode 100644 hw/arm/xlnx-versal.c
56
create mode 100644 hw/char/nrf51_uart.c
57
44
45
hw/arm/smmuv3-internal.h | 6 ++---
46
target/arm/cpu.h | 5 ++++
47
hw/arm/aspeed_ast2600.c | 3 +++
48
hw/arm/smmuv3.c | 28 +++++++++++++++-----
49
target/arm/arm-powerctl.c | 3 +++
50
target/arm/cpu.c | 65 +++++++++++++++++++++++++++++++++++++++++------
51
target/arm/helper.c | 42 +++++++++++++++++++++++-------
52
7 files changed, 125 insertions(+), 27 deletions(-)
53
diff view generated by jsdifflib
New patch
1
From: Andrew Jeffery <andrew@aj.id.au>
1
2
3
The corner-case codepath was adjusting nexttick such that overflow
4
wouldn't occur when timer_mod() scaled the value back up. Remove a use
5
of GTIMER_SCALE and avoid unnecessary operations by calling
6
timer_mod_ns() directly.
7
8
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Cédric Le Goater <clg@kaod.org>
11
Message-id: f8c680720e3abe55476e6d9cb604ad27fdbeb2e0.1576215453.git-series.andrew@aj.id.au
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
target/arm/helper.c | 5 +++--
15
1 file changed, 3 insertions(+), 2 deletions(-)
16
17
diff --git a/target/arm/helper.c b/target/arm/helper.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper.c
20
+++ b/target/arm/helper.c
21
@@ -XXX,XX +XXX,XX @@ static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
22
* timer expires we will reset the timer for any remaining period.
23
*/
24
if (nexttick > INT64_MAX / GTIMER_SCALE) {
25
- nexttick = INT64_MAX / GTIMER_SCALE;
26
+ timer_mod_ns(cpu->gt_timer[timeridx], INT64_MAX);
27
+ } else {
28
+ timer_mod(cpu->gt_timer[timeridx], nexttick);
29
}
30
- timer_mod(cpu->gt_timer[timeridx], nexttick);
31
trace_arm_gt_recalc(timeridx, irqstate, nexttick);
32
} else {
33
/* Timer disabled: ISTATUS and timer output always clear */
34
--
35
2.20.1
36
37
diff view generated by jsdifflib
1
From: Julia Suvorova via Qemu-devel <qemu-devel@nongnu.org>
1
From: Andrew Jeffery <andrew@aj.id.au>
2
2
3
New mini-kernel test for nRF51 SoC UART.
3
Prepare for SoCs such as the ASPEED AST2600 whose firmware configures
4
CNTFRQ to values significantly larger than the static 62.5MHz value
5
currently derived from GTIMER_SCALE. As the OS potentially derives its
6
timer periods from the CNTFRQ value the lack of support for running
7
QEMUTimers at the appropriate rate leads to sticky behaviour in the
8
guest.
4
9
5
Signed-off-by: Julia Suvorova <jusual@mail.ru>
10
Substitute the GTIMER_SCALE constant with use of a helper to derive the
6
Acked-by: Thomas Huth <thuth@redhat.com>
11
period from gt_cntfrq_hz stored in struct ARMCPU. Initially set
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
12
gt_cntfrq_hz to the frequency associated with GTIMER_SCALE so current
13
behaviour is maintained.
14
15
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
18
Message-id: 40bd8df043f66e1ccfb3e9482999d099ac72bb2e.1576215453.git-series.andrew@aj.id.au
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
20
---
10
tests/boot-serial-test.c | 19 +++++++++++++++++++
21
target/arm/cpu.h | 5 +++++
11
1 file changed, 19 insertions(+)
22
target/arm/cpu.c | 8 ++++++++
23
target/arm/helper.c | 10 +++++++---
24
3 files changed, 20 insertions(+), 3 deletions(-)
12
25
13
diff --git a/tests/boot-serial-test.c b/tests/boot-serial-test.c
26
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
15
--- a/tests/boot-serial-test.c
28
--- a/target/arm/cpu.h
16
+++ b/tests/boot-serial-test.c
29
+++ b/target/arm/cpu.h
17
@@ -XXX,XX +XXX,XX @@ static const uint8_t kernel_aarch64[] = {
30
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
18
0xfd, 0xff, 0xff, 0x17, /* b -12 (loop) */
31
*/
32
DECLARE_BITMAP(sve_vq_map, ARM_MAX_VQ);
33
DECLARE_BITMAP(sve_vq_init, ARM_MAX_VQ);
34
+
35
+ /* Generic timer counter frequency, in Hz */
36
+ uint64_t gt_cntfrq_hz;
19
};
37
};
20
38
21
+static const uint8_t kernel_nrf51[] = {
39
+unsigned int gt_cntfrq_period_ns(ARMCPU *cpu);
22
+ 0x00, 0x00, 0x00, 0x00, /* Stack top address */
23
+ 0x09, 0x00, 0x00, 0x00, /* Reset handler address */
24
+ 0x04, 0x4a, /* ldr r2, [pc, #16] Get ENABLE */
25
+ 0x04, 0x21, /* movs r1, #4 */
26
+ 0x11, 0x60, /* str r1, [r2] */
27
+ 0x04, 0x4a, /* ldr r2, [pc, #16] Get STARTTX */
28
+ 0x01, 0x21, /* movs r1, #1 */
29
+ 0x11, 0x60, /* str r1, [r2] */
30
+ 0x03, 0x4a, /* ldr r2, [pc, #12] Get TXD */
31
+ 0x54, 0x21, /* movs r1, 'T' */
32
+ 0x11, 0x60, /* str r1, [r2] */
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 */
37
+};
38
+
40
+
39
typedef struct testdef {
41
void arm_cpu_post_init(Object *obj);
40
const char *arch; /* Target architecture */
42
41
const char *machine; /* Name of the machine */
43
uint64_t arm_cpu_mp_affinity(int idx, uint8_t clustersz);
42
@@ -XXX,XX +XXX,XX @@ static testdef_t tests[] = {
44
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
43
{ "hppa", "hppa", "", "SeaBIOS wants SYSTEM HALT" },
45
index XXXXXXX..XXXXXXX 100644
44
{ "aarch64", "virt", "-cpu cortex-a57", "TT", sizeof(kernel_aarch64),
46
--- a/target/arm/cpu.c
45
kernel_aarch64 },
47
+++ b/target/arm/cpu.c
46
+ { "arm", "microbit", "", "T", sizeof(kernel_nrf51), kernel_nrf51 },
48
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_initfn(Object *obj)
47
49
if (tcg_enabled()) {
48
{ NULL }
50
cpu->psci_version = 2; /* TCG implements PSCI 0.2 */
49
};
51
}
52
+
53
+ cpu->gt_cntfrq_hz = NANOSECONDS_PER_SECOND / GTIMER_SCALE;
54
}
55
56
static Property arm_cpu_reset_cbar_property =
57
@@ -XXX,XX +XXX,XX @@ static void arm_set_init_svtor(Object *obj, Visitor *v, const char *name,
58
visit_type_uint32(v, name, &cpu->init_svtor, errp);
59
}
60
61
+unsigned int gt_cntfrq_period_ns(ARMCPU *cpu)
62
+{
63
+ return NANOSECONDS_PER_SECOND > cpu->gt_cntfrq_hz ?
64
+ NANOSECONDS_PER_SECOND / cpu->gt_cntfrq_hz : 1;
65
+}
66
+
67
void arm_cpu_post_init(Object *obj)
68
{
69
ARMCPU *cpu = ARM_CPU(obj);
70
diff --git a/target/arm/helper.c b/target/arm/helper.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/target/arm/helper.c
73
+++ b/target/arm/helper.c
74
@@ -XXX,XX +XXX,XX @@ static CPAccessResult gt_stimer_access(CPUARMState *env,
75
76
static uint64_t gt_get_countervalue(CPUARMState *env)
77
{
78
- return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / GTIMER_SCALE;
79
+ ARMCPU *cpu = env_archcpu(env);
80
+
81
+ return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / gt_cntfrq_period_ns(cpu);
82
}
83
84
static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
85
@@ -XXX,XX +XXX,XX @@ static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
86
* set the timer for as far in the future as possible. When the
87
* timer expires we will reset the timer for any remaining period.
88
*/
89
- if (nexttick > INT64_MAX / GTIMER_SCALE) {
90
+ if (nexttick > INT64_MAX / gt_cntfrq_period_ns(cpu)) {
91
timer_mod_ns(cpu->gt_timer[timeridx], INT64_MAX);
92
} else {
93
timer_mod(cpu->gt_timer[timeridx], nexttick);
94
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
95
96
static uint64_t gt_virt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri)
97
{
98
+ ARMCPU *cpu = env_archcpu(env);
99
+
100
/* Currently we have no support for QEMUTimer in linux-user so we
101
* can't call gt_get_countervalue(env), instead we directly
102
* call the lower level functions.
103
*/
104
- return cpu_get_clock() / GTIMER_SCALE;
105
+ return cpu_get_clock() / gt_cntfrq_period_ns(cpu);
106
}
107
108
static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
50
--
109
--
51
2.19.1
110
2.20.1
52
111
53
112
diff view generated by jsdifflib
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
1
From: Andrew Jeffery <andrew@aj.id.au>
2
2
3
Add a model of Xilinx Versal SoC.
3
The ASPEED AST2600 clocks the generic timer at the rate of HPLL. On
4
recent firmwares this is at 1125MHz, which is considerably quicker than
5
the assumed 62.5MHz of the current generic timer implementation. The
6
delta between the value as read from CNTFRQ and the true rate of the
7
underlying QEMUTimer leads to sticky behaviour in AST2600 guests.
4
8
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
9
Add a feature-gated property exposing CNTFRQ for ARM CPUs providing the
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
generic timer. This allows platforms to configure CNTFRQ (and the
11
associated QEMUTimer) to the appropriate frequency prior to starting the
12
guest.
13
14
As the platform can now determine the rate of CNTFRQ we're exposed to
15
limitations of QEMUTimer that didn't previously materialise: In the
16
course of emulation we need to arbitrarily and accurately convert
17
between guest ticks and time, but we're constrained by QEMUTimer's use
18
of an integer scaling factor. The effect is QEMUTimer cannot exactly
19
capture the period of frequencies that do not cleanly divide
20
NANOSECONDS_PER_SECOND for scaling ticks to time. As such, provide an
21
equally inaccurate scaling factor for scaling time to ticks so at least
22
a self-consistent inverse relationship holds.
23
24
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
25
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
26
Message-id: a22db9325f96e39f76e3c2baddcb712149f46bf2.1576215453.git-series.andrew@aj.id.au
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
28
---
9
hw/arm/Makefile.objs | 1 +
29
target/arm/cpu.c | 61 +++++++++++++++++++++++++++++++++++++--------
10
include/hw/arm/xlnx-versal.h | 122 +++++++++++
30
target/arm/helper.c | 9 ++++++-
11
hw/arm/xlnx-versal.c | 323 ++++++++++++++++++++++++++++
31
2 files changed, 59 insertions(+), 11 deletions(-)
12
default-configs/aarch64-softmmu.mak | 1 +
13
4 files changed, 447 insertions(+)
14
create mode 100644 include/hw/arm/xlnx-versal.h
15
create mode 100644 hw/arm/xlnx-versal.c
16
32
17
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
33
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
18
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/Makefile.objs
35
--- a/target/arm/cpu.c
20
+++ b/hw/arm/Makefile.objs
36
+++ b/target/arm/cpu.c
21
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o
37
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_initfn(Object *obj)
22
obj-$(CONFIG_RASPI) += bcm2835_peripherals.o bcm2836.o raspi.o
38
if (tcg_enabled()) {
23
obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o
39
cpu->psci_version = 2; /* TCG implements PSCI 0.2 */
24
obj-$(CONFIG_XLNX_ZYNQMP_ARM) += xlnx-zynqmp.o xlnx-zcu102.o
40
}
25
+obj-$(CONFIG_XLNX_VERSAL) += xlnx-versal.o
41
-
26
obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o
42
- cpu->gt_cntfrq_hz = NANOSECONDS_PER_SECOND / GTIMER_SCALE;
27
obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o
43
}
28
obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o
44
29
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
45
+static Property arm_cpu_gt_cntfrq_property =
30
new file mode 100644
46
+ DEFINE_PROP_UINT64("cntfrq", ARMCPU, gt_cntfrq_hz,
31
index XXXXXXX..XXXXXXX
47
+ NANOSECONDS_PER_SECOND / GTIMER_SCALE);
32
--- /dev/null
33
+++ b/include/hw/arm/xlnx-versal.h
34
@@ -XXX,XX +XXX,XX @@
35
+/*
36
+ * Model of the Xilinx Versal
37
+ *
38
+ * Copyright (c) 2018 Xilinx Inc.
39
+ * Written by Edgar E. Iglesias
40
+ *
41
+ * This program is free software; you can redistribute it and/or modify
42
+ * it under the terms of the GNU General Public License version 2 or
43
+ * (at your option) any later version.
44
+ */
45
+
48
+
46
+#ifndef XLNX_VERSAL_H
49
static Property arm_cpu_reset_cbar_property =
47
+#define XLNX_VERSAL_H
50
DEFINE_PROP_UINT64("reset-cbar", ARMCPU, reset_cbar, 0);
51
52
@@ -XXX,XX +XXX,XX @@ static void arm_set_init_svtor(Object *obj, Visitor *v, const char *name,
53
54
unsigned int gt_cntfrq_period_ns(ARMCPU *cpu)
55
{
56
+ /*
57
+ * The exact approach to calculating guest ticks is:
58
+ *
59
+ * muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), cpu->gt_cntfrq_hz,
60
+ * NANOSECONDS_PER_SECOND);
61
+ *
62
+ * We don't do that. Rather we intentionally use integer division
63
+ * truncation below and in the caller for the conversion of host monotonic
64
+ * time to guest ticks to provide the exact inverse for the semantics of
65
+ * the QEMUTimer scale factor. QEMUTimer's scale facter is an integer, so
66
+ * it loses precision when representing frequencies where
67
+ * `(NANOSECONDS_PER_SECOND % cpu->gt_cntfrq) > 0` holds. Failing to
68
+ * provide an exact inverse leads to scheduling timers with negative
69
+ * periods, which in turn leads to sticky behaviour in the guest.
70
+ *
71
+ * Finally, CNTFRQ is effectively capped at 1GHz to ensure our scale factor
72
+ * cannot become zero.
73
+ */
74
return NANOSECONDS_PER_SECOND > cpu->gt_cntfrq_hz ?
75
NANOSECONDS_PER_SECOND / cpu->gt_cntfrq_hz : 1;
76
}
77
@@ -XXX,XX +XXX,XX @@ void arm_cpu_post_init(Object *obj)
78
79
qdev_property_add_static(DEVICE(obj), &arm_cpu_cfgend_property,
80
&error_abort);
48
+
81
+
49
+#include "hw/sysbus.h"
82
+ if (arm_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER)) {
50
+#include "hw/arm/arm.h"
83
+ qdev_property_add_static(DEVICE(cpu), &arm_cpu_gt_cntfrq_property,
51
+#include "hw/intc/arm_gicv3.h"
84
+ &error_abort);
85
+ }
86
}
87
88
static void arm_cpu_finalizefn(Object *obj)
89
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
90
}
91
}
92
93
- cpu->gt_timer[GTIMER_PHYS] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
94
- arm_gt_ptimer_cb, cpu);
95
- cpu->gt_timer[GTIMER_VIRT] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
96
- arm_gt_vtimer_cb, cpu);
97
- cpu->gt_timer[GTIMER_HYP] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
98
- arm_gt_htimer_cb, cpu);
99
- cpu->gt_timer[GTIMER_SEC] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
100
- arm_gt_stimer_cb, cpu);
52
+
101
+
53
+#define TYPE_XLNX_VERSAL "xlnx-versal"
102
+ {
54
+#define XLNX_VERSAL(obj) OBJECT_CHECK(Versal, (obj), TYPE_XLNX_VERSAL)
103
+ uint64_t scale;
55
+
104
+
56
+#define XLNX_VERSAL_NR_ACPUS 2
105
+ if (arm_feature(env, ARM_FEATURE_GENERIC_TIMER)) {
57
+#define XLNX_VERSAL_NR_UARTS 2
106
+ if (!cpu->gt_cntfrq_hz) {
58
+#define XLNX_VERSAL_NR_GEMS 2
107
+ error_setg(errp, "Invalid CNTFRQ: %"PRId64"Hz",
59
+#define XLNX_VERSAL_NR_IRQS 256
108
+ cpu->gt_cntfrq_hz);
60
+
109
+ return;
61
+typedef struct Versal {
110
+ }
62
+ /*< private >*/
111
+ scale = gt_cntfrq_period_ns(cpu);
63
+ SysBusDevice parent_obj;
112
+ } else {
64
+
113
+ scale = GTIMER_SCALE;
65
+ /*< public >*/
66
+ struct {
67
+ struct {
68
+ MemoryRegion mr;
69
+ ARMCPU *cpu[XLNX_VERSAL_NR_ACPUS];
70
+ GICv3State gic;
71
+ } apu;
72
+ } fpd;
73
+
74
+ MemoryRegion mr_ps;
75
+
76
+ struct {
77
+ /* 4 ranges to access DDR. */
78
+ MemoryRegion mr_ddr_ranges[4];
79
+ } noc;
80
+
81
+ struct {
82
+ MemoryRegion mr_ocm;
83
+
84
+ struct {
85
+ SysBusDevice *uart[XLNX_VERSAL_NR_UARTS];
86
+ SysBusDevice *gem[XLNX_VERSAL_NR_GEMS];
87
+ } iou;
88
+ } lpd;
89
+
90
+ struct {
91
+ MemoryRegion *mr_ddr;
92
+ uint32_t psci_conduit;
93
+ } cfg;
94
+} Versal;
95
+
96
+/* Memory-map and IRQ definitions. Copied a subset from
97
+ * auto-generated files. */
98
+
99
+#define VERSAL_GIC_MAINT_IRQ 9
100
+#define VERSAL_TIMER_VIRT_IRQ 11
101
+#define VERSAL_TIMER_S_EL1_IRQ 13
102
+#define VERSAL_TIMER_NS_EL1_IRQ 14
103
+#define VERSAL_TIMER_NS_EL2_IRQ 10
104
+
105
+#define VERSAL_UART0_IRQ_0 18
106
+#define VERSAL_UART1_IRQ_0 19
107
+#define VERSAL_GEM0_IRQ_0 56
108
+#define VERSAL_GEM0_WAKE_IRQ_0 57
109
+#define VERSAL_GEM1_IRQ_0 58
110
+#define VERSAL_GEM1_WAKE_IRQ_0 59
111
+
112
+/* Architecturally eserved IRQs suitable for virtualization. */
113
+#define VERSAL_RSVD_HIGH_IRQ_FIRST 160
114
+#define VERSAL_RSVD_HIGH_IRQ_LAST 255
115
+
116
+#define MM_TOP_RSVD 0xa0000000U
117
+#define MM_TOP_RSVD_SIZE 0x4000000
118
+#define MM_GIC_APU_DIST_MAIN 0xf9000000U
119
+#define MM_GIC_APU_DIST_MAIN_SIZE 0x10000
120
+#define MM_GIC_APU_REDIST_0 0xf9080000U
121
+#define MM_GIC_APU_REDIST_0_SIZE 0x80000
122
+
123
+#define MM_UART0 0xff000000U
124
+#define MM_UART0_SIZE 0x10000
125
+#define MM_UART1 0xff010000U
126
+#define MM_UART1_SIZE 0x10000
127
+
128
+#define MM_GEM0 0xff0c0000U
129
+#define MM_GEM0_SIZE 0x10000
130
+#define MM_GEM1 0xff0d0000U
131
+#define MM_GEM1_SIZE 0x10000
132
+
133
+#define MM_OCM 0xfffc0000U
134
+#define MM_OCM_SIZE 0x40000
135
+
136
+#define MM_TOP_DDR 0x0
137
+#define MM_TOP_DDR_SIZE 0x80000000U
138
+#define MM_TOP_DDR_2 0x800000000ULL
139
+#define MM_TOP_DDR_2_SIZE 0x800000000ULL
140
+#define MM_TOP_DDR_3 0xc000000000ULL
141
+#define MM_TOP_DDR_3_SIZE 0x4000000000ULL
142
+#define MM_TOP_DDR_4 0x10000000000ULL
143
+#define MM_TOP_DDR_4_SIZE 0xb780000000ULL
144
+
145
+#define MM_PSM_START 0xffc80000U
146
+#define MM_PSM_END 0xffcf0000U
147
+
148
+#define MM_CRL 0xff5e0000U
149
+#define MM_CRL_SIZE 0x300000
150
+#define MM_IOU_SCNTR 0xff130000U
151
+#define MM_IOU_SCNTR_SIZE 0x10000
152
+#define MM_IOU_SCNTRS 0xff140000U
153
+#define MM_IOU_SCNTRS_SIZE 0x10000
154
+#define MM_FPD_CRF 0xfd1a0000U
155
+#define MM_FPD_CRF_SIZE 0x140000
156
+#endif
157
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
158
new file mode 100644
159
index XXXXXXX..XXXXXXX
160
--- /dev/null
161
+++ b/hw/arm/xlnx-versal.c
162
@@ -XXX,XX +XXX,XX @@
163
+/*
164
+ * Xilinx Versal SoC model.
165
+ *
166
+ * Copyright (c) 2018 Xilinx Inc.
167
+ * Written by Edgar E. Iglesias
168
+ *
169
+ * This program is free software; you can redistribute it and/or modify
170
+ * it under the terms of the GNU General Public License version 2 or
171
+ * (at your option) any later version.
172
+ */
173
+
174
+#include "qemu/osdep.h"
175
+#include "qapi/error.h"
176
+#include "qemu-common.h"
177
+#include "qemu/log.h"
178
+#include "hw/sysbus.h"
179
+#include "net/net.h"
180
+#include "sysemu/sysemu.h"
181
+#include "sysemu/kvm.h"
182
+#include "hw/arm/arm.h"
183
+#include "kvm_arm.h"
184
+#include "hw/misc/unimp.h"
185
+#include "hw/intc/arm_gicv3_common.h"
186
+#include "hw/arm/xlnx-versal.h"
187
+
188
+#define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
189
+#define GEM_REVISION 0x40070106
190
+
191
+static void versal_create_apu_cpus(Versal *s)
192
+{
193
+ int i;
194
+
195
+ for (i = 0; i < ARRAY_SIZE(s->fpd.apu.cpu); i++) {
196
+ Object *obj;
197
+ char *name;
198
+
199
+ obj = object_new(XLNX_VERSAL_ACPU_TYPE);
200
+ if (!obj) {
201
+ /* Secondary CPUs start in PSCI powered-down state */
202
+ error_report("Unable to create apu.cpu[%d] of type %s",
203
+ i, XLNX_VERSAL_ACPU_TYPE);
204
+ exit(EXIT_FAILURE);
205
+ }
114
+ }
206
+
115
+
207
+ name = g_strdup_printf("apu-cpu[%d]", i);
116
+ cpu->gt_timer[GTIMER_PHYS] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
208
+ object_property_add_child(OBJECT(s), name, obj, &error_fatal);
117
+ arm_gt_ptimer_cb, cpu);
209
+ g_free(name);
118
+ cpu->gt_timer[GTIMER_VIRT] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
119
+ arm_gt_vtimer_cb, cpu);
120
+ cpu->gt_timer[GTIMER_HYP] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
121
+ arm_gt_htimer_cb, cpu);
122
+ cpu->gt_timer[GTIMER_SEC] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
123
+ arm_gt_stimer_cb, cpu);
124
+ }
125
#endif
126
127
cpu_exec_realizefn(cs, &local_err);
128
diff --git a/target/arm/helper.c b/target/arm/helper.c
129
index XXXXXXX..XXXXXXX 100644
130
--- a/target/arm/helper.c
131
+++ b/target/arm/helper.c
132
@@ -XXX,XX +XXX,XX @@ void arm_gt_stimer_cb(void *opaque)
133
gt_recalc_timer(cpu, GTIMER_SEC);
134
}
135
136
+static void arm_gt_cntfrq_reset(CPUARMState *env, const ARMCPRegInfo *opaque)
137
+{
138
+ ARMCPU *cpu = env_archcpu(env);
210
+
139
+
211
+ object_property_set_int(obj, s->cfg.psci_conduit,
140
+ cpu->env.cp15.c14_cntfrq = cpu->gt_cntfrq_hz;
212
+ "psci-conduit", &error_abort);
213
+ if (i) {
214
+ object_property_set_bool(obj, true,
215
+ "start-powered-off", &error_abort);
216
+ }
217
+
218
+ object_property_set_int(obj, ARRAY_SIZE(s->fpd.apu.cpu),
219
+ "core-count", &error_abort);
220
+ object_property_set_link(obj, OBJECT(&s->fpd.apu.mr), "memory",
221
+ &error_abort);
222
+ object_property_set_bool(obj, true, "realized", &error_fatal);
223
+ s->fpd.apu.cpu[i] = ARM_CPU(obj);
224
+ }
225
+}
141
+}
226
+
142
+
227
+static void versal_create_apu_gic(Versal *s, qemu_irq *pic)
143
static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
228
+{
144
/* Note that CNTFRQ is purely reads-as-written for the benefit
229
+ static const uint64_t addrs[] = {
145
* of software; writing it doesn't actually change the timer frequency.
230
+ MM_GIC_APU_DIST_MAIN,
146
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
231
+ MM_GIC_APU_REDIST_0
147
.opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 0,
232
+ };
148
.access = PL1_RW | PL0_R, .accessfn = gt_cntfrq_access,
233
+ SysBusDevice *gicbusdev;
149
.fieldoffset = offsetof(CPUARMState, cp15.c14_cntfrq),
234
+ DeviceState *gicdev;
150
- .resetvalue = (1000 * 1000 * 1000) / GTIMER_SCALE,
235
+ int nr_apu_cpus = ARRAY_SIZE(s->fpd.apu.cpu);
151
+ .resetfn = arm_gt_cntfrq_reset,
236
+ int i;
152
},
237
+
153
/* overall control: mostly access permissions */
238
+ sysbus_init_child_obj(OBJECT(s), "apu-gic",
154
{ .name = "CNTKCTL", .state = ARM_CP_STATE_BOTH,
239
+ &s->fpd.apu.gic, sizeof(s->fpd.apu.gic),
240
+ gicv3_class_name());
241
+ gicbusdev = SYS_BUS_DEVICE(&s->fpd.apu.gic);
242
+ gicdev = DEVICE(&s->fpd.apu.gic);
243
+ qdev_prop_set_uint32(gicdev, "revision", 3);
244
+ qdev_prop_set_uint32(gicdev, "num-cpu", 2);
245
+ qdev_prop_set_uint32(gicdev, "num-irq", XLNX_VERSAL_NR_IRQS + 32);
246
+ qdev_prop_set_uint32(gicdev, "len-redist-region-count", 1);
247
+ qdev_prop_set_uint32(gicdev, "redist-region-count[0]", 2);
248
+ qdev_prop_set_bit(gicdev, "has-security-extensions", true);
249
+
250
+ object_property_set_bool(OBJECT(&s->fpd.apu.gic), true, "realized",
251
+ &error_fatal);
252
+
253
+ for (i = 0; i < ARRAY_SIZE(addrs); i++) {
254
+ MemoryRegion *mr;
255
+
256
+ mr = sysbus_mmio_get_region(gicbusdev, i);
257
+ memory_region_add_subregion(&s->fpd.apu.mr, addrs[i], mr);
258
+ }
259
+
260
+ for (i = 0; i < nr_apu_cpus; i++) {
261
+ DeviceState *cpudev = DEVICE(s->fpd.apu.cpu[i]);
262
+ int ppibase = XLNX_VERSAL_NR_IRQS + i * GIC_INTERNAL + GIC_NR_SGIS;
263
+ qemu_irq maint_irq;
264
+ int ti;
265
+ /* Mapping from the output timer irq lines from the CPU to the
266
+ * GIC PPI inputs.
267
+ */
268
+ const int timer_irq[] = {
269
+ [GTIMER_PHYS] = VERSAL_TIMER_NS_EL1_IRQ,
270
+ [GTIMER_VIRT] = VERSAL_TIMER_VIRT_IRQ,
271
+ [GTIMER_HYP] = VERSAL_TIMER_NS_EL2_IRQ,
272
+ [GTIMER_SEC] = VERSAL_TIMER_S_EL1_IRQ,
273
+ };
274
+
275
+ for (ti = 0; ti < ARRAY_SIZE(timer_irq); ti++) {
276
+ qdev_connect_gpio_out(cpudev, ti,
277
+ qdev_get_gpio_in(gicdev,
278
+ ppibase + timer_irq[ti]));
279
+ }
280
+ maint_irq = qdev_get_gpio_in(gicdev,
281
+ ppibase + VERSAL_GIC_MAINT_IRQ);
282
+ qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt",
283
+ 0, maint_irq);
284
+ sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
285
+ sysbus_connect_irq(gicbusdev, i + nr_apu_cpus,
286
+ qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
287
+ sysbus_connect_irq(gicbusdev, i + 2 * nr_apu_cpus,
288
+ qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
289
+ sysbus_connect_irq(gicbusdev, i + 3 * nr_apu_cpus,
290
+ qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
291
+ }
292
+
293
+ for (i = 0; i < XLNX_VERSAL_NR_IRQS; i++) {
294
+ pic[i] = qdev_get_gpio_in(gicdev, i);
295
+ }
296
+}
297
+
298
+static void versal_create_uarts(Versal *s, qemu_irq *pic)
299
+{
300
+ int i;
301
+
302
+ for (i = 0; i < ARRAY_SIZE(s->lpd.iou.uart); i++) {
303
+ static const int irqs[] = { VERSAL_UART0_IRQ_0, VERSAL_UART1_IRQ_0};
304
+ static const uint64_t addrs[] = { MM_UART0, MM_UART1 };
305
+ char *name = g_strdup_printf("uart%d", i);
306
+ DeviceState *dev;
307
+ MemoryRegion *mr;
308
+
309
+ dev = qdev_create(NULL, "pl011");
310
+ s->lpd.iou.uart[i] = SYS_BUS_DEVICE(dev);
311
+ qdev_prop_set_chr(dev, "chardev", serial_hd(i));
312
+ object_property_add_child(OBJECT(s), name, OBJECT(dev), &error_fatal);
313
+ qdev_init_nofail(dev);
314
+
315
+ mr = sysbus_mmio_get_region(s->lpd.iou.uart[i], 0);
316
+ memory_region_add_subregion(&s->mr_ps, addrs[i], mr);
317
+
318
+ sysbus_connect_irq(s->lpd.iou.uart[i], 0, pic[irqs[i]]);
319
+ g_free(name);
320
+ }
321
+}
322
+
323
+static void versal_create_gems(Versal *s, qemu_irq *pic)
324
+{
325
+ int i;
326
+
327
+ for (i = 0; i < ARRAY_SIZE(s->lpd.iou.gem); i++) {
328
+ static const int irqs[] = { VERSAL_GEM0_IRQ_0, VERSAL_GEM1_IRQ_0};
329
+ static const uint64_t addrs[] = { MM_GEM0, MM_GEM1 };
330
+ char *name = g_strdup_printf("gem%d", i);
331
+ NICInfo *nd = &nd_table[i];
332
+ DeviceState *dev;
333
+ MemoryRegion *mr;
334
+
335
+ dev = qdev_create(NULL, "cadence_gem");
336
+ s->lpd.iou.gem[i] = SYS_BUS_DEVICE(dev);
337
+ object_property_add_child(OBJECT(s), name, OBJECT(dev), &error_fatal);
338
+ if (nd->used) {
339
+ qemu_check_nic_model(nd, "cadence_gem");
340
+ qdev_set_nic_properties(dev, nd);
341
+ }
342
+ object_property_set_int(OBJECT(s->lpd.iou.gem[i]),
343
+ 2, "num-priority-queues",
344
+ &error_abort);
345
+ object_property_set_link(OBJECT(s->lpd.iou.gem[i]),
346
+ OBJECT(&s->mr_ps), "dma",
347
+ &error_abort);
348
+ qdev_init_nofail(dev);
349
+
350
+ mr = sysbus_mmio_get_region(s->lpd.iou.gem[i], 0);
351
+ memory_region_add_subregion(&s->mr_ps, addrs[i], mr);
352
+
353
+ sysbus_connect_irq(s->lpd.iou.gem[i], 0, pic[irqs[i]]);
354
+ g_free(name);
355
+ }
356
+}
357
+
358
+/* This takes the board allocated linear DDR memory and creates aliases
359
+ * for each split DDR range/aperture on the Versal address map.
360
+ */
361
+static void versal_map_ddr(Versal *s)
362
+{
363
+ uint64_t size = memory_region_size(s->cfg.mr_ddr);
364
+ /* Describes the various split DDR access regions. */
365
+ static const struct {
366
+ uint64_t base;
367
+ uint64_t size;
368
+ } addr_ranges[] = {
369
+ { MM_TOP_DDR, MM_TOP_DDR_SIZE },
370
+ { MM_TOP_DDR_2, MM_TOP_DDR_2_SIZE },
371
+ { MM_TOP_DDR_3, MM_TOP_DDR_3_SIZE },
372
+ { MM_TOP_DDR_4, MM_TOP_DDR_4_SIZE }
373
+ };
374
+ uint64_t offset = 0;
375
+ int i;
376
+
377
+ assert(ARRAY_SIZE(addr_ranges) == ARRAY_SIZE(s->noc.mr_ddr_ranges));
378
+ for (i = 0; i < ARRAY_SIZE(addr_ranges) && size; i++) {
379
+ char *name;
380
+ uint64_t mapsize;
381
+
382
+ mapsize = size < addr_ranges[i].size ? size : addr_ranges[i].size;
383
+ name = g_strdup_printf("noc-ddr-range%d", i);
384
+ /* Create the MR alias. */
385
+ memory_region_init_alias(&s->noc.mr_ddr_ranges[i], OBJECT(s),
386
+ name, s->cfg.mr_ddr,
387
+ offset, mapsize);
388
+
389
+ /* Map it onto the NoC MR. */
390
+ memory_region_add_subregion(&s->mr_ps, addr_ranges[i].base,
391
+ &s->noc.mr_ddr_ranges[i]);
392
+ offset += mapsize;
393
+ size -= mapsize;
394
+ g_free(name);
395
+ }
396
+}
397
+
398
+static void versal_unimp_area(Versal *s, const char *name,
399
+ MemoryRegion *mr,
400
+ hwaddr base, hwaddr size)
401
+{
402
+ DeviceState *dev = qdev_create(NULL, TYPE_UNIMPLEMENTED_DEVICE);
403
+ MemoryRegion *mr_dev;
404
+
405
+ qdev_prop_set_string(dev, "name", name);
406
+ qdev_prop_set_uint64(dev, "size", size);
407
+ object_property_add_child(OBJECT(s), name, OBJECT(dev), &error_fatal);
408
+ qdev_init_nofail(dev);
409
+
410
+ mr_dev = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
411
+ memory_region_add_subregion(mr, base, mr_dev);
412
+}
413
+
414
+static void versal_unimp(Versal *s)
415
+{
416
+ versal_unimp_area(s, "psm", &s->mr_ps,
417
+ MM_PSM_START, MM_PSM_END - MM_PSM_START);
418
+ versal_unimp_area(s, "crl", &s->mr_ps,
419
+ MM_CRL, MM_CRL_SIZE);
420
+ versal_unimp_area(s, "crf", &s->mr_ps,
421
+ MM_FPD_CRF, MM_FPD_CRF_SIZE);
422
+ versal_unimp_area(s, "iou-scntr", &s->mr_ps,
423
+ MM_IOU_SCNTR, MM_IOU_SCNTR_SIZE);
424
+ versal_unimp_area(s, "iou-scntr-seucre", &s->mr_ps,
425
+ MM_IOU_SCNTRS, MM_IOU_SCNTRS_SIZE);
426
+}
427
+
428
+static void versal_realize(DeviceState *dev, Error **errp)
429
+{
430
+ Versal *s = XLNX_VERSAL(dev);
431
+ qemu_irq pic[XLNX_VERSAL_NR_IRQS];
432
+
433
+ versal_create_apu_cpus(s);
434
+ versal_create_apu_gic(s, pic);
435
+ versal_create_uarts(s, pic);
436
+ versal_create_gems(s, pic);
437
+ versal_map_ddr(s);
438
+ versal_unimp(s);
439
+
440
+ /* Create the On Chip Memory (OCM). */
441
+ memory_region_init_ram(&s->lpd.mr_ocm, OBJECT(s), "ocm",
442
+ MM_OCM_SIZE, &error_fatal);
443
+
444
+ memory_region_add_subregion_overlap(&s->mr_ps, MM_OCM, &s->lpd.mr_ocm, 0);
445
+ memory_region_add_subregion_overlap(&s->fpd.apu.mr, 0, &s->mr_ps, 0);
446
+}
447
+
448
+static void versal_init(Object *obj)
449
+{
450
+ Versal *s = XLNX_VERSAL(obj);
451
+
452
+ memory_region_init(&s->fpd.apu.mr, obj, "mr-apu", UINT64_MAX);
453
+ memory_region_init(&s->mr_ps, obj, "mr-ps-switch", UINT64_MAX);
454
+}
455
+
456
+static Property versal_properties[] = {
457
+ DEFINE_PROP_LINK("ddr", Versal, cfg.mr_ddr, TYPE_MEMORY_REGION,
458
+ MemoryRegion *),
459
+ DEFINE_PROP_UINT32("psci-conduit", Versal, cfg.psci_conduit, 0),
460
+ DEFINE_PROP_END_OF_LIST()
461
+};
462
+
463
+static void versal_class_init(ObjectClass *klass, void *data)
464
+{
465
+ DeviceClass *dc = DEVICE_CLASS(klass);
466
+
467
+ dc->realize = versal_realize;
468
+ dc->props = versal_properties;
469
+ /* No VMSD since we haven't got any top-level SoC state to save. */
470
+}
471
+
472
+static const TypeInfo versal_info = {
473
+ .name = TYPE_XLNX_VERSAL,
474
+ .parent = TYPE_SYS_BUS_DEVICE,
475
+ .instance_size = sizeof(Versal),
476
+ .instance_init = versal_init,
477
+ .class_init = versal_class_init,
478
+};
479
+
480
+static void versal_register_types(void)
481
+{
482
+ type_register_static(&versal_info);
483
+}
484
+
485
+type_init(versal_register_types);
486
diff --git a/default-configs/aarch64-softmmu.mak b/default-configs/aarch64-softmmu.mak
487
index XXXXXXX..XXXXXXX 100644
488
--- a/default-configs/aarch64-softmmu.mak
489
+++ b/default-configs/aarch64-softmmu.mak
490
@@ -XXX,XX +XXX,XX @@ CONFIG_DDC=y
491
CONFIG_DPCD=y
492
CONFIG_XLNX_ZYNQMP=y
493
CONFIG_XLNX_ZYNQMP_ARM=y
494
+CONFIG_XLNX_VERSAL=y
495
CONFIG_ARM_SMMUV3=y
496
--
155
--
497
2.19.1
156
2.20.1
498
157
499
158
diff view generated by jsdifflib
New patch
1
From: Andrew Jeffery <andrew@aj.id.au>
1
2
3
This matches the configuration set by u-boot on the AST2600.
4
5
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Cédric Le Goater <clg@kaod.org>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Message-id: 080ca1267a09381c43cf3c50d434fb6c186f2b6e.1576215453.git-series.andrew@aj.id.au
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
hw/arm/aspeed_ast2600.c | 3 +++
13
1 file changed, 3 insertions(+)
14
15
diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/aspeed_ast2600.c
18
+++ b/hw/arm/aspeed_ast2600.c
19
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
20
object_property_set_int(OBJECT(&s->cpu[i]), aspeed_calc_affinity(i),
21
"mp-affinity", &error_abort);
22
23
+ object_property_set_int(OBJECT(&s->cpu[i]), 1125000000, "cntfrq",
24
+ &error_abort);
25
+
26
/*
27
* TODO: the secondary CPUs are started and a boot helper
28
* is needed when using -kernel
29
--
30
2.20.1
31
32
diff view generated by jsdifflib
New patch
1
From: Simon Veith <sveith@amazon.de>
1
2
3
In the SMMU_STRTAB_BASE register, the stream table base address only
4
occupies bits [51:6]. Other bits, such as RA (bit [62]), must be masked
5
out to obtain the base address.
6
7
The branch for 2-level stream tables correctly applies this mask by way
8
of SMMU_BASE_ADDR_MASK, but the one for linear stream tables does not.
9
10
Apply the missing mask in that case as well so that the correct stream
11
base address is used by guests which configure a linear stream table.
12
13
Linux guests are unaffected by this change because they choose a 2-level
14
stream table layout for the QEMU SMMUv3, based on the size of its stream
15
ID space.
16
17
ref. ARM IHI 0070C, section 6.3.23.
18
19
Signed-off-by: Simon Veith <sveith@amazon.de>
20
Acked-by: Eric Auger <eric.auger@redhat.com>
21
Tested-by: Eric Auger <eric.auger@redhat.com>
22
Message-id: 1576509312-13083-2-git-send-email-sveith@amazon.de
23
Cc: Eric Auger <eric.auger@redhat.com>
24
Cc: qemu-devel@nongnu.org
25
Cc: qemu-arm@nongnu.org
26
Acked-by: Eric Auger <eric.auger@redhat.com>
27
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
28
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
29
---
30
hw/arm/smmuv3.c | 2 +-
31
1 file changed, 1 insertion(+), 1 deletion(-)
32
33
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/hw/arm/smmuv3.c
36
+++ b/hw/arm/smmuv3.c
37
@@ -XXX,XX +XXX,XX @@ static int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste,
38
}
39
addr = l2ptr + l2_ste_offset * sizeof(*ste);
40
} else {
41
- addr = s->strtab_base + sid * sizeof(*ste);
42
+ addr = (s->strtab_base & SMMU_BASE_ADDR_MASK) + sid * sizeof(*ste);
43
}
44
45
if (smmu_get_ste(s, addr, ste, event)) {
46
--
47
2.20.1
48
49
diff view generated by jsdifflib
New patch
1
From: Simon Veith <sveith@amazon.de>
1
2
3
There are two issues with the current value of SMMU_BASE_ADDR_MASK:
4
5
- At the lower end, we are clearing bits [4:0]. Per the SMMUv3 spec,
6
we should also be treating bit 5 as zero in the base address.
7
- At the upper end, we are clearing bits [63:48]. Per the SMMUv3 spec,
8
only bits [63:52] must be explicitly treated as zero.
9
10
Update the SMMU_BASE_ADDR_MASK value to mask out bits [63:52] and [5:0].
11
12
ref. ARM IHI 0070C, section 6.3.23.
13
14
Signed-off-by: Simon Veith <sveith@amazon.de>
15
Acked-by: Eric Auger <eric.auger@redhat.com>
16
Tested-by: Eric Auger <eric.auger@redhat.com>
17
Message-id: 1576509312-13083-3-git-send-email-sveith@amazon.de
18
Cc: Eric Auger <eric.auger@redhat.com>
19
Cc: qemu-devel@nongnu.org
20
Cc: qemu-arm@nongnu.org
21
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
---
24
hw/arm/smmuv3-internal.h | 2 +-
25
1 file changed, 1 insertion(+), 1 deletion(-)
26
27
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
28
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/arm/smmuv3-internal.h
30
+++ b/hw/arm/smmuv3-internal.h
31
@@ -XXX,XX +XXX,XX @@ REG32(GERROR_IRQ_CFG2, 0x74)
32
33
#define A_STRTAB_BASE 0x80 /* 64b */
34
35
-#define SMMU_BASE_ADDR_MASK 0xffffffffffe0
36
+#define SMMU_BASE_ADDR_MASK 0xfffffffffffc0
37
38
REG32(STRTAB_BASE_CFG, 0x88)
39
FIELD(STRTAB_BASE_CFG, FMT, 16, 2)
40
--
41
2.20.1
42
43
diff view generated by jsdifflib
New patch
1
From: Simon Veith <sveith@amazon.de>
1
2
3
When checking whether a stream ID is in range of the stream table, we
4
have so far been only checking it against our implementation limit
5
(SMMU_IDR1_SIDSIZE). However, the guest can program the
6
STRTAB_BASE_CFG.LOG2SIZE field to a size that is smaller than this
7
limit.
8
9
Check the stream ID against this limit as well to match the hardware
10
behavior of raising C_BAD_STREAMID events in case the limit is exceeded.
11
Also, ensure that we do not go one entry beyond the end of the table by
12
checking that its index is strictly smaller than the table size.
13
14
ref. ARM IHI 0070C, section 6.3.24.
15
16
Signed-off-by: Simon Veith <sveith@amazon.de>
17
Acked-by: Eric Auger <eric.auger@redhat.com>
18
Tested-by: Eric Auger <eric.auger@redhat.com>
19
Message-id: 1576509312-13083-4-git-send-email-sveith@amazon.de
20
Cc: Eric Auger <eric.auger@redhat.com>
21
Cc: qemu-devel@nongnu.org
22
Cc: qemu-arm@nongnu.org
23
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
---
26
hw/arm/smmuv3.c | 8 ++++++--
27
1 file changed, 6 insertions(+), 2 deletions(-)
28
29
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/arm/smmuv3.c
32
+++ b/hw/arm/smmuv3.c
33
@@ -XXX,XX +XXX,XX @@ static int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste,
34
SMMUEventInfo *event)
35
{
36
dma_addr_t addr;
37
+ uint32_t log2size;
38
int ret;
39
40
trace_smmuv3_find_ste(sid, s->features, s->sid_split);
41
- /* Check SID range */
42
- if (sid > (1 << SMMU_IDR1_SIDSIZE)) {
43
+ log2size = FIELD_EX32(s->strtab_base_cfg, STRTAB_BASE_CFG, LOG2SIZE);
44
+ /*
45
+ * Check SID range against both guest-configured and implementation limits
46
+ */
47
+ if (sid >= (1 << MIN(log2size, SMMU_IDR1_SIDSIZE))) {
48
event->type = SMMU_EVT_C_BAD_STREAMID;
49
return -EINVAL;
50
}
51
--
52
2.20.1
53
54
diff view generated by jsdifflib
New patch
1
From: Simon Veith <sveith@amazon.de>
1
2
3
Per the specification, and as observed in hardware, the SMMUv3 aligns
4
the SMMU_STRTAB_BASE address to the size of the table by masking out the
5
respective least significant bits in the ADDR field.
6
7
Apply this masking logic to our smmu_find_ste() lookup function per the
8
specification.
9
10
ref. ARM IHI 0070C, section 6.3.23.
11
12
Signed-off-by: Simon Veith <sveith@amazon.de>
13
Acked-by: Eric Auger <eric.auger@redhat.com>
14
Tested-by: Eric Auger <eric.auger@redhat.com>
15
Message-id: 1576509312-13083-5-git-send-email-sveith@amazon.de
16
Cc: Eric Auger <eric.auger@redhat.com>
17
Cc: qemu-devel@nongnu.org
18
Cc: qemu-arm@nongnu.org
19
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
---
22
hw/arm/smmuv3.c | 18 ++++++++++++++----
23
1 file changed, 14 insertions(+), 4 deletions(-)
24
25
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/arm/smmuv3.c
28
+++ b/hw/arm/smmuv3.c
29
@@ -XXX,XX +XXX,XX @@ bad_ste:
30
static int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste,
31
SMMUEventInfo *event)
32
{
33
- dma_addr_t addr;
34
+ dma_addr_t addr, strtab_base;
35
uint32_t log2size;
36
+ int strtab_size_shift;
37
int ret;
38
39
trace_smmuv3_find_ste(sid, s->features, s->sid_split);
40
@@ -XXX,XX +XXX,XX @@ static int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste,
41
}
42
if (s->features & SMMU_FEATURE_2LVL_STE) {
43
int l1_ste_offset, l2_ste_offset, max_l2_ste, span;
44
- dma_addr_t strtab_base, l1ptr, l2ptr;
45
+ dma_addr_t l1ptr, l2ptr;
46
STEDesc l1std;
47
48
- strtab_base = s->strtab_base & SMMU_BASE_ADDR_MASK;
49
+ /*
50
+ * Align strtab base address to table size. For this purpose, assume it
51
+ * is not bounded by SMMU_IDR1_SIDSIZE.
52
+ */
53
+ strtab_size_shift = MAX(5, (int)log2size - s->sid_split - 1 + 3);
54
+ strtab_base = s->strtab_base & SMMU_BASE_ADDR_MASK &
55
+ ~MAKE_64BIT_MASK(0, strtab_size_shift);
56
l1_ste_offset = sid >> s->sid_split;
57
l2_ste_offset = sid & ((1 << s->sid_split) - 1);
58
l1ptr = (dma_addr_t)(strtab_base + l1_ste_offset * sizeof(l1std));
59
@@ -XXX,XX +XXX,XX @@ static int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste,
60
}
61
addr = l2ptr + l2_ste_offset * sizeof(*ste);
62
} else {
63
- addr = (s->strtab_base & SMMU_BASE_ADDR_MASK) + sid * sizeof(*ste);
64
+ strtab_size_shift = log2size + 5;
65
+ strtab_base = s->strtab_base & SMMU_BASE_ADDR_MASK &
66
+ ~MAKE_64BIT_MASK(0, strtab_size_shift);
67
+ addr = strtab_base + sid * sizeof(*ste);
68
}
69
70
if (smmu_get_ste(s, addr, ste, event)) {
71
--
72
2.20.1
73
74
diff view generated by jsdifflib
1
From: Julia Suvorova via Qemu-devel <qemu-devel@nongnu.org>
1
From: Simon Veith <sveith@amazon.de>
2
2
3
Wire up nRF51 UART in the corresponding SoC.
3
The bit offsets in the EVT_SET_ADDR2 macro do not match those specified
4
in the ARM SMMUv3 Architecture Specification. In all events that use
5
this macro, e.g. F_WALK_EABT, the faulting fetch address or IPA actually
6
occupies the 32-bit words 6 and 7 in the event record contiguously, with
7
the upper and lower unused bits clear due to alignment or maximum
8
supported address bits. How many bits are clear depends on the
9
individual event type.
4
10
5
Signed-off-by: Julia Suvorova <jusual@mail.ru>
11
Update the macro to write to the correct words in the event record so
6
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
12
that guest drivers can obtain accurate address information on events.
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
13
14
ref. ARM IHI 0070C, sections 7.3.12 through 7.3.16.
15
16
Signed-off-by: Simon Veith <sveith@amazon.de>
17
Acked-by: Eric Auger <eric.auger@redhat.com>
18
Tested-by: Eric Auger <eric.auger@redhat.com>
19
Message-id: 1576509312-13083-6-git-send-email-sveith@amazon.de
20
Cc: Eric Auger <eric.auger@redhat.com>
21
Cc: qemu-devel@nongnu.org
22
Cc: qemu-arm@nongnu.org
23
Acked-by: Eric Auger <eric.auger@redhat.com>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
24
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
26
---
11
include/hw/arm/nrf51_soc.h | 3 +++
27
hw/arm/smmuv3-internal.h | 4 ++--
12
hw/arm/microbit.c | 2 ++
28
1 file changed, 2 insertions(+), 2 deletions(-)
13
hw/arm/nrf51_soc.c | 20 ++++++++++++++++++++
14
3 files changed, 25 insertions(+)
15
29
16
diff --git a/include/hw/arm/nrf51_soc.h b/include/hw/arm/nrf51_soc.h
30
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
17
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/nrf51_soc.h
32
--- a/hw/arm/smmuv3-internal.h
19
+++ b/include/hw/arm/nrf51_soc.h
33
+++ b/hw/arm/smmuv3-internal.h
20
@@ -XXX,XX +XXX,XX @@
34
@@ -XXX,XX +XXX,XX @@ typedef struct SMMUEventInfo {
21
35
} while (0)
22
#include "hw/sysbus.h"
36
#define EVT_SET_ADDR2(x, addr) \
23
#include "hw/arm/armv7m.h"
37
do { \
24
+#include "hw/char/nrf51_uart.h"
38
- (x)->word[7] = deposit32((x)->word[7], 3, 29, addr >> 16); \
25
39
- (x)->word[7] = deposit32((x)->word[7], 0, 16, addr & 0xffff);\
26
#define TYPE_NRF51_SOC "nrf51-soc"
40
+ (x)->word[7] = (uint32_t)(addr >> 32); \
27
#define NRF51_SOC(obj) \
41
+ (x)->word[6] = (uint32_t)(addr & 0xffffffff); \
28
@@ -XXX,XX +XXX,XX @@ typedef struct NRF51State {
42
} while (0)
29
/*< public >*/
43
30
ARMv7MState cpu;
44
void smmuv3_record_event(SMMUv3State *s, SMMUEventInfo *event);
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)
75
}
76
memory_region_add_subregion(&s->container, SRAM_BASE, &s->sram);
77
78
+ /* UART */
79
+ object_property_set_bool(OBJECT(&s->uart), true, "realized", &err);
80
+ if (err) {
81
+ error_propagate(errp, err);
82
+ return;
83
+ }
84
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->uart), 0);
85
+ memory_region_add_subregion_overlap(&s->container, UART_BASE, mr, 0);
86
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart), 0,
87
+ qdev_get_gpio_in(DEVICE(&s->cpu),
88
+ BASE_TO_IRQ(UART_BASE)));
89
+
90
create_unimplemented_device("nrf51_soc.io", IOMEM_BASE, IOMEM_SIZE);
91
create_unimplemented_device("nrf51_soc.ficr", FICR_BASE, FICR_SIZE);
92
create_unimplemented_device("nrf51_soc.private",
93
@@ -XXX,XX +XXX,XX @@ static void nrf51_soc_init(Object *obj)
94
qdev_prop_set_string(DEVICE(&s->cpu), "cpu-type",
95
ARM_CPU_TYPE_NAME("cortex-m0"));
96
qdev_prop_set_uint32(DEVICE(&s->cpu), "num-irq", 32);
97
+
98
+ sysbus_init_child_obj(obj, "uart", &s->uart, sizeof(s->uart),
99
+ TYPE_NRF51_UART);
100
+ object_property_add_alias(obj, "serial0", OBJECT(&s->uart), "chardev",
101
+ &error_abort);
102
}
103
104
static Property nrf51_soc_properties[] = {
105
--
45
--
106
2.19.1
46
2.20.1
107
47
108
48
diff view generated by jsdifflib
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
1
From: Simon Veith <sveith@amazon.de>
2
2
3
Add a virtual Xilinx Versal board.
3
The smmuv3_record_event() function that generates the F_STE_FETCH error
4
uses the EVT_SET_ADDR macro to record the fetch address, placing it in
5
32-bit words 4 and 5.
4
6
5
This board is based on the Xilinx Versal SoC. The exact
7
The correct position for this address is in words 6 and 7, per the
6
details of what peripherals are attached to this board
8
SMMUv3 Architecture Specification.
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
9
11
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
10
Update the function to use the EVT_SET_ADDR2 macro instead, which is the
12
[PMM: removed stray blank line at EOF]
11
macro intended for writing to these words.
12
13
ref. ARM IHI 0070C, section 7.3.4.
14
15
Signed-off-by: Simon Veith <sveith@amazon.de>
16
Acked-by: Eric Auger <eric.auger@redhat.com>
17
Tested-by: Eric Auger <eric.auger@redhat.com>
18
Message-id: 1576509312-13083-7-git-send-email-sveith@amazon.de
19
Cc: Eric Auger <eric.auger@redhat.com>
20
Cc: qemu-devel@nongnu.org
21
Cc: qemu-arm@nongnu.org
22
Acked-by: Eric Auger <eric.auger@redhat.com>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
23
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
25
---
16
hw/arm/Makefile.objs | 2 +-
26
hw/arm/smmuv3.c | 2 +-
17
hw/arm/xlnx-versal-virt.c | 493 ++++++++++++++++++++++++++++++++++++++
27
1 file changed, 1 insertion(+), 1 deletion(-)
18
2 files changed, 494 insertions(+), 1 deletion(-)
19
create mode 100644 hw/arm/xlnx-versal-virt.c
20
28
21
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
29
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
22
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/arm/Makefile.objs
31
--- a/hw/arm/smmuv3.c
24
+++ b/hw/arm/Makefile.objs
32
+++ b/hw/arm/smmuv3.c
25
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o
33
@@ -XXX,XX +XXX,XX @@ void smmuv3_record_event(SMMUv3State *s, SMMUEventInfo *info)
26
obj-$(CONFIG_RASPI) += bcm2835_peripherals.o bcm2836.o raspi.o
34
case SMMU_EVT_F_STE_FETCH:
27
obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o
35
EVT_SET_SSID(&evt, info->u.f_ste_fetch.ssid);
28
obj-$(CONFIG_XLNX_ZYNQMP_ARM) += xlnx-zynqmp.o xlnx-zcu102.o
36
EVT_SET_SSV(&evt, info->u.f_ste_fetch.ssv);
29
-obj-$(CONFIG_XLNX_VERSAL) += xlnx-versal.o
37
- EVT_SET_ADDR(&evt, info->u.f_ste_fetch.addr);
30
+obj-$(CONFIG_XLNX_VERSAL) += xlnx-versal.o xlnx-versal-virt.o
38
+ EVT_SET_ADDR2(&evt, info->u.f_ste_fetch.addr);
31
obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o
39
break;
32
obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o
40
case SMMU_EVT_C_BAD_STE:
33
obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o
41
EVT_SET_SSID(&evt, info->u.c_bad_ste.ssid);
34
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
35
new file mode 100644
36
index XXXXXXX..XXXXXXX
37
--- /dev/null
38
+++ b/hw/arm/xlnx-versal-virt.c
39
@@ -XXX,XX +XXX,XX @@
40
+/*
41
+ * Xilinx Versal Virtual board.
42
+ *
43
+ * Copyright (c) 2018 Xilinx Inc.
44
+ * Written by Edgar E. Iglesias
45
+ *
46
+ * This program is free software; you can redistribute it and/or modify
47
+ * it under the terms of the GNU General Public License version 2 or
48
+ * (at your option) any later version.
49
+ */
50
+
51
+#include "qemu/osdep.h"
52
+#include "qemu/log.h"
53
+#include "qemu/error-report.h"
54
+#include "qapi/error.h"
55
+#include "sysemu/device_tree.h"
56
+#include "exec/address-spaces.h"
57
+#include "hw/boards.h"
58
+#include "hw/sysbus.h"
59
+#include "hw/arm/sysbus-fdt.h"
60
+#include "hw/arm/fdt.h"
61
+#include "cpu.h"
62
+#include "hw/arm/xlnx-versal.h"
63
+
64
+#define TYPE_XLNX_VERSAL_VIRT_MACHINE MACHINE_TYPE_NAME("xlnx-versal-virt")
65
+#define XLNX_VERSAL_VIRT_MACHINE(obj) \
66
+ OBJECT_CHECK(VersalVirt, (obj), TYPE_XLNX_VERSAL_VIRT_MACHINE)
67
+
68
+typedef struct VersalVirt {
69
+ MachineState parent_obj;
70
+
71
+ Versal soc;
72
+ MemoryRegion mr_ddr;
73
+
74
+ void *fdt;
75
+ int fdt_size;
76
+ struct {
77
+ uint32_t gic;
78
+ uint32_t ethernet_phy[2];
79
+ uint32_t clk_125Mhz;
80
+ uint32_t clk_25Mhz;
81
+ } phandle;
82
+ struct arm_boot_info binfo;
83
+
84
+ struct {
85
+ bool secure;
86
+ } cfg;
87
+} VersalVirt;
88
+
89
+static void fdt_create(VersalVirt *s)
90
+{
91
+ MachineClass *mc = MACHINE_GET_CLASS(s);
92
+ int i;
93
+
94
+ s->fdt = create_device_tree(&s->fdt_size);
95
+ if (!s->fdt) {
96
+ error_report("create_device_tree() failed");
97
+ exit(1);
98
+ }
99
+
100
+ /* Allocate all phandles. */
101
+ s->phandle.gic = qemu_fdt_alloc_phandle(s->fdt);
102
+ for (i = 0; i < ARRAY_SIZE(s->phandle.ethernet_phy); i++) {
103
+ s->phandle.ethernet_phy[i] = qemu_fdt_alloc_phandle(s->fdt);
104
+ }
105
+ s->phandle.clk_25Mhz = qemu_fdt_alloc_phandle(s->fdt);
106
+ s->phandle.clk_125Mhz = qemu_fdt_alloc_phandle(s->fdt);
107
+
108
+ /* Create /chosen node for load_dtb. */
109
+ qemu_fdt_add_subnode(s->fdt, "/chosen");
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_cells(s->fdt, name, "full-duplex");
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;
430
+
431
+ /*
432
+ * If the user provides an Operating System to be loaded, we expect them
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.
450
+ */
451
+ if (machine->kernel_filename) {
452
+ psci_conduit = QEMU_PSCI_CONDUIT_SMC;
453
+ }
454
+
455
+ memory_region_allocate_system_memory(&s->mr_ddr, NULL, "ddr",
456
+ machine->ram_size);
457
+
458
+ sysbus_init_child_obj(OBJECT(machine), "xlnx-ve", &s->soc,
459
+ sizeof(s->soc), TYPE_XLNX_VERSAL);
460
+ object_property_set_link(OBJECT(&s->soc), OBJECT(&s->mr_ddr),
461
+ "ddr", &error_abort);
462
+ object_property_set_int(OBJECT(&s->soc), psci_conduit,
463
+ "psci-conduit", &error_abort);
464
+ object_property_set_bool(OBJECT(&s->soc), true, "realized", &error_fatal);
465
+
466
+ fdt_create(s);
467
+ create_virtio_regions(s);
468
+ fdt_add_gem_nodes(s);
469
+ fdt_add_uart_nodes(s);
470
+ fdt_add_gic_nodes(s);
471
+ fdt_add_timer_nodes(s);
472
+ fdt_add_cpu_nodes(s, psci_conduit);
473
+ fdt_add_clk_node(s, "/clk125", 125000000, s->phandle.clk_125Mhz);
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)
509
+{
510
+ MachineClass *mc = MACHINE_CLASS(oc);
511
+
512
+ mc->desc = "Xilinx Versal Virtual development board";
513
+ mc->init = versal_virt_init;
514
+ mc->max_cpus = XLNX_VERSAL_NR_ACPUS;
515
+ mc->default_cpus = XLNX_VERSAL_NR_ACPUS;
516
+ mc->no_cdrom = true;
517
+}
518
+
519
+static const TypeInfo versal_virt_machine_init_typeinfo = {
520
+ .name = TYPE_XLNX_VERSAL_VIRT_MACHINE,
521
+ .parent = TYPE_MACHINE,
522
+ .class_init = versal_virt_machine_class_init,
523
+ .instance_init = versal_virt_machine_instance_init,
524
+ .instance_size = sizeof(VersalVirt),
525
+};
526
+
527
+static void versal_virt_machine_init_register_types(void)
528
+{
529
+ type_register_static(&versal_virt_machine_init_typeinfo);
530
+}
531
+
532
+type_init(versal_virt_machine_init_register_types)
533
--
42
--
534
2.19.1
43
2.20.1
535
44
536
45
diff view generated by jsdifflib
1
From: Julia Suvorova via Qemu-devel <qemu-devel@nongnu.org>
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
2
3
Not implemented: CTS/NCTS, PSEL*.
3
Instead of crashing in a confuse way, give some hint to the user
4
about why we aborted. He might report the issue without having
5
to use a debugger.
4
6
5
Signed-off-by: Julia Suvorova <jusual@mail.ru>
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Message-id: 20191209134552.27733-1-philmd@redhat.com
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Tested-by: Niek Linnenbank <nieklinnenbank@gmail.com>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
12
---
9
hw/char/Makefile.objs | 1 +
13
target/arm/helper.c | 18 +++++++++++++++---
10
include/hw/char/nrf51_uart.h | 78 +++++++++
14
1 file changed, 15 insertions(+), 3 deletions(-)
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
16
15
17
diff --git a/hw/char/Makefile.objs b/hw/char/Makefile.objs
16
diff --git a/target/arm/helper.c b/target/arm/helper.c
18
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/char/Makefile.objs
18
--- a/target/arm/helper.c
20
+++ b/hw/char/Makefile.objs
19
+++ b/target/arm/helper.c
21
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ void HELPER(rebuild_hflags_a64)(CPUARMState *env, int el)
22
common-obj-$(CONFIG_IPACK) += ipoctal232.o
21
env->hflags = rebuild_hflags_a64(env, el, fp_el, mmu_idx);
23
common-obj-$(CONFIG_ESCC) += escc.o
22
}
24
+common-obj-$(CONFIG_NRF51_SOC) += nrf51_uart.o
23
25
common-obj-$(CONFIG_PARALLEL) += parallel.o
24
+static inline void assert_hflags_rebuild_correctly(CPUARMState *env)
26
common-obj-$(CONFIG_PARALLEL) += parallel-isa.o
25
+{
27
common-obj-$(CONFIG_PL011) += pl011.o
26
+#ifdef CONFIG_DEBUG_TCG
28
diff --git a/include/hw/char/nrf51_uart.h b/include/hw/char/nrf51_uart.h
27
+ uint32_t env_flags_current = env->hflags;
29
new file mode 100644
28
+ uint32_t env_flags_rebuilt = rebuild_hflags_internal(env);
30
index XXXXXXX..XXXXXXX
31
--- /dev/null
32
+++ b/include/hw/char/nrf51_uart.h
33
@@ -XXX,XX +XXX,XX @@
34
+/*
35
+ * nRF51 SoC UART emulation
36
+ *
37
+ * Copyright (c) 2018 Julia Suvorova <jusual@mail.ru>
38
+ *
39
+ * This program is free software; you can redistribute it and/or modify
40
+ * it under the terms of the GNU General Public License version 2 or
41
+ * (at your option) any later version.
42
+ */
43
+
29
+
44
+#ifndef NRF51_UART_H
30
+ if (unlikely(env_flags_current != env_flags_rebuilt)) {
45
+#define NRF51_UART_H
31
+ fprintf(stderr, "TCG hflags mismatch (current:0x%08x rebuilt:0x%08x)\n",
46
+
32
+ env_flags_current, env_flags_rebuilt);
47
+#include "hw/sysbus.h"
33
+ abort();
48
+#include "chardev/char-fe.h"
34
+ }
49
+#include "hw/registerfields.h"
50
+
51
+#define UART_FIFO_LENGTH 6
52
+#define UART_BASE 0x40002000
53
+#define UART_SIZE 0x1000
54
+
55
+#define TYPE_NRF51_UART "nrf51_soc.uart"
56
+#define NRF51_UART(obj) OBJECT_CHECK(NRF51UARTState, (obj), TYPE_NRF51_UART)
57
+
58
+REG32(UART_STARTRX, 0x000)
59
+REG32(UART_STOPRX, 0x004)
60
+REG32(UART_STARTTX, 0x008)
61
+REG32(UART_STOPTX, 0x00C)
62
+REG32(UART_SUSPEND, 0x01C)
63
+
64
+REG32(UART_CTS, 0x100)
65
+REG32(UART_NCTS, 0x104)
66
+REG32(UART_RXDRDY, 0x108)
67
+REG32(UART_TXDRDY, 0x11C)
68
+REG32(UART_ERROR, 0x124)
69
+REG32(UART_RXTO, 0x144)
70
+
71
+REG32(UART_INTEN, 0x300)
72
+ FIELD(UART_INTEN, CTS, 0, 1)
73
+ FIELD(UART_INTEN, NCTS, 1, 1)
74
+ FIELD(UART_INTEN, RXDRDY, 2, 1)
75
+ FIELD(UART_INTEN, TXDRDY, 7, 1)
76
+ FIELD(UART_INTEN, ERROR, 9, 1)
77
+ FIELD(UART_INTEN, RXTO, 17, 1)
78
+REG32(UART_INTENSET, 0x304)
79
+REG32(UART_INTENCLR, 0x308)
80
+REG32(UART_ERRORSRC, 0x480)
81
+REG32(UART_ENABLE, 0x500)
82
+REG32(UART_PSELRTS, 0x508)
83
+REG32(UART_PSELTXD, 0x50C)
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
35
+#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
+}
36
+}
152
+
37
+
153
+static uint64_t uart_read(void *opaque, hwaddr addr, unsigned int size)
38
void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
154
+{
39
target_ulong *cs_base, uint32_t *pflags)
155
+ NRF51UARTState *s = NRF51_UART(opaque);
40
{
156
+ uint64_t r;
41
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
157
+
42
uint32_t pstate_for_ss;
158
+ if (!s->enabled) {
43
159
+ return 0;
44
*cs_base = 0;
160
+ }
45
-#ifdef CONFIG_DEBUG_TCG
161
+
46
- assert(flags == rebuild_hflags_internal(env));
162
+ switch (addr) {
47
-#endif
163
+ case A_UART_RXD:
48
+ assert_hflags_rebuild_correctly(env);
164
+ r = s->rx_fifo[s->rx_fifo_pos];
49
165
+ if (s->rx_started && s->rx_fifo_len) {
50
if (FIELD_EX32(flags, TBFLAG_ANY, AARCH64_STATE)) {
166
+ s->rx_fifo_pos = (s->rx_fifo_pos + 1) % UART_FIFO_LENGTH;
51
*pc = env->pc;
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,
309
+};
310
+
311
+static void nrf51_uart_reset(DeviceState *dev)
312
+{
313
+ NRF51UARTState *s = NRF51_UART(dev);
314
+
315
+ s->pending_tx_byte = 0;
316
+
317
+ uart_cancel_transmit(s);
318
+
319
+ memset(s->reg, 0, sizeof(s->reg));
320
+
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()
416
+ }
417
+};
418
+
419
+static Property nrf51_uart_properties[] = {
420
+ DEFINE_PROP_CHR("chardev", NRF51UARTState, chr),
421
+ DEFINE_PROP_END_OF_LIST(),
422
+};
423
+
424
+static void nrf51_uart_class_init(ObjectClass *klass, void *data)
425
+{
426
+ DeviceClass *dc = DEVICE_CLASS(klass);
427
+
428
+ dc->reset = nrf51_uart_reset;
429
+ dc->realize = nrf51_uart_realize;
430
+ dc->props = nrf51_uart_properties;
431
+ dc->vmsd = &nrf51_uart_vmstate;
432
+}
433
+
434
+static const TypeInfo nrf51_uart_info = {
435
+ .name = TYPE_NRF51_UART,
436
+ .parent = TYPE_SYS_BUS_DEVICE,
437
+ .instance_size = sizeof(NRF51UARTState),
438
+ .instance_init = nrf51_uart_init,
439
+ .class_init = nrf51_uart_class_init
440
+};
441
+
442
+static void nrf51_uart_register_types(void)
443
+{
444
+ type_register_static(&nrf51_uart_info);
445
+}
446
+
447
+type_init(nrf51_uart_register_types)
448
diff --git a/hw/char/trace-events b/hw/char/trace-events
449
index XXXXXXX..XXXXXXX 100644
450
--- a/hw/char/trace-events
451
+++ b/hw/char/trace-events
452
@@ -XXX,XX +XXX,XX @@ cmsdk_apb_uart_receive(uint8_t c) "CMSDK APB UART: got character 0x%x from backe
453
cmsdk_apb_uart_tx_pending(void) "CMSDK APB UART: character send to backend pending"
454
cmsdk_apb_uart_tx(uint8_t c) "CMSDK APB UART: character 0x%x sent to backend"
455
cmsdk_apb_uart_set_params(int speed) "CMSDK APB UART: params set to %d 8N1"
456
+
457
+# hw/char/nrf51_uart.c
458
+nrf51_uart_read(uint64_t addr, uint64_t r, unsigned int size) "addr 0x%" PRIx64 " value 0x%" PRIx64 " size %u"
459
+nrf51_uart_write(uint64_t addr, uint64_t value, unsigned int size) "addr 0x%" PRIx64 " value 0x%" PRIx64 " size %u"
460
--
52
--
461
2.19.1
53
2.20.1
462
54
463
55
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
2
2
3
We are missing the VIRT_COMPAT_3_0 definition and setting.
3
After setting CP15 bits in arm_set_cpu_on() the cached hflags must
4
Let's add them.
4
be rebuild to reflect the changed processor state. Without rebuilding,
5
the cached hflags would be inconsistent until the next call to
6
arm_rebuild_hflags(). When QEMU is compiled with debugging enabled
7
(--enable-debug), this problem is captured shortly after the first
8
call to arm_set_cpu_on() for CPUs running in ARM 32-bit non-secure mode:
5
9
6
Signed-off-by: Eric Auger <eric.auger@redhat.com>
10
qemu-system-arm: target/arm/helper.c:11359: cpu_get_tb_cpu_state:
7
Reviewed-by: Andrew Jones <drjones@redhat.com>
11
Assertion `flags == rebuild_hflags_internal(env)' failed.
8
Message-id: 20181024085602.16611-1-eric.auger@redhat.com
12
Aborted (core dumped)
13
14
Fixes: 0c7f8c43daf65
15
Cc: qemu-stable@nongnu.org
16
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
19
---
11
hw/arm/virt.c | 4 ++++
20
target/arm/arm-powerctl.c | 3 +++
12
1 file changed, 4 insertions(+)
21
1 file changed, 3 insertions(+)
13
22
14
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
23
diff --git a/target/arm/arm-powerctl.c b/target/arm/arm-powerctl.c
15
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/virt.c
25
--- a/target/arm/arm-powerctl.c
17
+++ b/hw/arm/virt.c
26
+++ b/target/arm/arm-powerctl.c
18
@@ -XXX,XX +XXX,XX @@ static void virt_machine_3_1_options(MachineClass *mc)
27
@@ -XXX,XX +XXX,XX @@ static void arm_set_cpu_on_async_work(CPUState *target_cpu_state,
19
}
28
target_cpu->env.regs[0] = info->context_id;
20
DEFINE_VIRT_MACHINE_AS_LATEST(3, 1)
29
}
21
30
22
+#define VIRT_COMPAT_3_0 \
31
+ /* CP15 update requires rebuilding hflags */
23
+ HW_COMPAT_3_0
32
+ arm_rebuild_hflags(&target_cpu->env);
24
+
33
+
25
static void virt_3_0_instance_init(Object *obj)
34
/* Start the new CPU at the requested address */
26
{
35
cpu_set_pc(target_cpu_state, info->entry);
27
virt_3_1_instance_init(obj);
28
@@ -XXX,XX +XXX,XX @@ static void virt_3_0_instance_init(Object *obj)
29
static void virt_machine_3_0_options(MachineClass *mc)
30
{
31
virt_machine_3_1_options(mc);
32
+ SET_MACHINE_COMPAT(mc, VIRT_COMPAT_3_0);
33
}
34
DEFINE_VIRT_MACHINE(3, 0)
35
36
36
--
37
--
37
2.19.1
38
2.20.1
38
39
39
40
diff view generated by jsdifflib