1
target-arm queue: the big things here are the new nRF51
1
Nuvoton new board models, and some more minor stuff. I also put
2
(microbit) devices and Luc's gdbstub multiprocess work.
2
in the deprecation patches for unicore32 and lm32.
3
3
4
thanks
4
thanks
5
-- PMM
5
-- PMM
6
6
7
The following changes since commit a29644590f95166c8a13e5797f8e7701134b31d0:
7
The following changes since commit a68694cd1f3e5448cca814ff39b871f9ebd71ed5:
8
8
9
Merge remote-tracking branch 'remotes/ericb/tags/pull-nbd-2019-01-05' into staging (2019-01-07 11:55:52 +0000)
9
Merge remote-tracking branch 'remotes/philmd-gitlab/tags/edk2-next-20200914' into staging (2020-09-14 12:18:58 +0100)
10
10
11
are available in the Git repository at:
11
are available in the Git repository at:
12
12
13
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20190107
13
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20200914
14
14
15
for you to fetch changes up to f831f955d420966471f5f8b316ba50d2523b1ff0:
15
for you to fetch changes up to dd44ae00fc5342ed99acb68ec3508f76a71d523a:
16
16
17
Support u-boot noload images for arm as used by, NetBSD/evbarm GENERIC kernel. (2019-01-07 15:46:20 +0000)
17
MAINTAINERS: Add maintainer entry for Xilinx ZynqMP CAN controller (2020-09-14 14:27:08 +0100)
18
18
19
----------------------------------------------------------------
19
----------------------------------------------------------------
20
target-arm queue:
20
target-arm queue:
21
* Support u-boot 'noload' images for Arm (as used by NetBSD/evbarm GENERIC kernel)
21
* hw/misc/a9scu: Do not allow invalid CPU count
22
* hw/misc/tz-mpc: Fix value of BLK_MAX register
22
* hw/misc/a9scu: Minor cleanups
23
* target/arm: Emit barriers for A32/T32 load-acquire/store-release insns
23
* hw/timer/armv7m_systick: assert that board code set system_clock_scale
24
* nRF51 SoC: add timer, GPIO, RNG peripherals
24
* decodetree: Improve identifier matching
25
* hw/arm/allwinner-a10: Add the 'A' SRAM and the SRAM controller
25
* target/arm: Clean up neon fp insn size field decode
26
* cpus.c: Fix race condition in cpu_stop_current()
26
* target/arm: Remove KVM support for 32-bit Arm hosts
27
* hw/arm: versal: Plug memory leaks
27
* hw/arm/mps2: New board models mps2-an386, mps2-an500
28
* Allow M profile boards to run even if -kernel not specified
28
* Deprecate Unicore32 port
29
* gdbstub: Add multiprocess extension support for use when the
29
* Deprecate lm32 port
30
board has multiple CPUs of different types (like the Xilinx Zynq boards)
30
* target/arm: Count PMU events when MDCR.SPME is set
31
* target/arm: Don't decode S bit in SVE brk[ab] merging insns
31
* hw/arm: versal-virt: Correct the tx/rx GEM clocks
32
* target/arm: Convert ARM_TBFLAG_* to FIELDs
32
* New Nuvoton iBMC board models npcm750-evb, quanta-gsj
33
* xlnx-zynqmp: implement ZynqMP CAN controllers
33
34
34
----------------------------------------------------------------
35
----------------------------------------------------------------
36
Aaron Lindsay (1):
37
target/arm: Count PMU events when MDCR.SPME is set
38
35
Edgar E. Iglesias (1):
39
Edgar E. Iglesias (1):
36
hw/arm: versal: Plug memory leaks
40
hw/arm: versal-virt: Correct the tx/rx GEM clocks
37
41
38
Luc Michel (16):
42
Havard Skinnemoen (14):
39
hw/cpu: introduce CPU clusters
43
hw/misc: Add NPCM7xx System Global Control Registers device model
40
gdbstub: introduce GDB processes
44
hw/misc: Add NPCM7xx Clock Controller device model
41
gdbstub: add multiprocess support to '?' packets
45
hw/timer: Add NPCM7xx Timer device model
42
gdbstub: add multiprocess support to 'H' and 'T' packets
46
hw/arm: Add NPCM730 and NPCM750 SoC models
43
gdbstub: add multiprocess support to vCont packets
47
hw/arm: Add two NPCM7xx-based machines
44
gdbstub: add multiprocess support to 'sC' packets
48
roms: Add virtual Boot ROM for NPCM7xx SoCs
45
gdbstub: add multiprocess support to (f|s)ThreadInfo and ThreadExtraInfo
49
hw/arm: Load -bios image as a boot ROM for npcm7xx
46
gdbstub: add multiprocess support to Xfer:features:read:
50
hw/nvram: NPCM7xx OTP device model
47
gdbstub: add multiprocess support to gdb_vm_state_change()
51
hw/mem: Stubbed out NPCM7xx Memory Controller model
48
gdbstub: add multiprocess support to 'D' packets
52
hw/ssi: NPCM7xx Flash Interface Unit device model
49
gdbstub: add support for extended mode packet
53
hw/arm: Wire up BMC boot flash for npcm750-evb and quanta-gsj
50
gdbstub: add support for vAttach packets
54
hw/arm/npcm7xx: add board setup stub for CPU and UART clocks
51
gdbstub: processes initialization on new peer connection
55
docs/system: Add Nuvoton machine documentation
52
gdbstub: gdb_set_stop_cpu: ignore request when process is not attached
56
tests/acceptance: console boot tests for quanta-gsj
53
gdbstub: add multiprocess extension support
54
arm/xlnx-zynqmp: put APUs and RPUs in separate CPU clusters
55
57
56
Nick Hudson (1):
58
Peter Maydell (11):
57
Support u-boot noload images for arm as used by, NetBSD/evbarm GENERIC kernel.
59
hw/timer/armv7m_systick: assert that board code set system_clock_scale
60
target/arm: Convert Neon 3-same-fp size field to MO_* in decode
61
target/arm: Convert Neon VCVT fp size field to MO_* in decode
62
target/arm: Convert VCMLA, VCADD size field to MO_* in decode
63
target/arm: Remove KVM support for 32-bit Arm hosts
64
target/arm: Remove no-longer-reachable 32-bit KVM code
65
hw/arm/mps2: New board model mps2-an386
66
hw/arm/mps2: New board model mps2-an500
67
docs/system/arm/mps2.rst: Make board list consistent
68
Deprecate Unicore32 port
69
Deprecate lm32 port
58
70
59
Peter Maydell (3):
71
Philippe Mathieu-Daudé (4):
60
cpus.c: Fix race condition in cpu_stop_current()
72
hw/misc/a9scu: Do not allow invalid CPU count
61
target/arm: Emit barriers for A32/T32 load-acquire/store-release insns
73
hw/misc/a9scu: Simplify setting MemoryRegionOps::valid fields
62
hw/misc/tz-mpc: Fix value of BLK_MAX register
74
hw/misc/a9scu: Simplify setting MemoryRegionOps::impl fields
75
hw/misc/a9scu: Report unimplemented accesses with qemu_log_mask(UNIMP)
63
76
64
Philippe Mathieu-Daudé (1):
77
Richard Henderson (1):
65
hw/arm/allwinner-a10: Add the 'A' SRAM and the SRAM controller
78
decodetree: Improve identifier matching
66
79
67
Richard Henderson (2):
80
Vikram Garhwal (4):
68
target/arm: Convert ARM_TBFLAG_* to FIELDs
81
hw/net/can: Introduce Xilinx ZynqMP CAN controller
69
target/arm: SVE brk[ab] merging does not have s bit
82
xlnx-zynqmp: Connect Xilinx ZynqMP CAN controllers
83
tests/qtest: Introduce tests for Xilinx ZynqMP CAN controller
84
MAINTAINERS: Add maintainer entry for Xilinx ZynqMP CAN controller
70
85
71
Stefan Hajnoczi (1):
86
docs/system/arm/mps2.rst | 20 +-
72
Revert "armv7m: Guard against no -kernel argument"
87
docs/system/arm/nuvoton.rst | 92 +++
88
docs/system/deprecated.rst | 32 +-
89
docs/system/target-arm.rst | 1 +
90
configure | 2 +-
91
default-configs/arm-softmmu.mak | 1 +
92
include/hw/arm/npcm7xx.h | 112 +++
93
include/hw/arm/xlnx-zynqmp.h | 8 +
94
include/hw/mem/npcm7xx_mc.h | 36 +
95
include/hw/misc/npcm7xx_clk.h | 48 ++
96
include/hw/misc/npcm7xx_gcr.h | 43 ++
97
include/hw/net/xlnx-zynqmp-can.h | 78 +++
98
include/hw/nvram/npcm7xx_otp.h | 79 +++
99
include/hw/ssi/npcm7xx_fiu.h | 73 ++
100
include/hw/timer/npcm7xx_timer.h | 78 +++
101
target/arm/kvm-consts.h | 7 -
102
target/arm/kvm_arm.h | 6 -
103
target/arm/neon-dp.decode | 18 +-
104
target/arm/neon-shared.decode | 18 +-
105
tests/decode/succ_ident1.decode | 7 +
106
hw/arm/mps2.c | 97 ++-
107
hw/arm/npcm7xx.c | 532 +++++++++++++++
108
hw/arm/npcm7xx_boards.c | 197 ++++++
109
hw/arm/xlnx-versal-virt.c | 2 +-
110
hw/arm/xlnx-zcu102.c | 20 +
111
hw/arm/xlnx-zynqmp.c | 34 +
112
hw/mem/npcm7xx_mc.c | 84 +++
113
hw/misc/a9scu.c | 59 +-
114
hw/misc/npcm7xx_clk.c | 266 ++++++++
115
hw/misc/npcm7xx_gcr.c | 269 ++++++++
116
hw/net/can/xlnx-zynqmp-can.c | 1165 ++++++++++++++++++++++++++++++++
117
hw/nvram/npcm7xx_otp.c | 440 ++++++++++++
118
hw/ssi/npcm7xx_fiu.c | 572 ++++++++++++++++
119
hw/timer/armv7m_systick.c | 8 +
120
hw/timer/npcm7xx_timer.c | 543 +++++++++++++++
121
target/arm/cpu.c | 101 ++-
122
target/arm/helper.c | 2 +-
123
target/arm/kvm.c | 7 -
124
target/arm/kvm32.c | 595 ----------------
125
tests/qtest/xlnx-can-test.c | 359 ++++++++++
126
.gitmodules | 3 +
127
MAINTAINERS | 18 +
128
hw/arm/Kconfig | 9 +
129
hw/arm/meson.build | 1 +
130
hw/mem/meson.build | 1 +
131
hw/misc/meson.build | 4 +
132
hw/misc/trace-events | 8 +
133
hw/net/can/meson.build | 1 +
134
hw/nvram/meson.build | 1 +
135
hw/ssi/meson.build | 1 +
136
hw/ssi/trace-events | 11 +
137
hw/timer/meson.build | 1 +
138
hw/timer/trace-events | 5 +
139
pc-bios/README | 6 +
140
pc-bios/meson.build | 1 +
141
pc-bios/npcm7xx_bootrom.bin | Bin 0 -> 768 bytes
142
roms/Makefile | 7 +
143
roms/vbootrom | 1 +
144
scripts/decodetree.py | 46 +-
145
target/arm/meson.build | 5 +-
146
target/arm/translate-neon.c.inc | 42 +-
147
tests/acceptance/boot_linux_console.py | 83 +++
148
tests/qtest/meson.build | 1 +
149
63 files changed, 5584 insertions(+), 783 deletions(-)
150
create mode 100644 docs/system/arm/nuvoton.rst
151
create mode 100644 include/hw/arm/npcm7xx.h
152
create mode 100644 include/hw/mem/npcm7xx_mc.h
153
create mode 100644 include/hw/misc/npcm7xx_clk.h
154
create mode 100644 include/hw/misc/npcm7xx_gcr.h
155
create mode 100644 include/hw/net/xlnx-zynqmp-can.h
156
create mode 100644 include/hw/nvram/npcm7xx_otp.h
157
create mode 100644 include/hw/ssi/npcm7xx_fiu.h
158
create mode 100644 include/hw/timer/npcm7xx_timer.h
159
create mode 100644 tests/decode/succ_ident1.decode
160
create mode 100644 hw/arm/npcm7xx.c
161
create mode 100644 hw/arm/npcm7xx_boards.c
162
create mode 100644 hw/mem/npcm7xx_mc.c
163
create mode 100644 hw/misc/npcm7xx_clk.c
164
create mode 100644 hw/misc/npcm7xx_gcr.c
165
create mode 100644 hw/net/can/xlnx-zynqmp-can.c
166
create mode 100644 hw/nvram/npcm7xx_otp.c
167
create mode 100644 hw/ssi/npcm7xx_fiu.c
168
create mode 100644 hw/timer/npcm7xx_timer.c
169
delete mode 100644 target/arm/kvm32.c
170
create mode 100644 tests/qtest/xlnx-can-test.c
171
create mode 100644 pc-bios/npcm7xx_bootrom.bin
172
create mode 160000 roms/vbootrom
73
173
74
Steffen Görtz (11):
75
qtest: Add set_irq_in command to set IRQ/GPIO level
76
arm: Add header to host common definition for nRF51 SOC peripherals
77
hw/misc/nrf51_rng: Add NRF51 random number generator peripheral
78
arm: Instantiate NRF51 random number generator
79
hw/gpio/nrf51_gpio: Add nRF51 GPIO peripheral
80
arm: Instantiate NRF51 general purpose I/O
81
tests/microbit-test: Add Tests for nRF51 GPIO
82
hw/timer/nrf51_timer: Add nRF51 Timer peripheral
83
arm: Instantiate NRF51 Timers
84
tests/microbit-test: Add Tests for nRF51 Timer
85
arm: Add Clock peripheral stub to NRF51 SOC
86
87
Thomas Huth (1):
88
MAINTAINERS: Add ARM-related files for hw/[misc|input|timer]/
89
90
Makefile.objs | 1 +
91
hw/cpu/Makefile.objs | 2 +-
92
hw/gpio/Makefile.objs | 1 +
93
hw/misc/Makefile.objs | 1 +
94
hw/timer/Makefile.objs | 1 +
95
tests/Makefile.include | 2 +
96
hw/core/uboot_image.h | 1 +
97
include/hw/arm/allwinner-a10.h | 1 +
98
include/hw/arm/nrf51.h | 45 +++
99
include/hw/arm/nrf51_soc.h | 9 +
100
include/hw/arm/xlnx-zynqmp.h | 3 +
101
include/hw/char/nrf51_uart.h | 1 -
102
include/hw/cpu/cluster.h | 58 ++++
103
include/hw/gpio/nrf51_gpio.h | 69 +++++
104
include/hw/loader.h | 7 +-
105
include/hw/misc/nrf51_rng.h | 83 +++++
106
include/hw/timer/nrf51_timer.h | 80 +++++
107
target/arm/cpu.h | 102 ++-----
108
tests/libqtest.h | 13 +
109
cpus.c | 3 +-
110
gdbstub.c | 672 ++++++++++++++++++++++++++++++++++++-----
111
hw/arm/allwinner-a10.c | 6 +
112
hw/arm/armv7m.c | 5 -
113
hw/arm/boot.c | 8 +-
114
hw/arm/nrf51_soc.c | 117 +++++--
115
hw/arm/xlnx-versal-virt.c | 2 +
116
hw/arm/xlnx-zynqmp.c | 23 +-
117
hw/core/loader.c | 19 +-
118
hw/cpu/cluster.c | 50 +++
119
hw/gpio/nrf51_gpio.c | 300 ++++++++++++++++++
120
hw/microblaze/boot.c | 2 +-
121
hw/misc/nrf51_rng.c | 262 ++++++++++++++++
122
hw/misc/tz-mpc.c | 2 +-
123
hw/nios2/boot.c | 2 +-
124
hw/ppc/e500.c | 1 +
125
hw/ppc/ppc440_bamboo.c | 2 +-
126
hw/ppc/sam460ex.c | 2 +-
127
hw/timer/nrf51_timer.c | 393 ++++++++++++++++++++++++
128
qtest.c | 43 +++
129
target/arm/helper.c | 49 ++-
130
target/arm/translate-a64.c | 22 +-
131
target/arm/translate.c | 73 +++--
132
tests/libqtest.c | 10 +
133
tests/microbit-test.c | 255 ++++++++++++++++
134
MAINTAINERS | 18 +-
135
hw/gpio/trace-events | 7 +
136
hw/timer/trace-events | 5 +
137
target/arm/sve.decode | 5 +-
138
48 files changed, 2567 insertions(+), 271 deletions(-)
139
create mode 100644 include/hw/arm/nrf51.h
140
create mode 100644 include/hw/cpu/cluster.h
141
create mode 100644 include/hw/gpio/nrf51_gpio.h
142
create mode 100644 include/hw/misc/nrf51_rng.h
143
create mode 100644 include/hw/timer/nrf51_timer.h
144
create mode 100644 hw/cpu/cluster.c
145
create mode 100644 hw/gpio/nrf51_gpio.c
146
create mode 100644 hw/misc/nrf51_rng.c
147
create mode 100644 hw/timer/nrf51_timer.c
148
create mode 100644 tests/microbit-test.c
149
create mode 100644 hw/gpio/trace-events
150
diff view generated by jsdifflib
1
From: Steffen Görtz <contrib@steffen-goertz.de>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
Instantiates GPIO peripheral model
3
Per the datasheet (DDI0407 r2p0):
4
4
5
Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
5
"The SCU connects one to four Cortex-A9 processors to
6
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
the memory system through the AXI interfaces."
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
8
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Change the instance_init() handler to a device_realize()
9
Message-id: 20190103091119.9367-7-stefanha@redhat.com
9
one so we can verify the property is in range, and return
10
an error to the caller if not.
11
12
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20200901144100.116742-2-f4bug@amsat.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
16
---
12
include/hw/arm/nrf51_soc.h | 2 ++
17
hw/misc/a9scu.c | 18 +++++++++++++-----
13
hw/arm/nrf51_soc.c | 16 ++++++++++++++++
18
1 file changed, 13 insertions(+), 5 deletions(-)
14
2 files changed, 18 insertions(+)
15
19
16
diff --git a/include/hw/arm/nrf51_soc.h b/include/hw/arm/nrf51_soc.h
20
diff --git a/hw/misc/a9scu.c b/hw/misc/a9scu.c
17
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/nrf51_soc.h
22
--- a/hw/misc/a9scu.c
19
+++ b/include/hw/arm/nrf51_soc.h
23
+++ b/hw/misc/a9scu.c
20
@@ -XXX,XX +XXX,XX @@
24
@@ -XXX,XX +XXX,XX @@
21
#include "hw/arm/armv7m.h"
25
#include "hw/misc/a9scu.h"
22
#include "hw/char/nrf51_uart.h"
26
#include "hw/qdev-properties.h"
23
#include "hw/misc/nrf51_rng.h"
27
#include "migration/vmstate.h"
24
+#include "hw/gpio/nrf51_gpio.h"
28
+#include "qapi/error.h"
25
29
#include "qemu/module.h"
26
#define TYPE_NRF51_SOC "nrf51-soc"
30
27
#define NRF51_SOC(obj) \
31
+#define A9_SCU_CPU_MAX 4
28
@@ -XXX,XX +XXX,XX @@ typedef struct NRF51State {
32
+
29
33
static uint64_t a9_scu_read(void *opaque, hwaddr offset,
30
NRF51UARTState uart;
34
unsigned size)
31
NRF51RNGState rng;
35
{
32
+ NRF51GPIOState gpio;
36
@@ -XXX,XX +XXX,XX @@ static void a9_scu_reset(DeviceState *dev)
33
37
s->control = 0;
34
MemoryRegion iomem;
38
}
35
MemoryRegion sram;
39
36
diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c
40
-static void a9_scu_init(Object *obj)
37
index XXXXXXX..XXXXXXX 100644
41
+static void a9_scu_realize(DeviceState *dev, Error **errp)
38
--- a/hw/arm/nrf51_soc.c
42
{
39
+++ b/hw/arm/nrf51_soc.c
43
- A9SCUState *s = A9_SCU(obj);
40
@@ -XXX,XX +XXX,XX @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
44
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
41
qdev_get_gpio_in(DEVICE(&s->cpu),
45
+ A9SCUState *s = A9_SCU(dev);
42
BASE_TO_IRQ(NRF51_RNG_BASE)));
46
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
43
47
44
+ /* GPIO */
48
- memory_region_init_io(&s->iomem, obj, &a9_scu_ops, s,
45
+ object_property_set_bool(OBJECT(&s->gpio), true, "realized", &err);
49
+ if (!s->num_cpu || s->num_cpu > A9_SCU_CPU_MAX) {
46
+ if (err) {
50
+ error_setg(errp, "Illegal CPU count: %u", s->num_cpu);
47
+ error_propagate(errp, err);
48
+ return;
51
+ return;
49
+ }
52
+ }
50
+
53
+
51
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->gpio), 0);
54
+ memory_region_init_io(&s->iomem, OBJECT(s), &a9_scu_ops, s,
52
+ memory_region_add_subregion_overlap(&s->container, NRF51_GPIO_BASE, mr, 0);
55
"a9-scu", 0x100);
53
+
56
sysbus_init_mmio(sbd, &s->iomem);
54
+ /* Pass all GPIOs to the SOC layer so they are available to the board */
55
+ qdev_pass_gpios(DEVICE(&s->gpio), dev_soc, NULL);
56
+
57
create_unimplemented_device("nrf51_soc.io", NRF51_IOMEM_BASE,
58
NRF51_IOMEM_SIZE);
59
create_unimplemented_device("nrf51_soc.ficr", NRF51_FICR_BASE,
60
@@ -XXX,XX +XXX,XX @@ static void nrf51_soc_init(Object *obj)
61
62
sysbus_init_child_obj(obj, "rng", &s->rng, sizeof(s->rng),
63
TYPE_NRF51_RNG);
64
+
65
+ sysbus_init_child_obj(obj, "gpio", &s->gpio, sizeof(s->gpio),
66
+ TYPE_NRF51_GPIO);
67
}
57
}
68
58
@@ -XXX,XX +XXX,XX @@ static void a9_scu_class_init(ObjectClass *klass, void *data)
69
static Property nrf51_soc_properties[] = {
59
device_class_set_props(dc, a9_scu_properties);
60
dc->vmsd = &vmstate_a9_scu;
61
dc->reset = a9_scu_reset;
62
+ dc->realize = a9_scu_realize;
63
}
64
65
static const TypeInfo a9_scu_info = {
66
.name = TYPE_A9_SCU,
67
.parent = TYPE_SYS_BUS_DEVICE,
68
.instance_size = sizeof(A9SCUState),
69
- .instance_init = a9_scu_init,
70
.class_init = a9_scu_class_init,
71
};
72
70
--
73
--
71
2.19.2
74
2.20.1
72
75
73
76
diff view generated by jsdifflib
1
From: Nick Hudson <nick.hudson@gmx.co.uk>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
noload kernels are loaded with the u-boot image header and as a result
3
Per the datasheet (DDI0407 r2p0):
4
the header size needs adding to the entry point. Fake up a hdr so the
5
kernel image is loaded at the right address and the entry point is
6
adjusted appropriately.
7
4
8
The default location for the uboot file is 32MiB above bottom of DRAM.
5
"All SCU registers are byte accessible" and are 32-bit aligned.
9
This matches the recommendation in Documentation/arm/Booting.
10
6
11
Clarify the load_uimage API to state the passing of a load address when an
7
Set MemoryRegionOps::valid min/max fields and simplify the write()
12
image doesn't specify one, or when loading a ramdisk is expected.
8
handler.
13
9
14
Adjust callers of load_uimage, etc.
10
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Signed-off-by: Nick Hudson <skrll@netbsd.org>
12
Message-id: 20200901144100.116742-3-f4bug@amsat.org
17
Message-id: 11488a08-1fe0-a278-2210-deb64731107f@gmx.co.uk
18
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
---
14
---
21
hw/core/uboot_image.h | 1 +
15
hw/misc/a9scu.c | 21 +++++----------------
22
include/hw/loader.h | 7 ++++++-
16
1 file changed, 5 insertions(+), 16 deletions(-)
23
hw/arm/boot.c | 8 +++++---
24
hw/core/loader.c | 19 ++++++++++++++++---
25
hw/microblaze/boot.c | 2 +-
26
hw/nios2/boot.c | 2 +-
27
hw/ppc/e500.c | 1 +
28
hw/ppc/ppc440_bamboo.c | 2 +-
29
hw/ppc/sam460ex.c | 2 +-
30
9 files changed, 33 insertions(+), 11 deletions(-)
31
17
32
diff --git a/hw/core/uboot_image.h b/hw/core/uboot_image.h
18
diff --git a/hw/misc/a9scu.c b/hw/misc/a9scu.c
33
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
34
--- a/hw/core/uboot_image.h
20
--- a/hw/misc/a9scu.c
35
+++ b/hw/core/uboot_image.h
21
+++ b/hw/misc/a9scu.c
36
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@ static void a9_scu_write(void *opaque, hwaddr offset,
37
#define IH_TYPE_SCRIPT        6    /* Script file            */
23
uint64_t value, unsigned size)
38
#define IH_TYPE_FILESYSTEM    7    /* Filesystem Image (any type)    */
24
{
39
#define IH_TYPE_FLATDT        8    /* Binary Flat Device Tree Blob    */
25
A9SCUState *s = (A9SCUState *)opaque;
40
+#define IH_TYPE_KERNEL_NOLOAD 14    /* OS Kernel Image (noload)    */
26
- uint32_t mask;
41
27
+ uint32_t mask = MAKE_64BIT_MASK(0, size * 8);
42
/*
28
uint32_t shift;
43
* Compression Types
29
- switch (size) {
44
diff --git a/include/hw/loader.h b/include/hw/loader.h
30
- case 1:
45
index XXXXXXX..XXXXXXX 100644
31
- mask = 0xff;
46
--- a/include/hw/loader.h
32
- break;
47
+++ b/include/hw/loader.h
33
- case 2:
48
@@ -XXX,XX +XXX,XX @@ void load_elf_hdr(const char *filename, void *hdr, bool *is64, Error **errp);
34
- mask = 0xffff;
49
int load_aout(const char *filename, hwaddr addr, int max_sz,
35
- break;
50
int bswap_needed, hwaddr target_page_size);
36
- case 4:
51
37
- mask = 0xffffffff;
52
+#define LOAD_UIMAGE_LOADADDR_INVALID (-1)
38
- break;
53
+
39
- default:
54
/** load_uimage_as:
40
- fprintf(stderr, "Invalid size %u in write to a9 scu register %x\n",
55
* @filename: Path of uimage file
41
- size, (unsigned)offset);
56
* @ep: Populated with program entry point. Ignored if NULL.
42
- return;
57
- * @loadaddr: Populated with the load address. Ignored if NULL.
43
- }
58
+ * @loadaddr: load address if none specified in the image or when loading a
44
59
+ * ramdisk. Populated with the load address. Ignored if NULL or
45
switch (offset) {
60
+ * LOAD_UIMAGE_LOADADDR_INVALID (images which do not specify a load
46
case 0x00: /* Control */
61
+ * address will not be loadable).
47
@@ -XXX,XX +XXX,XX @@ static void a9_scu_write(void *opaque, hwaddr offset,
62
* @is_linux: Is set to true if the image loaded is Linux. Ignored if NULL.
48
static const MemoryRegionOps a9_scu_ops = {
63
* @translate_fn: optional function to translate load addresses
49
.read = a9_scu_read,
64
* @translate_opaque: opaque data passed to @translate_fn
50
.write = a9_scu_write,
65
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
51
+ .valid = {
66
index XXXXXXX..XXXXXXX 100644
52
+ .min_access_size = 1,
67
--- a/hw/arm/boot.c
53
+ .max_access_size = 4,
68
+++ b/hw/arm/boot.c
54
+ },
69
@@ -XXX,XX +XXX,XX @@
55
.endianness = DEVICE_NATIVE_ENDIAN,
70
* Documentation/arm/Booting and Documentation/arm64/booting.txt
56
};
71
* They have different preferred image load offsets from system RAM base.
57
72
*/
73
-#define KERNEL_ARGS_ADDR 0x100
74
-#define KERNEL_LOAD_ADDR 0x00010000
75
+#define KERNEL_ARGS_ADDR 0x100
76
+#define KERNEL_NOLOAD_ADDR 0x02000000
77
+#define KERNEL_LOAD_ADDR 0x00010000
78
#define KERNEL64_LOAD_ADDR 0x00080000
79
80
#define ARM64_TEXT_OFFSET_OFFSET 8
81
@@ -XXX,XX +XXX,XX @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
82
}
83
entry = elf_entry;
84
if (kernel_size < 0) {
85
- kernel_size = load_uimage_as(info->kernel_filename, &entry, NULL,
86
+ uint64_t loadaddr = info->loader_start + KERNEL_NOLOAD_ADDR;
87
+ kernel_size = load_uimage_as(info->kernel_filename, &entry, &loadaddr,
88
&is_linux, NULL, NULL, as);
89
}
90
if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64) && kernel_size < 0) {
91
diff --git a/hw/core/loader.c b/hw/core/loader.c
92
index XXXXXXX..XXXXXXX 100644
93
--- a/hw/core/loader.c
94
+++ b/hw/core/loader.c
95
@@ -XXX,XX +XXX,XX @@ static int load_uboot_image(const char *filename, hwaddr *ep, hwaddr *loadaddr,
96
goto out;
97
98
if (hdr->ih_type != image_type) {
99
- fprintf(stderr, "Wrong image type %d, expected %d\n", hdr->ih_type,
100
- image_type);
101
- goto out;
102
+ if (!(image_type == IH_TYPE_KERNEL &&
103
+ hdr->ih_type == IH_TYPE_KERNEL_NOLOAD)) {
104
+ fprintf(stderr, "Wrong image type %d, expected %d\n", hdr->ih_type,
105
+ image_type);
106
+ goto out;
107
+ }
108
}
109
110
/* TODO: Implement other image types. */
111
switch (hdr->ih_type) {
112
+ case IH_TYPE_KERNEL_NOLOAD:
113
+ if (!loadaddr || *loadaddr == LOAD_UIMAGE_LOADADDR_INVALID) {
114
+ fprintf(stderr, "this image format (kernel_noload) cannot be "
115
+ "loaded on this machine type");
116
+ goto out;
117
+ }
118
+
119
+ hdr->ih_load = *loadaddr + sizeof(*hdr);
120
+ hdr->ih_ep += hdr->ih_load;
121
+ /* fall through */
122
case IH_TYPE_KERNEL:
123
address = hdr->ih_load;
124
if (translate_fn) {
125
diff --git a/hw/microblaze/boot.c b/hw/microblaze/boot.c
126
index XXXXXXX..XXXXXXX 100644
127
--- a/hw/microblaze/boot.c
128
+++ b/hw/microblaze/boot.c
129
@@ -XXX,XX +XXX,XX @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base,
130
131
/* If it wasn't an ELF image, try an u-boot image. */
132
if (kernel_size < 0) {
133
- hwaddr uentry, loadaddr;
134
+ hwaddr uentry, loadaddr = LOAD_UIMAGE_LOADADDR_INVALID;
135
136
kernel_size = load_uimage(kernel_filename, &uentry, &loadaddr, 0,
137
NULL, NULL);
138
diff --git a/hw/nios2/boot.c b/hw/nios2/boot.c
139
index XXXXXXX..XXXXXXX 100644
140
--- a/hw/nios2/boot.c
141
+++ b/hw/nios2/boot.c
142
@@ -XXX,XX +XXX,XX @@ void nios2_load_kernel(Nios2CPU *cpu, hwaddr ddr_base,
143
144
/* If it wasn't an ELF image, try an u-boot image. */
145
if (kernel_size < 0) {
146
- hwaddr uentry, loadaddr;
147
+ hwaddr uentry, loadaddr = LOAD_UIMAGE_LOADADDR_INVALID;
148
149
kernel_size = load_uimage(kernel_filename, &uentry, &loadaddr, 0,
150
NULL, NULL);
151
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
152
index XXXXXXX..XXXXXXX 100644
153
--- a/hw/ppc/e500.c
154
+++ b/hw/ppc/e500.c
155
@@ -XXX,XX +XXX,XX @@ void ppce500_init(MachineState *machine)
156
* Hrm. No ELF image? Try a uImage, maybe someone is giving us an
157
* ePAPR compliant kernel
158
*/
159
+ loadaddr = LOAD_UIMAGE_LOADADDR_INVALID;
160
payload_size = load_uimage(filename, &bios_entry, &loadaddr, NULL,
161
NULL, NULL);
162
if (payload_size < 0) {
163
diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c
164
index XXXXXXX..XXXXXXX 100644
165
--- a/hw/ppc/ppc440_bamboo.c
166
+++ b/hw/ppc/ppc440_bamboo.c
167
@@ -XXX,XX +XXX,XX @@ static void bamboo_init(MachineState *machine)
168
CPUPPCState *env;
169
uint64_t elf_entry;
170
uint64_t elf_lowaddr;
171
- hwaddr loadaddr = 0;
172
+ hwaddr loadaddr = LOAD_UIMAGE_LOADADDR_INVALID;
173
target_long initrd_size = 0;
174
DeviceState *dev;
175
int success;
176
diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c
177
index XXXXXXX..XXXXXXX 100644
178
--- a/hw/ppc/sam460ex.c
179
+++ b/hw/ppc/sam460ex.c
180
@@ -XXX,XX +XXX,XX @@ static void sam460ex_init(MachineState *machine)
181
CPUPPCState *env;
182
PPC4xxI2CState *i2c[2];
183
hwaddr entry = UBOOT_ENTRY;
184
- hwaddr loadaddr = 0;
185
+ hwaddr loadaddr = LOAD_UIMAGE_LOADADDR_INVALID;
186
target_long initrd_size = 0;
187
DeviceState *dev;
188
SysBusDevice *sbdev;
189
--
58
--
190
2.19.2
59
2.20.1
191
60
192
61
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
From the "A10 User Manual V1.20" p.29: "3.2. Memory Mapping" and:
3
This model implementation is designed for 32-bit accesses.
4
We can simplify setting the MemoryRegionOps::impl min/max
5
fields to 32-bit (memory::access_with_adjusted_size() will
6
take care of the 8/16-bit accesses).
4
7
5
7. System Control
6
7.1. Overview
7
8
A10 embeds a high-speed SRAM which has been split into five segments.
9
See detailed memory mapping in following table:
10
11
Area Address Size (Bytes)
12
A1 0x00000000-0x00003FFF 16K
13
A2 0x00004000-0x00007FFF 16K
14
A3 0x00008000-0x0000B3FF 13K
15
A4 0x0000B400-0x0000BFFF 3K
16
17
Since for emulation purpose we don't need the segmentations, we simply define
18
the 'A' area as a single 48KB SRAM.
19
20
We don't implement the following others areas:
21
- 'B': 'Secure RAM' (64K),
22
- 'C': Debug/ISP SRAM
23
- 'D': USB SRAM
24
25
(qemu) info mtree
26
address-space: memory
27
0000000000000000-ffffffffffffffff (prio 0, i/o): system
28
0000000000000000-000000000000bfff (prio 0, ram): sram A
29
0000000001c00000-0000000001c00fff (prio -1000, i/o): a10-sram-ctrl
30
0000000001c0b000-0000000001c0bfff (prio 0, i/o): aw_emac
31
0000000001c18000-0000000001c18fff (prio 0, i/o): ahci
32
0000000001c18080-0000000001c180ff (prio 0, i/o): allwinner-ahci
33
0000000001c20400-0000000001c207ff (prio 0, i/o): allwinner-a10-pic
34
0000000001c20c00-0000000001c20fff (prio 0, i/o): allwinner-A10-timer
35
0000000001c28000-0000000001c2801f (prio 0, i/o): serial
36
0000000040000000-0000000047ffffff (prio 0, ram): cubieboard.ram
37
38
Reported-by: Charlie Smurthwaite <charlie@atech.media>
39
Tested-by: Charlie Smurthwaite <charlie@atech.media>
40
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
41
Message-id: 20190104142921.878-1-f4bug@amsat.org
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
42
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Message-id: 20200901144100.116742-4-f4bug@amsat.org
43
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
44
---
12
---
45
include/hw/arm/allwinner-a10.h | 1 +
13
hw/misc/a9scu.c | 16 +++++-----------
46
hw/arm/allwinner-a10.c | 6 ++++++
14
1 file changed, 5 insertions(+), 11 deletions(-)
47
2 files changed, 7 insertions(+)
48
15
49
diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h
16
diff --git a/hw/misc/a9scu.c b/hw/misc/a9scu.c
50
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
51
--- a/include/hw/arm/allwinner-a10.h
18
--- a/hw/misc/a9scu.c
52
+++ b/include/hw/arm/allwinner-a10.h
19
+++ b/hw/misc/a9scu.c
53
@@ -XXX,XX +XXX,XX @@ typedef struct AwA10State {
20
@@ -XXX,XX +XXX,XX @@ static uint64_t a9_scu_read(void *opaque, hwaddr offset,
54
AwA10PICState intc;
21
return (((1 << s->num_cpu) - 1) << 4) | (s->num_cpu - 1);
55
AwEmacState emac;
22
case 0x08: /* CPU Power Status */
56
AllwinnerAHCIState sata;
23
return s->status;
57
+ MemoryRegion sram_a;
24
- case 0x09: /* CPU status. */
58
} AwA10State;
25
- return s->status >> 8;
59
26
- case 0x0a: /* CPU status. */
60
#define ALLWINNER_H_
27
- return s->status >> 16;
61
diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c
28
- case 0x0b: /* CPU status. */
62
index XXXXXXX..XXXXXXX 100644
29
- return s->status >> 24;
63
--- a/hw/arm/allwinner-a10.c
30
case 0x0c: /* Invalidate All Registers In Secure State */
64
+++ b/hw/arm/allwinner-a10.c
31
return 0;
65
@@ -XXX,XX +XXX,XX @@
32
case 0x40: /* Filtering Start Address Register */
66
#include "hw/sysbus.h"
33
@@ -XXX,XX +XXX,XX @@ static void a9_scu_write(void *opaque, hwaddr offset,
67
#include "hw/devices.h"
34
uint64_t value, unsigned size)
68
#include "hw/arm/allwinner-a10.h"
69
+#include "hw/misc/unimp.h"
70
71
static void aw_a10_init(Object *obj)
72
{
35
{
73
@@ -XXX,XX +XXX,XX @@ static void aw_a10_realize(DeviceState *dev, Error **errp)
36
A9SCUState *s = (A9SCUState *)opaque;
74
sysbus_connect_irq(sysbusdev, 4, s->irq[67]);
37
- uint32_t mask = MAKE_64BIT_MASK(0, size * 8);
75
sysbus_connect_irq(sysbusdev, 5, s->irq[68]);
38
- uint32_t shift;
76
39
77
+ memory_region_init_ram(&s->sram_a, OBJECT(dev), "sram A", 48 * KiB,
40
switch (offset) {
78
+ &error_fatal);
41
case 0x00: /* Control */
79
+ memory_region_add_subregion(get_system_memory(), 0x00000000, &s->sram_a);
42
@@ -XXX,XX +XXX,XX @@ static void a9_scu_write(void *opaque, hwaddr offset,
80
+ create_unimplemented_device("a10-sram-ctrl", 0x01c00000, 4 * KiB);
43
case 0x4: /* Configuration: RO */
81
+
44
break;
82
/* FIXME use qdev NIC properties instead of nd_table[] */
45
case 0x08: case 0x09: case 0x0A: case 0x0B: /* Power Control */
83
if (nd_table[0].used) {
46
- shift = (offset - 0x8) * 8;
84
qemu_check_nic_model(&nd_table[0], TYPE_AW_EMAC);
47
- s->status &= ~(mask << shift);
48
- s->status |= ((value & mask) << shift);
49
+ s->status = value;
50
break;
51
case 0x0c: /* Invalidate All Registers In Secure State */
52
/* no-op as we do not implement caches */
53
@@ -XXX,XX +XXX,XX @@ static void a9_scu_write(void *opaque, hwaddr offset,
54
static const MemoryRegionOps a9_scu_ops = {
55
.read = a9_scu_read,
56
.write = a9_scu_write,
57
+ .impl = {
58
+ .min_access_size = 4,
59
+ .max_access_size = 4,
60
+ },
61
.valid = {
62
.min_access_size = 1,
63
.max_access_size = 4,
85
--
64
--
86
2.19.2
65
2.20.1
87
66
88
67
diff view generated by jsdifflib
1
From: Luc Michel <luc.michel@greensocs.com>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
Add multiprocess extension support by enabling multiprocess mode when
3
Report unimplemented register accesses using qemu_log_mask(UNIMP).
4
the peer requests it, and by replying that we actually support it in the
5
qSupported reply packet.
6
4
7
Signed-off-by: Luc Michel <luc.michel@greensocs.com>
5
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Acked-by: Alistair Francis <alistair.francis@wdc.com>
7
Message-id: 20200901144100.116742-5-f4bug@amsat.org
10
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
11
Message-id: 20181207090135.7651-16-luc.michel@greensocs.com
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
9
---
14
gdbstub.c | 6 ++++++
10
hw/misc/a9scu.c | 6 ++++++
15
1 file changed, 6 insertions(+)
11
1 file changed, 6 insertions(+)
16
12
17
diff --git a/gdbstub.c b/gdbstub.c
13
diff --git a/hw/misc/a9scu.c b/hw/misc/a9scu.c
18
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
19
--- a/gdbstub.c
15
--- a/hw/misc/a9scu.c
20
+++ b/gdbstub.c
16
+++ b/hw/misc/a9scu.c
21
@@ -XXX,XX +XXX,XX @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
17
@@ -XXX,XX +XXX,XX @@
22
if (cc->gdb_core_xml_file != NULL) {
18
#include "hw/qdev-properties.h"
23
pstrcat(buf, sizeof(buf), ";qXfer:features:read+");
19
#include "migration/vmstate.h"
24
}
20
#include "qapi/error.h"
25
+
21
+#include "qemu/log.h"
26
+ if (strstr(p, "multiprocess+")) {
22
#include "qemu/module.h"
27
+ s->multiprocess = true;
23
28
+ }
24
#define A9_SCU_CPU_MAX 4
29
+ pstrcat(buf, sizeof(buf), ";multiprocess+");
25
@@ -XXX,XX +XXX,XX @@ static uint64_t a9_scu_read(void *opaque, hwaddr offset,
30
+
26
case 0x54: /* SCU Non-secure Access Control Register */
31
put_packet(s, buf);
27
/* unimplemented, fall through */
32
break;
28
default:
33
}
29
+ qemu_log_mask(LOG_UNIMP, "%s: Unsupported offset 0x%"HWADDR_PRIx"\n",
30
+ __func__, offset);
31
return 0;
32
}
33
}
34
@@ -XXX,XX +XXX,XX @@ static void a9_scu_write(void *opaque, hwaddr offset,
35
case 0x54: /* SCU Non-secure Access Control Register */
36
/* unimplemented, fall through */
37
default:
38
+ qemu_log_mask(LOG_UNIMP, "%s: Unsupported offset 0x%"HWADDR_PRIx
39
+ " value 0x%"PRIx64"\n",
40
+ __func__, offset, value);
41
break;
42
}
43
}
34
--
44
--
35
2.19.2
45
2.20.1
36
46
37
47
diff view generated by jsdifflib
1
From: Luc Michel <luc.michel@greensocs.com>
1
It is the responsibility of board code for an armv7m system to set
2
system_clock_scale appropriately for the CPU speed of the core.
3
If it forgets to do this, then QEMU will hang if the guest tries
4
to use the systick timer in the "tick at the CPU clock frequency" mode.
2
5
3
Add support for the vAttach packets. In multiprocess mode, GDB sends
6
We forgot that in a couple of our boards (see commits ce4f70e81ed23c93f,
4
them to attach to additional processes.
7
e7e5a9595ab1136). Add an assertion in the systick reset method so
8
we don't let any new boards in with the same bug.
5
9
6
Signed-off-by: Luc Michel <luc.michel@greensocs.com>
7
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Acked-by: Alistair Francis <alistair.francis@wdc.com>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Message-id: 20181207090135.7651-13-luc.michel@greensocs.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Message-id: 20200825160847.18091-1-peter.maydell@linaro.org
12
---
13
---
13
gdbstub.c | 35 +++++++++++++++++++++++++++++++++++
14
hw/timer/armv7m_systick.c | 8 ++++++++
14
1 file changed, 35 insertions(+)
15
1 file changed, 8 insertions(+)
15
16
16
diff --git a/gdbstub.c b/gdbstub.c
17
diff --git a/hw/timer/armv7m_systick.c b/hw/timer/armv7m_systick.c
17
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
18
--- a/gdbstub.c
19
--- a/hw/timer/armv7m_systick.c
19
+++ b/gdbstub.c
20
+++ b/hw/timer/armv7m_systick.c
20
@@ -XXX,XX +XXX,XX @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
21
@@ -XXX,XX +XXX,XX @@ static void systick_reset(DeviceState *dev)
21
goto unknown_command;
22
{
22
}
23
SysTickState *s = SYSTICK(dev);
23
break;
24
24
+ } else if (strncmp(p, "Attach;", 7) == 0) {
25
+ /*
25
+ unsigned long pid;
26
+ * Forgetting to set system_clock_scale is always a board code
27
+ * bug. We can't check this earlier because for some boards
28
+ * (like stellaris) it is not yet configured at the point where
29
+ * the systick device is realized.
30
+ */
31
+ assert(system_clock_scale != 0);
26
+
32
+
27
+ p += 7;
33
s->control = 0;
28
+
34
s->reload = 0;
29
+ if (qemu_strtoul(p, &p, 16, &pid)) {
35
s->tick = 0;
30
+ put_packet(s, "E22");
31
+ break;
32
+ }
33
+
34
+ process = gdb_get_process(s, pid);
35
+
36
+ if (process == NULL) {
37
+ put_packet(s, "E22");
38
+ break;
39
+ }
40
+
41
+ cpu = get_first_cpu_in_process(s, process);
42
+
43
+ if (cpu == NULL) {
44
+ /* Refuse to attach an empty process */
45
+ put_packet(s, "E22");
46
+ break;
47
+ }
48
+
49
+ process->attached = true;
50
+
51
+ s->g_cpu = cpu;
52
+ s->c_cpu = cpu;
53
+
54
+ snprintf(buf, sizeof(buf), "T%02xthread:%s;", GDB_SIGNAL_TRAP,
55
+ gdb_fmt_thread_id(s, cpu, thread_id, sizeof(thread_id)));
56
+
57
+ put_packet(s, buf);
58
+ break;
59
} else {
60
goto unknown_command;
61
}
62
--
36
--
63
2.19.2
37
2.20.1
64
38
65
39
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
While brk[ab] zeroing has a flags setting option, the merging variant
3
Only argument set members have to be C identifiers, everything
4
does not. Retain the same argument structure, to share expansion but
4
else gets prefixed during conversion to C. Some places just
5
force the flag zero and do not decode bit 22.
5
checked the leading character, and some places matched a leading
6
character plus a C identifier.
6
7
7
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
8
Convert everything to match full identifiers, including the
9
[&%@&] prefix, and drop the full C identifier requirement.
10
11
Reported-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20181226215003.31438-1-richard.henderson@linaro.org
13
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Message-id: 20200903192334.1603773-1-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
16
---
13
target/arm/sve.decode | 5 +++--
17
tests/decode/succ_ident1.decode | 7 +++++
14
1 file changed, 3 insertions(+), 2 deletions(-)
18
scripts/decodetree.py | 46 +++++++++++++++++++++------------
19
2 files changed, 37 insertions(+), 16 deletions(-)
20
create mode 100644 tests/decode/succ_ident1.decode
15
21
16
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
22
diff --git a/tests/decode/succ_ident1.decode b/tests/decode/succ_ident1.decode
23
new file mode 100644
24
index XXXXXXX..XXXXXXX
25
--- /dev/null
26
+++ b/tests/decode/succ_ident1.decode
27
@@ -XXX,XX +XXX,XX @@
28
+%1f 0:8
29
+%2f 8:8
30
+%3f 16:8
31
+
32
+&3arg a b c
33
+@3arg ........ ........ ........ ........ &3arg a=%1f b=%2f c=%3f
34
+3insn 00000000 ........ ........ ........ @3arg
35
diff --git a/scripts/decodetree.py b/scripts/decodetree.py
17
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/sve.decode
37
--- a/scripts/decodetree.py
19
+++ b/target/arm/sve.decode
38
+++ b/scripts/decodetree.py
20
@@ -XXX,XX +XXX,XX @@
39
@@ -XXX,XX +XXX,XX @@ output_fd = None
21
40
insntype = 'uint32_t'
22
# Two operand with governing predicate, flags setting
41
decode_function = 'decode'
23
@pd_pg_pn_s ........ . s:1 ...... .. pg:4 . rn:4 . rd:4 &rpr_s
42
24
+@pd_pg_pn_s0 ........ . . ...... .. pg:4 . rn:4 . rd:4 &rpr_s s=0
43
-re_ident = '[a-zA-Z][a-zA-Z0-9_]*'
25
44
+# An identifier for C.
26
# Three operand with unused vector element size
45
+re_C_ident = '[a-zA-Z][a-zA-Z0-9_]*'
27
@rd_rn_rm_e0 ........ ... rm:5 ... ... rn:5 rd:5 &rrr_esz esz=0
46
28
@@ -XXX,XX +XXX,XX @@ BRKPB 00100101 0. 00 .... 11 .... 0 .... 1 .... @pd_pg_pn_pm_s
47
+# Identifiers for Arguments, Fields, Formats and Patterns.
29
# SVE partition break condition
48
+re_arg_ident = '&[a-zA-Z0-9_]*'
30
BRKA_z 00100101 0. 01000001 .... 0 .... 0 .... @pd_pg_pn_s
49
+re_fld_ident = '%[a-zA-Z0-9_]*'
31
BRKB_z 00100101 1. 01000001 .... 0 .... 0 .... @pd_pg_pn_s
50
+re_fmt_ident = '@[a-zA-Z0-9_]*'
32
-BRKA_m 00100101 0. 01000001 .... 0 .... 1 .... @pd_pg_pn_s
51
+re_pat_ident = '[a-zA-Z0-9_]*'
33
-BRKB_m 00100101 1. 01000001 .... 0 .... 1 .... @pd_pg_pn_s
52
34
+BRKA_m 00100101 00 01000001 .... 0 .... 1 .... @pd_pg_pn_s0
53
def error_with_file(file, lineno, *args):
35
+BRKB_m 00100101 10 01000001 .... 0 .... 1 .... @pd_pg_pn_s0
54
"""Print an error message from file:line and args and exit."""
36
55
@@ -XXX,XX +XXX,XX @@ class ExcMultiPattern(MultiPattern):
37
# SVE propagate break to next partition
56
def parse_field(lineno, name, toks):
38
BRKN 00100101 0. 01100001 .... 0 .... 0 .... @pd_pg_pn_s
57
"""Parse one instruction field from TOKS at LINENO"""
58
global fields
59
- global re_ident
60
global insnwidth
61
62
# A "simple" field will have only one entry;
63
@@ -XXX,XX +XXX,XX @@ def parse_field(lineno, name, toks):
64
width = 0
65
func = None
66
for t in toks:
67
- if re.fullmatch('!function=' + re_ident, t):
68
+ if re.match('^!function=', t):
69
if func:
70
error(lineno, 'duplicate function')
71
func = t.split('=')
72
@@ -XXX,XX +XXX,XX @@ def parse_field(lineno, name, toks):
73
def parse_arguments(lineno, name, toks):
74
"""Parse one argument set from TOKS at LINENO"""
75
global arguments
76
- global re_ident
77
+ global re_C_ident
78
global anyextern
79
80
flds = []
81
@@ -XXX,XX +XXX,XX @@ def parse_arguments(lineno, name, toks):
82
extern = True
83
anyextern = True
84
continue
85
- if not re.fullmatch(re_ident, t):
86
+ if not re.fullmatch(re_C_ident, t):
87
error(lineno, 'invalid argument set token "{0}"'.format(t))
88
if t in flds:
89
error(lineno, 'duplicate argument "{0}"'.format(t))
90
@@ -XXX,XX +XXX,XX @@ def parse_generic(lineno, parent_pat, name, toks):
91
global arguments
92
global formats
93
global allpatterns
94
- global re_ident
95
+ global re_arg_ident
96
+ global re_fld_ident
97
+ global re_fmt_ident
98
+ global re_C_ident
99
global insnwidth
100
global insnmask
101
global variablewidth
102
@@ -XXX,XX +XXX,XX @@ def parse_generic(lineno, parent_pat, name, toks):
103
fmt = None
104
for t in toks:
105
# '&Foo' gives a format an explcit argument set.
106
- if t[0] == '&':
107
+ if re.fullmatch(re_arg_ident, t):
108
tt = t[1:]
109
if arg:
110
error(lineno, 'multiple argument sets')
111
@@ -XXX,XX +XXX,XX @@ def parse_generic(lineno, parent_pat, name, toks):
112
continue
113
114
# '@Foo' gives a pattern an explicit format.
115
- if t[0] == '@':
116
+ if re.fullmatch(re_fmt_ident, t):
117
tt = t[1:]
118
if fmt:
119
error(lineno, 'multiple formats')
120
@@ -XXX,XX +XXX,XX @@ def parse_generic(lineno, parent_pat, name, toks):
121
continue
122
123
# '%Foo' imports a field.
124
- if t[0] == '%':
125
+ if re.fullmatch(re_fld_ident, t):
126
tt = t[1:]
127
flds = add_field_byname(lineno, flds, tt, tt)
128
continue
129
130
# 'Foo=%Bar' imports a field with a different name.
131
- if re.fullmatch(re_ident + '=%' + re_ident, t):
132
+ if re.fullmatch(re_C_ident + '=' + re_fld_ident, t):
133
(fname, iname) = t.split('=%')
134
flds = add_field_byname(lineno, flds, fname, iname)
135
continue
136
137
# 'Foo=number' sets an argument field to a constant value
138
- if re.fullmatch(re_ident + '=[+-]?[0-9]+', t):
139
+ if re.fullmatch(re_C_ident + '=[+-]?[0-9]+', t):
140
(fname, value) = t.split('=')
141
value = int(value)
142
flds = add_field(lineno, flds, fname, ConstField(value))
143
@@ -XXX,XX +XXX,XX @@ def parse_generic(lineno, parent_pat, name, toks):
144
fixedmask = (fixedmask << shift) | fms
145
undefmask = (undefmask << shift) | ubm
146
# Otherwise, fieldname:fieldwidth
147
- elif re.fullmatch(re_ident + ':s?[0-9]+', t):
148
+ elif re.fullmatch(re_C_ident + ':s?[0-9]+', t):
149
(fname, flen) = t.split(':')
150
sign = False
151
if flen[0] == 's':
152
@@ -XXX,XX +XXX,XX @@ def parse_generic(lineno, parent_pat, name, toks):
153
154
def parse_file(f, parent_pat):
155
"""Parse all of the patterns within a file"""
156
+ global re_arg_ident
157
+ global re_fld_ident
158
+ global re_fmt_ident
159
+ global re_pat_ident
160
161
# Read all of the lines of the file. Concatenate lines
162
# ending in backslash; discard empty lines and comments.
163
@@ -XXX,XX +XXX,XX @@ def parse_file(f, parent_pat):
164
continue
165
166
# Determine the type of object needing to be parsed.
167
- if name[0] == '%':
168
+ if re.fullmatch(re_fld_ident, name):
169
parse_field(start_lineno, name[1:], toks)
170
- elif name[0] == '&':
171
+ elif re.fullmatch(re_arg_ident, name):
172
parse_arguments(start_lineno, name[1:], toks)
173
- elif name[0] == '@':
174
+ elif re.fullmatch(re_fmt_ident, name):
175
parse_generic(start_lineno, None, name[1:], toks)
176
- else:
177
+ elif re.fullmatch(re_pat_ident, name):
178
parse_generic(start_lineno, parent_pat, name, toks)
179
+ else:
180
+ error(lineno, 'invalid token "{0}"'.format(name))
181
toks = []
182
183
if nesting != 0:
39
--
184
--
40
2.19.2
185
2.20.1
41
186
42
187
diff view generated by jsdifflib
1
From: Steffen Görtz <contrib@steffen-goertz.de>
1
In the Neon instructions, some instruction formats have a 2-bit size
2
field which corresponds exactly to QEMU's MO_8/16/32/64. However the
3
floating-point insns in the 3-same group have a 1-bit size field
4
which is "0 for 32-bit float and 1 for 16-bit float". Currently we
5
pass these values directly through to trans_ functions, which means
6
that when reading a particular trans_ function you need to know if
7
that insn uses a 2-bit size or a 1-bit size.
2
8
3
Adds a new qtest command "set_irq_in" which allows
9
Move the handling of the 1-bit size to the decodetree file, so that
4
to set qemu gpio lines to a given level.
10
all these insns consistently pass a size to the trans_ function which
11
is an MO_8/16/32/64 value.
5
12
6
Based on https://lists.gnu.org/archive/html/qemu-devel/2012-12/msg02363.html
13
In this commit we switch over the insns using the 3same_fp and
7
which never got merged.
14
3same_fp_q0 formats.
8
15
9
Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
10
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Reviewed-by: Thomas Huth <thuth@redhat.com>
12
Reviewed-by: Laurent Vivier <lvivier@redhat.com>
13
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
14
Message-id: 20190103091119.9367-2-stefanha@redhat.com
15
Originally-by: Matthew Ogilvie <mmogilvi_qemu@miniinfo.net>
16
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
17
Reviewed-by: Thomas Huth <thuth@redhat.com>
18
Reviewed-by: Laurent Vivier <lvivier@redhat.com>
19
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Message-id: 20200903133209.5141-2-peter.maydell@linaro.org
21
---
19
---
22
tests/libqtest.h | 13 +++++++++++++
20
target/arm/neon-dp.decode | 15 ++++++++++-----
23
qtest.c | 43 +++++++++++++++++++++++++++++++++++++++++++
21
target/arm/translate-neon.c.inc | 16 +++++++++++-----
24
tests/libqtest.c | 10 ++++++++++
22
2 files changed, 21 insertions(+), 10 deletions(-)
25
3 files changed, 66 insertions(+)
26
23
27
diff --git a/tests/libqtest.h b/tests/libqtest.h
24
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
28
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
29
--- a/tests/libqtest.h
26
--- a/target/arm/neon-dp.decode
30
+++ b/tests/libqtest.h
27
+++ b/target/arm/neon-dp.decode
31
@@ -XXX,XX +XXX,XX @@ void qtest_irq_intercept_in(QTestState *s, const char *string);
28
@@ -XXX,XX +XXX,XX @@
32
*/
29
@3same_q0 .... ... . . . size:2 .... .... .... . 0 . . .... \
33
void qtest_irq_intercept_out(QTestState *s, const char *string);
30
&3same vm=%vm_dp vn=%vn_dp vd=%vd_dp q=0
34
31
35
+/**
32
-# For FP insns the high bit of 'size' is used as part of opcode decode
36
+ * qtest_set_irq_in:
33
-@3same_fp .... ... . . . . size:1 .... .... .... . q:1 . . .... \
37
+ * @s: QTestState instance to operate on.
34
- &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp
38
+ * @string: QOM path of a device
35
-@3same_fp_q0 .... ... . . . . size:1 .... .... .... . 0 . . .... \
39
+ * @name: IRQ name
36
- &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp q=0
40
+ * @irq: IRQ number
37
+# For FP insns the high bit of 'size' is used as part of opcode decode,
41
+ * @level: IRQ level
38
+# and the 'size' bit is 0 for 32-bit float and 1 for 16-bit float.
42
+ *
39
+# This converts this encoding to the same MO_8/16/32/64 values that the
43
+ * Force given device/irq GPIO-in pin to the given level.
40
+# integer neon insns use.
44
+ */
41
+%3same_fp_size 20:1 !function=neon_3same_fp_size
45
+void qtest_set_irq_in(QTestState *s, const char *string, const char *name,
46
+ int irq, int level);
47
+
42
+
48
/**
43
+@3same_fp .... ... . . . . . .... .... .... . q:1 . . .... \
49
* qtest_outb:
44
+ &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp size=%3same_fp_size
50
* @s: #QTestState instance to operate on.
45
+@3same_fp_q0 .... ... . . . . . .... .... .... . 0 . . .... \
51
diff --git a/qtest.c b/qtest.c
46
+ &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp q=0 size=%3same_fp_size
47
48
VHADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 0 .... @3same
49
VHADD_U_3s 1111 001 1 0 . .. .... .... 0000 . . . 0 .... @3same
50
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
52
index XXXXXXX..XXXXXXX 100644
51
index XXXXXXX..XXXXXXX 100644
53
--- a/qtest.c
52
--- a/target/arm/translate-neon.c.inc
54
+++ b/qtest.c
53
+++ b/target/arm/translate-neon.c.inc
55
@@ -XXX,XX +XXX,XX @@ static bool qtest_opened;
54
@@ -XXX,XX +XXX,XX @@ static inline int rsub_8(DisasContext *s, int x)
56
* where NUM is an IRQ number. For the PC, interrupts can be intercepted
55
return 8 - x;
57
* simply with "irq_intercept_in ioapic" (note that IRQ0 comes out with
58
* NUM=0 even though it is remapped to GSI 2).
59
+ *
60
+ * Setting interrupt level:
61
+ *
62
+ * > set_irq_in QOM-PATH NAME NUM LEVEL
63
+ * < OK
64
+ *
65
+ * where NAME is the name of the irq/gpio list, NUM is an IRQ number and
66
+ * LEVEL is an signed integer IRQ level.
67
+ *
68
+ * Forcibly set the given interrupt pin to the given level.
69
+ *
70
*/
71
72
static int hex2nib(char ch)
73
@@ -XXX,XX +XXX,XX @@ static void qtest_process_command(CharBackend *chr, gchar **words)
74
irq_intercept_dev = dev;
75
qtest_send_prefix(chr);
76
qtest_send(chr, "OK\n");
77
+ } else if (strcmp(words[0], "set_irq_in") == 0) {
78
+ DeviceState *dev;
79
+ qemu_irq irq;
80
+ char *name;
81
+ int ret;
82
+ int num;
83
+ int level;
84
85
+ g_assert(words[1] && words[2] && words[3] && words[4]);
86
+
87
+ dev = DEVICE(object_resolve_path(words[1], NULL));
88
+ if (!dev) {
89
+ qtest_send_prefix(chr);
90
+ qtest_send(chr, "FAIL Unknown device\n");
91
+ return;
92
+ }
93
+
94
+ if (strcmp(words[2], "unnamed-gpio-in") == 0) {
95
+ name = NULL;
96
+ } else {
97
+ name = words[2];
98
+ }
99
+
100
+ ret = qemu_strtoi(words[3], NULL, 0, &num);
101
+ g_assert(!ret);
102
+ ret = qemu_strtoi(words[4], NULL, 0, &level);
103
+ g_assert(!ret);
104
+
105
+ irq = qdev_get_gpio_in_named(dev, name, num);
106
+
107
+ qemu_set_irq(irq, level);
108
+ qtest_send_prefix(chr);
109
+ qtest_send(chr, "OK\n");
110
} else if (strcmp(words[0], "outb") == 0 ||
111
strcmp(words[0], "outw") == 0 ||
112
strcmp(words[0], "outl") == 0) {
113
diff --git a/tests/libqtest.c b/tests/libqtest.c
114
index XXXXXXX..XXXXXXX 100644
115
--- a/tests/libqtest.c
116
+++ b/tests/libqtest.c
117
@@ -XXX,XX +XXX,XX @@ void qtest_irq_intercept_in(QTestState *s, const char *qom_path)
118
qtest_rsp(s, 0);
119
}
56
}
120
57
121
+void qtest_set_irq_in(QTestState *s, const char *qom_path, const char *name,
58
+static inline int neon_3same_fp_size(DisasContext *s, int x)
122
+ int num, int level)
123
+{
59
+{
124
+ if (!name) {
60
+ /* Convert 0==fp32, 1==fp16 into a MO_* value */
125
+ name = "unnamed-gpio-in";
61
+ return MO_32 - x;
126
+ }
127
+ qtest_sendf(s, "set_irq_in %s %s %d %d\n", qom_path, name, num, level);
128
+ qtest_rsp(s, 0);
129
+}
62
+}
130
+
63
+
131
static void qtest_out(QTestState *s, const char *cmd, uint16_t addr, uint32_t value)
64
/* Include the generated Neon decoder */
132
{
65
#include "decode-neon-dp.c.inc"
133
qtest_sendf(s, "%s 0x%x 0x%x\n", cmd, addr, value);
66
#include "decode-neon-ls.c.inc"
67
@@ -XXX,XX +XXX,XX @@ DO_3SAME_VQDMULH(VQRDMULH, qrdmulh)
68
WRAP_FP_GVEC(gen_##INSN##_fp16_3s, FPST_STD_F16, HFUNC) \
69
static bool trans_##INSN##_fp_3s(DisasContext *s, arg_3same *a) \
70
{ \
71
- if (a->size != 0) { \
72
+ if (a->size == MO_16) { \
73
if (!dc_isar_feature(aa32_fp16_arith, s)) { \
74
return false; \
75
} \
76
@@ -XXX,XX +XXX,XX @@ static bool trans_VMAXNM_fp_3s(DisasContext *s, arg_3same *a)
77
return false;
78
}
79
80
- if (a->size != 0) {
81
+ if (a->size == MO_16) {
82
if (!dc_isar_feature(aa32_fp16_arith, s)) {
83
return false;
84
}
85
@@ -XXX,XX +XXX,XX @@ static bool trans_VMINNM_fp_3s(DisasContext *s, arg_3same *a)
86
return false;
87
}
88
89
- if (a->size != 0) {
90
+ if (a->size == MO_16) {
91
if (!dc_isar_feature(aa32_fp16_arith, s)) {
92
return false;
93
}
94
@@ -XXX,XX +XXX,XX @@ static bool do_3same_fp_pair(DisasContext *s, arg_3same *a,
95
assert(a->q == 0); /* enforced by decode patterns */
96
97
98
- fpstatus = fpstatus_ptr(a->size != 0 ? FPST_STD_F16 : FPST_STD);
99
+ fpstatus = fpstatus_ptr(a->size == MO_16 ? FPST_STD_F16 : FPST_STD);
100
tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd),
101
vfp_reg_offset(1, a->vn),
102
vfp_reg_offset(1, a->vm),
103
@@ -XXX,XX +XXX,XX @@ static bool do_3same_fp_pair(DisasContext *s, arg_3same *a,
104
#define DO_3S_FP_PAIR(INSN,FUNC) \
105
static bool trans_##INSN##_fp_3s(DisasContext *s, arg_3same *a) \
106
{ \
107
- if (a->size != 0) { \
108
+ if (a->size == MO_16) { \
109
if (!dc_isar_feature(aa32_fp16_arith, s)) { \
110
return false; \
111
} \
134
--
112
--
135
2.19.2
113
2.20.1
136
114
137
115
diff view generated by jsdifflib
1
From: Steffen Görtz <contrib@steffen-goertz.de>
1
Convert the insns using the 2reg_vcvt and 2reg_vcvt_f16 formats
2
to pass the size through to the trans function as a MO_* value
3
rather than the '0==f32, 1==f16' used in the fp 3-same encodings.
2
4
3
This stubs enables the microbit-micropython firmware to run
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
on the microbit machine.
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200903133209.5141-3-peter.maydell@linaro.org
8
---
9
target/arm/neon-dp.decode | 3 +--
10
target/arm/translate-neon.c.inc | 4 ++--
11
2 files changed, 3 insertions(+), 4 deletions(-)
5
12
6
Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
13
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Message-id: 20190103091119.9367-12-stefanha@redhat.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
include/hw/arm/nrf51_soc.h | 1 +
13
hw/arm/nrf51_soc.c | 26 ++++++++++++++++++++++++++
14
2 files changed, 27 insertions(+)
15
16
diff --git a/include/hw/arm/nrf51_soc.h b/include/hw/arm/nrf51_soc.h
17
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/nrf51_soc.h
15
--- a/target/arm/neon-dp.decode
19
+++ b/include/hw/arm/nrf51_soc.h
16
+++ b/target/arm/neon-dp.decode
20
@@ -XXX,XX +XXX,XX @@ typedef struct NRF51State {
17
@@ -XXX,XX +XXX,XX @@ VMINNM_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 1 .... @3same_fp
21
MemoryRegion iomem;
18
@2reg_shll_b .... ... . . . 001 shift:3 .... .... 0 . . . .... \
22
MemoryRegion sram;
19
&2reg_shift vm=%vm_dp vd=%vd_dp size=0 q=0
23
MemoryRegion flash;
20
24
+ MemoryRegion clock;
21
-# We use size=0 for fp32 and size=1 for fp16 to match the 3-same encodings.
25
22
@2reg_vcvt .... ... . . . 1 ..... .... .... . q:1 . . .... \
26
uint32_t sram_size;
23
- &2reg_shift vm=%vm_dp vd=%vd_dp size=0 shift=%neon_rshift_i5
27
uint32_t flash_size;
24
+ &2reg_shift vm=%vm_dp vd=%vd_dp size=2 shift=%neon_rshift_i5
28
diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c
25
@2reg_vcvt_f16 .... ... . . . 11 .... .... .... . q:1 . . .... \
26
&2reg_shift vm=%vm_dp vd=%vd_dp size=1 shift=%neon_rshift_i4
27
28
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
29
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
30
--- a/hw/arm/nrf51_soc.c
30
--- a/target/arm/translate-neon.c.inc
31
+++ b/hw/arm/nrf51_soc.c
31
+++ b/target/arm/translate-neon.c.inc
32
@@ -XXX,XX +XXX,XX @@
32
@@ -XXX,XX +XXX,XX @@ static bool do_fp_2sh(DisasContext *s, arg_2reg_shift *a,
33
33
return false;
34
#define BASE_TO_IRQ(base) ((base >> 12) & 0x1F)
35
36
+static uint64_t clock_read(void *opaque, hwaddr addr, unsigned int size)
37
+{
38
+ qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " [%u]\n",
39
+ __func__, addr, size);
40
+ return 1;
41
+}
42
+
43
+static void clock_write(void *opaque, hwaddr addr, uint64_t data,
44
+ unsigned int size)
45
+{
46
+ qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " <- 0x%" PRIx64 " [%u]\n",
47
+ __func__, addr, data, size);
48
+}
49
+
50
+static const MemoryRegionOps clock_ops = {
51
+ .read = clock_read,
52
+ .write = clock_write
53
+};
54
+
55
+
56
static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
57
{
58
NRF51State *s = NRF51_SOC(dev_soc);
59
@@ -XXX,XX +XXX,XX @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
60
BASE_TO_IRQ(base_addr)));
61
}
34
}
62
35
63
+ /* STUB Peripherals */
36
- if (a->size != 0) {
64
+ memory_region_init_io(&s->clock, NULL, &clock_ops, NULL,
37
+ if (a->size == MO_16) {
65
+ "nrf51_soc.clock", 0x1000);
38
if (!dc_isar_feature(aa32_fp16_arith, s)) {
66
+ memory_region_add_subregion_overlap(&s->container,
39
return false;
67
+ NRF51_IOMEM_BASE, &s->clock, -1);
40
}
68
+
41
@@ -XXX,XX +XXX,XX @@ static bool do_fp_2sh(DisasContext *s, arg_2reg_shift *a,
69
create_unimplemented_device("nrf51_soc.io", NRF51_IOMEM_BASE,
42
return true;
70
NRF51_IOMEM_SIZE);
43
}
71
create_unimplemented_device("nrf51_soc.ficr", NRF51_FICR_BASE,
44
45
- fpst = fpstatus_ptr(a->size ? FPST_STD_F16 : FPST_STD);
46
+ fpst = fpstatus_ptr(a->size == MO_16 ? FPST_STD_F16 : FPST_STD);
47
tcg_gen_gvec_2_ptr(rd_ofs, rm_ofs, fpst, vec_size, vec_size, a->shift, fn);
48
tcg_temp_free_ptr(fpst);
49
return true;
72
--
50
--
73
2.19.2
51
2.20.1
74
52
75
53
diff view generated by jsdifflib
1
From: Luc Michel <luc.michel@greensocs.com>
1
The VCMLA and VCADD insns have a size field which is 0 for fp16
2
and 1 for fp32 (note that this is the reverse of the Neon 3-same
3
encoding!). Convert it to MO_* values in decode for consistency.
2
4
3
When a new connection is established, we set the first process to be
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
attached, and the others detached. The first CPU of the first process
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
is selected as the current CPU.
7
Message-id: 20200903133209.5141-4-peter.maydell@linaro.org
8
---
9
target/arm/neon-shared.decode | 18 ++++++++++++------
10
target/arm/translate-neon.c.inc | 22 ++++++++++++----------
11
2 files changed, 24 insertions(+), 16 deletions(-)
6
12
7
Signed-off-by: Luc Michel <luc.michel@greensocs.com>
13
diff --git a/target/arm/neon-shared.decode b/target/arm/neon-shared.decode
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
Message-id: 20181207090135.7651-14-luc.michel@greensocs.com
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
gdbstub.c | 20 +++++++++++++++-----
15
1 file changed, 15 insertions(+), 5 deletions(-)
16
17
diff --git a/gdbstub.c b/gdbstub.c
18
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
19
--- a/gdbstub.c
15
--- a/target/arm/neon-shared.decode
20
+++ b/gdbstub.c
16
+++ b/target/arm/neon-shared.decode
21
@@ -XXX,XX +XXX,XX @@ static bool gdb_accept(void)
17
@@ -XXX,XX +XXX,XX @@
18
%vd_dp 22:1 12:4
19
%vd_sp 12:4 22:1
20
21
-VCMLA 1111 110 rot:2 . 1 size:1 .... .... 1000 . q:1 . 0 .... \
22
- vm=%vm_dp vn=%vn_dp vd=%vd_dp
23
+# For VCMLA/VCADD insns, convert the single-bit size field
24
+# which is 0 for fp16 and 1 for fp32 into a MO_* constant.
25
+# (Note that this is the reverse of the sense of the 1-bit size
26
+# field in the 3same_fp Neon insns.)
27
+%vcadd_size 20:1 !function=plus1
28
29
-VCADD 1111 110 rot:1 1 . 0 size:1 .... .... 1000 . q:1 . 0 .... \
30
- vm=%vm_dp vn=%vn_dp vd=%vd_dp
31
+VCMLA 1111 110 rot:2 . 1 . .... .... 1000 . q:1 . 0 .... \
32
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp size=%vcadd_size
33
+
34
+VCADD 1111 110 rot:1 1 . 0 . .... .... 1000 . q:1 . 0 .... \
35
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp size=%vcadd_size
36
37
# VUDOT and VSDOT
38
VDOT 1111 110 00 . 10 .... .... 1101 . q:1 . u:1 .... \
39
@@ -XXX,XX +XXX,XX @@ VFML 1111 110 0 s:1 . 10 .... .... 1000 . 1 . 1 .... \
40
vm=%vm_dp vn=%vn_dp vd=%vd_dp q=1
41
42
VCMLA_scalar 1111 1110 0 . rot:2 .... .... 1000 . q:1 index:1 0 vm:4 \
43
- vn=%vn_dp vd=%vd_dp size=0
44
+ vn=%vn_dp vd=%vd_dp size=1
45
VCMLA_scalar 1111 1110 1 . rot:2 .... .... 1000 . q:1 . 0 .... \
46
- vm=%vm_dp vn=%vn_dp vd=%vd_dp size=1 index=0
47
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp size=2 index=0
48
49
VDOT_scalar 1111 1110 0 . 10 .... .... 1101 . q:1 index:1 u:1 rm:4 \
50
vm=%vm_dp vn=%vn_dp vd=%vd_dp
51
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
52
index XXXXXXX..XXXXXXX 100644
53
--- a/target/arm/translate-neon.c.inc
54
+++ b/target/arm/translate-neon.c.inc
55
@@ -XXX,XX +XXX,XX @@ static bool trans_VCMLA(DisasContext *s, arg_VCMLA *a)
56
gen_helper_gvec_3_ptr *fn_gvec_ptr;
57
58
if (!dc_isar_feature(aa32_vcma, s)
59
- || (!a->size && !dc_isar_feature(aa32_fp16_arith, s))) {
60
+ || (a->size == MO_16 && !dc_isar_feature(aa32_fp16_arith, s))) {
61
return false;
22
}
62
}
23
63
24
s = g_malloc0(sizeof(GDBState));
64
@@ -XXX,XX +XXX,XX @@ static bool trans_VCMLA(DisasContext *s, arg_VCMLA *a)
25
- s->c_cpu = first_cpu;
26
- s->g_cpu = first_cpu;
27
create_default_process(s);
28
+ s->processes[0].attached = true;
29
+ s->c_cpu = gdb_first_attached_cpu(s);
30
+ s->g_cpu = s->c_cpu;
31
s->fd = fd;
32
gdb_has_xml = false;
33
34
@@ -XXX,XX +XXX,XX @@ static void gdb_chr_receive(void *opaque, const uint8_t *buf, int size)
35
36
static void gdb_chr_event(void *opaque, int event)
37
{
38
+ int i;
39
+ GDBState *s = (GDBState *) opaque;
40
+
41
switch (event) {
42
case CHR_EVENT_OPENED:
43
+ /* Start with first process attached, others detached */
44
+ for (i = 0; i < s->process_num; i++) {
45
+ s->processes[i].attached = !i;
46
+ }
47
+
48
+ s->c_cpu = gdb_first_attached_cpu(s);
49
+ s->g_cpu = s->c_cpu;
50
+
51
vm_stop(RUN_STATE_PAUSED);
52
gdb_has_xml = false;
53
break;
54
@@ -XXX,XX +XXX,XX @@ int gdbserver_start(const char *device)
55
memset(s, 0, sizeof(GDBState));
56
s->mon_chr = mon_chr;
57
}
65
}
58
- s->c_cpu = first_cpu;
66
59
- s->g_cpu = first_cpu;
67
opr_sz = (1 + a->q) * 8;
60
68
- fpst = fpstatus_ptr(a->size == 0 ? FPST_STD_F16 : FPST_STD);
61
create_processes(s);
69
- fn_gvec_ptr = a->size ? gen_helper_gvec_fcmlas : gen_helper_gvec_fcmlah;
62
70
+ fpst = fpstatus_ptr(a->size == MO_16 ? FPST_STD_F16 : FPST_STD);
63
if (chr) {
71
+ fn_gvec_ptr = (a->size == MO_16) ?
64
qemu_chr_fe_init(&s->chr, chr, &error_abort);
72
+ gen_helper_gvec_fcmlah : gen_helper_gvec_fcmlas;
65
qemu_chr_fe_set_handlers(&s->chr, gdb_chr_can_receive, gdb_chr_receive,
73
tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd),
66
- gdb_chr_event, NULL, NULL, NULL, true);
74
vfp_reg_offset(1, a->vn),
67
+ gdb_chr_event, NULL, s, NULL, true);
75
vfp_reg_offset(1, a->vm),
76
@@ -XXX,XX +XXX,XX @@ static bool trans_VCADD(DisasContext *s, arg_VCADD *a)
77
gen_helper_gvec_3_ptr *fn_gvec_ptr;
78
79
if (!dc_isar_feature(aa32_vcma, s)
80
- || (!a->size && !dc_isar_feature(aa32_fp16_arith, s))) {
81
+ || (a->size == MO_16 && !dc_isar_feature(aa32_fp16_arith, s))) {
82
return false;
68
}
83
}
69
s->state = chr ? RS_IDLE : RS_INACTIVE;
84
70
s->mon_chr = mon_chr;
85
@@ -XXX,XX +XXX,XX @@ static bool trans_VCADD(DisasContext *s, arg_VCADD *a)
86
}
87
88
opr_sz = (1 + a->q) * 8;
89
- fpst = fpstatus_ptr(a->size == 0 ? FPST_STD_F16 : FPST_STD);
90
- fn_gvec_ptr = a->size ? gen_helper_gvec_fcadds : gen_helper_gvec_fcaddh;
91
+ fpst = fpstatus_ptr(a->size == MO_16 ? FPST_STD_F16 : FPST_STD);
92
+ fn_gvec_ptr = (a->size == MO_16) ?
93
+ gen_helper_gvec_fcaddh : gen_helper_gvec_fcadds;
94
tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd),
95
vfp_reg_offset(1, a->vn),
96
vfp_reg_offset(1, a->vm),
97
@@ -XXX,XX +XXX,XX @@ static bool trans_VCMLA_scalar(DisasContext *s, arg_VCMLA_scalar *a)
98
if (!dc_isar_feature(aa32_vcma, s)) {
99
return false;
100
}
101
- if (a->size == 0 && !dc_isar_feature(aa32_fp16_arith, s)) {
102
+ if (a->size == MO_16 && !dc_isar_feature(aa32_fp16_arith, s)) {
103
return false;
104
}
105
106
@@ -XXX,XX +XXX,XX @@ static bool trans_VCMLA_scalar(DisasContext *s, arg_VCMLA_scalar *a)
107
return true;
108
}
109
110
- fn_gvec_ptr = (a->size ? gen_helper_gvec_fcmlas_idx
111
- : gen_helper_gvec_fcmlah_idx);
112
+ fn_gvec_ptr = (a->size == MO_16) ?
113
+ gen_helper_gvec_fcmlah_idx : gen_helper_gvec_fcmlas_idx;
114
opr_sz = (1 + a->q) * 8;
115
- fpst = fpstatus_ptr(a->size == 0 ? FPST_STD_F16 : FPST_STD);
116
+ fpst = fpstatus_ptr(a->size == MO_16 ? FPST_STD_F16 : FPST_STD);
117
tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd),
118
vfp_reg_offset(1, a->vn),
119
vfp_reg_offset(1, a->vm),
71
--
120
--
72
2.19.2
121
2.20.1
73
122
74
123
diff view generated by jsdifflib
1
In the TZ Memory Protection Controller, the BLK_MAX register is supposed
1
We deprecated the support for KVM on 32-bit Arm hosts in time
2
to return the maximum permitted value of the BLK_IDX register. Our
2
for release 5.0, which means that our deprecation policy allows
3
implementation incorrectly returned max+1 (ie the total number of
3
us to drop it in release 5.2. Remove the code.
4
valid index values, since BLK_IDX is zero-based).
5
4
6
Correct this off-by-one error. Since we consistently initialize
5
To repeat the rationale from the deprecation note: the Linux
7
and use s->blk_max throughout the implementation as the 'size'
6
kernel dropped support for 32-bit Arm KVM hosts in 5.7.
8
of the LUT, just adjust the value we return when the guest reads
9
the BLK_MAX register, rather than trying to change the semantics
10
of the s->blk_max internal struct field.
11
7
12
Fixes: https://bugs.launchpad.net/qemu/+bug/1806824
8
Running 32-bit guests on a 64-bit Arm host remains supported.
9
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20181213183249.3468-1-peter.maydell@linaro.org
12
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
13
Message-id: 20200904154156.31943-2-peter.maydell@linaro.org
16
---
14
---
17
hw/misc/tz-mpc.c | 2 +-
15
docs/system/deprecated.rst | 16 +-
18
1 file changed, 1 insertion(+), 1 deletion(-)
16
configure | 2 +-
17
target/arm/kvm32.c | 595 -------------------------------------
18
target/arm/meson.build | 5 +-
19
4 files changed, 10 insertions(+), 608 deletions(-)
20
delete mode 100644 target/arm/kvm32.c
19
21
20
diff --git a/hw/misc/tz-mpc.c b/hw/misc/tz-mpc.c
22
diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst
21
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/misc/tz-mpc.c
24
--- a/docs/system/deprecated.rst
23
+++ b/hw/misc/tz-mpc.c
25
+++ b/docs/system/deprecated.rst
24
@@ -XXX,XX +XXX,XX @@ static MemTxResult tz_mpc_reg_read(void *opaque, hwaddr addr,
26
@@ -XXX,XX +XXX,XX @@ The ``compat`` property used to set backwards compatibility modes for
25
r = s->ctrl;
27
the processor has been deprecated. The ``max-cpu-compat`` property of
26
break;
28
the ``pseries`` machine type should be used instead.
27
case A_BLK_MAX:
29
28
- r = s->blk_max;
30
-KVM guest support on 32-bit Arm hosts (since 5.0)
29
+ r = s->blk_max - 1;
31
-'''''''''''''''''''''''''''''''''''''''''''''''''
30
break;
32
-
31
case A_BLK_CFG:
33
-The Linux kernel has dropped support for allowing 32-bit Arm systems
32
/* We are never in "init in progress state", so this just indicates
34
-to host KVM guests as of the 5.7 kernel. Accordingly, QEMU is deprecating
35
-its support for this configuration and will remove it in a future version.
36
-Running 32-bit guests on a 64-bit Arm host remains supported.
37
-
38
System emulator devices
39
-----------------------
40
41
@@ -XXX,XX +XXX,XX @@ should be used instead of the 1.09.1 version.
42
System emulator CPUS
43
--------------------
44
45
+KVM guest support on 32-bit Arm hosts (removed in 5.2)
46
+''''''''''''''''''''''''''''''''''''''''''''''''''''''
47
+
48
+The Linux kernel has dropped support for allowing 32-bit Arm systems
49
+to host KVM guests as of the 5.7 kernel. Accordingly, QEMU is deprecating
50
+its support for this configuration and will remove it in a future version.
51
+Running 32-bit guests on a 64-bit Arm host remains supported.
52
+
53
RISC-V ISA Specific CPUs (removed in 5.1)
54
'''''''''''''''''''''''''''''''''''''''''
55
56
diff --git a/configure b/configure
57
index XXXXXXX..XXXXXXX 100755
58
--- a/configure
59
+++ b/configure
60
@@ -XXX,XX +XXX,XX @@ supported_kvm_target() {
61
test "$kvm" = "yes" || return 1
62
glob "$1" "*-softmmu" || return 1
63
case "${1%-softmmu}:$cpu" in
64
- arm:arm | aarch64:aarch64 | \
65
+ aarch64:aarch64 | \
66
i386:i386 | i386:x86_64 | i386:x32 | \
67
x86_64:i386 | x86_64:x86_64 | x86_64:x32 | \
68
mips:mips | mipsel:mips | mips64:mips | mips64el:mips | \
69
diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c
70
deleted file mode 100644
71
index XXXXXXX..XXXXXXX
72
--- a/target/arm/kvm32.c
73
+++ /dev/null
74
@@ -XXX,XX +XXX,XX @@
75
-/*
76
- * ARM implementation of KVM hooks, 32 bit specific code.
77
- *
78
- * Copyright Christoffer Dall 2009-2010
79
- *
80
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
81
- * See the COPYING file in the top-level directory.
82
- *
83
- */
84
-
85
-#include "qemu/osdep.h"
86
-#include <sys/ioctl.h>
87
-
88
-#include <linux/kvm.h>
89
-
90
-#include "qemu-common.h"
91
-#include "cpu.h"
92
-#include "qemu/timer.h"
93
-#include "sysemu/runstate.h"
94
-#include "sysemu/kvm.h"
95
-#include "kvm_arm.h"
96
-#include "internals.h"
97
-#include "qemu/log.h"
98
-
99
-static int read_sys_reg32(int fd, uint32_t *pret, uint64_t id)
100
-{
101
- struct kvm_one_reg idreg = { .id = id, .addr = (uintptr_t)pret };
102
-
103
- assert((id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U32);
104
- return ioctl(fd, KVM_GET_ONE_REG, &idreg);
105
-}
106
-
107
-bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
108
-{
109
- /* Identify the feature bits corresponding to the host CPU, and
110
- * fill out the ARMHostCPUClass fields accordingly. To do this
111
- * we have to create a scratch VM, create a single CPU inside it,
112
- * and then query that CPU for the relevant ID registers.
113
- */
114
- int err = 0, fdarray[3];
115
- uint32_t midr, id_pfr0;
116
- uint64_t features = 0;
117
-
118
- /* Old kernels may not know about the PREFERRED_TARGET ioctl: however
119
- * we know these will only support creating one kind of guest CPU,
120
- * which is its preferred CPU type.
121
- */
122
- static const uint32_t cpus_to_try[] = {
123
- QEMU_KVM_ARM_TARGET_CORTEX_A15,
124
- QEMU_KVM_ARM_TARGET_NONE
125
- };
126
- /*
127
- * target = -1 informs kvm_arm_create_scratch_host_vcpu()
128
- * to use the preferred target
129
- */
130
- struct kvm_vcpu_init init = { .target = -1, };
131
-
132
- if (!kvm_arm_create_scratch_host_vcpu(cpus_to_try, fdarray, &init)) {
133
- return false;
134
- }
135
-
136
- ahcf->target = init.target;
137
-
138
- /* This is not strictly blessed by the device tree binding docs yet,
139
- * but in practice the kernel does not care about this string so
140
- * there is no point maintaining an KVM_ARM_TARGET_* -> string table.
141
- */
142
- ahcf->dtb_compatible = "arm,arm-v7";
143
-
144
- err |= read_sys_reg32(fdarray[2], &midr, ARM_CP15_REG32(0, 0, 0, 0));
145
- err |= read_sys_reg32(fdarray[2], &id_pfr0, ARM_CP15_REG32(0, 0, 1, 0));
146
-
147
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar0,
148
- ARM_CP15_REG32(0, 0, 2, 0));
149
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar1,
150
- ARM_CP15_REG32(0, 0, 2, 1));
151
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar2,
152
- ARM_CP15_REG32(0, 0, 2, 2));
153
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar3,
154
- ARM_CP15_REG32(0, 0, 2, 3));
155
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar4,
156
- ARM_CP15_REG32(0, 0, 2, 4));
157
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar5,
158
- ARM_CP15_REG32(0, 0, 2, 5));
159
- if (read_sys_reg32(fdarray[2], &ahcf->isar.id_isar6,
160
- ARM_CP15_REG32(0, 0, 2, 7))) {
161
- /*
162
- * Older kernels don't support reading ID_ISAR6. This register was
163
- * only introduced in ARMv8, so we can assume that it is zero on a
164
- * CPU that a kernel this old is running on.
165
- */
166
- ahcf->isar.id_isar6 = 0;
167
- }
168
-
169
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_dfr0,
170
- ARM_CP15_REG32(0, 0, 1, 2));
171
-
172
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr0,
173
- KVM_REG_ARM | KVM_REG_SIZE_U32 |
174
- KVM_REG_ARM_VFP | KVM_REG_ARM_VFP_MVFR0);
175
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr1,
176
- KVM_REG_ARM | KVM_REG_SIZE_U32 |
177
- KVM_REG_ARM_VFP | KVM_REG_ARM_VFP_MVFR1);
178
- /*
179
- * FIXME: There is not yet a way to read MVFR2.
180
- * Fortunately there is not yet anything in there that affects migration.
181
- */
182
-
183
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr0,
184
- ARM_CP15_REG32(0, 0, 1, 4));
185
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr1,
186
- ARM_CP15_REG32(0, 0, 1, 5));
187
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr2,
188
- ARM_CP15_REG32(0, 0, 1, 6));
189
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr3,
190
- ARM_CP15_REG32(0, 0, 1, 7));
191
- if (read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr4,
192
- ARM_CP15_REG32(0, 0, 2, 6))) {
193
- /*
194
- * Older kernels don't support reading ID_MMFR4 (a new in v8
195
- * register); assume it's zero.
196
- */
197
- ahcf->isar.id_mmfr4 = 0;
198
- }
199
-
200
- /*
201
- * There is no way to read DBGDIDR, because currently 32-bit KVM
202
- * doesn't implement debug at all. Leave it at zero.
203
- */
204
-
205
- kvm_arm_destroy_scratch_host_vcpu(fdarray);
206
-
207
- if (err < 0) {
208
- return false;
209
- }
210
-
211
- /* Now we've retrieved all the register information we can
212
- * set the feature bits based on the ID register fields.
213
- * We can assume any KVM supporting CPU is at least a v7
214
- * with VFPv3, virtualization extensions, and the generic
215
- * timers; this in turn implies most of the other feature
216
- * bits, but a few must be tested.
217
- */
218
- features |= 1ULL << ARM_FEATURE_V7VE;
219
- features |= 1ULL << ARM_FEATURE_GENERIC_TIMER;
220
-
221
- if (extract32(id_pfr0, 12, 4) == 1) {
222
- features |= 1ULL << ARM_FEATURE_THUMB2EE;
223
- }
224
- if (extract32(ahcf->isar.mvfr1, 12, 4) == 1) {
225
- features |= 1ULL << ARM_FEATURE_NEON;
226
- }
227
-
228
- ahcf->features = features;
229
-
230
- return true;
231
-}
232
-
233
-bool kvm_arm_reg_syncs_via_cpreg_list(uint64_t regidx)
234
-{
235
- /* Return true if the regidx is a register we should synchronize
236
- * via the cpreg_tuples array (ie is not a core reg we sync by
237
- * hand in kvm_arch_get/put_registers())
238
- */
239
- switch (regidx & KVM_REG_ARM_COPROC_MASK) {
240
- case KVM_REG_ARM_CORE:
241
- case KVM_REG_ARM_VFP:
242
- return false;
243
- default:
244
- return true;
245
- }
246
-}
247
-
248
-typedef struct CPRegStateLevel {
249
- uint64_t regidx;
250
- int level;
251
-} CPRegStateLevel;
252
-
253
-/* All coprocessor registers not listed in the following table are assumed to
254
- * be of the level KVM_PUT_RUNTIME_STATE. If a register should be written less
255
- * often, you must add it to this table with a state of either
256
- * KVM_PUT_RESET_STATE or KVM_PUT_FULL_STATE.
257
- */
258
-static const CPRegStateLevel non_runtime_cpregs[] = {
259
- { KVM_REG_ARM_TIMER_CNT, KVM_PUT_FULL_STATE },
260
-};
261
-
262
-int kvm_arm_cpreg_level(uint64_t regidx)
263
-{
264
- int i;
265
-
266
- for (i = 0; i < ARRAY_SIZE(non_runtime_cpregs); i++) {
267
- const CPRegStateLevel *l = &non_runtime_cpregs[i];
268
- if (l->regidx == regidx) {
269
- return l->level;
270
- }
271
- }
272
-
273
- return KVM_PUT_RUNTIME_STATE;
274
-}
275
-
276
-#define ARM_CPU_ID_MPIDR 0, 0, 0, 5
277
-
278
-int kvm_arch_init_vcpu(CPUState *cs)
279
-{
280
- int ret;
281
- uint64_t v;
282
- uint32_t mpidr;
283
- struct kvm_one_reg r;
284
- ARMCPU *cpu = ARM_CPU(cs);
285
-
286
- if (cpu->kvm_target == QEMU_KVM_ARM_TARGET_NONE) {
287
- fprintf(stderr, "KVM is not supported for this guest CPU type\n");
288
- return -EINVAL;
289
- }
290
-
291
- qemu_add_vm_change_state_handler(kvm_arm_vm_state_change, cs);
292
-
293
- /* Determine init features for this CPU */
294
- memset(cpu->kvm_init_features, 0, sizeof(cpu->kvm_init_features));
295
- if (cs->start_powered_off) {
296
- cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_POWER_OFF;
297
- }
298
- if (kvm_check_extension(cs->kvm_state, KVM_CAP_ARM_PSCI_0_2)) {
299
- cpu->psci_version = 2;
300
- cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_PSCI_0_2;
301
- }
302
-
303
- /* Do KVM_ARM_VCPU_INIT ioctl */
304
- ret = kvm_arm_vcpu_init(cs);
305
- if (ret) {
306
- return ret;
307
- }
308
-
309
- /* Query the kernel to make sure it supports 32 VFP
310
- * registers: QEMU's "cortex-a15" CPU is always a
311
- * VFP-D32 core. The simplest way to do this is just
312
- * to attempt to read register d31.
313
- */
314
- r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP | 31;
315
- r.addr = (uintptr_t)(&v);
316
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
317
- if (ret == -ENOENT) {
318
- return -EINVAL;
319
- }
320
-
321
- /*
322
- * When KVM is in use, PSCI is emulated in-kernel and not by qemu.
323
- * Currently KVM has its own idea about MPIDR assignment, so we
324
- * override our defaults with what we get from KVM.
325
- */
326
- ret = kvm_get_one_reg(cs, ARM_CP15_REG32(ARM_CPU_ID_MPIDR), &mpidr);
327
- if (ret) {
328
- return ret;
329
- }
330
- cpu->mp_affinity = mpidr & ARM32_AFFINITY_MASK;
331
-
332
- /* Check whether userspace can specify guest syndrome value */
333
- kvm_arm_init_serror_injection(cs);
334
-
335
- return kvm_arm_init_cpreg_list(cpu);
336
-}
337
-
338
-int kvm_arch_destroy_vcpu(CPUState *cs)
339
-{
340
-    return 0;
341
-}
342
-
343
-typedef struct Reg {
344
- uint64_t id;
345
- int offset;
346
-} Reg;
347
-
348
-#define COREREG(KERNELNAME, QEMUFIELD) \
349
- { \
350
- KVM_REG_ARM | KVM_REG_SIZE_U32 | \
351
- KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(KERNELNAME), \
352
- offsetof(CPUARMState, QEMUFIELD) \
353
- }
354
-
355
-#define VFPSYSREG(R) \
356
- { \
357
- KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_VFP | \
358
- KVM_REG_ARM_VFP_##R, \
359
- offsetof(CPUARMState, vfp.xregs[ARM_VFP_##R]) \
360
- }
361
-
362
-/* Like COREREG, but handle fields which are in a uint64_t in CPUARMState. */
363
-#define COREREG64(KERNELNAME, QEMUFIELD) \
364
- { \
365
- KVM_REG_ARM | KVM_REG_SIZE_U32 | \
366
- KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(KERNELNAME), \
367
- offsetoflow32(CPUARMState, QEMUFIELD) \
368
- }
369
-
370
-static const Reg regs[] = {
371
- /* R0_usr .. R14_usr */
372
- COREREG(usr_regs.uregs[0], regs[0]),
373
- COREREG(usr_regs.uregs[1], regs[1]),
374
- COREREG(usr_regs.uregs[2], regs[2]),
375
- COREREG(usr_regs.uregs[3], regs[3]),
376
- COREREG(usr_regs.uregs[4], regs[4]),
377
- COREREG(usr_regs.uregs[5], regs[5]),
378
- COREREG(usr_regs.uregs[6], regs[6]),
379
- COREREG(usr_regs.uregs[7], regs[7]),
380
- COREREG(usr_regs.uregs[8], usr_regs[0]),
381
- COREREG(usr_regs.uregs[9], usr_regs[1]),
382
- COREREG(usr_regs.uregs[10], usr_regs[2]),
383
- COREREG(usr_regs.uregs[11], usr_regs[3]),
384
- COREREG(usr_regs.uregs[12], usr_regs[4]),
385
- COREREG(usr_regs.uregs[13], banked_r13[BANK_USRSYS]),
386
- COREREG(usr_regs.uregs[14], banked_r14[BANK_USRSYS]),
387
- /* R13, R14, SPSR for SVC, ABT, UND, IRQ banks */
388
- COREREG(svc_regs[0], banked_r13[BANK_SVC]),
389
- COREREG(svc_regs[1], banked_r14[BANK_SVC]),
390
- COREREG64(svc_regs[2], banked_spsr[BANK_SVC]),
391
- COREREG(abt_regs[0], banked_r13[BANK_ABT]),
392
- COREREG(abt_regs[1], banked_r14[BANK_ABT]),
393
- COREREG64(abt_regs[2], banked_spsr[BANK_ABT]),
394
- COREREG(und_regs[0], banked_r13[BANK_UND]),
395
- COREREG(und_regs[1], banked_r14[BANK_UND]),
396
- COREREG64(und_regs[2], banked_spsr[BANK_UND]),
397
- COREREG(irq_regs[0], banked_r13[BANK_IRQ]),
398
- COREREG(irq_regs[1], banked_r14[BANK_IRQ]),
399
- COREREG64(irq_regs[2], banked_spsr[BANK_IRQ]),
400
- /* R8_fiq .. R14_fiq and SPSR_fiq */
401
- COREREG(fiq_regs[0], fiq_regs[0]),
402
- COREREG(fiq_regs[1], fiq_regs[1]),
403
- COREREG(fiq_regs[2], fiq_regs[2]),
404
- COREREG(fiq_regs[3], fiq_regs[3]),
405
- COREREG(fiq_regs[4], fiq_regs[4]),
406
- COREREG(fiq_regs[5], banked_r13[BANK_FIQ]),
407
- COREREG(fiq_regs[6], banked_r14[BANK_FIQ]),
408
- COREREG64(fiq_regs[7], banked_spsr[BANK_FIQ]),
409
- /* R15 */
410
- COREREG(usr_regs.uregs[15], regs[15]),
411
- /* VFP system registers */
412
- VFPSYSREG(FPSID),
413
- VFPSYSREG(MVFR1),
414
- VFPSYSREG(MVFR0),
415
- VFPSYSREG(FPEXC),
416
- VFPSYSREG(FPINST),
417
- VFPSYSREG(FPINST2),
418
-};
419
-
420
-int kvm_arch_put_registers(CPUState *cs, int level)
421
-{
422
- ARMCPU *cpu = ARM_CPU(cs);
423
- CPUARMState *env = &cpu->env;
424
- struct kvm_one_reg r;
425
- int mode, bn;
426
- int ret, i;
427
- uint32_t cpsr, fpscr;
428
-
429
- /* Make sure the banked regs are properly set */
430
- mode = env->uncached_cpsr & CPSR_M;
431
- bn = bank_number(mode);
432
- if (mode == ARM_CPU_MODE_FIQ) {
433
- memcpy(env->fiq_regs, env->regs + 8, 5 * sizeof(uint32_t));
434
- } else {
435
- memcpy(env->usr_regs, env->regs + 8, 5 * sizeof(uint32_t));
436
- }
437
- env->banked_r13[bn] = env->regs[13];
438
- env->banked_spsr[bn] = env->spsr;
439
- env->banked_r14[r14_bank_number(mode)] = env->regs[14];
440
-
441
- /* Now we can safely copy stuff down to the kernel */
442
- for (i = 0; i < ARRAY_SIZE(regs); i++) {
443
- r.id = regs[i].id;
444
- r.addr = (uintptr_t)(env) + regs[i].offset;
445
- ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
446
- if (ret) {
447
- return ret;
448
- }
449
- }
450
-
451
- /* Special cases which aren't a single CPUARMState field */
452
- cpsr = cpsr_read(env);
453
- r.id = KVM_REG_ARM | KVM_REG_SIZE_U32 |
454
- KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(usr_regs.ARM_cpsr);
455
- r.addr = (uintptr_t)(&cpsr);
456
- ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
457
- if (ret) {
458
- return ret;
459
- }
460
-
461
- /* VFP registers */
462
- r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP;
463
- for (i = 0; i < 32; i++) {
464
- r.addr = (uintptr_t)aa32_vfp_dreg(env, i);
465
- ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
466
- if (ret) {
467
- return ret;
468
- }
469
- r.id++;
470
- }
471
-
472
- r.id = KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_VFP |
473
- KVM_REG_ARM_VFP_FPSCR;
474
- fpscr = vfp_get_fpscr(env);
475
- r.addr = (uintptr_t)&fpscr;
476
- ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
477
- if (ret) {
478
- return ret;
479
- }
480
-
481
- write_cpustate_to_list(cpu, true);
482
-
483
- if (!write_list_to_kvmstate(cpu, level)) {
484
- return EINVAL;
485
- }
486
-
487
- /*
488
- * Setting VCPU events should be triggered after syncing the registers
489
- * to avoid overwriting potential changes made by KVM upon calling
490
- * KVM_SET_VCPU_EVENTS ioctl
491
- */
492
- ret = kvm_put_vcpu_events(cpu);
493
- if (ret) {
494
- return ret;
495
- }
496
-
497
- kvm_arm_sync_mpstate_to_kvm(cpu);
498
-
499
- return ret;
500
-}
501
-
502
-int kvm_arch_get_registers(CPUState *cs)
503
-{
504
- ARMCPU *cpu = ARM_CPU(cs);
505
- CPUARMState *env = &cpu->env;
506
- struct kvm_one_reg r;
507
- int mode, bn;
508
- int ret, i;
509
- uint32_t cpsr, fpscr;
510
-
511
- for (i = 0; i < ARRAY_SIZE(regs); i++) {
512
- r.id = regs[i].id;
513
- r.addr = (uintptr_t)(env) + regs[i].offset;
514
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
515
- if (ret) {
516
- return ret;
517
- }
518
- }
519
-
520
- /* Special cases which aren't a single CPUARMState field */
521
- r.id = KVM_REG_ARM | KVM_REG_SIZE_U32 |
522
- KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(usr_regs.ARM_cpsr);
523
- r.addr = (uintptr_t)(&cpsr);
524
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
525
- if (ret) {
526
- return ret;
527
- }
528
- cpsr_write(env, cpsr, 0xffffffff, CPSRWriteRaw);
529
-
530
- /* Make sure the current mode regs are properly set */
531
- mode = env->uncached_cpsr & CPSR_M;
532
- bn = bank_number(mode);
533
- if (mode == ARM_CPU_MODE_FIQ) {
534
- memcpy(env->regs + 8, env->fiq_regs, 5 * sizeof(uint32_t));
535
- } else {
536
- memcpy(env->regs + 8, env->usr_regs, 5 * sizeof(uint32_t));
537
- }
538
- env->regs[13] = env->banked_r13[bn];
539
- env->spsr = env->banked_spsr[bn];
540
- env->regs[14] = env->banked_r14[r14_bank_number(mode)];
541
-
542
- /* VFP registers */
543
- r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP;
544
- for (i = 0; i < 32; i++) {
545
- r.addr = (uintptr_t)aa32_vfp_dreg(env, i);
546
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
547
- if (ret) {
548
- return ret;
549
- }
550
- r.id++;
551
- }
552
-
553
- r.id = KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_VFP |
554
- KVM_REG_ARM_VFP_FPSCR;
555
- r.addr = (uintptr_t)&fpscr;
556
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
557
- if (ret) {
558
- return ret;
559
- }
560
- vfp_set_fpscr(env, fpscr);
561
-
562
- ret = kvm_get_vcpu_events(cpu);
563
- if (ret) {
564
- return ret;
565
- }
566
-
567
- if (!write_kvmstate_to_list(cpu)) {
568
- return EINVAL;
569
- }
570
- /* Note that it's OK to have registers which aren't in CPUState,
571
- * so we can ignore a failure return here.
572
- */
573
- write_list_to_cpustate(cpu);
574
-
575
- kvm_arm_sync_mpstate_to_qemu(cpu);
576
-
577
- return 0;
578
-}
579
-
580
-int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
581
-{
582
- qemu_log_mask(LOG_UNIMP, "%s: guest debug not yet implemented\n", __func__);
583
- return -EINVAL;
584
-}
585
-
586
-int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
587
-{
588
- qemu_log_mask(LOG_UNIMP, "%s: guest debug not yet implemented\n", __func__);
589
- return -EINVAL;
590
-}
591
-
592
-bool kvm_arm_handle_debug(CPUState *cs, struct kvm_debug_exit_arch *debug_exit)
593
-{
594
- qemu_log_mask(LOG_UNIMP, "%s: guest debug not yet implemented\n", __func__);
595
- return false;
596
-}
597
-
598
-int kvm_arch_insert_hw_breakpoint(target_ulong addr,
599
- target_ulong len, int type)
600
-{
601
- qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
602
- return -EINVAL;
603
-}
604
-
605
-int kvm_arch_remove_hw_breakpoint(target_ulong addr,
606
- target_ulong len, int type)
607
-{
608
- qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
609
- return -EINVAL;
610
-}
611
-
612
-void kvm_arch_remove_all_hw_breakpoints(void)
613
-{
614
- qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
615
-}
616
-
617
-void kvm_arm_copy_hw_debug_data(struct kvm_guest_debug_arch *ptr)
618
-{
619
- qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
620
-}
621
-
622
-bool kvm_arm_hw_debug_active(CPUState *cs)
623
-{
624
- return false;
625
-}
626
-
627
-void kvm_arm_pmu_set_irq(CPUState *cs, int irq)
628
-{
629
- qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
630
-}
631
-
632
-void kvm_arm_pmu_init(CPUState *cs)
633
-{
634
- qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
635
-}
636
-
637
-#define ARM_REG_DFSR ARM_CP15_REG32(0, 5, 0, 0)
638
-#define ARM_REG_TTBCR ARM_CP15_REG32(0, 2, 0, 2)
639
-/*
640
- *DFSR:
641
- * TTBCR.EAE == 0
642
- * FS[4] - DFSR[10]
643
- * FS[3:0] - DFSR[3:0]
644
- * TTBCR.EAE == 1
645
- * FS, bits [5:0]
646
- */
647
-#define DFSR_FSC(lpae, v) \
648
- ((lpae) ? ((v) & 0x3F) : (((v) >> 6) | ((v) & 0x1F)))
649
-
650
-#define DFSC_EXTABT(lpae) ((lpae) ? 0x10 : 0x08)
651
-
652
-bool kvm_arm_verify_ext_dabt_pending(CPUState *cs)
653
-{
654
- uint32_t dfsr_val;
655
-
656
- if (!kvm_get_one_reg(cs, ARM_REG_DFSR, &dfsr_val)) {
657
- ARMCPU *cpu = ARM_CPU(cs);
658
- CPUARMState *env = &cpu->env;
659
- uint32_t ttbcr;
660
- int lpae = 0;
661
-
662
- if (!kvm_get_one_reg(cs, ARM_REG_TTBCR, &ttbcr)) {
663
- lpae = arm_feature(env, ARM_FEATURE_LPAE) && (ttbcr & TTBCR_EAE);
664
- }
665
- /* The verification is based on FS filed of the DFSR reg only*/
666
- return (DFSR_FSC(lpae, dfsr_val) == DFSC_EXTABT(lpae));
667
- }
668
- return false;
669
-}
670
diff --git a/target/arm/meson.build b/target/arm/meson.build
671
index XXXXXXX..XXXXXXX 100644
672
--- a/target/arm/meson.build
673
+++ b/target/arm/meson.build
674
@@ -XXX,XX +XXX,XX @@ arm_ss.add(zlib)
675
676
arm_ss.add(when: 'CONFIG_TCG', if_true: files('arm-semi.c'))
677
678
-kvm_ss = ss.source_set()
679
-kvm_ss.add(when: 'TARGET_AARCH64', if_true: files('kvm64.c'), if_false: files('kvm32.c'))
680
-arm_ss.add_all(when: 'CONFIG_KVM', if_true: kvm_ss)
681
-arm_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c'), if_false: files('kvm-stub.c'))
682
+arm_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c', 'kvm64.c'), if_false: files('kvm-stub.c'))
683
684
arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
685
'cpu64.c',
33
--
686
--
34
2.19.2
687
2.20.1
35
688
36
689
diff view generated by jsdifflib
1
From: Stefan Hajnoczi <stefanha@redhat.com>
1
Now that 32-bit KVM host support is gone, KVM can never
2
2
be enabled unless CONFIG_AARCH64 is true, and some code
3
This reverts commit 01fd41ab3fb69971c24a69ed49cde96086d81278.
3
paths are no longer reachable and can be deleted.
4
4
5
The generic loader device (-device loader,file=kernel.bin) can be used
6
to load a kernel instead of the -kernel option. Some boards have flash
7
memory (pflash) that is set via the -pflash or -drive options.
8
9
Allow starting QEMU without the -kernel option to accommodate these
10
scenarios.
11
12
Suggested-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
14
Message-id: 20190103144124.18917-1-stefanha@redhat.com
15
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Message-id: 20200904154156.31943-3-peter.maydell@linaro.org
17
---
9
---
18
hw/arm/armv7m.c | 5 -----
10
target/arm/kvm-consts.h | 7 ---
19
1 file changed, 5 deletions(-)
11
target/arm/kvm_arm.h | 6 ---
20
12
target/arm/cpu.c | 101 +++++++++++++++++++---------------------
21
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
13
target/arm/kvm.c | 7 ---
22
index XXXXXXX..XXXXXXX 100644
14
4 files changed, 47 insertions(+), 74 deletions(-)
23
--- a/hw/arm/armv7m.c
15
24
+++ b/hw/arm/armv7m.c
16
diff --git a/target/arm/kvm-consts.h b/target/arm/kvm-consts.h
25
@@ -XXX,XX +XXX,XX @@ void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size)
17
index XXXXXXX..XXXXXXX 100644
26
big_endian = 0;
18
--- a/target/arm/kvm-consts.h
19
+++ b/target/arm/kvm-consts.h
20
@@ -XXX,XX +XXX,XX @@ MISMATCH_CHECK(QEMU_PSCI_RET_DISABLED, PSCI_RET_DISABLED);
21
*/
22
#define QEMU_KVM_ARM_TARGET_NONE UINT_MAX
23
24
-#ifdef TARGET_AARCH64
25
MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_AEM_V8, KVM_ARM_TARGET_AEM_V8);
26
MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_FOUNDATION_V8, KVM_ARM_TARGET_FOUNDATION_V8);
27
MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A57, KVM_ARM_TARGET_CORTEX_A57);
28
MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_XGENE_POTENZA, KVM_ARM_TARGET_XGENE_POTENZA);
29
MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A53, KVM_ARM_TARGET_CORTEX_A53);
30
-#else
31
-MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A15, KVM_ARM_TARGET_CORTEX_A15);
32
-MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A7, KVM_ARM_TARGET_CORTEX_A7);
33
-#endif
34
35
#define CP_REG_ARM64 0x6000000000000000ULL
36
#define CP_REG_ARM_COPROC_MASK 0x000000000FFF0000
37
@@ -XXX,XX +XXX,XX @@ MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A7, KVM_ARM_TARGET_CORTEX_A7);
38
/* No kernel define but it's useful to QEMU */
39
#define CP_REG_ARM64_SYSREG_CP (CP_REG_ARM64_SYSREG >> CP_REG_ARM_COPROC_SHIFT)
40
41
-#ifdef TARGET_AARCH64
42
MISMATCH_CHECK(CP_REG_ARM64, KVM_REG_ARM64);
43
MISMATCH_CHECK(CP_REG_ARM_COPROC_MASK, KVM_REG_ARM_COPROC_MASK);
44
MISMATCH_CHECK(CP_REG_ARM_COPROC_SHIFT, KVM_REG_ARM_COPROC_SHIFT);
45
@@ -XXX,XX +XXX,XX @@ MISMATCH_CHECK(CP_REG_ARM64_SYSREG_CRM_MASK, KVM_REG_ARM64_SYSREG_CRM_MASK);
46
MISMATCH_CHECK(CP_REG_ARM64_SYSREG_CRM_SHIFT, KVM_REG_ARM64_SYSREG_CRM_SHIFT);
47
MISMATCH_CHECK(CP_REG_ARM64_SYSREG_OP2_MASK, KVM_REG_ARM64_SYSREG_OP2_MASK);
48
MISMATCH_CHECK(CP_REG_ARM64_SYSREG_OP2_SHIFT, KVM_REG_ARM64_SYSREG_OP2_SHIFT);
49
-#endif
50
51
#undef MISMATCH_CHECK
52
53
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
54
index XXXXXXX..XXXXXXX 100644
55
--- a/target/arm/kvm_arm.h
56
+++ b/target/arm/kvm_arm.h
57
@@ -XXX,XX +XXX,XX @@ static inline const char *gic_class_name(void)
58
static inline const char *gicv3_class_name(void)
59
{
60
if (kvm_irqchip_in_kernel()) {
61
-#ifdef TARGET_AARCH64
62
return "kvm-arm-gicv3";
63
-#else
64
- error_report("KVM GICv3 acceleration is not supported on this "
65
- "platform");
66
- exit(1);
67
-#endif
68
} else {
69
if (kvm_enabled()) {
70
error_report("Userspace GICv3 is not supported with KVM");
71
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
72
index XXXXXXX..XXXXXXX 100644
73
--- a/target/arm/cpu.c
74
+++ b/target/arm/cpu.c
75
@@ -XXX,XX +XXX,XX @@ static void cortex_a15_initfn(Object *obj)
76
}
77
78
#ifndef TARGET_AARCH64
79
-/* -cpu max: if KVM is enabled, like -cpu host (best possible with this host);
80
- * otherwise, a CPU with as many features enabled as our emulation supports.
81
+/*
82
+ * -cpu max: a CPU with as many features enabled as our emulation supports.
83
* The version of '-cpu max' for qemu-system-aarch64 is defined in cpu64.c;
84
- * this only needs to handle 32 bits.
85
+ * this only needs to handle 32 bits, and need not care about KVM.
86
*/
87
static void arm_max_initfn(Object *obj)
88
{
89
ARMCPU *cpu = ARM_CPU(obj);
90
91
- if (kvm_enabled()) {
92
- kvm_arm_set_cpu_features_from_host(cpu);
93
- } else {
94
- cortex_a15_initfn(obj);
95
+ cortex_a15_initfn(obj);
96
97
- /* old-style VFP short-vector support */
98
- cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1);
99
+ /* old-style VFP short-vector support */
100
+ cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1);
101
102
#ifdef CONFIG_USER_ONLY
103
- /* We don't set these in system emulation mode for the moment,
104
- * since we don't correctly set (all of) the ID registers to
105
- * advertise them.
106
- */
107
- set_feature(&cpu->env, ARM_FEATURE_V8);
108
- {
109
- uint32_t t;
110
+ /*
111
+ * We don't set these in system emulation mode for the moment,
112
+ * since we don't correctly set (all of) the ID registers to
113
+ * advertise them.
114
+ */
115
+ set_feature(&cpu->env, ARM_FEATURE_V8);
116
+ {
117
+ uint32_t t;
118
119
- t = cpu->isar.id_isar5;
120
- t = FIELD_DP32(t, ID_ISAR5, AES, 2);
121
- t = FIELD_DP32(t, ID_ISAR5, SHA1, 1);
122
- t = FIELD_DP32(t, ID_ISAR5, SHA2, 1);
123
- t = FIELD_DP32(t, ID_ISAR5, CRC32, 1);
124
- t = FIELD_DP32(t, ID_ISAR5, RDM, 1);
125
- t = FIELD_DP32(t, ID_ISAR5, VCMA, 1);
126
- cpu->isar.id_isar5 = t;
127
+ t = cpu->isar.id_isar5;
128
+ t = FIELD_DP32(t, ID_ISAR5, AES, 2);
129
+ t = FIELD_DP32(t, ID_ISAR5, SHA1, 1);
130
+ t = FIELD_DP32(t, ID_ISAR5, SHA2, 1);
131
+ t = FIELD_DP32(t, ID_ISAR5, CRC32, 1);
132
+ t = FIELD_DP32(t, ID_ISAR5, RDM, 1);
133
+ t = FIELD_DP32(t, ID_ISAR5, VCMA, 1);
134
+ cpu->isar.id_isar5 = t;
135
136
- t = cpu->isar.id_isar6;
137
- t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1);
138
- t = FIELD_DP32(t, ID_ISAR6, DP, 1);
139
- t = FIELD_DP32(t, ID_ISAR6, FHM, 1);
140
- t = FIELD_DP32(t, ID_ISAR6, SB, 1);
141
- t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1);
142
- cpu->isar.id_isar6 = t;
143
+ t = cpu->isar.id_isar6;
144
+ t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1);
145
+ t = FIELD_DP32(t, ID_ISAR6, DP, 1);
146
+ t = FIELD_DP32(t, ID_ISAR6, FHM, 1);
147
+ t = FIELD_DP32(t, ID_ISAR6, SB, 1);
148
+ t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1);
149
+ cpu->isar.id_isar6 = t;
150
151
- t = cpu->isar.mvfr1;
152
- t = FIELD_DP32(t, MVFR1, FPHP, 3); /* v8.2-FP16 */
153
- t = FIELD_DP32(t, MVFR1, SIMDHP, 2); /* v8.2-FP16 */
154
- cpu->isar.mvfr1 = t;
155
+ t = cpu->isar.mvfr1;
156
+ t = FIELD_DP32(t, MVFR1, FPHP, 3); /* v8.2-FP16 */
157
+ t = FIELD_DP32(t, MVFR1, SIMDHP, 2); /* v8.2-FP16 */
158
+ cpu->isar.mvfr1 = t;
159
160
- t = cpu->isar.mvfr2;
161
- t = FIELD_DP32(t, MVFR2, SIMDMISC, 3); /* SIMD MaxNum */
162
- t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */
163
- cpu->isar.mvfr2 = t;
164
+ t = cpu->isar.mvfr2;
165
+ t = FIELD_DP32(t, MVFR2, SIMDMISC, 3); /* SIMD MaxNum */
166
+ t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */
167
+ cpu->isar.mvfr2 = t;
168
169
- t = cpu->isar.id_mmfr3;
170
- t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* ATS1E1 */
171
- cpu->isar.id_mmfr3 = t;
172
+ t = cpu->isar.id_mmfr3;
173
+ t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* ATS1E1 */
174
+ cpu->isar.id_mmfr3 = t;
175
176
- t = cpu->isar.id_mmfr4;
177
- t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */
178
- t = FIELD_DP32(t, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */
179
- t = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* TTCNP */
180
- t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* TTS2UXN */
181
- cpu->isar.id_mmfr4 = t;
182
- }
183
-#endif
184
+ t = cpu->isar.id_mmfr4;
185
+ t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */
186
+ t = FIELD_DP32(t, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */
187
+ t = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* TTCNP */
188
+ t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* TTS2UXN */
189
+ cpu->isar.id_mmfr4 = t;
190
}
191
+#endif
192
}
27
#endif
193
#endif
28
194
29
- if (!kernel_filename && !qtest_enabled()) {
195
@@ -XXX,XX +XXX,XX @@ static void arm_host_initfn(Object *obj)
30
- error_report("Guest image must be specified (using -kernel)");
196
31
- exit(1);
197
static const TypeInfo host_arm_cpu_type_info = {
32
- }
198
.name = TYPE_ARM_HOST_CPU,
33
-
199
-#ifdef TARGET_AARCH64
34
if (arm_feature(&cpu->env, ARM_FEATURE_EL3)) {
200
.parent = TYPE_AARCH64_CPU,
35
asidx = ARMASIdx_S;
201
-#else
36
} else {
202
- .parent = TYPE_ARM_CPU,
203
-#endif
204
.instance_init = arm_host_initfn,
205
};
206
207
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
208
index XXXXXXX..XXXXXXX 100644
209
--- a/target/arm/kvm.c
210
+++ b/target/arm/kvm.c
211
@@ -XXX,XX +XXX,XX @@ int kvm_arch_process_async_events(CPUState *cs)
212
return 0;
213
}
214
215
-/* The #ifdef protections are until 32bit headers are imported and can
216
- * be removed once both 32 and 64 bit reach feature parity.
217
- */
218
void kvm_arch_update_guest_debug(CPUState *cs, struct kvm_guest_debug *dbg)
219
{
220
-#ifdef KVM_GUESTDBG_USE_SW_BP
221
if (kvm_sw_breakpoints_active(cs)) {
222
dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP;
223
}
224
-#endif
225
-#ifdef KVM_GUESTDBG_USE_HW
226
if (kvm_arm_hw_debug_active(cs)) {
227
dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW;
228
kvm_arm_copy_hw_debug_data(&dbg->arch);
229
}
230
-#endif
231
}
232
233
void kvm_arch_init_irq_routing(KVMState *s)
37
--
234
--
38
2.19.2
235
2.20.1
39
236
40
237
diff view generated by jsdifflib
1
From: Luc Michel <luc.michel@greensocs.com>
1
Implement a model of the MPS2 with the AN386 firmware. This is
2
essentially identical to the AN385 firmware, but it has a
3
Cortex-M4 rather than a Cortex-M3.
2
4
3
Add the gdb_first_attached_cpu() and gdb_next_attached_cpu() to iterate
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
over all the CPUs in currently attached processes.
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20200903202048.15370-2-peter.maydell@linaro.org
9
---
10
docs/system/arm/mps2.rst | 8 +++++---
11
hw/arm/mps2.c | 34 +++++++++++++++++++++++++++++-----
12
2 files changed, 34 insertions(+), 8 deletions(-)
5
13
6
Add the gdb_first_cpu_in_process() and gdb_next_cpu_in_process() to
14
diff --git a/docs/system/arm/mps2.rst b/docs/system/arm/mps2.rst
7
iterate over CPUs of a given process.
8
9
Use them to add multiprocess extension support to vCont packets.
10
11
Signed-off-by: Luc Michel <luc.michel@greensocs.com>
12
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
13
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
14
Acked-by: Alistair Francis <alistair.francis@wdc.com>
15
Message-id: 20181207090135.7651-6-luc.michel@greensocs.com
16
[PMM: corrected checkpatch comment style nit]
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
19
gdbstub.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++-------
20
1 file changed, 100 insertions(+), 15 deletions(-)
21
22
diff --git a/gdbstub.c b/gdbstub.c
23
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
24
--- a/gdbstub.c
16
--- a/docs/system/arm/mps2.rst
25
+++ b/gdbstub.c
17
+++ b/docs/system/arm/mps2.rst
26
@@ -XXX,XX +XXX,XX @@ static CPUState *find_cpu(uint32_t thread_id)
18
@@ -XXX,XX +XXX,XX @@
27
return NULL;
19
-Arm MPS2 boards (``mps2-an385``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``)
20
-================================================================================
21
+Arm MPS2 boards (``mps2-an385``, ``mps2-an386``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``)
22
+================================================================================================
23
24
These board models all use Arm M-profile CPUs.
25
26
@@ -XXX,XX +XXX,XX @@ QEMU models the following FPGA images:
27
28
``mps2-an385``
29
Cortex-M3 as documented in ARM Application Note AN385
30
+``mps2-an386``
31
+ Cortex-M4 as documented in ARM Application Note AN386
32
``mps2-an511``
33
Cortex-M3 'DesignStart' as documented in AN511
34
``mps2-an505``
35
@@ -XXX,XX +XXX,XX @@ QEMU models the following FPGA images:
36
37
Differences between QEMU and real hardware:
38
39
-- AN385 remapping of low 16K of memory to either ZBT SSRAM1 or to
40
+- AN385/AN386 remapping of low 16K of memory to either ZBT SSRAM1 or to
41
block RAM is unimplemented (QEMU always maps this to ZBT SSRAM1, as
42
if zbt_boot_ctrl is always zero)
43
- QEMU provides a LAN9118 ethernet rather than LAN9220; the only guest
44
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/hw/arm/mps2.c
47
+++ b/hw/arm/mps2.c
48
@@ -XXX,XX +XXX,XX @@
49
* as seen by the guest depend significantly on the FPGA image.
50
* We model the following FPGA images:
51
* "mps2-an385" -- Cortex-M3 as documented in ARM Application Note AN385
52
+ * "mps2-an386" -- Cortex-M4 as documented in ARM Application Note AN386
53
* "mps2-an511" -- Cortex-M3 'DesignStart' as documented in AN511
54
*
55
* Links to the TRM for the board itself and to the various Application
56
@@ -XXX,XX +XXX,XX @@
57
58
typedef enum MPS2FPGAType {
59
FPGA_AN385,
60
+ FPGA_AN386,
61
FPGA_AN511,
62
} MPS2FPGAType;
63
64
@@ -XXX,XX +XXX,XX @@ typedef struct MPS2MachineState MPS2MachineState;
65
66
#define TYPE_MPS2_MACHINE "mps2"
67
#define TYPE_MPS2_AN385_MACHINE MACHINE_TYPE_NAME("mps2-an385")
68
+#define TYPE_MPS2_AN386_MACHINE MACHINE_TYPE_NAME("mps2-an386")
69
#define TYPE_MPS2_AN511_MACHINE MACHINE_TYPE_NAME("mps2-an511")
70
71
DECLARE_OBJ_CHECKERS(MPS2MachineState, MPS2MachineClass,
72
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
73
* tradeoffs. For QEMU they're all just RAM, though. We arbitrarily
74
* call the 16MB our "system memory", as it's the largest lump.
75
*
76
- * Common to both boards:
77
- * 0x21000000..0x21ffffff : PSRAM (16MB)
78
- * AN385 only:
79
+ * AN385/AN386/AN511:
80
+ * 0x21000000 .. 0x21ffffff : PSRAM (16MB)
81
+ * AN385/AN386 only:
82
* 0x00000000 .. 0x003fffff : ZBT SSRAM1
83
* 0x00400000 .. 0x007fffff : mirror of ZBT SSRAM1
84
* 0x20000000 .. 0x203fffff : ZBT SSRAM 2&3
85
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
86
* 0x20000000 .. 0x2001ffff : SRAM
87
* 0x20400000 .. 0x207fffff : ZBT SSRAM 2&3
88
*
89
- * The AN385 has a feature where the lowest 16K can be mapped
90
+ * The AN385/AN386 has a feature where the lowest 16K can be mapped
91
* either to the bottom of the ZBT SSRAM1 or to the block RAM.
92
* This is of no use for QEMU so we don't implement it (as if
93
* zbt_boot_ctrl is always zero).
94
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
95
96
switch (mmc->fpga_type) {
97
case FPGA_AN385:
98
+ case FPGA_AN386:
99
make_ram(&mms->ssram1, "mps.ssram1", 0x0, 0x400000);
100
make_ram_alias(&mms->ssram1_m, "mps.ssram1_m", &mms->ssram1, 0x400000);
101
make_ram(&mms->ssram23, "mps.ssram23", 0x20000000, 0x400000);
102
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
103
armv7m = DEVICE(&mms->armv7m);
104
switch (mmc->fpga_type) {
105
case FPGA_AN385:
106
+ case FPGA_AN386:
107
qdev_prop_set_uint32(armv7m, "num-irq", 32);
108
break;
109
case FPGA_AN511:
110
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
111
112
switch (mmc->fpga_type) {
113
case FPGA_AN385:
114
+ case FPGA_AN386:
115
{
116
/* The overflow IRQs for UARTs 0, 1 and 2 are ORed together.
117
* Overflow for UARTs 4 and 5 doesn't trigger any interrupt.
118
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
119
*/
120
lan9118_init(&nd_table[0], 0x40200000,
121
qdev_get_gpio_in(armv7m,
122
- mmc->fpga_type == FPGA_AN385 ? 13 : 47));
123
+ mmc->fpga_type == FPGA_AN511 ? 47 : 13));
124
125
system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ;
126
127
@@ -XXX,XX +XXX,XX @@ static void mps2_an385_class_init(ObjectClass *oc, void *data)
128
mmc->scc_id = 0x41043850;
28
}
129
}
29
130
30
+static CPUState *get_first_cpu_in_process(const GDBState *s,
131
+static void mps2_an386_class_init(ObjectClass *oc, void *data)
31
+ GDBProcess *process)
32
+{
132
+{
33
+ CPUState *cpu;
133
+ MachineClass *mc = MACHINE_CLASS(oc);
134
+ MPS2MachineClass *mmc = MPS2_MACHINE_CLASS(oc);
34
+
135
+
35
+ CPU_FOREACH(cpu) {
136
+ mc->desc = "ARM MPS2 with AN386 FPGA image for Cortex-M4";
36
+ if (gdb_get_cpu_pid(s, cpu) == process->pid) {
137
+ mmc->fpga_type = FPGA_AN386;
37
+ return cpu;
138
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m4");
38
+ }
139
+ mmc->scc_id = 0x41043860;
39
+ }
40
+
41
+ return NULL;
42
+}
140
+}
43
+
141
+
44
+static CPUState *gdb_next_cpu_in_process(const GDBState *s, CPUState *cpu)
142
static void mps2_an511_class_init(ObjectClass *oc, void *data)
45
+{
143
{
46
+ uint32_t pid = gdb_get_cpu_pid(s, cpu);
144
MachineClass *mc = MACHINE_CLASS(oc);
47
+ cpu = CPU_NEXT(cpu);
145
@@ -XXX,XX +XXX,XX @@ static const TypeInfo mps2_an385_info = {
146
.class_init = mps2_an385_class_init,
147
};
148
149
+static const TypeInfo mps2_an386_info = {
150
+ .name = TYPE_MPS2_AN386_MACHINE,
151
+ .parent = TYPE_MPS2_MACHINE,
152
+ .class_init = mps2_an386_class_init,
153
+};
48
+
154
+
49
+ while (cpu) {
155
static const TypeInfo mps2_an511_info = {
50
+ if (gdb_get_cpu_pid(s, cpu) == pid) {
156
.name = TYPE_MPS2_AN511_MACHINE,
51
+ break;
157
.parent = TYPE_MPS2_MACHINE,
52
+ }
158
@@ -XXX,XX +XXX,XX @@ static void mps2_machine_init(void)
53
+
54
+ cpu = CPU_NEXT(cpu);
55
+ }
56
+
57
+ return cpu;
58
+}
59
+
60
static CPUState *gdb_get_cpu(const GDBState *s, uint32_t pid, uint32_t tid)
61
{
159
{
62
GDBProcess *process;
160
type_register_static(&mps2_info);
63
@@ -XXX,XX +XXX,XX @@ static CPUState *gdb_get_cpu(const GDBState *s, uint32_t pid, uint32_t tid)
161
type_register_static(&mps2_an385_info);
64
return cpu;
162
+ type_register_static(&mps2_an386_info);
163
type_register_static(&mps2_an511_info);
65
}
164
}
66
165
67
+/* Return the cpu following @cpu, while ignoring unattached processes. */
68
+static CPUState *gdb_next_attached_cpu(const GDBState *s, CPUState *cpu)
69
+{
70
+ cpu = CPU_NEXT(cpu);
71
+
72
+ while (cpu) {
73
+ if (gdb_get_cpu_process(s, cpu)->attached) {
74
+ break;
75
+ }
76
+
77
+ cpu = CPU_NEXT(cpu);
78
+ }
79
+
80
+ return cpu;
81
+}
82
+
83
+/* Return the first attached cpu */
84
+static CPUState *gdb_first_attached_cpu(const GDBState *s)
85
+{
86
+ CPUState *cpu = first_cpu;
87
+ GDBProcess *process = gdb_get_cpu_process(s, cpu);
88
+
89
+ if (!process->attached) {
90
+ return gdb_next_attached_cpu(s, cpu);
91
+ }
92
+
93
+ return cpu;
94
+}
95
+
96
static const char *get_feature_xml(const char *p, const char **newp,
97
CPUClass *cc)
98
{
99
@@ -XXX,XX +XXX,XX @@ static int is_query_packet(const char *p, const char *query, char separator)
100
*/
101
static int gdb_handle_vcont(GDBState *s, const char *p)
102
{
103
- int res, idx, signal = 0;
104
+ int res, signal = 0;
105
char cur_action;
106
char *newstates;
107
unsigned long tmp;
108
+ uint32_t pid, tid;
109
+ GDBProcess *process;
110
CPUState *cpu;
111
#ifdef CONFIG_USER_ONLY
112
int max_cpus = 1; /* global variable max_cpus exists only in system mode */
113
@@ -XXX,XX +XXX,XX @@ static int gdb_handle_vcont(GDBState *s, const char *p)
114
res = -ENOTSUP;
115
goto out;
116
}
117
- /* thread specification. special values: (none), -1 = all; 0 = any */
118
- if ((p[0] == ':' && p[1] == '-' && p[2] == '1') || (p[0] != ':')) {
119
- if (*p == ':') {
120
- p += 3;
121
- }
122
- for (idx = 0; idx < max_cpus; idx++) {
123
- if (newstates[idx] == 1) {
124
- newstates[idx] = cur_action;
125
+
126
+ if (*p++ != ':') {
127
+ res = -ENOTSUP;
128
+ goto out;
129
+ }
130
+
131
+ switch (read_thread_id(p, &p, &pid, &tid)) {
132
+ case GDB_READ_THREAD_ERR:
133
+ res = -EINVAL;
134
+ goto out;
135
+
136
+ case GDB_ALL_PROCESSES:
137
+ cpu = gdb_first_attached_cpu(s);
138
+ while (cpu) {
139
+ if (newstates[cpu->cpu_index] == 1) {
140
+ newstates[cpu->cpu_index] = cur_action;
141
}
142
+
143
+ cpu = gdb_next_attached_cpu(s, cpu);
144
}
145
- } else if (*p == ':') {
146
- p++;
147
- res = qemu_strtoul(p, &p, 16, &tmp);
148
- if (res) {
149
+ break;
150
+
151
+ case GDB_ALL_THREADS:
152
+ process = gdb_get_process(s, pid);
153
+
154
+ if (!process->attached) {
155
+ res = -EINVAL;
156
goto out;
157
}
158
159
- /* 0 means any thread, so we pick the first valid CPU */
160
- cpu = tmp ? find_cpu(tmp) : first_cpu;
161
+ cpu = get_first_cpu_in_process(s, process);
162
+ while (cpu) {
163
+ if (newstates[cpu->cpu_index] == 1) {
164
+ newstates[cpu->cpu_index] = cur_action;
165
+ }
166
+
167
+ cpu = gdb_next_cpu_in_process(s, cpu);
168
+ }
169
+ break;
170
+
171
+ case GDB_ONE_THREAD:
172
+ cpu = gdb_get_cpu(s, pid, tid);
173
174
/* invalid CPU/thread specified */
175
if (!cpu) {
176
@@ -XXX,XX +XXX,XX @@ static int gdb_handle_vcont(GDBState *s, const char *p)
177
if (newstates[cpu->cpu_index] == 1) {
178
newstates[cpu->cpu_index] = cur_action;
179
}
180
+ break;
181
}
182
}
183
s->signal = signal;
184
--
166
--
185
2.19.2
167
2.20.1
186
168
187
169
diff view generated by jsdifflib
1
From: Steffen Görtz <contrib@steffen-goertz.de>
1
Implement a model of the MPS2 with the AN500 firmware. This is
2
2
similar to the AN385, with the following differences:
3
Use RNG in SOC.
3
* Cortex-M7 CPU
4
4
* PSRAM is at 0x6000_0000
5
Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
5
* Ethernet is at 0xa000_0000
6
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
* No zbt_boot_ctrl remapping of the low 16K
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
(but QEMU doesn't implement this anyway)
8
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
8
* no "block RAM" at 0x01000000
9
Message-id: 20190103091119.9367-5-stefanha@redhat.com
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Message-id: 20200903202048.15370-3-peter.maydell@linaro.org
11
---
13
---
12
include/hw/arm/nrf51_soc.h | 2 ++
14
docs/system/arm/mps2.rst | 6 ++--
13
hw/arm/nrf51_soc.c | 16 ++++++++++++++++
15
hw/arm/mps2.c | 67 +++++++++++++++++++++++++++++++++-------
14
2 files changed, 18 insertions(+)
16
2 files changed, 60 insertions(+), 13 deletions(-)
15
17
16
diff --git a/include/hw/arm/nrf51_soc.h b/include/hw/arm/nrf51_soc.h
18
diff --git a/docs/system/arm/mps2.rst b/docs/system/arm/mps2.rst
17
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/nrf51_soc.h
20
--- a/docs/system/arm/mps2.rst
19
+++ b/include/hw/arm/nrf51_soc.h
21
+++ b/docs/system/arm/mps2.rst
20
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@
21
#include "hw/sysbus.h"
23
-Arm MPS2 boards (``mps2-an385``, ``mps2-an386``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``)
22
#include "hw/arm/armv7m.h"
24
-================================================================================================
23
#include "hw/char/nrf51_uart.h"
25
+Arm MPS2 boards (``mps2-an385``, ``mps2-an386``, ``mps2-an500``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``)
24
+#include "hw/misc/nrf51_rng.h"
26
+================================================================================================================
25
27
26
#define TYPE_NRF51_SOC "nrf51-soc"
28
These board models all use Arm M-profile CPUs.
27
#define NRF51_SOC(obj) \
29
28
@@ -XXX,XX +XXX,XX @@ typedef struct NRF51State {
30
@@ -XXX,XX +XXX,XX @@ QEMU models the following FPGA images:
29
ARMv7MState cpu;
31
Cortex-M3 as documented in ARM Application Note AN385
30
32
``mps2-an386``
31
NRF51UARTState uart;
33
Cortex-M4 as documented in ARM Application Note AN386
32
+ NRF51RNGState rng;
34
+``mps2-an500``
33
35
+ Cortex-M7 as documented in ARM Application Note AN500
34
MemoryRegion iomem;
36
``mps2-an511``
35
MemoryRegion sram;
37
Cortex-M3 'DesignStart' as documented in AN511
36
diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c
38
``mps2-an505``
39
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
37
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
38
--- a/hw/arm/nrf51_soc.c
41
--- a/hw/arm/mps2.c
39
+++ b/hw/arm/nrf51_soc.c
42
+++ b/hw/arm/mps2.c
40
@@ -XXX,XX +XXX,XX @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
43
@@ -XXX,XX +XXX,XX @@
41
qdev_get_gpio_in(DEVICE(&s->cpu),
44
* We model the following FPGA images:
42
BASE_TO_IRQ(NRF51_UART_BASE)));
45
* "mps2-an385" -- Cortex-M3 as documented in ARM Application Note AN385
43
46
* "mps2-an386" -- Cortex-M4 as documented in ARM Application Note AN386
44
+ /* RNG */
47
+ * "mps2-an500" -- Cortex-M7 as documented in ARM Application Note AN500
45
+ object_property_set_bool(OBJECT(&s->rng), true, "realized", &err);
48
* "mps2-an511" -- Cortex-M3 'DesignStart' as documented in AN511
46
+ if (err) {
49
*
47
+ error_propagate(errp, err);
50
* Links to the TRM for the board itself and to the various Application
48
+ return;
51
@@ -XXX,XX +XXX,XX @@
52
typedef enum MPS2FPGAType {
53
FPGA_AN385,
54
FPGA_AN386,
55
+ FPGA_AN500,
56
FPGA_AN511,
57
} MPS2FPGAType;
58
59
@@ -XXX,XX +XXX,XX @@ struct MPS2MachineClass {
60
MachineClass parent;
61
MPS2FPGAType fpga_type;
62
uint32_t scc_id;
63
+ bool has_block_ram;
64
+ hwaddr ethernet_base;
65
+ hwaddr psram_base;
66
};
67
typedef struct MPS2MachineClass MPS2MachineClass;
68
69
@@ -XXX,XX +XXX,XX @@ typedef struct MPS2MachineState MPS2MachineState;
70
#define TYPE_MPS2_MACHINE "mps2"
71
#define TYPE_MPS2_AN385_MACHINE MACHINE_TYPE_NAME("mps2-an385")
72
#define TYPE_MPS2_AN386_MACHINE MACHINE_TYPE_NAME("mps2-an386")
73
+#define TYPE_MPS2_AN500_MACHINE MACHINE_TYPE_NAME("mps2-an500")
74
#define TYPE_MPS2_AN511_MACHINE MACHINE_TYPE_NAME("mps2-an511")
75
76
DECLARE_OBJ_CHECKERS(MPS2MachineState, MPS2MachineClass,
77
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
78
*
79
* AN385/AN386/AN511:
80
* 0x21000000 .. 0x21ffffff : PSRAM (16MB)
81
- * AN385/AN386 only:
82
+ * AN385/AN386/AN500:
83
* 0x00000000 .. 0x003fffff : ZBT SSRAM1
84
* 0x00400000 .. 0x007fffff : mirror of ZBT SSRAM1
85
* 0x20000000 .. 0x203fffff : ZBT SSRAM 2&3
86
* 0x20400000 .. 0x207fffff : mirror of ZBT SSRAM 2&3
87
+ * AN385/AN386 only:
88
* 0x01000000 .. 0x01003fff : block RAM (16K)
89
* 0x01004000 .. 0x01007fff : mirror of above
90
* 0x01008000 .. 0x0100bfff : mirror of above
91
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
92
* 0x00400000 .. 0x007fffff : ZBT SSRAM1
93
* 0x20000000 .. 0x2001ffff : SRAM
94
* 0x20400000 .. 0x207fffff : ZBT SSRAM 2&3
95
+ * AN500 only:
96
+ * 0x60000000 .. 0x60ffffff : PSRAM (16MB)
97
*
98
* The AN385/AN386 has a feature where the lowest 16K can be mapped
99
* either to the bottom of the ZBT SSRAM1 or to the block RAM.
100
* This is of no use for QEMU so we don't implement it (as if
101
* zbt_boot_ctrl is always zero).
102
*/
103
- memory_region_add_subregion(system_memory, 0x21000000, machine->ram);
104
+ memory_region_add_subregion(system_memory, mmc->psram_base, machine->ram);
105
106
- switch (mmc->fpga_type) {
107
- case FPGA_AN385:
108
- case FPGA_AN386:
109
- make_ram(&mms->ssram1, "mps.ssram1", 0x0, 0x400000);
110
- make_ram_alias(&mms->ssram1_m, "mps.ssram1_m", &mms->ssram1, 0x400000);
111
- make_ram(&mms->ssram23, "mps.ssram23", 0x20000000, 0x400000);
112
- make_ram_alias(&mms->ssram23_m, "mps.ssram23_m",
113
- &mms->ssram23, 0x20400000);
114
+ if (mmc->has_block_ram) {
115
make_ram(&mms->blockram, "mps.blockram", 0x01000000, 0x4000);
116
make_ram_alias(&mms->blockram_m1, "mps.blockram_m1",
117
&mms->blockram, 0x01004000);
118
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
119
&mms->blockram, 0x01008000);
120
make_ram_alias(&mms->blockram_m3, "mps.blockram_m3",
121
&mms->blockram, 0x0100c000);
49
+ }
122
+ }
50
+
123
+
51
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->rng), 0);
124
+ switch (mmc->fpga_type) {
52
+ memory_region_add_subregion_overlap(&s->container, NRF51_RNG_BASE, mr, 0);
125
+ case FPGA_AN385:
53
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->rng), 0,
126
+ case FPGA_AN386:
54
+ qdev_get_gpio_in(DEVICE(&s->cpu),
127
+ case FPGA_AN500:
55
+ BASE_TO_IRQ(NRF51_RNG_BASE)));
128
+ make_ram(&mms->ssram1, "mps.ssram1", 0x0, 0x400000);
56
+
129
+ make_ram_alias(&mms->ssram1_m, "mps.ssram1_m", &mms->ssram1, 0x400000);
57
create_unimplemented_device("nrf51_soc.io", NRF51_IOMEM_BASE,
130
+ make_ram(&mms->ssram23, "mps.ssram23", 0x20000000, 0x400000);
58
NRF51_IOMEM_SIZE);
131
+ make_ram_alias(&mms->ssram23_m, "mps.ssram23_m",
59
create_unimplemented_device("nrf51_soc.ficr", NRF51_FICR_BASE,
132
+ &mms->ssram23, 0x20400000);
60
@@ -XXX,XX +XXX,XX @@ static void nrf51_soc_init(Object *obj)
133
break;
61
TYPE_NRF51_UART);
134
case FPGA_AN511:
62
object_property_add_alias(obj, "serial0", OBJECT(&s->uart), "chardev",
135
make_ram(&mms->blockram, "mps.blockram", 0x0, 0x40000);
63
&error_abort);
136
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
64
+
137
switch (mmc->fpga_type) {
65
+ sysbus_init_child_obj(obj, "rng", &s->rng, sizeof(s->rng),
138
case FPGA_AN385:
66
+ TYPE_NRF51_RNG);
139
case FPGA_AN386:
67
}
140
+ case FPGA_AN500:
68
141
qdev_prop_set_uint32(armv7m, "num-irq", 32);
69
static Property nrf51_soc_properties[] = {
142
break;
143
case FPGA_AN511:
144
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
145
switch (mmc->fpga_type) {
146
case FPGA_AN385:
147
case FPGA_AN386:
148
+ case FPGA_AN500:
149
{
150
/* The overflow IRQs for UARTs 0, 1 and 2 are ORed together.
151
* Overflow for UARTs 4 and 5 doesn't trigger any interrupt.
152
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
153
/* In hardware this is a LAN9220; the LAN9118 is software compatible
154
* except that it doesn't support the checksum-offload feature.
155
*/
156
- lan9118_init(&nd_table[0], 0x40200000,
157
+ lan9118_init(&nd_table[0], mmc->ethernet_base,
158
qdev_get_gpio_in(armv7m,
159
mmc->fpga_type == FPGA_AN511 ? 47 : 13));
160
161
@@ -XXX,XX +XXX,XX @@ static void mps2_an385_class_init(ObjectClass *oc, void *data)
162
mmc->fpga_type = FPGA_AN385;
163
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m3");
164
mmc->scc_id = 0x41043850;
165
+ mmc->psram_base = 0x21000000;
166
+ mmc->ethernet_base = 0x40200000;
167
+ mmc->has_block_ram = true;
168
}
169
170
static void mps2_an386_class_init(ObjectClass *oc, void *data)
171
@@ -XXX,XX +XXX,XX @@ static void mps2_an386_class_init(ObjectClass *oc, void *data)
172
mmc->fpga_type = FPGA_AN386;
173
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m4");
174
mmc->scc_id = 0x41043860;
175
+ mmc->psram_base = 0x21000000;
176
+ mmc->ethernet_base = 0x40200000;
177
+ mmc->has_block_ram = true;
178
+}
179
+
180
+static void mps2_an500_class_init(ObjectClass *oc, void *data)
181
+{
182
+ MachineClass *mc = MACHINE_CLASS(oc);
183
+ MPS2MachineClass *mmc = MPS2_MACHINE_CLASS(oc);
184
+
185
+ mc->desc = "ARM MPS2 with AN500 FPGA image for Cortex-M7";
186
+ mmc->fpga_type = FPGA_AN500;
187
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m7");
188
+ mmc->scc_id = 0x41045000;
189
+ mmc->psram_base = 0x60000000;
190
+ mmc->ethernet_base = 0xa0000000;
191
+ mmc->has_block_ram = false;
192
}
193
194
static void mps2_an511_class_init(ObjectClass *oc, void *data)
195
@@ -XXX,XX +XXX,XX @@ static void mps2_an511_class_init(ObjectClass *oc, void *data)
196
mmc->fpga_type = FPGA_AN511;
197
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m3");
198
mmc->scc_id = 0x41045110;
199
+ mmc->psram_base = 0x21000000;
200
+ mmc->ethernet_base = 0x40200000;
201
+ mmc->has_block_ram = false;
202
}
203
204
static const TypeInfo mps2_info = {
205
@@ -XXX,XX +XXX,XX @@ static const TypeInfo mps2_an386_info = {
206
.class_init = mps2_an386_class_init,
207
};
208
209
+static const TypeInfo mps2_an500_info = {
210
+ .name = TYPE_MPS2_AN500_MACHINE,
211
+ .parent = TYPE_MPS2_MACHINE,
212
+ .class_init = mps2_an500_class_init,
213
+};
214
+
215
static const TypeInfo mps2_an511_info = {
216
.name = TYPE_MPS2_AN511_MACHINE,
217
.parent = TYPE_MPS2_MACHINE,
218
@@ -XXX,XX +XXX,XX @@ static void mps2_machine_init(void)
219
type_register_static(&mps2_info);
220
type_register_static(&mps2_an385_info);
221
type_register_static(&mps2_an386_info);
222
+ type_register_static(&mps2_an500_info);
223
type_register_static(&mps2_an511_info);
224
}
225
70
--
226
--
71
2.19.2
227
2.20.1
72
228
73
229
diff view generated by jsdifflib
1
Now that MTTCG is here, the comment in the 32-bit Arm decoder that
1
Make the list of MPS2 boards consistent in the phrasing of each
2
"Since the emulation does not have barriers, the acquire/release
2
entry, use the correct casing of "Arm", and move the mps2-an511
3
semantics need no special handling" is no longer true. Emit the
3
entry so the list is in numeric order.
4
correct barriers for the load-acquire/store-release insns, as
5
we already do in the A64 decoder.
6
4
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Tested-by: Alex Bennée <alex.bennee@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Message-id: 20200903202048.15370-4-peter.maydell@linaro.org
10
---
8
---
11
target/arm/translate.c | 33 ++++++++++++++++++++++++++-------
9
docs/system/arm/mps2.rst | 14 +++++++-------
12
1 file changed, 26 insertions(+), 7 deletions(-)
10
1 file changed, 7 insertions(+), 7 deletions(-)
13
11
14
diff --git a/target/arm/translate.c b/target/arm/translate.c
12
diff --git a/docs/system/arm/mps2.rst b/docs/system/arm/mps2.rst
15
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/translate.c
14
--- a/docs/system/arm/mps2.rst
17
+++ b/target/arm/translate.c
15
+++ b/docs/system/arm/mps2.rst
18
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
16
@@ -XXX,XX +XXX,XX @@ as seen by the guest depend significantly on the FPGA image.
19
rd = (insn >> 12) & 0xf;
17
QEMU models the following FPGA images:
20
if (insn & (1 << 23)) {
18
21
/* load/store exclusive */
19
``mps2-an385``
22
+ bool is_ld = extract32(insn, 20, 1);
20
- Cortex-M3 as documented in ARM Application Note AN385
23
+ bool is_lasr = !extract32(insn, 8, 1);
21
+ Cortex-M3 as documented in Arm Application Note AN385
24
int op2 = (insn >> 8) & 3;
22
``mps2-an386``
25
op1 = (insn >> 21) & 0x3;
23
- Cortex-M4 as documented in ARM Application Note AN386
26
24
+ Cortex-M4 as documented in Arm Application Note AN386
27
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
25
``mps2-an500``
28
addr = tcg_temp_local_new_i32();
26
- Cortex-M7 as documented in ARM Application Note AN500
29
load_reg_var(s, addr, rn);
27
-``mps2-an511``
30
28
- Cortex-M3 'DesignStart' as documented in AN511
31
- /* Since the emulation does not have barriers,
29
+ Cortex-M7 as documented in Arm Application Note AN500
32
- the acquire/release semantics need no special
30
``mps2-an505``
33
- handling */
31
- Cortex-M33 as documented in ARM Application Note AN505
34
+ if (is_lasr && !is_ld) {
32
+ Cortex-M33 as documented in Arm Application Note AN505
35
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
33
+``mps2-an511``
36
+ }
34
+ Cortex-M3 'DesignStart' as documented in Arm Application Note AN511
37
+
35
``mps2-an521``
38
if (op2 == 0) {
36
- Dual Cortex-M33 as documented in Application Note AN521
39
- if (insn & (1 << 20)) {
37
+ Dual Cortex-M33 as documented in Arm Application Note AN521
40
+ if (is_ld) {
38
41
tmp = tcg_temp_new_i32();
39
Differences between QEMU and real hardware:
42
switch (op1) {
40
43
case 0: /* lda */
44
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
45
}
46
tcg_temp_free_i32(tmp);
47
}
48
- } else if (insn & (1 << 20)) {
49
+ } else if (is_ld) {
50
switch (op1) {
51
case 0: /* ldrex */
52
gen_load_exclusive(s, rd, 15, addr, 2);
53
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
54
}
55
}
56
tcg_temp_free_i32(addr);
57
+
58
+ if (is_lasr && is_ld) {
59
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
60
+ }
61
} else if ((insn & 0x00300f00) == 0) {
62
/* 0bcccc_0001_0x00_xxxx_xxxx_0000_1001_xxxx
63
* - SWP, SWPB
64
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
65
tcg_gen_addi_i32(tmp, tmp, s->pc);
66
store_reg(s, 15, tmp);
67
} else {
68
+ bool is_lasr = false;
69
+ bool is_ld = extract32(insn, 20, 1);
70
int op2 = (insn >> 6) & 0x3;
71
op = (insn >> 4) & 0x3;
72
switch (op2) {
73
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
74
case 3:
75
/* Load-acquire/store-release exclusive */
76
ARCH(8);
77
+ is_lasr = true;
78
break;
79
}
80
+
81
+ if (is_lasr && !is_ld) {
82
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
83
+ }
84
+
85
addr = tcg_temp_local_new_i32();
86
load_reg_var(s, addr, rn);
87
if (!(op2 & 1)) {
88
- if (insn & (1 << 20)) {
89
+ if (is_ld) {
90
tmp = tcg_temp_new_i32();
91
switch (op) {
92
case 0: /* ldab */
93
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
94
}
95
tcg_temp_free_i32(tmp);
96
}
97
- } else if (insn & (1 << 20)) {
98
+ } else if (is_ld) {
99
gen_load_exclusive(s, rs, rd, addr, op);
100
} else {
101
gen_store_exclusive(s, rm, rs, rd, addr, op);
102
}
103
tcg_temp_free_i32(addr);
104
+
105
+ if (is_lasr && is_ld) {
106
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
107
+ }
108
}
109
} else {
110
/* Load/store multiple, RFE, SRS. */
111
--
41
--
112
2.19.2
42
2.20.1
113
43
114
44
diff view generated by jsdifflib
1
From: Steffen Görtz <contrib@steffen-goertz.de>
1
Deprecate our Unicore32 target support:
2
* the Linux kernel dropped support for unicore32 in commit
3
05119217a9bd199c for its 5.9 release (with rationale in the
4
cover letter: https://lkml.org/lkml/2020/8/3/232 )
5
* there is apparently no upstream toolchain that can create unicore32
6
binaries
7
* the maintainer doesn't seem to have made any contributions to
8
QEMU since the port first landed in 2012
9
* nobody else seems to have made changes to the unicore code except
10
for generic cleanups either
2
11
3
Basic tests for nRF51 Timer Peripheral.
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
14
Message-id: 20200825172719.19422-1-peter.maydell@linaro.org
15
---
16
docs/system/deprecated.rst | 8 ++++++++
17
1 file changed, 8 insertions(+)
4
18
5
Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
19
diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst
6
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
7
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Message-id: 20190103091119.9367-11-stefanha@redhat.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
tests/microbit-test.c | 95 +++++++++++++++++++++++++++++++++++++++++++
12
1 file changed, 95 insertions(+)
13
14
diff --git a/tests/microbit-test.c b/tests/microbit-test.c
15
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
16
--- a/tests/microbit-test.c
21
--- a/docs/system/deprecated.rst
17
+++ b/tests/microbit-test.c
22
+++ b/docs/system/deprecated.rst
18
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@ The above, converted to the current supported format::
19
24
linux-user mode CPUs
20
#include "hw/arm/nrf51.h"
25
--------------------
21
#include "hw/gpio/nrf51_gpio.h"
26
22
+#include "hw/timer/nrf51_timer.h"
27
+``unicore32`` CPUs (since 5.2.0)
23
28
+''''''''''''''''''''''''''''''''
24
static void test_nrf51_gpio(void)
25
{
26
@@ -XXX,XX +XXX,XX @@ static void test_nrf51_gpio(void)
27
qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, 0);
28
}
29
30
+static void timer_task(hwaddr task)
31
+{
32
+ writel(NRF51_TIMER_BASE + task, NRF51_TRIGGER_TASK);
33
+}
34
+
29
+
35
+static void timer_clear_event(hwaddr event)
30
+The ``unicore32`` guest CPU support is deprecated and will be removed in
36
+{
31
+a future version of QEMU. Support for this CPU was removed from the
37
+ writel(NRF51_TIMER_BASE + event, NRF51_EVENT_CLEAR);
32
+upstream Linux kernel, and there is no available upstream toolchain
38
+}
33
+to build binaries for it.
39
+
34
+
40
+static void timer_set_bitmode(uint8_t mode)
35
``tilegx`` CPUs (since 5.1.0)
41
+{
36
'''''''''''''''''''''''''''''
42
+ writel(NRF51_TIMER_BASE + NRF51_TIMER_REG_BITMODE, mode);
43
+}
44
+
45
+static void timer_set_prescaler(uint8_t prescaler)
46
+{
47
+ writel(NRF51_TIMER_BASE + NRF51_TIMER_REG_PRESCALER, prescaler);
48
+}
49
+
50
+static void timer_set_cc(size_t idx, uint32_t value)
51
+{
52
+ writel(NRF51_TIMER_BASE + NRF51_TIMER_REG_CC0 + idx * 4, value);
53
+}
54
+
55
+static void timer_assert_events(uint32_t ev0, uint32_t ev1, uint32_t ev2,
56
+ uint32_t ev3)
57
+{
58
+ g_assert(readl(NRF51_TIMER_BASE + NRF51_TIMER_EVENT_COMPARE_0) == ev0);
59
+ g_assert(readl(NRF51_TIMER_BASE + NRF51_TIMER_EVENT_COMPARE_1) == ev1);
60
+ g_assert(readl(NRF51_TIMER_BASE + NRF51_TIMER_EVENT_COMPARE_2) == ev2);
61
+ g_assert(readl(NRF51_TIMER_BASE + NRF51_TIMER_EVENT_COMPARE_3) == ev3);
62
+}
63
+
64
+static void test_nrf51_timer(void)
65
+{
66
+ uint32_t steps_to_overflow = 408;
67
+
68
+ /* Compare Match */
69
+ timer_task(NRF51_TIMER_TASK_STOP);
70
+ timer_task(NRF51_TIMER_TASK_CLEAR);
71
+
72
+ timer_clear_event(NRF51_TIMER_EVENT_COMPARE_0);
73
+ timer_clear_event(NRF51_TIMER_EVENT_COMPARE_1);
74
+ timer_clear_event(NRF51_TIMER_EVENT_COMPARE_2);
75
+ timer_clear_event(NRF51_TIMER_EVENT_COMPARE_3);
76
+
77
+ timer_set_bitmode(NRF51_TIMER_WIDTH_16); /* 16 MHz Timer */
78
+ timer_set_prescaler(0);
79
+ /* Swept over in first step */
80
+ timer_set_cc(0, 2);
81
+ /* Barely miss on first step */
82
+ timer_set_cc(1, 162);
83
+ /* Spot on on third step */
84
+ timer_set_cc(2, 480);
85
+
86
+ timer_assert_events(0, 0, 0, 0);
87
+
88
+ timer_task(NRF51_TIMER_TASK_START);
89
+ clock_step(10000);
90
+ timer_assert_events(1, 0, 0, 0);
91
+
92
+ /* Swept over on first overflow */
93
+ timer_set_cc(3, 114);
94
+
95
+ clock_step(10000);
96
+ timer_assert_events(1, 1, 0, 0);
97
+
98
+ clock_step(10000);
99
+ timer_assert_events(1, 1, 1, 0);
100
+
101
+ /* Wrap time until internal counter overflows */
102
+ while (steps_to_overflow--) {
103
+ timer_assert_events(1, 1, 1, 0);
104
+ clock_step(10000);
105
+ }
106
+
107
+ timer_assert_events(1, 1, 1, 1);
108
+
109
+ timer_clear_event(NRF51_TIMER_EVENT_COMPARE_0);
110
+ timer_clear_event(NRF51_TIMER_EVENT_COMPARE_1);
111
+ timer_clear_event(NRF51_TIMER_EVENT_COMPARE_2);
112
+ timer_clear_event(NRF51_TIMER_EVENT_COMPARE_3);
113
+ timer_assert_events(0, 0, 0, 0);
114
+
115
+ timer_task(NRF51_TIMER_TASK_STOP);
116
+
117
+ /* Test Proposal: Stop/Shutdown */
118
+ /* Test Proposal: Shortcut Compare -> Clear */
119
+ /* Test Proposal: Shortcut Compare -> Stop */
120
+ /* Test Proposal: Counter Mode */
121
+}
122
+
123
int main(int argc, char **argv)
124
{
125
int ret;
126
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
127
global_qtest = qtest_initf("-machine microbit");
128
129
qtest_add_func("/microbit/nrf51/gpio", test_nrf51_gpio);
130
+ qtest_add_func("/microbit/nrf51/timer", test_nrf51_timer);
131
132
ret = g_test_run();
133
37
134
--
38
--
135
2.19.2
39
2.20.1
136
40
137
41
diff view generated by jsdifflib
1
We use cpu_stop_current() to ensure the current CPU has stopped
1
Deprecate our lm32 target support. Michael Walle (former lm32 maintainer)
2
from places like qemu_system_reset_request(). Unfortunately its
2
suggested that we do this in 2019:
3
current implementation has a race. It calls qemu_cpu_stop(),
3
https://www.mail-archive.com/qemu-devel@nongnu.org/msg605024.html
4
which sets cpu->stopped to true even though the CPU hasn't
4
because the only public user of the architecture is the many-years-dead
5
actually stopped yet. The main thread will look at the flags
5
milkymist project. (The Linux port to lm32 was never merged upstream.)
6
set by qemu_system_reset_request() and call pause_all_vcpus().
7
pause_all_vcpus() waits for every cpu to have cpu->stopped true,
8
so it can continue (and we will start the system reset operation)
9
before the vcpu thread has got back to its top level loop.
10
6
11
Instead, just set cpu->stop and call cpu_exit(). This will
7
In commit 4b4d96c776f552e (March 2020) we marked it as 'orphan' in
12
cause the vcpu to exit back to the top level loop, and there
8
the MAINTAINERS file, but didn't officially deprecate it. Mark it
13
(as part of the wait_io_event code) it will call qemu_cpu_stop().
9
deprecated now, with the intention of removing it from QEMU in
14
10
mid-2021 before the 6.1 release.
15
This fixes bugs where the reset request appeared to be ignored
16
or the CPU misbehaved because the reset operation started
17
to change vcpu state while the vcpu thread was still using it.
18
11
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Reviewed-by: Emilio G. Cota <cota@braap.org>
13
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
21
Tested-by: Jaap Crezee <jaap@jcz.nl>
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
22
Message-id: 20181207155911.12710-1-peter.maydell@linaro.org
15
Reviewed-by: Thomas Huth <thuth@redhat.com>
16
Acked-by: Michael Walle <michael@walle.cc>
17
Message-id: 20200827113259.25064-1-peter.maydell@linaro.org
23
---
18
---
24
cpus.c | 3 ++-
19
docs/system/deprecated.rst | 8 ++++++++
25
1 file changed, 2 insertions(+), 1 deletion(-)
20
1 file changed, 8 insertions(+)
26
21
27
diff --git a/cpus.c b/cpus.c
22
diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst
28
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
29
--- a/cpus.c
24
--- a/docs/system/deprecated.rst
30
+++ b/cpus.c
25
+++ b/docs/system/deprecated.rst
31
@@ -XXX,XX +XXX,XX @@ void qemu_init_vcpu(CPUState *cpu)
26
@@ -XXX,XX +XXX,XX @@ The above, converted to the current supported format::
32
void cpu_stop_current(void)
27
linux-user mode CPUs
33
{
28
--------------------
34
if (current_cpu) {
29
35
- qemu_cpu_stop(current_cpu, true);
30
+``lm32`` CPUs (since 5.2.0)
36
+ current_cpu->stop = true;
31
+'''''''''''''''''''''''''''
37
+ cpu_exit(current_cpu);
32
+
38
}
33
+The ``lm32`` guest CPU support is deprecated and will be removed in
39
}
34
+a future version of QEMU. The only public user of this architecture
35
+was the milkymist project, which has been dead for years; there was
36
+never an upstream Linux port.
37
+
38
``unicore32`` CPUs (since 5.2.0)
39
''''''''''''''''''''''''''''''''
40
40
41
--
41
--
42
2.19.2
42
2.20.1
43
43
44
44
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Aaron Lindsay <aaron@os.amperecomputing.com>
2
2
3
Use "register" TBFLAG_ANY to indicate shared state between
3
This check was backwards when introduced in commit
4
A32 and A64, and "registers" TBFLAG_A32 & TBFLAG_A64 for
4
033614c47de78409ad3fb39bb7bd1483b71c6789:
5
fields that are specific to the given cpu state.
6
5
7
Move ARM_TBFLAG_BE_DATA to shared state, instead of its current
6
target/arm: Filter cycle counter based on PMCCFILTR_EL0
8
placement within "Bit usage when in AArch32 state".
9
7
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Cc: qemu-stable@nongnu.org
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Signed-off-by: Aaron Lindsay <aaron@os.amperecomputing.com>
12
Message-id: 20181218164348.7127-1-richard.henderson@linaro.org
13
[PMM: removed the renaming of BE_DATA flag to BE]
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
12
---
17
target/arm/cpu.h | 102 ++++++++-----------------------------
13
target/arm/helper.c | 2 +-
18
target/arm/helper.c | 49 +++++++++---------
14
1 file changed, 1 insertion(+), 1 deletion(-)
19
target/arm/translate-a64.c | 22 ++++----
20
target/arm/translate.c | 40 ++++++++-------
21
4 files changed, 78 insertions(+), 135 deletions(-)
22
15
23
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
24
index XXXXXXX..XXXXXXX 100644
25
--- a/target/arm/cpu.h
26
+++ b/target/arm/cpu.h
27
@@ -XXX,XX +XXX,XX @@ static inline bool arm_cpu_data_is_big_endian(CPUARMState *env)
28
* We put flags which are shared between 32 and 64 bit mode at the top
29
* of the word, and flags which apply to only one mode at the bottom.
30
*/
31
-#define ARM_TBFLAG_AARCH64_STATE_SHIFT 31
32
-#define ARM_TBFLAG_AARCH64_STATE_MASK (1U << ARM_TBFLAG_AARCH64_STATE_SHIFT)
33
-#define ARM_TBFLAG_MMUIDX_SHIFT 28
34
-#define ARM_TBFLAG_MMUIDX_MASK (0x7 << ARM_TBFLAG_MMUIDX_SHIFT)
35
-#define ARM_TBFLAG_SS_ACTIVE_SHIFT 27
36
-#define ARM_TBFLAG_SS_ACTIVE_MASK (1 << ARM_TBFLAG_SS_ACTIVE_SHIFT)
37
-#define ARM_TBFLAG_PSTATE_SS_SHIFT 26
38
-#define ARM_TBFLAG_PSTATE_SS_MASK (1 << ARM_TBFLAG_PSTATE_SS_SHIFT)
39
+FIELD(TBFLAG_ANY, AARCH64_STATE, 31, 1)
40
+FIELD(TBFLAG_ANY, MMUIDX, 28, 3)
41
+FIELD(TBFLAG_ANY, SS_ACTIVE, 27, 1)
42
+FIELD(TBFLAG_ANY, PSTATE_SS, 26, 1)
43
/* Target EL if we take a floating-point-disabled exception */
44
-#define ARM_TBFLAG_FPEXC_EL_SHIFT 24
45
-#define ARM_TBFLAG_FPEXC_EL_MASK (0x3 << ARM_TBFLAG_FPEXC_EL_SHIFT)
46
+FIELD(TBFLAG_ANY, FPEXC_EL, 24, 2)
47
+FIELD(TBFLAG_ANY, BE_DATA, 23, 1)
48
49
/* Bit usage when in AArch32 state: */
50
-#define ARM_TBFLAG_THUMB_SHIFT 0
51
-#define ARM_TBFLAG_THUMB_MASK (1 << ARM_TBFLAG_THUMB_SHIFT)
52
-#define ARM_TBFLAG_VECLEN_SHIFT 1
53
-#define ARM_TBFLAG_VECLEN_MASK (0x7 << ARM_TBFLAG_VECLEN_SHIFT)
54
-#define ARM_TBFLAG_VECSTRIDE_SHIFT 4
55
-#define ARM_TBFLAG_VECSTRIDE_MASK (0x3 << ARM_TBFLAG_VECSTRIDE_SHIFT)
56
-#define ARM_TBFLAG_VFPEN_SHIFT 7
57
-#define ARM_TBFLAG_VFPEN_MASK (1 << ARM_TBFLAG_VFPEN_SHIFT)
58
-#define ARM_TBFLAG_CONDEXEC_SHIFT 8
59
-#define ARM_TBFLAG_CONDEXEC_MASK (0xff << ARM_TBFLAG_CONDEXEC_SHIFT)
60
-#define ARM_TBFLAG_SCTLR_B_SHIFT 16
61
-#define ARM_TBFLAG_SCTLR_B_MASK (1 << ARM_TBFLAG_SCTLR_B_SHIFT)
62
+FIELD(TBFLAG_A32, THUMB, 0, 1)
63
+FIELD(TBFLAG_A32, VECLEN, 1, 3)
64
+FIELD(TBFLAG_A32, VECSTRIDE, 4, 2)
65
+FIELD(TBFLAG_A32, VFPEN, 7, 1)
66
+FIELD(TBFLAG_A32, CONDEXEC, 8, 8)
67
+FIELD(TBFLAG_A32, SCTLR_B, 16, 1)
68
/* We store the bottom two bits of the CPAR as TB flags and handle
69
* checks on the other bits at runtime
70
*/
71
-#define ARM_TBFLAG_XSCALE_CPAR_SHIFT 17
72
-#define ARM_TBFLAG_XSCALE_CPAR_MASK (3 << ARM_TBFLAG_XSCALE_CPAR_SHIFT)
73
+FIELD(TBFLAG_A32, XSCALE_CPAR, 17, 2)
74
/* Indicates whether cp register reads and writes by guest code should access
75
* the secure or nonsecure bank of banked registers; note that this is not
76
* the same thing as the current security state of the processor!
77
*/
78
-#define ARM_TBFLAG_NS_SHIFT 19
79
-#define ARM_TBFLAG_NS_MASK (1 << ARM_TBFLAG_NS_SHIFT)
80
-#define ARM_TBFLAG_BE_DATA_SHIFT 20
81
-#define ARM_TBFLAG_BE_DATA_MASK (1 << ARM_TBFLAG_BE_DATA_SHIFT)
82
+FIELD(TBFLAG_A32, NS, 19, 1)
83
/* For M profile only, Handler (ie not Thread) mode */
84
-#define ARM_TBFLAG_HANDLER_SHIFT 21
85
-#define ARM_TBFLAG_HANDLER_MASK (1 << ARM_TBFLAG_HANDLER_SHIFT)
86
+FIELD(TBFLAG_A32, HANDLER, 21, 1)
87
/* For M profile only, whether we should generate stack-limit checks */
88
-#define ARM_TBFLAG_STACKCHECK_SHIFT 22
89
-#define ARM_TBFLAG_STACKCHECK_MASK (1 << ARM_TBFLAG_STACKCHECK_SHIFT)
90
+FIELD(TBFLAG_A32, STACKCHECK, 22, 1)
91
92
/* Bit usage when in AArch64 state */
93
-#define ARM_TBFLAG_TBI0_SHIFT 0 /* TBI0 for EL0/1 or TBI for EL2/3 */
94
-#define ARM_TBFLAG_TBI0_MASK (0x1ull << ARM_TBFLAG_TBI0_SHIFT)
95
-#define ARM_TBFLAG_TBI1_SHIFT 1 /* TBI1 for EL0/1 */
96
-#define ARM_TBFLAG_TBI1_MASK (0x1ull << ARM_TBFLAG_TBI1_SHIFT)
97
-#define ARM_TBFLAG_SVEEXC_EL_SHIFT 2
98
-#define ARM_TBFLAG_SVEEXC_EL_MASK (0x3 << ARM_TBFLAG_SVEEXC_EL_SHIFT)
99
-#define ARM_TBFLAG_ZCR_LEN_SHIFT 4
100
-#define ARM_TBFLAG_ZCR_LEN_MASK (0xf << ARM_TBFLAG_ZCR_LEN_SHIFT)
101
-
102
-/* some convenience accessor macros */
103
-#define ARM_TBFLAG_AARCH64_STATE(F) \
104
- (((F) & ARM_TBFLAG_AARCH64_STATE_MASK) >> ARM_TBFLAG_AARCH64_STATE_SHIFT)
105
-#define ARM_TBFLAG_MMUIDX(F) \
106
- (((F) & ARM_TBFLAG_MMUIDX_MASK) >> ARM_TBFLAG_MMUIDX_SHIFT)
107
-#define ARM_TBFLAG_SS_ACTIVE(F) \
108
- (((F) & ARM_TBFLAG_SS_ACTIVE_MASK) >> ARM_TBFLAG_SS_ACTIVE_SHIFT)
109
-#define ARM_TBFLAG_PSTATE_SS(F) \
110
- (((F) & ARM_TBFLAG_PSTATE_SS_MASK) >> ARM_TBFLAG_PSTATE_SS_SHIFT)
111
-#define ARM_TBFLAG_FPEXC_EL(F) \
112
- (((F) & ARM_TBFLAG_FPEXC_EL_MASK) >> ARM_TBFLAG_FPEXC_EL_SHIFT)
113
-#define ARM_TBFLAG_THUMB(F) \
114
- (((F) & ARM_TBFLAG_THUMB_MASK) >> ARM_TBFLAG_THUMB_SHIFT)
115
-#define ARM_TBFLAG_VECLEN(F) \
116
- (((F) & ARM_TBFLAG_VECLEN_MASK) >> ARM_TBFLAG_VECLEN_SHIFT)
117
-#define ARM_TBFLAG_VECSTRIDE(F) \
118
- (((F) & ARM_TBFLAG_VECSTRIDE_MASK) >> ARM_TBFLAG_VECSTRIDE_SHIFT)
119
-#define ARM_TBFLAG_VFPEN(F) \
120
- (((F) & ARM_TBFLAG_VFPEN_MASK) >> ARM_TBFLAG_VFPEN_SHIFT)
121
-#define ARM_TBFLAG_CONDEXEC(F) \
122
- (((F) & ARM_TBFLAG_CONDEXEC_MASK) >> ARM_TBFLAG_CONDEXEC_SHIFT)
123
-#define ARM_TBFLAG_SCTLR_B(F) \
124
- (((F) & ARM_TBFLAG_SCTLR_B_MASK) >> ARM_TBFLAG_SCTLR_B_SHIFT)
125
-#define ARM_TBFLAG_XSCALE_CPAR(F) \
126
- (((F) & ARM_TBFLAG_XSCALE_CPAR_MASK) >> ARM_TBFLAG_XSCALE_CPAR_SHIFT)
127
-#define ARM_TBFLAG_NS(F) \
128
- (((F) & ARM_TBFLAG_NS_MASK) >> ARM_TBFLAG_NS_SHIFT)
129
-#define ARM_TBFLAG_BE_DATA(F) \
130
- (((F) & ARM_TBFLAG_BE_DATA_MASK) >> ARM_TBFLAG_BE_DATA_SHIFT)
131
-#define ARM_TBFLAG_HANDLER(F) \
132
- (((F) & ARM_TBFLAG_HANDLER_MASK) >> ARM_TBFLAG_HANDLER_SHIFT)
133
-#define ARM_TBFLAG_STACKCHECK(F) \
134
- (((F) & ARM_TBFLAG_STACKCHECK_MASK) >> ARM_TBFLAG_STACKCHECK_SHIFT)
135
-#define ARM_TBFLAG_TBI0(F) \
136
- (((F) & ARM_TBFLAG_TBI0_MASK) >> ARM_TBFLAG_TBI0_SHIFT)
137
-#define ARM_TBFLAG_TBI1(F) \
138
- (((F) & ARM_TBFLAG_TBI1_MASK) >> ARM_TBFLAG_TBI1_SHIFT)
139
-#define ARM_TBFLAG_SVEEXC_EL(F) \
140
- (((F) & ARM_TBFLAG_SVEEXC_EL_MASK) >> ARM_TBFLAG_SVEEXC_EL_SHIFT)
141
-#define ARM_TBFLAG_ZCR_LEN(F) \
142
- (((F) & ARM_TBFLAG_ZCR_LEN_MASK) >> ARM_TBFLAG_ZCR_LEN_SHIFT)
143
+FIELD(TBFLAG_A64, TBI0, 0, 1)
144
+FIELD(TBFLAG_A64, TBI1, 1, 1)
145
+FIELD(TBFLAG_A64, SVEEXC_EL, 2, 2)
146
+FIELD(TBFLAG_A64, ZCR_LEN, 4, 4)
147
148
static inline bool bswap_code(bool sctlr_b)
149
{
150
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
diff --git a/target/arm/helper.c b/target/arm/helper.c
151
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
152
--- a/target/arm/helper.c
18
--- a/target/arm/helper.c
153
+++ b/target/arm/helper.c
19
+++ b/target/arm/helper.c
154
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
20
@@ -XXX,XX +XXX,XX @@ static bool pmu_counter_enabled(CPUARMState *env, uint8_t counter)
155
ARMMMUIdx mmu_idx = core_to_arm_mmu_idx(env, cpu_mmu_index(env, false));
156
int current_el = arm_current_el(env);
157
int fp_el = fp_exception_el(env, current_el);
158
- uint32_t flags;
159
+ uint32_t flags = 0;
160
161
if (is_a64(env)) {
162
ARMCPU *cpu = arm_env_get_cpu(env);
163
164
*pc = env->pc;
165
- flags = ARM_TBFLAG_AARCH64_STATE_MASK;
166
+ flags = FIELD_DP32(flags, TBFLAG_ANY, AARCH64_STATE, 1);
167
/* Get control bits for tagged addresses */
168
- flags |= (arm_regime_tbi0(env, mmu_idx) << ARM_TBFLAG_TBI0_SHIFT);
169
- flags |= (arm_regime_tbi1(env, mmu_idx) << ARM_TBFLAG_TBI1_SHIFT);
170
+ flags = FIELD_DP32(flags, TBFLAG_A64, TBI0,
171
+ arm_regime_tbi0(env, mmu_idx));
172
+ flags = FIELD_DP32(flags, TBFLAG_A64, TBI1,
173
+ arm_regime_tbi1(env, mmu_idx));
174
175
if (cpu_isar_feature(aa64_sve, cpu)) {
176
int sve_el = sve_exception_el(env, current_el);
177
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
178
} else {
179
zcr_len = sve_zcr_len_for_el(env, current_el);
180
}
181
- flags |= sve_el << ARM_TBFLAG_SVEEXC_EL_SHIFT;
182
- flags |= zcr_len << ARM_TBFLAG_ZCR_LEN_SHIFT;
183
+ flags = FIELD_DP32(flags, TBFLAG_A64, SVEEXC_EL, sve_el);
184
+ flags = FIELD_DP32(flags, TBFLAG_A64, ZCR_LEN, zcr_len);
185
}
21
}
186
} else {
22
} else {
187
*pc = env->regs[15];
23
prohibited = arm_feature(env, ARM_FEATURE_EL3) &&
188
- flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT)
24
- (env->cp15.mdcr_el3 & MDCR_SPME);
189
- | (env->vfp.vec_len << ARM_TBFLAG_VECLEN_SHIFT)
25
+ !(env->cp15.mdcr_el3 & MDCR_SPME);
190
- | (env->vfp.vec_stride << ARM_TBFLAG_VECSTRIDE_SHIFT)
191
- | (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT)
192
- | (arm_sctlr_b(env) << ARM_TBFLAG_SCTLR_B_SHIFT);
193
- if (!(access_secure_reg(env))) {
194
- flags |= ARM_TBFLAG_NS_MASK;
195
- }
196
+ flags = FIELD_DP32(flags, TBFLAG_A32, THUMB, env->thumb);
197
+ flags = FIELD_DP32(flags, TBFLAG_A32, VECLEN, env->vfp.vec_len);
198
+ flags = FIELD_DP32(flags, TBFLAG_A32, VECSTRIDE, env->vfp.vec_stride);
199
+ flags = FIELD_DP32(flags, TBFLAG_A32, CONDEXEC, env->condexec_bits);
200
+ flags = FIELD_DP32(flags, TBFLAG_A32, SCTLR_B, arm_sctlr_b(env));
201
+ flags = FIELD_DP32(flags, TBFLAG_A32, NS, !access_secure_reg(env));
202
if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)
203
|| arm_el_is_aa64(env, 1)) {
204
- flags |= ARM_TBFLAG_VFPEN_MASK;
205
+ flags = FIELD_DP32(flags, TBFLAG_A32, VFPEN, 1);
206
}
207
- flags |= (extract32(env->cp15.c15_cpar, 0, 2)
208
- << ARM_TBFLAG_XSCALE_CPAR_SHIFT);
209
+ flags = FIELD_DP32(flags, TBFLAG_A32, XSCALE_CPAR, env->cp15.c15_cpar);
210
}
26
}
211
27
212
- flags |= (arm_to_core_mmu_idx(mmu_idx) << ARM_TBFLAG_MMUIDX_SHIFT);
28
if (prohibited && counter == 31) {
213
+ flags = FIELD_DP32(flags, TBFLAG_ANY, MMUIDX, arm_to_core_mmu_idx(mmu_idx));
214
215
/* The SS_ACTIVE and PSTATE_SS bits correspond to the state machine
216
* states defined in the ARM ARM for software singlestep:
217
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
218
* 1 1 Active-not-pending
219
*/
220
if (arm_singlestep_active(env)) {
221
- flags |= ARM_TBFLAG_SS_ACTIVE_MASK;
222
+ flags = FIELD_DP32(flags, TBFLAG_ANY, SS_ACTIVE, 1);
223
if (is_a64(env)) {
224
if (env->pstate & PSTATE_SS) {
225
- flags |= ARM_TBFLAG_PSTATE_SS_MASK;
226
+ flags = FIELD_DP32(flags, TBFLAG_ANY, PSTATE_SS, 1);
227
}
228
} else {
229
if (env->uncached_cpsr & PSTATE_SS) {
230
- flags |= ARM_TBFLAG_PSTATE_SS_MASK;
231
+ flags = FIELD_DP32(flags, TBFLAG_ANY, PSTATE_SS, 1);
232
}
233
}
234
}
235
if (arm_cpu_data_is_big_endian(env)) {
236
- flags |= ARM_TBFLAG_BE_DATA_MASK;
237
+ flags = FIELD_DP32(flags, TBFLAG_ANY, BE_DATA, 1);
238
}
239
- flags |= fp_el << ARM_TBFLAG_FPEXC_EL_SHIFT;
240
+ flags = FIELD_DP32(flags, TBFLAG_ANY, FPEXC_EL, fp_el);
241
242
if (arm_v7m_is_handler_mode(env)) {
243
- flags |= ARM_TBFLAG_HANDLER_MASK;
244
+ flags = FIELD_DP32(flags, TBFLAG_A32, HANDLER, 1);
245
}
246
247
/* v8M always applies stack limit checks unless CCR.STKOFHFNMIGN is
248
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
249
arm_feature(env, ARM_FEATURE_M) &&
250
!((mmu_idx & ARM_MMU_IDX_M_NEGPRI) &&
251
(env->v7m.ccr[env->v7m.secure] & R_V7M_CCR_STKOFHFNMIGN_MASK))) {
252
- flags |= ARM_TBFLAG_STACKCHECK_MASK;
253
+ flags = FIELD_DP32(flags, TBFLAG_A32, STACKCHECK, 1);
254
}
255
256
*pflags = flags;
257
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
258
index XXXXXXX..XXXXXXX 100644
259
--- a/target/arm/translate-a64.c
260
+++ b/target/arm/translate-a64.c
261
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
262
DisasContext *dc = container_of(dcbase, DisasContext, base);
263
CPUARMState *env = cpu->env_ptr;
264
ARMCPU *arm_cpu = arm_env_get_cpu(env);
265
- int bound;
266
+ uint32_t tb_flags = dc->base.tb->flags;
267
+ int bound, core_mmu_idx;
268
269
dc->isar = &arm_cpu->isar;
270
dc->pc = dc->base.pc_first;
271
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
272
!arm_el_is_aa64(env, 3);
273
dc->thumb = 0;
274
dc->sctlr_b = 0;
275
- dc->be_data = ARM_TBFLAG_BE_DATA(dc->base.tb->flags) ? MO_BE : MO_LE;
276
+ dc->be_data = FIELD_EX32(tb_flags, TBFLAG_ANY, BE_DATA) ? MO_BE : MO_LE;
277
dc->condexec_mask = 0;
278
dc->condexec_cond = 0;
279
- dc->mmu_idx = core_to_arm_mmu_idx(env, ARM_TBFLAG_MMUIDX(dc->base.tb->flags));
280
- dc->tbi0 = ARM_TBFLAG_TBI0(dc->base.tb->flags);
281
- dc->tbi1 = ARM_TBFLAG_TBI1(dc->base.tb->flags);
282
+ core_mmu_idx = FIELD_EX32(tb_flags, TBFLAG_ANY, MMUIDX);
283
+ dc->mmu_idx = core_to_arm_mmu_idx(env, core_mmu_idx);
284
+ dc->tbi0 = FIELD_EX32(tb_flags, TBFLAG_A64, TBI0);
285
+ dc->tbi1 = FIELD_EX32(tb_flags, TBFLAG_A64, TBI1);
286
dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx);
287
#if !defined(CONFIG_USER_ONLY)
288
dc->user = (dc->current_el == 0);
289
#endif
290
- dc->fp_excp_el = ARM_TBFLAG_FPEXC_EL(dc->base.tb->flags);
291
- dc->sve_excp_el = ARM_TBFLAG_SVEEXC_EL(dc->base.tb->flags);
292
- dc->sve_len = (ARM_TBFLAG_ZCR_LEN(dc->base.tb->flags) + 1) * 16;
293
+ dc->fp_excp_el = FIELD_EX32(tb_flags, TBFLAG_ANY, FPEXC_EL);
294
+ dc->sve_excp_el = FIELD_EX32(tb_flags, TBFLAG_A64, SVEEXC_EL);
295
+ dc->sve_len = (FIELD_EX32(tb_flags, TBFLAG_A64, ZCR_LEN) + 1) * 16;
296
dc->vec_len = 0;
297
dc->vec_stride = 0;
298
dc->cp_regs = arm_cpu->cp_regs;
299
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
300
* emit code to generate a software step exception
301
* end the TB
302
*/
303
- dc->ss_active = ARM_TBFLAG_SS_ACTIVE(dc->base.tb->flags);
304
- dc->pstate_ss = ARM_TBFLAG_PSTATE_SS(dc->base.tb->flags);
305
+ dc->ss_active = FIELD_EX32(tb_flags, TBFLAG_ANY, SS_ACTIVE);
306
+ dc->pstate_ss = FIELD_EX32(tb_flags, TBFLAG_ANY, PSTATE_SS);
307
dc->is_ldex = false;
308
dc->ss_same_el = (arm_debug_target_el(env) == dc->current_el);
309
310
diff --git a/target/arm/translate.c b/target/arm/translate.c
311
index XXXXXXX..XXXXXXX 100644
312
--- a/target/arm/translate.c
313
+++ b/target/arm/translate.c
314
@@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
315
DisasContext *dc = container_of(dcbase, DisasContext, base);
316
CPUARMState *env = cs->env_ptr;
317
ARMCPU *cpu = arm_env_get_cpu(env);
318
+ uint32_t tb_flags = dc->base.tb->flags;
319
+ uint32_t condexec, core_mmu_idx;
320
321
dc->isar = &cpu->isar;
322
dc->pc = dc->base.pc_first;
323
@@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
324
*/
325
dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
326
!arm_el_is_aa64(env, 3);
327
- dc->thumb = ARM_TBFLAG_THUMB(dc->base.tb->flags);
328
- dc->sctlr_b = ARM_TBFLAG_SCTLR_B(dc->base.tb->flags);
329
- dc->be_data = ARM_TBFLAG_BE_DATA(dc->base.tb->flags) ? MO_BE : MO_LE;
330
- dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(dc->base.tb->flags) & 0xf) << 1;
331
- dc->condexec_cond = ARM_TBFLAG_CONDEXEC(dc->base.tb->flags) >> 4;
332
- dc->mmu_idx = core_to_arm_mmu_idx(env, ARM_TBFLAG_MMUIDX(dc->base.tb->flags));
333
+ dc->thumb = FIELD_EX32(tb_flags, TBFLAG_A32, THUMB);
334
+ dc->sctlr_b = FIELD_EX32(tb_flags, TBFLAG_A32, SCTLR_B);
335
+ dc->be_data = FIELD_EX32(tb_flags, TBFLAG_ANY, BE_DATA) ? MO_BE : MO_LE;
336
+ condexec = FIELD_EX32(tb_flags, TBFLAG_A32, CONDEXEC);
337
+ dc->condexec_mask = (condexec & 0xf) << 1;
338
+ dc->condexec_cond = condexec >> 4;
339
+ core_mmu_idx = FIELD_EX32(tb_flags, TBFLAG_ANY, MMUIDX);
340
+ dc->mmu_idx = core_to_arm_mmu_idx(env, core_mmu_idx);
341
dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx);
342
#if !defined(CONFIG_USER_ONLY)
343
dc->user = (dc->current_el == 0);
344
#endif
345
- dc->ns = ARM_TBFLAG_NS(dc->base.tb->flags);
346
- dc->fp_excp_el = ARM_TBFLAG_FPEXC_EL(dc->base.tb->flags);
347
- dc->vfp_enabled = ARM_TBFLAG_VFPEN(dc->base.tb->flags);
348
- dc->vec_len = ARM_TBFLAG_VECLEN(dc->base.tb->flags);
349
- dc->vec_stride = ARM_TBFLAG_VECSTRIDE(dc->base.tb->flags);
350
- dc->c15_cpar = ARM_TBFLAG_XSCALE_CPAR(dc->base.tb->flags);
351
- dc->v7m_handler_mode = ARM_TBFLAG_HANDLER(dc->base.tb->flags);
352
+ dc->ns = FIELD_EX32(tb_flags, TBFLAG_A32, NS);
353
+ dc->fp_excp_el = FIELD_EX32(tb_flags, TBFLAG_ANY, FPEXC_EL);
354
+ dc->vfp_enabled = FIELD_EX32(tb_flags, TBFLAG_A32, VFPEN);
355
+ dc->vec_len = FIELD_EX32(tb_flags, TBFLAG_A32, VECLEN);
356
+ dc->vec_stride = FIELD_EX32(tb_flags, TBFLAG_A32, VECSTRIDE);
357
+ dc->c15_cpar = FIELD_EX32(tb_flags, TBFLAG_A32, XSCALE_CPAR);
358
+ dc->v7m_handler_mode = FIELD_EX32(tb_flags, TBFLAG_A32, HANDLER);
359
dc->v8m_secure = arm_feature(env, ARM_FEATURE_M_SECURITY) &&
360
regime_is_secure(env, dc->mmu_idx);
361
- dc->v8m_stackcheck = ARM_TBFLAG_STACKCHECK(dc->base.tb->flags);
362
+ dc->v8m_stackcheck = FIELD_EX32(tb_flags, TBFLAG_A32, STACKCHECK);
363
dc->cp_regs = cpu->cp_regs;
364
dc->features = env->features;
365
366
@@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
367
* emit code to generate a software step exception
368
* end the TB
369
*/
370
- dc->ss_active = ARM_TBFLAG_SS_ACTIVE(dc->base.tb->flags);
371
- dc->pstate_ss = ARM_TBFLAG_PSTATE_SS(dc->base.tb->flags);
372
+ dc->ss_active = FIELD_EX32(tb_flags, TBFLAG_ANY, SS_ACTIVE);
373
+ dc->pstate_ss = FIELD_EX32(tb_flags, TBFLAG_ANY, PSTATE_SS);
374
dc->is_ldex = false;
375
dc->ss_same_el = false; /* Can't be true since EL_d must be AArch64 */
376
377
@@ -XXX,XX +XXX,XX @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
378
DisasContext dc;
379
const TranslatorOps *ops = &arm_translator_ops;
380
381
- if (ARM_TBFLAG_THUMB(tb->flags)) {
382
+ if (FIELD_EX32(tb->flags, TBFLAG_A32, THUMB)) {
383
ops = &thumb_translator_ops;
384
}
385
#ifdef TARGET_AARCH64
386
- if (ARM_TBFLAG_AARCH64_STATE(tb->flags)) {
387
+ if (FIELD_EX32(tb->flags, TBFLAG_ANY, AARCH64_STATE)) {
388
ops = &aarch64_translator_ops;
389
}
390
#endif
391
--
29
--
392
2.19.2
30
2.20.1
393
31
394
32
diff view generated by jsdifflib
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
2
2
3
Plug a couple of "board creation time" memory leaks.
3
Correct the GEMs tx/rx clocks to use the 125Mhz fixed-clock.
4
This matches the setup with the fixed-link 100Mbit PHY.
5
It also avoids the following warnings from the Linux kernel
6
driver:
4
7
5
Fixes: 6f16da53ffe4567 ("hw/arm: versal: Add a virtual Xilinx Versal board")
8
eth0: unable to generate target frequency: 125000000 Hz
6
Reported-by: Peter Maydell <peter.maydell@linaro.org>
9
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
7
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
12
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
13
Message-id: 20200909174647.662864-2-edgar.iglesias@gmail.com
9
Message-id: 20190104104749.5314-2-edgar.iglesias@gmail.com
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
15
---
13
hw/arm/xlnx-versal-virt.c | 2 ++
16
hw/arm/xlnx-versal-virt.c | 2 +-
14
1 file changed, 2 insertions(+)
17
1 file changed, 1 insertion(+), 1 deletion(-)
15
18
16
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
19
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
17
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/xlnx-versal-virt.c
21
--- a/hw/arm/xlnx-versal-virt.c
19
+++ b/hw/arm/xlnx-versal-virt.c
22
+++ b/hw/arm/xlnx-versal-virt.c
20
@@ -XXX,XX +XXX,XX @@ static void fdt_add_gic_nodes(VersalVirt *s)
23
@@ -XXX,XX +XXX,XX @@ static void fdt_add_gem_nodes(VersalVirt *s)
21
2, MM_GIC_APU_REDIST_0_SIZE);
24
s->phandle.ethernet_phy[i]);
22
qemu_fdt_setprop_cell(s->fdt, nodename, "#interrupt-cells", 3);
25
qemu_fdt_setprop_cells(s->fdt, name, "clocks",
23
qemu_fdt_setprop_string(s->fdt, nodename, "compatible", "arm,gic-v3");
26
s->phandle.clk_25Mhz, s->phandle.clk_25Mhz,
24
+ g_free(nodename);
27
- s->phandle.clk_25Mhz, s->phandle.clk_25Mhz);
25
}
28
+ s->phandle.clk_125Mhz, s->phandle.clk_125Mhz);
26
29
qemu_fdt_setprop(s->fdt, name, "clock-names",
27
static void fdt_add_timer_nodes(VersalVirt *s)
30
clocknames, sizeof(clocknames));
28
@@ -XXX,XX +XXX,XX @@ static void create_virtio_regions(VersalVirt *s)
31
qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
29
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic_irq);
30
mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
31
memory_region_add_subregion(&s->soc.mr_ps, base, mr);
32
+ g_free(name);
33
}
34
35
for (i = 0; i < NUM_VIRTIO_TRANSPORT; i++) {
36
--
32
--
37
2.19.2
33
2.20.1
38
34
39
35
diff view generated by jsdifflib
1
From: Luc Michel <luc.michel@greensocs.com>
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
2
3
This commit adds the cpu-cluster type. It aims at gathering CPUs from
3
Implement a device model for the System Global Control Registers in the
4
the same cluster in a machine.
4
NPCM730 and NPCM750 BMC SoCs.
5
5
6
For now it only has a `cluster-id` property.
6
This is primarily used to enable SMP boot (the boot ROM spins reading
7
7
the SCRPAD register) and DDR memory initialization; other registers are
8
Documentation in cluster.h written with the help of Peter Maydell.
8
best effort for now.
9
9
10
Signed-off-by: Luc Michel <luc.michel@greensocs.com>
10
The reset values of the MDLR and PWRON registers are determined by the
11
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
11
SoC variant (730 vs 750) and board straps respectively.
12
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
12
13
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
13
Reviewed-by: Joel Stanley <joel@jms.id.au>
14
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
14
Reviewed-by: Cédric Le Goater <clg@kaod.org>
15
Message-id: 20181207090135.7651-2-luc.michel@greensocs.com
15
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
16
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Tested-by: Alexander Bulekov <alxndr@bu.edu>
18
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
19
Message-id: 20200911052101.2602693-2-hskinnemoen@google.com
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
21
---
18
hw/cpu/Makefile.objs | 2 +-
22
include/hw/misc/npcm7xx_gcr.h | 43 ++++++
19
include/hw/cpu/cluster.h | 58 ++++++++++++++++++++++++++++++++++++++++
23
hw/misc/npcm7xx_gcr.c | 269 ++++++++++++++++++++++++++++++++++
20
hw/cpu/cluster.c | 50 ++++++++++++++++++++++++++++++++++
24
MAINTAINERS | 8 +
21
MAINTAINERS | 2 ++
25
hw/arm/Kconfig | 3 +
22
4 files changed, 111 insertions(+), 1 deletion(-)
26
hw/misc/meson.build | 3 +
23
create mode 100644 include/hw/cpu/cluster.h
27
hw/misc/trace-events | 4 +
24
create mode 100644 hw/cpu/cluster.c
28
6 files changed, 330 insertions(+)
25
29
create mode 100644 include/hw/misc/npcm7xx_gcr.h
26
diff --git a/hw/cpu/Makefile.objs b/hw/cpu/Makefile.objs
30
create mode 100644 hw/misc/npcm7xx_gcr.c
27
index XXXXXXX..XXXXXXX 100644
31
28
--- a/hw/cpu/Makefile.objs
32
diff --git a/include/hw/misc/npcm7xx_gcr.h b/include/hw/misc/npcm7xx_gcr.h
29
+++ b/hw/cpu/Makefile.objs
30
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_ARM11MPCORE) += arm11mpcore.o
31
obj-$(CONFIG_REALVIEW) += realview_mpcore.o
32
obj-$(CONFIG_A9MPCORE) += a9mpcore.o
33
obj-$(CONFIG_A15MPCORE) += a15mpcore.o
34
-common-obj-y += core.o
35
+common-obj-y += core.o cluster.o
36
diff --git a/include/hw/cpu/cluster.h b/include/hw/cpu/cluster.h
37
new file mode 100644
33
new file mode 100644
38
index XXXXXXX..XXXXXXX
34
index XXXXXXX..XXXXXXX
39
--- /dev/null
35
--- /dev/null
40
+++ b/include/hw/cpu/cluster.h
36
+++ b/include/hw/misc/npcm7xx_gcr.h
41
@@ -XXX,XX +XXX,XX @@
37
@@ -XXX,XX +XXX,XX @@
42
+/*
38
+/*
43
+ * QEMU CPU cluster
39
+ * Nuvoton NPCM7xx System Global Control Registers.
44
+ *
40
+ *
45
+ * Copyright (c) 2018 GreenSocs SAS
41
+ * Copyright 2020 Google LLC
46
+ *
42
+ *
47
+ * This program is free software; you can redistribute it and/or
43
+ * This program is free software; you can redistribute it and/or modify it
48
+ * modify it under the terms of the GNU General Public License
44
+ * under the terms of the GNU General Public License as published by the
49
+ * as published by the Free Software Foundation; either version 2
45
+ * Free Software Foundation; either version 2 of the License, or
50
+ * of the License, or (at your option) any later version.
46
+ * (at your option) any later version.
51
+ *
47
+ *
52
+ * This program is distributed in the hope that it will be useful,
48
+ * This program is distributed in the hope that it will be useful, but WITHOUT
53
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
49
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
54
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
50
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
55
+ * GNU General Public License for more details.
51
+ * for more details.
56
+ *
57
+ * You should have received a copy of the GNU General Public License
58
+ * along with this program; if not, see
59
+ * <http://www.gnu.org/licenses/gpl-2.0.html>
60
+ */
52
+ */
61
+#ifndef HW_CPU_CLUSTER_H
53
+#ifndef NPCM7XX_GCR_H
62
+#define HW_CPU_CLUSTER_H
54
+#define NPCM7XX_GCR_H
63
+
55
+
64
+#include "qemu/osdep.h"
56
+#include "exec/memory.h"
65
+#include "hw/qdev.h"
57
+#include "hw/sysbus.h"
66
+
58
+
67
+/*
59
+/*
68
+ * CPU Cluster type
60
+ * Number of registers in our device state structure. Don't change this without
69
+ *
61
+ * incrementing the version_id in the vmstate.
70
+ * A cluster is a group of CPUs which are all identical and have the same view
71
+ * of the rest of the system. It is mainly an internal QEMU representation and
72
+ * does not necessarily match with the notion of clusters on the real hardware.
73
+ *
74
+ * If CPUs are not identical (for example, Cortex-A53 and Cortex-A57 CPUs in an
75
+ * Arm big.LITTLE system) they should be in different clusters. If the CPUs do
76
+ * not have the same view of memory (for example the main CPU and a management
77
+ * controller processor) they should be in different clusters.
78
+ */
62
+ */
79
+
63
+#define NPCM7XX_GCR_NR_REGS (0x148 / sizeof(uint32_t))
80
+#define TYPE_CPU_CLUSTER "cpu-cluster"
64
+
81
+#define CPU_CLUSTER(obj) \
65
+typedef struct NPCM7xxGCRState {
82
+ OBJECT_CHECK(CPUClusterState, (obj), TYPE_CPU_CLUSTER)
66
+ SysBusDevice parent;
83
+
67
+
84
+/**
68
+ MemoryRegion iomem;
85
+ * CPUClusterState:
69
+
86
+ * @cluster_id: The cluster ID. This value is for internal use only and should
70
+ uint32_t regs[NPCM7XX_GCR_NR_REGS];
87
+ * not be exposed directly to the user or to the guest.
71
+
88
+ *
72
+ uint32_t reset_pwron;
89
+ * State of a CPU cluster.
73
+ uint32_t reset_mdlr;
90
+ */
74
+ uint32_t reset_intcr3;
91
+typedef struct CPUClusterState {
75
+} NPCM7xxGCRState;
92
+ /*< private >*/
76
+
93
+ DeviceState parent_obj;
77
+#define TYPE_NPCM7XX_GCR "npcm7xx-gcr"
94
+
78
+#define NPCM7XX_GCR(obj) OBJECT_CHECK(NPCM7xxGCRState, (obj), TYPE_NPCM7XX_GCR)
95
+ /*< public >*/
79
+
96
+ uint32_t cluster_id;
80
+#endif /* NPCM7XX_GCR_H */
97
+} CPUClusterState;
81
diff --git a/hw/misc/npcm7xx_gcr.c b/hw/misc/npcm7xx_gcr.c
98
+
99
+#endif
100
diff --git a/hw/cpu/cluster.c b/hw/cpu/cluster.c
101
new file mode 100644
82
new file mode 100644
102
index XXXXXXX..XXXXXXX
83
index XXXXXXX..XXXXXXX
103
--- /dev/null
84
--- /dev/null
104
+++ b/hw/cpu/cluster.c
85
+++ b/hw/misc/npcm7xx_gcr.c
105
@@ -XXX,XX +XXX,XX @@
86
@@ -XXX,XX +XXX,XX @@
106
+/*
87
+/*
107
+ * QEMU CPU cluster
88
+ * Nuvoton NPCM7xx System Global Control Registers.
108
+ *
89
+ *
109
+ * Copyright (c) 2018 GreenSocs SAS
90
+ * Copyright 2020 Google LLC
110
+ *
91
+ *
111
+ * This program is free software; you can redistribute it and/or
92
+ * This program is free software; you can redistribute it and/or modify it
112
+ * modify it under the terms of the GNU General Public License
93
+ * under the terms of the GNU General Public License as published by the
113
+ * as published by the Free Software Foundation; either version 2
94
+ * Free Software Foundation; either version 2 of the License, or
114
+ * of the License, or (at your option) any later version.
95
+ * (at your option) any later version.
115
+ *
96
+ *
116
+ * This program is distributed in the hope that it will be useful,
97
+ * This program is distributed in the hope that it will be useful, but WITHOUT
117
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
98
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
118
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
99
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
119
+ * GNU General Public License for more details.
100
+ * for more details.
120
+ *
121
+ * You should have received a copy of the GNU General Public License
122
+ * along with this program; if not, see
123
+ * <http://www.gnu.org/licenses/gpl-2.0.html>
124
+ */
101
+ */
125
+
102
+
126
+#include "qemu/osdep.h"
103
+#include "qemu/osdep.h"
127
+#include "hw/cpu/cluster.h"
104
+
105
+#include "hw/misc/npcm7xx_gcr.h"
106
+#include "hw/qdev-properties.h"
107
+#include "migration/vmstate.h"
128
+#include "qapi/error.h"
108
+#include "qapi/error.h"
109
+#include "qemu/cutils.h"
110
+#include "qemu/log.h"
129
+#include "qemu/module.h"
111
+#include "qemu/module.h"
130
+
112
+#include "qemu/units.h"
131
+static Property cpu_cluster_properties[] = {
113
+
132
+ DEFINE_PROP_UINT32("cluster-id", CPUClusterState, cluster_id, 0),
114
+#include "trace.h"
133
+ DEFINE_PROP_END_OF_LIST()
115
+
134
+};
116
+#define NPCM7XX_GCR_MIN_DRAM_SIZE (128 * MiB)
135
+
117
+#define NPCM7XX_GCR_MAX_DRAM_SIZE (2 * GiB)
136
+static void cpu_cluster_class_init(ObjectClass *klass, void *data)
118
+
137
+{
119
+enum NPCM7xxGCRRegisters {
120
+ NPCM7XX_GCR_PDID,
121
+ NPCM7XX_GCR_PWRON,
122
+ NPCM7XX_GCR_MFSEL1 = 0x0c / sizeof(uint32_t),
123
+ NPCM7XX_GCR_MFSEL2,
124
+ NPCM7XX_GCR_MISCPE,
125
+ NPCM7XX_GCR_SPSWC = 0x038 / sizeof(uint32_t),
126
+ NPCM7XX_GCR_INTCR,
127
+ NPCM7XX_GCR_INTSR,
128
+ NPCM7XX_GCR_HIFCR = 0x050 / sizeof(uint32_t),
129
+ NPCM7XX_GCR_INTCR2 = 0x060 / sizeof(uint32_t),
130
+ NPCM7XX_GCR_MFSEL3,
131
+ NPCM7XX_GCR_SRCNT,
132
+ NPCM7XX_GCR_RESSR,
133
+ NPCM7XX_GCR_RLOCKR1,
134
+ NPCM7XX_GCR_FLOCKR1,
135
+ NPCM7XX_GCR_DSCNT,
136
+ NPCM7XX_GCR_MDLR,
137
+ NPCM7XX_GCR_SCRPAD3,
138
+ NPCM7XX_GCR_SCRPAD2,
139
+ NPCM7XX_GCR_DAVCLVLR = 0x098 / sizeof(uint32_t),
140
+ NPCM7XX_GCR_INTCR3,
141
+ NPCM7XX_GCR_VSINTR = 0x0ac / sizeof(uint32_t),
142
+ NPCM7XX_GCR_MFSEL4,
143
+ NPCM7XX_GCR_CPBPNTR = 0x0c4 / sizeof(uint32_t),
144
+ NPCM7XX_GCR_CPCTL = 0x0d0 / sizeof(uint32_t),
145
+ NPCM7XX_GCR_CP2BST,
146
+ NPCM7XX_GCR_B2CPNT,
147
+ NPCM7XX_GCR_CPPCTL,
148
+ NPCM7XX_GCR_I2CSEGSEL,
149
+ NPCM7XX_GCR_I2CSEGCTL,
150
+ NPCM7XX_GCR_VSRCR,
151
+ NPCM7XX_GCR_MLOCKR,
152
+ NPCM7XX_GCR_SCRPAD = 0x013c / sizeof(uint32_t),
153
+ NPCM7XX_GCR_USB1PHYCTL,
154
+ NPCM7XX_GCR_USB2PHYCTL,
155
+ NPCM7XX_GCR_REGS_END,
156
+};
157
+
158
+static const uint32_t cold_reset_values[NPCM7XX_GCR_NR_REGS] = {
159
+ [NPCM7XX_GCR_PDID] = 0x04a92750, /* Poleg A1 */
160
+ [NPCM7XX_GCR_MISCPE] = 0x0000ffff,
161
+ [NPCM7XX_GCR_SPSWC] = 0x00000003,
162
+ [NPCM7XX_GCR_INTCR] = 0x0000035e,
163
+ [NPCM7XX_GCR_HIFCR] = 0x0000004e,
164
+ [NPCM7XX_GCR_INTCR2] = (1U << 19), /* DDR initialized */
165
+ [NPCM7XX_GCR_RESSR] = 0x80000000,
166
+ [NPCM7XX_GCR_DSCNT] = 0x000000c0,
167
+ [NPCM7XX_GCR_DAVCLVLR] = 0x5a00f3cf,
168
+ [NPCM7XX_GCR_SCRPAD] = 0x00000008,
169
+ [NPCM7XX_GCR_USB1PHYCTL] = 0x034730e4,
170
+ [NPCM7XX_GCR_USB2PHYCTL] = 0x034730e4,
171
+};
172
+
173
+static uint64_t npcm7xx_gcr_read(void *opaque, hwaddr offset, unsigned size)
174
+{
175
+ uint32_t reg = offset / sizeof(uint32_t);
176
+ NPCM7xxGCRState *s = opaque;
177
+
178
+ if (reg >= NPCM7XX_GCR_NR_REGS) {
179
+ qemu_log_mask(LOG_GUEST_ERROR,
180
+ "%s: offset 0x%04" HWADDR_PRIx " out of range\n",
181
+ __func__, offset);
182
+ return 0;
183
+ }
184
+
185
+ trace_npcm7xx_gcr_read(offset, s->regs[reg]);
186
+
187
+ return s->regs[reg];
188
+}
189
+
190
+static void npcm7xx_gcr_write(void *opaque, hwaddr offset,
191
+ uint64_t v, unsigned size)
192
+{
193
+ uint32_t reg = offset / sizeof(uint32_t);
194
+ NPCM7xxGCRState *s = opaque;
195
+ uint32_t value = v;
196
+
197
+ trace_npcm7xx_gcr_write(offset, value);
198
+
199
+ if (reg >= NPCM7XX_GCR_NR_REGS) {
200
+ qemu_log_mask(LOG_GUEST_ERROR,
201
+ "%s: offset 0x%04" HWADDR_PRIx " out of range\n",
202
+ __func__, offset);
203
+ return;
204
+ }
205
+
206
+ switch (reg) {
207
+ case NPCM7XX_GCR_PDID:
208
+ case NPCM7XX_GCR_PWRON:
209
+ case NPCM7XX_GCR_INTSR:
210
+ qemu_log_mask(LOG_GUEST_ERROR,
211
+ "%s: register @ 0x%04" HWADDR_PRIx " is read-only\n",
212
+ __func__, offset);
213
+ return;
214
+
215
+ case NPCM7XX_GCR_RESSR:
216
+ case NPCM7XX_GCR_CP2BST:
217
+ /* Write 1 to clear */
218
+ value = s->regs[reg] & ~value;
219
+ break;
220
+
221
+ case NPCM7XX_GCR_RLOCKR1:
222
+ case NPCM7XX_GCR_MDLR:
223
+ /* Write 1 to set */
224
+ value |= s->regs[reg];
225
+ break;
226
+ };
227
+
228
+ s->regs[reg] = value;
229
+}
230
+
231
+static const struct MemoryRegionOps npcm7xx_gcr_ops = {
232
+ .read = npcm7xx_gcr_read,
233
+ .write = npcm7xx_gcr_write,
234
+ .endianness = DEVICE_LITTLE_ENDIAN,
235
+ .valid = {
236
+ .min_access_size = 4,
237
+ .max_access_size = 4,
238
+ .unaligned = false,
239
+ },
240
+};
241
+
242
+static void npcm7xx_gcr_enter_reset(Object *obj, ResetType type)
243
+{
244
+ NPCM7xxGCRState *s = NPCM7XX_GCR(obj);
245
+
246
+ QEMU_BUILD_BUG_ON(sizeof(s->regs) != sizeof(cold_reset_values));
247
+
248
+ switch (type) {
249
+ case RESET_TYPE_COLD:
250
+ memcpy(s->regs, cold_reset_values, sizeof(s->regs));
251
+ s->regs[NPCM7XX_GCR_PWRON] = s->reset_pwron;
252
+ s->regs[NPCM7XX_GCR_MDLR] = s->reset_mdlr;
253
+ s->regs[NPCM7XX_GCR_INTCR3] = s->reset_intcr3;
254
+ break;
255
+ }
256
+}
257
+
258
+static void npcm7xx_gcr_realize(DeviceState *dev, Error **errp)
259
+{
260
+ ERRP_GUARD();
261
+ NPCM7xxGCRState *s = NPCM7XX_GCR(dev);
262
+ uint64_t dram_size;
263
+ Object *obj;
264
+
265
+ obj = object_property_get_link(OBJECT(dev), "dram-mr", errp);
266
+ if (!obj) {
267
+ error_prepend(errp, "%s: required dram-mr link not found: ", __func__);
268
+ return;
269
+ }
270
+ dram_size = memory_region_size(MEMORY_REGION(obj));
271
+ if (!is_power_of_2(dram_size) ||
272
+ dram_size < NPCM7XX_GCR_MIN_DRAM_SIZE ||
273
+ dram_size > NPCM7XX_GCR_MAX_DRAM_SIZE) {
274
+ g_autofree char *sz = size_to_str(dram_size);
275
+ g_autofree char *min_sz = size_to_str(NPCM7XX_GCR_MIN_DRAM_SIZE);
276
+ g_autofree char *max_sz = size_to_str(NPCM7XX_GCR_MAX_DRAM_SIZE);
277
+ error_setg(errp, "%s: unsupported DRAM size %s", __func__, sz);
278
+ error_append_hint(errp,
279
+ "DRAM size must be a power of two between %s and %s,"
280
+ " inclusive.\n", min_sz, max_sz);
281
+ return;
282
+ }
283
+
284
+ /* Power-on reset value */
285
+ s->reset_intcr3 = 0x00001002;
286
+
287
+ /*
288
+ * The GMMAP (Graphics Memory Map) field is used by u-boot to detect the
289
+ * DRAM size, and is normally initialized by the boot block as part of DRAM
290
+ * training. However, since we don't have a complete emulation of the
291
+ * memory controller and try to make it look like it has already been
292
+ * initialized, the boot block will skip this initialization, and we need
293
+ * to make sure this field is set correctly up front.
294
+ *
295
+ * WARNING: some versions of u-boot only looks at bits 8 and 9, so 2 GiB of
296
+ * DRAM will be interpreted as 128 MiB.
297
+ *
298
+ * https://github.com/Nuvoton-Israel/u-boot/blob/2aef993bd2aafeb5408dbaad0f3ce099ee40c4aa/board/nuvoton/poleg/poleg.c#L244
299
+ */
300
+ s->reset_intcr3 |= ctz64(dram_size / NPCM7XX_GCR_MIN_DRAM_SIZE) << 8;
301
+}
302
+
303
+static void npcm7xx_gcr_init(Object *obj)
304
+{
305
+ NPCM7xxGCRState *s = NPCM7XX_GCR(obj);
306
+
307
+ memory_region_init_io(&s->iomem, obj, &npcm7xx_gcr_ops, s,
308
+ TYPE_NPCM7XX_GCR, 4 * KiB);
309
+ sysbus_init_mmio(&s->parent, &s->iomem);
310
+}
311
+
312
+static const VMStateDescription vmstate_npcm7xx_gcr = {
313
+ .name = "npcm7xx-gcr",
314
+ .version_id = 0,
315
+ .minimum_version_id = 0,
316
+ .fields = (VMStateField[]) {
317
+ VMSTATE_UINT32_ARRAY(regs, NPCM7xxGCRState, NPCM7XX_GCR_NR_REGS),
318
+ VMSTATE_END_OF_LIST(),
319
+ },
320
+};
321
+
322
+static Property npcm7xx_gcr_properties[] = {
323
+ DEFINE_PROP_UINT32("disabled-modules", NPCM7xxGCRState, reset_mdlr, 0),
324
+ DEFINE_PROP_UINT32("power-on-straps", NPCM7xxGCRState, reset_pwron, 0),
325
+ DEFINE_PROP_END_OF_LIST(),
326
+};
327
+
328
+static void npcm7xx_gcr_class_init(ObjectClass *klass, void *data)
329
+{
330
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
138
+ DeviceClass *dc = DEVICE_CLASS(klass);
331
+ DeviceClass *dc = DEVICE_CLASS(klass);
139
+
332
+
140
+ dc->props = cpu_cluster_properties;
333
+ QEMU_BUILD_BUG_ON(NPCM7XX_GCR_REGS_END > NPCM7XX_GCR_NR_REGS);
141
+}
334
+
142
+
335
+ dc->desc = "NPCM7xx System Global Control Registers";
143
+static const TypeInfo cpu_cluster_type_info = {
336
+ dc->realize = npcm7xx_gcr_realize;
144
+ .name = TYPE_CPU_CLUSTER,
337
+ dc->vmsd = &vmstate_npcm7xx_gcr;
145
+ .parent = TYPE_DEVICE,
338
+ rc->phases.enter = npcm7xx_gcr_enter_reset;
146
+ .instance_size = sizeof(CPUClusterState),
339
+
147
+ .class_init = cpu_cluster_class_init,
340
+ device_class_set_props(dc, npcm7xx_gcr_properties);
148
+};
341
+}
149
+
342
+
150
+static void cpu_cluster_register_types(void)
343
+static const TypeInfo npcm7xx_gcr_info = {
151
+{
344
+ .name = TYPE_NPCM7XX_GCR,
152
+ type_register_static(&cpu_cluster_type_info);
345
+ .parent = TYPE_SYS_BUS_DEVICE,
153
+}
346
+ .instance_size = sizeof(NPCM7xxGCRState),
154
+
347
+ .instance_init = npcm7xx_gcr_init,
155
+type_init(cpu_cluster_register_types)
348
+ .class_init = npcm7xx_gcr_class_init,
349
+};
350
+
351
+static void npcm7xx_gcr_register_type(void)
352
+{
353
+ type_register_static(&npcm7xx_gcr_info);
354
+}
355
+type_init(npcm7xx_gcr_register_type);
156
diff --git a/MAINTAINERS b/MAINTAINERS
356
diff --git a/MAINTAINERS b/MAINTAINERS
157
index XXXXXXX..XXXXXXX 100644
357
index XXXXXXX..XXXXXXX 100644
158
--- a/MAINTAINERS
358
--- a/MAINTAINERS
159
+++ b/MAINTAINERS
359
+++ b/MAINTAINERS
160
@@ -XXX,XX +XXX,XX @@ M: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
360
@@ -XXX,XX +XXX,XX @@ S: Odd Fixes
161
S: Supported
361
F: hw/arm/musicpal.c
162
F: hw/core/machine.c
362
F: docs/system/arm/musicpal.rst
163
F: hw/core/null-machine.c
363
164
+F: hw/cpu/cluster.c
364
+Nuvoton NPCM7xx
165
F: include/hw/boards.h
365
+M: Havard Skinnemoen <hskinnemoen@google.com>
166
+F: include/hw/cpu/cluster.h
366
+M: Tyrone Ting <kfting@nuvoton.com>
167
T: git https://github.com/ehabkost/qemu.git machine-next
367
+L: qemu-arm@nongnu.org
168
368
+S: Supported
169
Xtensa Machines
369
+F: hw/*/npcm7xx*
370
+F: include/hw/*/npcm7xx*
371
+
372
nSeries
373
M: Andrzej Zaborowski <balrogg@gmail.com>
374
M: Peter Maydell <peter.maydell@linaro.org>
375
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
376
index XXXXXXX..XXXXXXX 100644
377
--- a/hw/arm/Kconfig
378
+++ b/hw/arm/Kconfig
379
@@ -XXX,XX +XXX,XX @@ config XLNX_VERSAL
380
select VIRTIO_MMIO
381
select UNIMP
382
383
+config NPCM7XX
384
+ bool
385
+
386
config FSL_IMX25
387
bool
388
select IMX
389
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
390
index XXXXXXX..XXXXXXX 100644
391
--- a/hw/misc/meson.build
392
+++ b/hw/misc/meson.build
393
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_IMX', if_true: files(
394
))
395
softmmu_ss.add(when: 'CONFIG_MILKYMIST', if_true: files('milkymist-hpdmc.c', 'milkymist-pfpu.c'))
396
softmmu_ss.add(when: 'CONFIG_MAINSTONE', if_true: files('mst_fpga.c'))
397
+softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files(
398
+ 'npcm7xx_gcr.c',
399
+))
400
softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files(
401
'omap_clk.c',
402
'omap_gpmc.c',
403
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
404
index XXXXXXX..XXXXXXX 100644
405
--- a/hw/misc/trace-events
406
+++ b/hw/misc/trace-events
407
@@ -XXX,XX +XXX,XX @@ mos6522_set_sr_int(void) "set sr_int"
408
mos6522_write(uint64_t addr, uint64_t val) "reg=0x%"PRIx64 " val=0x%"PRIx64
409
mos6522_read(uint64_t addr, unsigned val) "reg=0x%"PRIx64 " val=0x%x"
410
411
+# npcm7xx_gcr.c
412
+npcm7xx_gcr_read(uint64_t offset, uint32_t value) " offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
413
+npcm7xx_gcr_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
414
+
415
# stm32f4xx_syscfg.c
416
stm32f4xx_syscfg_set_irq(int gpio, int line, int level) "Interupt: GPIO: %d, Line: %d; Level: %d"
417
stm32f4xx_pulse_exti(int irq) "Pulse EXTI: %d"
170
--
418
--
171
2.19.2
419
2.20.1
172
420
173
421
diff view generated by jsdifflib
1
From: Luc Michel <luc.michel@greensocs.com>
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
2
3
When gdb_set_stop_cpu() is called with a CPU associated to a process
3
Enough functionality to boot the Linux kernel has been implemented. This
4
currently not attached by the GDB client, return without modifying the
4
includes:
5
stop CPU. Otherwise, GDB gets confused if it receives packets with a
5
6
thread-id it does not know about.
6
- Correct power-on reset values so the various clock rates can be
7
7
accurately calculated.
8
Signed-off-by: Luc Michel <luc.michel@greensocs.com>
8
- Clock enables stick around when written.
9
Acked-by: Alistair Francis <alistair.francis@wdc.com>
9
10
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
10
In addition, a best effort attempt to implement SECCNT and CNTR25M was
11
Message-id: 20181207090135.7651-15-luc.michel@greensocs.com
11
made even though I don't think the kernel needs them.
12
[PMM: fix checkpatch comment style nit]
12
13
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
14
Reviewed-by: Joel Stanley <joel@jms.id.au>
15
Reviewed-by: Cédric Le Goater <clg@kaod.org>
16
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
18
Tested-by: Alexander Bulekov <alxndr@bu.edu>
19
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
20
Message-id: 20200911052101.2602693-3-hskinnemoen@google.com
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
22
---
15
gdbstub.c | 10 ++++++++++
23
include/hw/misc/npcm7xx_clk.h | 48 ++++++
16
1 file changed, 10 insertions(+)
24
hw/misc/npcm7xx_clk.c | 266 ++++++++++++++++++++++++++++++++++
17
25
hw/misc/meson.build | 1 +
18
diff --git a/gdbstub.c b/gdbstub.c
26
hw/misc/trace-events | 4 +
19
index XXXXXXX..XXXXXXX 100644
27
4 files changed, 319 insertions(+)
20
--- a/gdbstub.c
28
create mode 100644 include/hw/misc/npcm7xx_clk.h
21
+++ b/gdbstub.c
29
create mode 100644 hw/misc/npcm7xx_clk.c
22
@@ -XXX,XX +XXX,XX @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
30
23
31
diff --git a/include/hw/misc/npcm7xx_clk.h b/include/hw/misc/npcm7xx_clk.h
24
void gdb_set_stop_cpu(CPUState *cpu)
32
new file mode 100644
25
{
33
index XXXXXXX..XXXXXXX
26
+ GDBProcess *p = gdb_get_cpu_process(gdbserver_state, cpu);
34
--- /dev/null
27
+
35
+++ b/include/hw/misc/npcm7xx_clk.h
28
+ if (!p->attached) {
36
@@ -XXX,XX +XXX,XX @@
37
+/*
38
+ * Nuvoton NPCM7xx Clock Control Registers.
39
+ *
40
+ * Copyright 2020 Google LLC
41
+ *
42
+ * This program is free software; you can redistribute it and/or modify it
43
+ * under the terms of the GNU General Public License as published by the
44
+ * Free Software Foundation; either version 2 of the License, or
45
+ * (at your option) any later version.
46
+ *
47
+ * This program is distributed in the hope that it will be useful, but WITHOUT
48
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
49
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
50
+ * for more details.
51
+ */
52
+#ifndef NPCM7XX_CLK_H
53
+#define NPCM7XX_CLK_H
54
+
55
+#include "exec/memory.h"
56
+#include "hw/sysbus.h"
57
+
58
+/*
59
+ * The reference clock frequency for the timer modules, and the SECCNT and
60
+ * CNTR25M registers in this module, is always 25 MHz.
61
+ */
62
+#define NPCM7XX_TIMER_REF_HZ (25000000)
63
+
64
+/*
65
+ * Number of registers in our device state structure. Don't change this without
66
+ * incrementing the version_id in the vmstate.
67
+ */
68
+#define NPCM7XX_CLK_NR_REGS (0x70 / sizeof(uint32_t))
69
+
70
+typedef struct NPCM7xxCLKState {
71
+ SysBusDevice parent;
72
+
73
+ MemoryRegion iomem;
74
+
75
+ uint32_t regs[NPCM7XX_CLK_NR_REGS];
76
+
77
+ /* Time reference for SECCNT and CNTR25M, initialized by power on reset */
78
+ int64_t ref_ns;
79
+} NPCM7xxCLKState;
80
+
81
+#define TYPE_NPCM7XX_CLK "npcm7xx-clk"
82
+#define NPCM7XX_CLK(obj) OBJECT_CHECK(NPCM7xxCLKState, (obj), TYPE_NPCM7XX_CLK)
83
+
84
+#endif /* NPCM7XX_CLK_H */
85
diff --git a/hw/misc/npcm7xx_clk.c b/hw/misc/npcm7xx_clk.c
86
new file mode 100644
87
index XXXXXXX..XXXXXXX
88
--- /dev/null
89
+++ b/hw/misc/npcm7xx_clk.c
90
@@ -XXX,XX +XXX,XX @@
91
+/*
92
+ * Nuvoton NPCM7xx Clock Control Registers.
93
+ *
94
+ * Copyright 2020 Google LLC
95
+ *
96
+ * This program is free software; you can redistribute it and/or modify it
97
+ * under the terms of the GNU General Public License as published by the
98
+ * Free Software Foundation; either version 2 of the License, or
99
+ * (at your option) any later version.
100
+ *
101
+ * This program is distributed in the hope that it will be useful, but WITHOUT
102
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
103
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
104
+ * for more details.
105
+ */
106
+
107
+#include "qemu/osdep.h"
108
+
109
+#include "hw/misc/npcm7xx_clk.h"
110
+#include "migration/vmstate.h"
111
+#include "qemu/error-report.h"
112
+#include "qemu/log.h"
113
+#include "qemu/module.h"
114
+#include "qemu/timer.h"
115
+#include "qemu/units.h"
116
+#include "trace.h"
117
+
118
+#define PLLCON_LOKI BIT(31)
119
+#define PLLCON_LOKS BIT(30)
120
+#define PLLCON_PWDEN BIT(12)
121
+
122
+enum NPCM7xxCLKRegisters {
123
+ NPCM7XX_CLK_CLKEN1,
124
+ NPCM7XX_CLK_CLKSEL,
125
+ NPCM7XX_CLK_CLKDIV1,
126
+ NPCM7XX_CLK_PLLCON0,
127
+ NPCM7XX_CLK_PLLCON1,
128
+ NPCM7XX_CLK_SWRSTR,
129
+ NPCM7XX_CLK_IPSRST1 = 0x20 / sizeof(uint32_t),
130
+ NPCM7XX_CLK_IPSRST2,
131
+ NPCM7XX_CLK_CLKEN2,
132
+ NPCM7XX_CLK_CLKDIV2,
133
+ NPCM7XX_CLK_CLKEN3,
134
+ NPCM7XX_CLK_IPSRST3,
135
+ NPCM7XX_CLK_WD0RCR,
136
+ NPCM7XX_CLK_WD1RCR,
137
+ NPCM7XX_CLK_WD2RCR,
138
+ NPCM7XX_CLK_SWRSTC1,
139
+ NPCM7XX_CLK_SWRSTC2,
140
+ NPCM7XX_CLK_SWRSTC3,
141
+ NPCM7XX_CLK_SWRSTC4,
142
+ NPCM7XX_CLK_PLLCON2,
143
+ NPCM7XX_CLK_CLKDIV3,
144
+ NPCM7XX_CLK_CORSTC,
145
+ NPCM7XX_CLK_PLLCONG,
146
+ NPCM7XX_CLK_AHBCKFI,
147
+ NPCM7XX_CLK_SECCNT,
148
+ NPCM7XX_CLK_CNTR25M,
149
+ NPCM7XX_CLK_REGS_END,
150
+};
151
+
152
+/*
153
+ * These reset values were taken from version 0.91 of the NPCM750R data sheet.
154
+ *
155
+ * All are loaded on power-up reset. CLKENx and SWRSTR should also be loaded on
156
+ * core domain reset, but this reset type is not yet supported by QEMU.
157
+ */
158
+static const uint32_t cold_reset_values[NPCM7XX_CLK_NR_REGS] = {
159
+ [NPCM7XX_CLK_CLKEN1] = 0xffffffff,
160
+ [NPCM7XX_CLK_CLKSEL] = 0x004aaaaa,
161
+ [NPCM7XX_CLK_CLKDIV1] = 0x5413f855,
162
+ [NPCM7XX_CLK_PLLCON0] = 0x00222101 | PLLCON_LOKI,
163
+ [NPCM7XX_CLK_PLLCON1] = 0x00202101 | PLLCON_LOKI,
164
+ [NPCM7XX_CLK_IPSRST1] = 0x00001000,
165
+ [NPCM7XX_CLK_IPSRST2] = 0x80000000,
166
+ [NPCM7XX_CLK_CLKEN2] = 0xffffffff,
167
+ [NPCM7XX_CLK_CLKDIV2] = 0xaa4f8f9f,
168
+ [NPCM7XX_CLK_CLKEN3] = 0xffffffff,
169
+ [NPCM7XX_CLK_IPSRST3] = 0x03000000,
170
+ [NPCM7XX_CLK_WD0RCR] = 0xffffffff,
171
+ [NPCM7XX_CLK_WD1RCR] = 0xffffffff,
172
+ [NPCM7XX_CLK_WD2RCR] = 0xffffffff,
173
+ [NPCM7XX_CLK_SWRSTC1] = 0x00000003,
174
+ [NPCM7XX_CLK_PLLCON2] = 0x00c02105 | PLLCON_LOKI,
175
+ [NPCM7XX_CLK_CORSTC] = 0x04000003,
176
+ [NPCM7XX_CLK_PLLCONG] = 0x01228606 | PLLCON_LOKI,
177
+ [NPCM7XX_CLK_AHBCKFI] = 0x000000c8,
178
+};
179
+
180
+static uint64_t npcm7xx_clk_read(void *opaque, hwaddr offset, unsigned size)
181
+{
182
+ uint32_t reg = offset / sizeof(uint32_t);
183
+ NPCM7xxCLKState *s = opaque;
184
+ int64_t now_ns;
185
+ uint32_t value = 0;
186
+
187
+ if (reg >= NPCM7XX_CLK_NR_REGS) {
188
+ qemu_log_mask(LOG_GUEST_ERROR,
189
+ "%s: offset 0x%04" HWADDR_PRIx " out of range\n",
190
+ __func__, offset);
191
+ return 0;
192
+ }
193
+
194
+ switch (reg) {
195
+ case NPCM7XX_CLK_SWRSTR:
196
+ qemu_log_mask(LOG_GUEST_ERROR,
197
+ "%s: register @ 0x%04" HWADDR_PRIx " is write-only\n",
198
+ __func__, offset);
199
+ break;
200
+
201
+ case NPCM7XX_CLK_SECCNT:
202
+ now_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
203
+ value = (now_ns - s->ref_ns) / NANOSECONDS_PER_SECOND;
204
+ break;
205
+
206
+ case NPCM7XX_CLK_CNTR25M:
207
+ now_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
29
+ /*
208
+ /*
30
+ * Having a stop CPU corresponding to a process that is not attached
209
+ * This register counts 25 MHz cycles, updating every 640 ns. It rolls
31
+ * confuses GDB. So we ignore the request.
210
+ * over to zero every second.
211
+ *
212
+ * The 4 LSBs are always zero: (1e9 / 640) << 4 = 25000000.
32
+ */
213
+ */
214
+ value = (((now_ns - s->ref_ns) / 640) << 4) % NPCM7XX_TIMER_REF_HZ;
215
+ break;
216
+
217
+ default:
218
+ value = s->regs[reg];
219
+ break;
220
+ };
221
+
222
+ trace_npcm7xx_clk_read(offset, value);
223
+
224
+ return value;
225
+}
226
+
227
+static void npcm7xx_clk_write(void *opaque, hwaddr offset,
228
+ uint64_t v, unsigned size)
229
+{
230
+ uint32_t reg = offset / sizeof(uint32_t);
231
+ NPCM7xxCLKState *s = opaque;
232
+ uint32_t value = v;
233
+
234
+ trace_npcm7xx_clk_write(offset, value);
235
+
236
+ if (reg >= NPCM7XX_CLK_NR_REGS) {
237
+ qemu_log_mask(LOG_GUEST_ERROR,
238
+ "%s: offset 0x%04" HWADDR_PRIx " out of range\n",
239
+ __func__, offset);
33
+ return;
240
+ return;
34
+ }
241
+ }
35
+
242
+
36
gdbserver_state->c_cpu = cpu;
243
+ switch (reg) {
37
gdbserver_state->g_cpu = cpu;
244
+ case NPCM7XX_CLK_SWRSTR:
38
}
245
+ qemu_log_mask(LOG_UNIMP, "%s: SW reset not implemented: 0x%02x\n",
246
+ __func__, value);
247
+ value = 0;
248
+ break;
249
+
250
+ case NPCM7XX_CLK_PLLCON0:
251
+ case NPCM7XX_CLK_PLLCON1:
252
+ case NPCM7XX_CLK_PLLCON2:
253
+ case NPCM7XX_CLK_PLLCONG:
254
+ if (value & PLLCON_PWDEN) {
255
+ /* Power down -- clear lock and indicate loss of lock */
256
+ value &= ~PLLCON_LOKI;
257
+ value |= PLLCON_LOKS;
258
+ } else {
259
+ /* Normal mode -- assume always locked */
260
+ value |= PLLCON_LOKI;
261
+ /* Keep LOKS unchanged unless cleared by writing 1 */
262
+ if (value & PLLCON_LOKS) {
263
+ value &= ~PLLCON_LOKS;
264
+ } else {
265
+ value |= (value & PLLCON_LOKS);
266
+ }
267
+ }
268
+ break;
269
+
270
+ case NPCM7XX_CLK_CNTR25M:
271
+ qemu_log_mask(LOG_GUEST_ERROR,
272
+ "%s: register @ 0x%04" HWADDR_PRIx " is read-only\n",
273
+ __func__, offset);
274
+ return;
275
+ }
276
+
277
+ s->regs[reg] = value;
278
+}
279
+
280
+static const struct MemoryRegionOps npcm7xx_clk_ops = {
281
+ .read = npcm7xx_clk_read,
282
+ .write = npcm7xx_clk_write,
283
+ .endianness = DEVICE_LITTLE_ENDIAN,
284
+ .valid = {
285
+ .min_access_size = 4,
286
+ .max_access_size = 4,
287
+ .unaligned = false,
288
+ },
289
+};
290
+
291
+static void npcm7xx_clk_enter_reset(Object *obj, ResetType type)
292
+{
293
+ NPCM7xxCLKState *s = NPCM7XX_CLK(obj);
294
+
295
+ QEMU_BUILD_BUG_ON(sizeof(s->regs) != sizeof(cold_reset_values));
296
+
297
+ switch (type) {
298
+ case RESET_TYPE_COLD:
299
+ memcpy(s->regs, cold_reset_values, sizeof(cold_reset_values));
300
+ s->ref_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
301
+ return;
302
+ }
303
+
304
+ /*
305
+ * A small number of registers need to be reset on a core domain reset,
306
+ * but no such reset type exists yet.
307
+ */
308
+ qemu_log_mask(LOG_UNIMP, "%s: reset type %d not implemented.",
309
+ __func__, type);
310
+}
311
+
312
+static void npcm7xx_clk_init(Object *obj)
313
+{
314
+ NPCM7xxCLKState *s = NPCM7XX_CLK(obj);
315
+
316
+ memory_region_init_io(&s->iomem, obj, &npcm7xx_clk_ops, s,
317
+ TYPE_NPCM7XX_CLK, 4 * KiB);
318
+ sysbus_init_mmio(&s->parent, &s->iomem);
319
+}
320
+
321
+static const VMStateDescription vmstate_npcm7xx_clk = {
322
+ .name = "npcm7xx-clk",
323
+ .version_id = 0,
324
+ .minimum_version_id = 0,
325
+ .fields = (VMStateField[]) {
326
+ VMSTATE_UINT32_ARRAY(regs, NPCM7xxCLKState, NPCM7XX_CLK_NR_REGS),
327
+ VMSTATE_INT64(ref_ns, NPCM7xxCLKState),
328
+ VMSTATE_END_OF_LIST(),
329
+ },
330
+};
331
+
332
+static void npcm7xx_clk_class_init(ObjectClass *klass, void *data)
333
+{
334
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
335
+ DeviceClass *dc = DEVICE_CLASS(klass);
336
+
337
+ QEMU_BUILD_BUG_ON(NPCM7XX_CLK_REGS_END > NPCM7XX_CLK_NR_REGS);
338
+
339
+ dc->desc = "NPCM7xx Clock Control Registers";
340
+ dc->vmsd = &vmstate_npcm7xx_clk;
341
+ rc->phases.enter = npcm7xx_clk_enter_reset;
342
+}
343
+
344
+static const TypeInfo npcm7xx_clk_info = {
345
+ .name = TYPE_NPCM7XX_CLK,
346
+ .parent = TYPE_SYS_BUS_DEVICE,
347
+ .instance_size = sizeof(NPCM7xxCLKState),
348
+ .instance_init = npcm7xx_clk_init,
349
+ .class_init = npcm7xx_clk_class_init,
350
+};
351
+
352
+static void npcm7xx_clk_register_type(void)
353
+{
354
+ type_register_static(&npcm7xx_clk_info);
355
+}
356
+type_init(npcm7xx_clk_register_type);
357
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
358
index XXXXXXX..XXXXXXX 100644
359
--- a/hw/misc/meson.build
360
+++ b/hw/misc/meson.build
361
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_IMX', if_true: files(
362
softmmu_ss.add(when: 'CONFIG_MILKYMIST', if_true: files('milkymist-hpdmc.c', 'milkymist-pfpu.c'))
363
softmmu_ss.add(when: 'CONFIG_MAINSTONE', if_true: files('mst_fpga.c'))
364
softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files(
365
+ 'npcm7xx_clk.c',
366
'npcm7xx_gcr.c',
367
))
368
softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files(
369
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
370
index XXXXXXX..XXXXXXX 100644
371
--- a/hw/misc/trace-events
372
+++ b/hw/misc/trace-events
373
@@ -XXX,XX +XXX,XX @@ mos6522_set_sr_int(void) "set sr_int"
374
mos6522_write(uint64_t addr, uint64_t val) "reg=0x%"PRIx64 " val=0x%"PRIx64
375
mos6522_read(uint64_t addr, unsigned val) "reg=0x%"PRIx64 " val=0x%x"
376
377
+# npcm7xx_clk.c
378
+npcm7xx_clk_read(uint64_t offset, uint32_t value) " offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
379
+npcm7xx_clk_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
380
+
381
# npcm7xx_gcr.c
382
npcm7xx_gcr_read(uint64_t offset, uint32_t value) " offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
383
npcm7xx_gcr_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
39
--
384
--
40
2.19.2
385
2.20.1
41
386
42
387
diff view generated by jsdifflib
1
From: Steffen Görtz <contrib@steffen-goertz.de>
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
2
3
This patch adds the model for the nRF51 timer peripheral.
3
The NPCM730 and NPCM750 SoCs have three timer modules each holding five
4
Currently, only the TIMER mode is implemented.
4
timers and some shared registers (e.g. interrupt status).
5
5
6
Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
6
Each timer runs at 25 MHz divided by a prescaler, and counts down from a
7
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
7
configurable initial value to zero. When zero is reached, the interrupt
8
Message-id: 20190103091119.9367-9-stefanha@redhat.com
8
flag for the timer is set, and the timer is disabled (one-shot mode) or
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
reloaded from its initial value (periodic mode).
10
11
This implementation is sufficient to boot a Linux kernel configured for
12
NPCM750. Note that the kernel does not seem to actually turn on the
13
interrupts.
14
15
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
16
Reviewed-by: Joel Stanley <joel@jms.id.au>
17
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
18
Tested-by: Alexander Bulekov <alxndr@bu.edu>
19
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
20
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
21
Message-id: 20200911052101.2602693-4-hskinnemoen@google.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
23
---
12
hw/timer/Makefile.objs | 1 +
24
include/hw/timer/npcm7xx_timer.h | 78 +++++
13
include/hw/timer/nrf51_timer.h | 80 +++++++
25
hw/timer/npcm7xx_timer.c | 543 +++++++++++++++++++++++++++++++
14
hw/timer/nrf51_timer.c | 393 +++++++++++++++++++++++++++++++++
26
hw/timer/meson.build | 1 +
15
hw/timer/trace-events | 5 +
27
hw/timer/trace-events | 5 +
16
4 files changed, 479 insertions(+)
28
4 files changed, 627 insertions(+)
17
create mode 100644 include/hw/timer/nrf51_timer.h
29
create mode 100644 include/hw/timer/npcm7xx_timer.h
18
create mode 100644 hw/timer/nrf51_timer.c
30
create mode 100644 hw/timer/npcm7xx_timer.c
19
31
20
diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs
32
diff --git a/include/hw/timer/npcm7xx_timer.h b/include/hw/timer/npcm7xx_timer.h
21
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/timer/Makefile.objs
23
+++ b/hw/timer/Makefile.objs
24
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_IMX) += imx_gpt.o
25
common-obj-$(CONFIG_LM32) += lm32_timer.o
26
common-obj-$(CONFIG_MILKYMIST) += milkymist-sysctl.o
27
common-obj-$(CONFIG_XLNX_ZYNQMP) += xlnx-zynqmp-rtc.o
28
+common-obj-$(CONFIG_NRF51_SOC) += nrf51_timer.o
29
30
obj-$(CONFIG_ALTERA_TIMER) += altera_timer.o
31
obj-$(CONFIG_EXYNOS4) += exynos4210_mct.o
32
diff --git a/include/hw/timer/nrf51_timer.h b/include/hw/timer/nrf51_timer.h
33
new file mode 100644
33
new file mode 100644
34
index XXXXXXX..XXXXXXX
34
index XXXXXXX..XXXXXXX
35
--- /dev/null
35
--- /dev/null
36
+++ b/include/hw/timer/nrf51_timer.h
36
+++ b/include/hw/timer/npcm7xx_timer.h
37
@@ -XXX,XX +XXX,XX @@
37
@@ -XXX,XX +XXX,XX @@
38
+/*
38
+/*
39
+ * nRF51 System-on-Chip Timer peripheral
39
+ * Nuvoton NPCM7xx Timer Controller
40
+ *
40
+ *
41
+ * QEMU interface:
41
+ * Copyright 2020 Google LLC
42
+ * + sysbus MMIO regions 0: GPIO registers
43
+ * + sysbus irq
44
+ *
42
+ *
45
+ * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
43
+ * This program is free software; you can redistribute it and/or modify it
44
+ * under the terms of the GNU General Public License as published by the
45
+ * Free Software Foundation; either version 2 of the License, or
46
+ * (at your option) any later version.
46
+ *
47
+ *
47
+ * This code is licensed under the GPL version 2 or later. See
48
+ * This program is distributed in the hope that it will be useful, but WITHOUT
48
+ * the COPYING file in the top-level directory.
49
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
49
+ */
50
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
50
+#ifndef NRF51_TIMER_H
51
+ * for more details.
51
+#define NRF51_TIMER_H
52
+ */
52
+
53
+#ifndef NPCM7XX_TIMER_H
54
+#define NPCM7XX_TIMER_H
55
+
56
+#include "exec/memory.h"
53
+#include "hw/sysbus.h"
57
+#include "hw/sysbus.h"
54
+#include "qemu/timer.h"
58
+#include "qemu/timer.h"
55
+#define TYPE_NRF51_TIMER "nrf51_soc.timer"
59
+
56
+#define NRF51_TIMER(obj) OBJECT_CHECK(NRF51TimerState, (obj), TYPE_NRF51_TIMER)
60
+/* Each Timer Module (TIM) instance holds five 25 MHz timers. */
57
+
61
+#define NPCM7XX_TIMERS_PER_CTRL (5)
58
+#define NRF51_TIMER_REG_COUNT 4
62
+
59
+
63
+/*
60
+#define NRF51_TIMER_TASK_START 0x000
64
+ * Number of registers in our device state structure. Don't change this without
61
+#define NRF51_TIMER_TASK_STOP 0x004
65
+ * incrementing the version_id in the vmstate.
62
+#define NRF51_TIMER_TASK_COUNT 0x008
66
+ */
63
+#define NRF51_TIMER_TASK_CLEAR 0x00C
67
+#define NPCM7XX_TIMER_NR_REGS (0x54 / sizeof(uint32_t))
64
+#define NRF51_TIMER_TASK_SHUTDOWN 0x010
68
+
65
+#define NRF51_TIMER_TASK_CAPTURE_0 0x040
69
+typedef struct NPCM7xxTimerCtrlState NPCM7xxTimerCtrlState;
66
+#define NRF51_TIMER_TASK_CAPTURE_3 0x04C
70
+
67
+
71
+/**
68
+#define NRF51_TIMER_EVENT_COMPARE_0 0x140
72
+ * struct NPCM7xxTimer - Individual timer state.
69
+#define NRF51_TIMER_EVENT_COMPARE_1 0x144
73
+ * @irq: GIC interrupt line to fire on expiration (if enabled).
70
+#define NRF51_TIMER_EVENT_COMPARE_2 0x148
74
+ * @qtimer: QEMU timer that notifies us on expiration.
71
+#define NRF51_TIMER_EVENT_COMPARE_3 0x14C
75
+ * @expires_ns: Absolute virtual expiration time.
72
+
76
+ * @remaining_ns: Remaining time until expiration if timer is paused.
73
+#define NRF51_TIMER_REG_SHORTS 0x200
77
+ * @tcsr: The Timer Control and Status Register.
74
+#define NRF51_TIMER_REG_SHORTS_MASK 0xf0f
78
+ * @ticr: The Timer Initial Count Register.
75
+#define NRF51_TIMER_REG_INTENSET 0x304
79
+ */
76
+#define NRF51_TIMER_REG_INTENCLR 0x308
80
+typedef struct NPCM7xxTimer {
77
+#define NRF51_TIMER_REG_INTEN_MASK 0xf0000
81
+ NPCM7xxTimerCtrlState *ctrl;
78
+#define NRF51_TIMER_REG_MODE 0x504
82
+
79
+#define NRF51_TIMER_REG_MODE_MASK 0x01
83
+ qemu_irq irq;
80
+#define NRF51_TIMER_TIMER 0
84
+ QEMUTimer qtimer;
81
+#define NRF51_TIMER_COUNTER 1
85
+ int64_t expires_ns;
82
+#define NRF51_TIMER_REG_BITMODE 0x508
86
+ int64_t remaining_ns;
83
+#define NRF51_TIMER_REG_BITMODE_MASK 0x03
87
+
84
+#define NRF51_TIMER_WIDTH_16 0
88
+ uint32_t tcsr;
85
+#define NRF51_TIMER_WIDTH_8 1
89
+ uint32_t ticr;
86
+#define NRF51_TIMER_WIDTH_24 2
90
+} NPCM7xxTimer;
87
+#define NRF51_TIMER_WIDTH_32 3
91
+
88
+#define NRF51_TIMER_REG_PRESCALER 0x510
92
+/**
89
+#define NRF51_TIMER_REG_PRESCALER_MASK 0x0F
93
+ * struct NPCM7xxTimerCtrlState - Timer Module device state.
90
+#define NRF51_TIMER_REG_CC0 0x540
94
+ * @parent: System bus device.
91
+#define NRF51_TIMER_REG_CC3 0x54C
95
+ * @iomem: Memory region through which registers are accessed.
92
+
96
+ * @tisr: The Timer Interrupt Status Register.
93
+typedef struct NRF51TimerState {
97
+ * @wtcr: The Watchdog Timer Control Register.
94
+ SysBusDevice parent_obj;
98
+ * @timer: The five individual timers managed by this module.
99
+ */
100
+struct NPCM7xxTimerCtrlState {
101
+ SysBusDevice parent;
95
+
102
+
96
+ MemoryRegion iomem;
103
+ MemoryRegion iomem;
97
+ qemu_irq irq;
104
+
98
+
105
+ uint32_t tisr;
99
+ QEMUTimer timer;
106
+ uint32_t wtcr;
100
+ int64_t timer_start_ns;
107
+
101
+ int64_t update_counter_ns;
108
+ NPCM7xxTimer timer[NPCM7XX_TIMERS_PER_CTRL];
102
+ uint32_t counter;
109
+};
103
+
110
+
104
+ bool running;
111
+#define TYPE_NPCM7XX_TIMER "npcm7xx-timer"
105
+
112
+#define NPCM7XX_TIMER(obj) \
106
+ uint8_t events_compare[NRF51_TIMER_REG_COUNT];
113
+ OBJECT_CHECK(NPCM7xxTimerCtrlState, (obj), TYPE_NPCM7XX_TIMER)
107
+ uint32_t cc[NRF51_TIMER_REG_COUNT];
114
+
108
+ uint32_t shorts;
115
+#endif /* NPCM7XX_TIMER_H */
109
+ uint32_t inten;
116
diff --git a/hw/timer/npcm7xx_timer.c b/hw/timer/npcm7xx_timer.c
110
+ uint32_t mode;
111
+ uint32_t bitmode;
112
+ uint32_t prescaler;
113
+
114
+} NRF51TimerState;
115
+
116
+
117
+#endif
118
diff --git a/hw/timer/nrf51_timer.c b/hw/timer/nrf51_timer.c
119
new file mode 100644
117
new file mode 100644
120
index XXXXXXX..XXXXXXX
118
index XXXXXXX..XXXXXXX
121
--- /dev/null
119
--- /dev/null
122
+++ b/hw/timer/nrf51_timer.c
120
+++ b/hw/timer/npcm7xx_timer.c
123
@@ -XXX,XX +XXX,XX @@
121
@@ -XXX,XX +XXX,XX @@
124
+/*
122
+/*
125
+ * nRF51 System-on-Chip Timer peripheral
123
+ * Nuvoton NPCM7xx Timer Controller
126
+ *
124
+ *
127
+ * Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.pdf
125
+ * Copyright 2020 Google LLC
128
+ * Product Spec: http://infocenter.nordicsemi.com/pdf/nRF51822_PS_v3.1.pdf
129
+ *
126
+ *
130
+ * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
127
+ * This program is free software; you can redistribute it and/or modify it
131
+ * Copyright (c) 2019 Red Hat, Inc.
128
+ * under the terms of the GNU General Public License as published by the
129
+ * Free Software Foundation; either version 2 of the License, or
130
+ * (at your option) any later version.
132
+ *
131
+ *
133
+ * This code is licensed under the GPL version 2 or later. See
132
+ * This program is distributed in the hope that it will be useful, but WITHOUT
134
+ * the COPYING file in the top-level directory.
133
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
134
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
135
+ * for more details.
135
+ */
136
+ */
136
+
137
+
137
+#include "qemu/osdep.h"
138
+#include "qemu/osdep.h"
139
+
140
+#include "hw/irq.h"
141
+#include "hw/misc/npcm7xx_clk.h"
142
+#include "hw/timer/npcm7xx_timer.h"
143
+#include "migration/vmstate.h"
144
+#include "qemu/bitops.h"
145
+#include "qemu/error-report.h"
138
+#include "qemu/log.h"
146
+#include "qemu/log.h"
139
+#include "hw/arm/nrf51.h"
147
+#include "qemu/module.h"
140
+#include "hw/timer/nrf51_timer.h"
148
+#include "qemu/timer.h"
149
+#include "qemu/units.h"
141
+#include "trace.h"
150
+#include "trace.h"
142
+
151
+
143
+#define TIMER_CLK_FREQ 16000000UL
152
+/* 32-bit register indices. */
144
+
153
+enum NPCM7xxTimerRegisters {
145
+static uint32_t const bitwidths[] = {16, 8, 24, 32};
154
+ NPCM7XX_TIMER_TCSR0,
146
+
155
+ NPCM7XX_TIMER_TCSR1,
147
+static uint32_t ns_to_ticks(NRF51TimerState *s, int64_t ns)
156
+ NPCM7XX_TIMER_TICR0,
148
+{
157
+ NPCM7XX_TIMER_TICR1,
149
+ uint32_t freq = TIMER_CLK_FREQ >> s->prescaler;
158
+ NPCM7XX_TIMER_TDR0,
150
+
159
+ NPCM7XX_TIMER_TDR1,
151
+ return muldiv64(ns, freq, NANOSECONDS_PER_SECOND);
160
+ NPCM7XX_TIMER_TISR,
152
+}
161
+ NPCM7XX_TIMER_WTCR,
153
+
162
+ NPCM7XX_TIMER_TCSR2,
154
+static int64_t ticks_to_ns(NRF51TimerState *s, uint32_t ticks)
163
+ NPCM7XX_TIMER_TCSR3,
155
+{
164
+ NPCM7XX_TIMER_TICR2,
156
+ uint32_t freq = TIMER_CLK_FREQ >> s->prescaler;
165
+ NPCM7XX_TIMER_TICR3,
157
+
166
+ NPCM7XX_TIMER_TDR2,
158
+ return muldiv64(ticks, NANOSECONDS_PER_SECOND, freq);
167
+ NPCM7XX_TIMER_TDR3,
159
+}
168
+ NPCM7XX_TIMER_TCSR4 = 0x0040 / sizeof(uint32_t),
160
+
169
+ NPCM7XX_TIMER_TICR4 = 0x0048 / sizeof(uint32_t),
161
+/* Returns number of ticks since last call */
170
+ NPCM7XX_TIMER_TDR4 = 0x0050 / sizeof(uint32_t),
162
+static uint32_t update_counter(NRF51TimerState *s, int64_t now)
171
+ NPCM7XX_TIMER_REGS_END,
163
+{
172
+};
164
+ uint32_t ticks = ns_to_ticks(s, now - s->update_counter_ns);
173
+
165
+
174
+/* Register field definitions. */
166
+ s->counter = (s->counter + ticks) % BIT(bitwidths[s->bitmode]);
175
+#define NPCM7XX_TCSR_CEN BIT(30)
167
+ s->update_counter_ns = now;
176
+#define NPCM7XX_TCSR_IE BIT(29)
168
+ return ticks;
177
+#define NPCM7XX_TCSR_PERIODIC BIT(27)
169
+}
178
+#define NPCM7XX_TCSR_CRST BIT(26)
170
+
179
+#define NPCM7XX_TCSR_CACT BIT(25)
171
+/* Assumes s->counter is up-to-date */
180
+#define NPCM7XX_TCSR_RSVD 0x01ffff00
172
+static void rearm_timer(NRF51TimerState *s, int64_t now)
181
+#define NPCM7XX_TCSR_PRESCALE_START 0
173
+{
182
+#define NPCM7XX_TCSR_PRESCALE_LEN 8
174
+ int64_t min_ns = INT64_MAX;
183
+
175
+ size_t i;
184
+/*
176
+
185
+ * Returns the index of timer in the tc->timer array. This can be used to
177
+ for (i = 0; i < NRF51_TIMER_REG_COUNT; i++) {
186
+ * locate the registers that belong to this timer.
178
+ int64_t delta_ns;
187
+ */
179
+
188
+static int npcm7xx_timer_index(NPCM7xxTimerCtrlState *tc, NPCM7xxTimer *timer)
180
+ if (s->events_compare[i]) {
189
+{
181
+ continue; /* already expired, ignore it for now */
190
+ int index = timer - tc->timer;
191
+
192
+ g_assert(index >= 0 && index < NPCM7XX_TIMERS_PER_CTRL);
193
+
194
+ return index;
195
+}
196
+
197
+/* Return the value by which to divide the reference clock rate. */
198
+static uint32_t npcm7xx_tcsr_prescaler(uint32_t tcsr)
199
+{
200
+ return extract32(tcsr, NPCM7XX_TCSR_PRESCALE_START,
201
+ NPCM7XX_TCSR_PRESCALE_LEN) + 1;
202
+}
203
+
204
+/* Convert a timer cycle count to a time interval in nanoseconds. */
205
+static int64_t npcm7xx_timer_count_to_ns(NPCM7xxTimer *t, uint32_t count)
206
+{
207
+ int64_t ns = count;
208
+
209
+ ns *= NANOSECONDS_PER_SECOND / NPCM7XX_TIMER_REF_HZ;
210
+ ns *= npcm7xx_tcsr_prescaler(t->tcsr);
211
+
212
+ return ns;
213
+}
214
+
215
+/* Convert a time interval in nanoseconds to a timer cycle count. */
216
+static uint32_t npcm7xx_timer_ns_to_count(NPCM7xxTimer *t, int64_t ns)
217
+{
218
+ int64_t count;
219
+
220
+ count = ns / (NANOSECONDS_PER_SECOND / NPCM7XX_TIMER_REF_HZ);
221
+ count /= npcm7xx_tcsr_prescaler(t->tcsr);
222
+
223
+ return count;
224
+}
225
+
226
+/*
227
+ * Raise the interrupt line if there's a pending interrupt and interrupts are
228
+ * enabled for this timer. If not, lower it.
229
+ */
230
+static void npcm7xx_timer_check_interrupt(NPCM7xxTimer *t)
231
+{
232
+ NPCM7xxTimerCtrlState *tc = t->ctrl;
233
+ int index = npcm7xx_timer_index(tc, t);
234
+ bool pending = (t->tcsr & NPCM7XX_TCSR_IE) && (tc->tisr & BIT(index));
235
+
236
+ qemu_set_irq(t->irq, pending);
237
+ trace_npcm7xx_timer_irq(DEVICE(tc)->canonical_path, index, pending);
238
+}
239
+
240
+/* Start or resume the timer. */
241
+static void npcm7xx_timer_start(NPCM7xxTimer *t)
242
+{
243
+ int64_t now;
244
+
245
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
246
+ t->expires_ns = now + t->remaining_ns;
247
+ timer_mod(&t->qtimer, t->expires_ns);
248
+}
249
+
250
+/*
251
+ * Called when the counter reaches zero. Sets the interrupt flag, and either
252
+ * restarts or disables the timer.
253
+ */
254
+static void npcm7xx_timer_reached_zero(NPCM7xxTimer *t)
255
+{
256
+ NPCM7xxTimerCtrlState *tc = t->ctrl;
257
+ int index = npcm7xx_timer_index(tc, t);
258
+
259
+ tc->tisr |= BIT(index);
260
+
261
+ if (t->tcsr & NPCM7XX_TCSR_PERIODIC) {
262
+ t->remaining_ns = npcm7xx_timer_count_to_ns(t, t->ticr);
263
+ if (t->tcsr & NPCM7XX_TCSR_CEN) {
264
+ npcm7xx_timer_start(t);
182
+ }
265
+ }
183
+
266
+ } else {
184
+ if (s->cc[i] <= s->counter) {
267
+ t->tcsr &= ~(NPCM7XX_TCSR_CEN | NPCM7XX_TCSR_CACT);
185
+ delta_ns = ticks_to_ns(s, BIT(bitwidths[s->bitmode]) -
268
+ }
186
+ s->counter + s->cc[i]);
269
+
270
+ npcm7xx_timer_check_interrupt(t);
271
+}
272
+
273
+/* Stop counting. Record the time remaining so we can continue later. */
274
+static void npcm7xx_timer_pause(NPCM7xxTimer *t)
275
+{
276
+ int64_t now;
277
+
278
+ timer_del(&t->qtimer);
279
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
280
+ t->remaining_ns = t->expires_ns - now;
281
+ if (t->remaining_ns <= 0) {
282
+ npcm7xx_timer_reached_zero(t);
283
+ }
284
+}
285
+
286
+/*
287
+ * Restart the timer from its initial value. If the timer was enabled and stays
288
+ * enabled, adjust the QEMU timer according to the new count. If the timer is
289
+ * transitioning from disabled to enabled, the caller is expected to start the
290
+ * timer later.
291
+ */
292
+static void npcm7xx_timer_restart(NPCM7xxTimer *t, uint32_t old_tcsr)
293
+{
294
+ t->remaining_ns = npcm7xx_timer_count_to_ns(t, t->ticr);
295
+
296
+ if (old_tcsr & t->tcsr & NPCM7XX_TCSR_CEN) {
297
+ npcm7xx_timer_start(t);
298
+ }
299
+}
300
+
301
+/* Register read and write handlers */
302
+
303
+static uint32_t npcm7xx_timer_read_tdr(NPCM7xxTimer *t)
304
+{
305
+ if (t->tcsr & NPCM7XX_TCSR_CEN) {
306
+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
307
+
308
+ return npcm7xx_timer_ns_to_count(t, t->expires_ns - now);
309
+ }
310
+
311
+ return npcm7xx_timer_ns_to_count(t, t->remaining_ns);
312
+}
313
+
314
+static void npcm7xx_timer_write_tcsr(NPCM7xxTimer *t, uint32_t new_tcsr)
315
+{
316
+ uint32_t old_tcsr = t->tcsr;
317
+ uint32_t tdr;
318
+
319
+ if (new_tcsr & NPCM7XX_TCSR_RSVD) {
320
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: reserved bits in 0x%08x ignored\n",
321
+ __func__, new_tcsr);
322
+ new_tcsr &= ~NPCM7XX_TCSR_RSVD;
323
+ }
324
+ if (new_tcsr & NPCM7XX_TCSR_CACT) {
325
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: read-only bits in 0x%08x ignored\n",
326
+ __func__, new_tcsr);
327
+ new_tcsr &= ~NPCM7XX_TCSR_CACT;
328
+ }
329
+ if ((new_tcsr & NPCM7XX_TCSR_CRST) && (new_tcsr & NPCM7XX_TCSR_CEN)) {
330
+ qemu_log_mask(LOG_GUEST_ERROR,
331
+ "%s: both CRST and CEN set; ignoring CEN.\n",
332
+ __func__);
333
+ new_tcsr &= ~NPCM7XX_TCSR_CEN;
334
+ }
335
+
336
+ /* Calculate the value of TDR before potentially changing the prescaler. */
337
+ tdr = npcm7xx_timer_read_tdr(t);
338
+
339
+ t->tcsr = (t->tcsr & NPCM7XX_TCSR_CACT) | new_tcsr;
340
+
341
+ if (npcm7xx_tcsr_prescaler(old_tcsr) != npcm7xx_tcsr_prescaler(new_tcsr)) {
342
+ /* Recalculate time remaining based on the current TDR value. */
343
+ t->remaining_ns = npcm7xx_timer_count_to_ns(t, tdr);
344
+ if (old_tcsr & t->tcsr & NPCM7XX_TCSR_CEN) {
345
+ npcm7xx_timer_start(t);
346
+ }
347
+ }
348
+
349
+ if ((old_tcsr ^ new_tcsr) & NPCM7XX_TCSR_IE) {
350
+ npcm7xx_timer_check_interrupt(t);
351
+ }
352
+ if (new_tcsr & NPCM7XX_TCSR_CRST) {
353
+ npcm7xx_timer_restart(t, old_tcsr);
354
+ t->tcsr &= ~NPCM7XX_TCSR_CRST;
355
+ }
356
+ if ((old_tcsr ^ new_tcsr) & NPCM7XX_TCSR_CEN) {
357
+ if (new_tcsr & NPCM7XX_TCSR_CEN) {
358
+ t->tcsr |= NPCM7XX_TCSR_CACT;
359
+ npcm7xx_timer_start(t);
187
+ } else {
360
+ } else {
188
+ delta_ns = ticks_to_ns(s, s->cc[i] - s->counter);
361
+ t->tcsr &= ~NPCM7XX_TCSR_CACT;
362
+ npcm7xx_timer_pause(t);
189
+ }
363
+ }
190
+
364
+ }
191
+ if (delta_ns < min_ns) {
365
+}
192
+ min_ns = delta_ns;
366
+
367
+static void npcm7xx_timer_write_ticr(NPCM7xxTimer *t, uint32_t new_ticr)
368
+{
369
+ t->ticr = new_ticr;
370
+
371
+ npcm7xx_timer_restart(t, t->tcsr);
372
+}
373
+
374
+static void npcm7xx_timer_write_tisr(NPCM7xxTimerCtrlState *s, uint32_t value)
375
+{
376
+ int i;
377
+
378
+ s->tisr &= ~value;
379
+ for (i = 0; i < ARRAY_SIZE(s->timer); i++) {
380
+ if (value & (1U << i)) {
381
+ npcm7xx_timer_check_interrupt(&s->timer[i]);
193
+ }
382
+ }
194
+ }
383
+ }
195
+
384
+}
196
+ if (min_ns != INT64_MAX) {
385
+
197
+ timer_mod_ns(&s->timer, now + min_ns);
386
+static hwaddr npcm7xx_tcsr_index(hwaddr reg)
198
+ }
387
+{
199
+}
388
+ switch (reg) {
200
+
389
+ case NPCM7XX_TIMER_TCSR0:
201
+static void update_irq(NRF51TimerState *s)
390
+ return 0;
202
+{
391
+ case NPCM7XX_TIMER_TCSR1:
203
+ bool flag = false;
392
+ return 1;
204
+ size_t i;
393
+ case NPCM7XX_TIMER_TCSR2:
205
+
394
+ return 2;
206
+ for (i = 0; i < NRF51_TIMER_REG_COUNT; i++) {
395
+ case NPCM7XX_TIMER_TCSR3:
207
+ flag |= s->events_compare[i] && extract32(s->inten, 16 + i, 1);
396
+ return 3;
208
+ }
397
+ case NPCM7XX_TIMER_TCSR4:
209
+ qemu_set_irq(s->irq, flag);
398
+ return 4;
210
+}
399
+ default:
211
+
400
+ g_assert_not_reached();
212
+static void timer_expire(void *opaque)
401
+ }
213
+{
402
+}
214
+ NRF51TimerState *s = NRF51_TIMER(opaque);
403
+
215
+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
404
+static hwaddr npcm7xx_ticr_index(hwaddr reg)
216
+ uint32_t cc_remaining[NRF51_TIMER_REG_COUNT];
405
+{
217
+ bool should_stop = false;
406
+ switch (reg) {
218
+ uint32_t ticks;
407
+ case NPCM7XX_TIMER_TICR0:
219
+ size_t i;
408
+ return 0;
220
+
409
+ case NPCM7XX_TIMER_TICR1:
221
+ for (i = 0; i < NRF51_TIMER_REG_COUNT; i++) {
410
+ return 1;
222
+ if (s->cc[i] > s->counter) {
411
+ case NPCM7XX_TIMER_TICR2:
223
+ cc_remaining[i] = s->cc[i] - s->counter;
412
+ return 2;
224
+ } else {
413
+ case NPCM7XX_TIMER_TICR3:
225
+ cc_remaining[i] = BIT(bitwidths[s->bitmode]) -
414
+ return 3;
226
+ s->counter + s->cc[i];
415
+ case NPCM7XX_TIMER_TICR4:
227
+ }
416
+ return 4;
228
+ }
417
+ default:
229
+
418
+ g_assert_not_reached();
230
+ ticks = update_counter(s, now);
419
+ }
231
+
420
+}
232
+ for (i = 0; i < NRF51_TIMER_REG_COUNT; i++) {
421
+
233
+ if (cc_remaining[i] <= ticks) {
422
+static hwaddr npcm7xx_tdr_index(hwaddr reg)
234
+ s->events_compare[i] = 1;
423
+{
235
+
424
+ switch (reg) {
236
+ if (s->shorts & BIT(i)) {
425
+ case NPCM7XX_TIMER_TDR0:
237
+ s->timer_start_ns = now;
426
+ return 0;
238
+ s->update_counter_ns = s->timer_start_ns;
427
+ case NPCM7XX_TIMER_TDR1:
239
+ s->counter = 0;
428
+ return 1;
240
+ }
429
+ case NPCM7XX_TIMER_TDR2:
241
+
430
+ return 2;
242
+ should_stop |= s->shorts & BIT(i + 8);
431
+ case NPCM7XX_TIMER_TDR3:
243
+ }
432
+ return 3;
244
+ }
433
+ case NPCM7XX_TIMER_TDR4:
245
+
434
+ return 4;
246
+ update_irq(s);
435
+ default:
247
+
436
+ g_assert_not_reached();
248
+ if (should_stop) {
437
+ }
249
+ s->running = false;
438
+}
250
+ timer_del(&s->timer);
439
+
251
+ } else {
440
+static uint64_t npcm7xx_timer_read(void *opaque, hwaddr offset, unsigned size)
252
+ rearm_timer(s, now);
441
+{
253
+ }
442
+ NPCM7xxTimerCtrlState *s = opaque;
254
+}
443
+ uint64_t value = 0;
255
+
444
+ hwaddr reg;
256
+static void counter_compare(NRF51TimerState *s)
445
+
257
+{
446
+ reg = offset / sizeof(uint32_t);
258
+ uint32_t counter = s->counter;
447
+ switch (reg) {
259
+ size_t i;
448
+ case NPCM7XX_TIMER_TCSR0:
260
+
449
+ case NPCM7XX_TIMER_TCSR1:
261
+ for (i = 0; i < NRF51_TIMER_REG_COUNT; i++) {
450
+ case NPCM7XX_TIMER_TCSR2:
262
+ if (counter == s->cc[i]) {
451
+ case NPCM7XX_TIMER_TCSR3:
263
+ s->events_compare[i] = 1;
452
+ case NPCM7XX_TIMER_TCSR4:
264
+
453
+ value = s->timer[npcm7xx_tcsr_index(reg)].tcsr;
265
+ if (s->shorts & BIT(i)) {
266
+ s->counter = 0;
267
+ }
268
+ }
269
+ }
270
+}
271
+
272
+static uint64_t nrf51_timer_read(void *opaque, hwaddr offset, unsigned int size)
273
+{
274
+ NRF51TimerState *s = NRF51_TIMER(opaque);
275
+ uint64_t r = 0;
276
+
277
+ switch (offset) {
278
+ case NRF51_TIMER_EVENT_COMPARE_0 ... NRF51_TIMER_EVENT_COMPARE_3:
279
+ r = s->events_compare[(offset - NRF51_TIMER_EVENT_COMPARE_0) / 4];
280
+ break;
454
+ break;
281
+ case NRF51_TIMER_REG_SHORTS:
455
+
282
+ r = s->shorts;
456
+ case NPCM7XX_TIMER_TICR0:
457
+ case NPCM7XX_TIMER_TICR1:
458
+ case NPCM7XX_TIMER_TICR2:
459
+ case NPCM7XX_TIMER_TICR3:
460
+ case NPCM7XX_TIMER_TICR4:
461
+ value = s->timer[npcm7xx_ticr_index(reg)].ticr;
283
+ break;
462
+ break;
284
+ case NRF51_TIMER_REG_INTENSET:
463
+
285
+ r = s->inten;
464
+ case NPCM7XX_TIMER_TDR0:
465
+ case NPCM7XX_TIMER_TDR1:
466
+ case NPCM7XX_TIMER_TDR2:
467
+ case NPCM7XX_TIMER_TDR3:
468
+ case NPCM7XX_TIMER_TDR4:
469
+ value = npcm7xx_timer_read_tdr(&s->timer[npcm7xx_tdr_index(reg)]);
286
+ break;
470
+ break;
287
+ case NRF51_TIMER_REG_INTENCLR:
471
+
288
+ r = s->inten;
472
+ case NPCM7XX_TIMER_TISR:
473
+ value = s->tisr;
289
+ break;
474
+ break;
290
+ case NRF51_TIMER_REG_MODE:
475
+
291
+ r = s->mode;
476
+ case NPCM7XX_TIMER_WTCR:
477
+ value = s->wtcr;
292
+ break;
478
+ break;
293
+ case NRF51_TIMER_REG_BITMODE:
479
+
294
+ r = s->bitmode;
295
+ break;
296
+ case NRF51_TIMER_REG_PRESCALER:
297
+ r = s->prescaler;
298
+ break;
299
+ case NRF51_TIMER_REG_CC0 ... NRF51_TIMER_REG_CC3:
300
+ r = s->cc[(offset - NRF51_TIMER_REG_CC0) / 4];
301
+ break;
302
+ default:
480
+ default:
303
+ qemu_log_mask(LOG_GUEST_ERROR,
481
+ qemu_log_mask(LOG_GUEST_ERROR,
304
+ "%s: bad read offset 0x%" HWADDR_PRIx "\n",
482
+ "%s: invalid offset 0x%04" HWADDR_PRIx "\n",
305
+ __func__, offset);
483
+ __func__, offset);
306
+ }
307
+
308
+ trace_nrf51_timer_read(offset, r, size);
309
+
310
+ return r;
311
+}
312
+
313
+static void nrf51_timer_write(void *opaque, hwaddr offset,
314
+ uint64_t value, unsigned int size)
315
+{
316
+ NRF51TimerState *s = NRF51_TIMER(opaque);
317
+ uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
318
+ size_t idx;
319
+
320
+ trace_nrf51_timer_write(offset, value, size);
321
+
322
+ switch (offset) {
323
+ case NRF51_TIMER_TASK_START:
324
+ if (value == NRF51_TRIGGER_TASK && s->mode == NRF51_TIMER_TIMER) {
325
+ s->running = true;
326
+ s->timer_start_ns = now - ticks_to_ns(s, s->counter);
327
+ s->update_counter_ns = s->timer_start_ns;
328
+ rearm_timer(s, now);
329
+ }
330
+ break;
484
+ break;
331
+ case NRF51_TIMER_TASK_STOP:
485
+ }
332
+ case NRF51_TIMER_TASK_SHUTDOWN:
486
+
333
+ if (value == NRF51_TRIGGER_TASK) {
487
+ trace_npcm7xx_timer_read(DEVICE(s)->canonical_path, offset, value);
334
+ s->running = false;
488
+
335
+ timer_del(&s->timer);
489
+ return value;
336
+ }
490
+}
337
+ break;
491
+
338
+ case NRF51_TIMER_TASK_COUNT:
492
+static void npcm7xx_timer_write(void *opaque, hwaddr offset,
339
+ if (value == NRF51_TRIGGER_TASK && s->mode == NRF51_TIMER_COUNTER) {
493
+ uint64_t v, unsigned size)
340
+ s->counter = (s->counter + 1) % BIT(bitwidths[s->bitmode]);
494
+{
341
+ counter_compare(s);
495
+ uint32_t reg = offset / sizeof(uint32_t);
342
+ }
496
+ NPCM7xxTimerCtrlState *s = opaque;
343
+ break;
497
+ uint32_t value = v;
344
+ case NRF51_TIMER_TASK_CLEAR:
498
+
345
+ if (value == NRF51_TRIGGER_TASK) {
499
+ trace_npcm7xx_timer_write(DEVICE(s)->canonical_path, offset, value);
346
+ s->timer_start_ns = now;
500
+
347
+ s->update_counter_ns = s->timer_start_ns;
501
+ switch (reg) {
348
+ s->counter = 0;
502
+ case NPCM7XX_TIMER_TCSR0:
349
+ if (s->running) {
503
+ case NPCM7XX_TIMER_TCSR1:
350
+ rearm_timer(s, now);
504
+ case NPCM7XX_TIMER_TCSR2:
351
+ }
505
+ case NPCM7XX_TIMER_TCSR3:
352
+ }
506
+ case NPCM7XX_TIMER_TCSR4:
353
+ break;
507
+ npcm7xx_timer_write_tcsr(&s->timer[npcm7xx_tcsr_index(reg)], value);
354
+ case NRF51_TIMER_TASK_CAPTURE_0 ... NRF51_TIMER_TASK_CAPTURE_3:
508
+ return;
355
+ if (value == NRF51_TRIGGER_TASK) {
509
+
356
+ if (s->running) {
510
+ case NPCM7XX_TIMER_TICR0:
357
+ timer_expire(s); /* update counter and all state */
511
+ case NPCM7XX_TIMER_TICR1:
358
+ }
512
+ case NPCM7XX_TIMER_TICR2:
359
+
513
+ case NPCM7XX_TIMER_TICR3:
360
+ idx = (offset - NRF51_TIMER_TASK_CAPTURE_0) / 4;
514
+ case NPCM7XX_TIMER_TICR4:
361
+ s->cc[idx] = s->counter;
515
+ npcm7xx_timer_write_ticr(&s->timer[npcm7xx_ticr_index(reg)], value);
362
+ }
516
+ return;
363
+ break;
517
+
364
+ case NRF51_TIMER_EVENT_COMPARE_0 ... NRF51_TIMER_EVENT_COMPARE_3:
518
+ case NPCM7XX_TIMER_TDR0:
365
+ if (value == NRF51_EVENT_CLEAR) {
519
+ case NPCM7XX_TIMER_TDR1:
366
+ s->events_compare[(offset - NRF51_TIMER_EVENT_COMPARE_0) / 4] = 0;
520
+ case NPCM7XX_TIMER_TDR2:
367
+
521
+ case NPCM7XX_TIMER_TDR3:
368
+ if (s->running) {
522
+ case NPCM7XX_TIMER_TDR4:
369
+ timer_expire(s); /* update counter and all state */
370
+ }
371
+ }
372
+ break;
373
+ case NRF51_TIMER_REG_SHORTS:
374
+ s->shorts = value & NRF51_TIMER_REG_SHORTS_MASK;
375
+ break;
376
+ case NRF51_TIMER_REG_INTENSET:
377
+ s->inten |= value & NRF51_TIMER_REG_INTEN_MASK;
378
+ break;
379
+ case NRF51_TIMER_REG_INTENCLR:
380
+ s->inten &= ~(value & NRF51_TIMER_REG_INTEN_MASK);
381
+ break;
382
+ case NRF51_TIMER_REG_MODE:
383
+ s->mode = value;
384
+ break;
385
+ case NRF51_TIMER_REG_BITMODE:
386
+ if (s->mode == NRF51_TIMER_TIMER && s->running) {
387
+ qemu_log_mask(LOG_GUEST_ERROR,
388
+ "%s: erroneous change of BITMODE while timer is running\n",
389
+ __func__);
390
+ }
391
+ s->bitmode = value & NRF51_TIMER_REG_BITMODE_MASK;
392
+ break;
393
+ case NRF51_TIMER_REG_PRESCALER:
394
+ if (s->mode == NRF51_TIMER_TIMER && s->running) {
395
+ qemu_log_mask(LOG_GUEST_ERROR,
396
+ "%s: erroneous change of PRESCALER while timer is running\n",
397
+ __func__);
398
+ }
399
+ s->prescaler = value & NRF51_TIMER_REG_PRESCALER_MASK;
400
+ break;
401
+ case NRF51_TIMER_REG_CC0 ... NRF51_TIMER_REG_CC3:
402
+ if (s->running) {
403
+ timer_expire(s); /* update counter */
404
+ }
405
+
406
+ idx = (offset - NRF51_TIMER_REG_CC0) / 4;
407
+ s->cc[idx] = value % BIT(bitwidths[s->bitmode]);
408
+
409
+ if (s->running) {
410
+ rearm_timer(s, now);
411
+ }
412
+ break;
413
+ default:
414
+ qemu_log_mask(LOG_GUEST_ERROR,
523
+ qemu_log_mask(LOG_GUEST_ERROR,
415
+ "%s: bad write offset 0x%" HWADDR_PRIx "\n",
524
+ "%s: register @ 0x%04" HWADDR_PRIx " is read-only\n",
416
+ __func__, offset);
525
+ __func__, offset);
417
+ }
526
+ return;
418
+
527
+
419
+ update_irq(s);
528
+ case NPCM7XX_TIMER_TISR:
420
+}
529
+ npcm7xx_timer_write_tisr(s, value);
421
+
530
+ return;
422
+static const MemoryRegionOps rng_ops = {
531
+
423
+ .read = nrf51_timer_read,
532
+ case NPCM7XX_TIMER_WTCR:
424
+ .write = nrf51_timer_write,
533
+ qemu_log_mask(LOG_UNIMP, "%s: WTCR write not implemented: 0x%08x\n",
534
+ __func__, value);
535
+ return;
536
+ }
537
+
538
+ qemu_log_mask(LOG_GUEST_ERROR,
539
+ "%s: invalid offset 0x%04" HWADDR_PRIx "\n",
540
+ __func__, offset);
541
+}
542
+
543
+static const struct MemoryRegionOps npcm7xx_timer_ops = {
544
+ .read = npcm7xx_timer_read,
545
+ .write = npcm7xx_timer_write,
425
+ .endianness = DEVICE_LITTLE_ENDIAN,
546
+ .endianness = DEVICE_LITTLE_ENDIAN,
426
+ .impl.min_access_size = 4,
547
+ .valid = {
427
+ .impl.max_access_size = 4,
548
+ .min_access_size = 4,
549
+ .max_access_size = 4,
550
+ .unaligned = false,
551
+ },
428
+};
552
+};
429
+
553
+
430
+static void nrf51_timer_init(Object *obj)
554
+/* Called when the QEMU timer expires. */
431
+{
555
+static void npcm7xx_timer_expired(void *opaque)
432
+ NRF51TimerState *s = NRF51_TIMER(obj);
556
+{
433
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
557
+ NPCM7xxTimer *t = opaque;
434
+
558
+
435
+ memory_region_init_io(&s->iomem, obj, &rng_ops, s,
559
+ if (t->tcsr & NPCM7XX_TCSR_CEN) {
436
+ TYPE_NRF51_TIMER, NRF51_TIMER_SIZE);
560
+ npcm7xx_timer_reached_zero(t);
561
+ }
562
+}
563
+
564
+static void npcm7xx_timer_enter_reset(Object *obj, ResetType type)
565
+{
566
+ NPCM7xxTimerCtrlState *s = NPCM7XX_TIMER(obj);
567
+ int i;
568
+
569
+ for (i = 0; i < NPCM7XX_TIMERS_PER_CTRL; i++) {
570
+ NPCM7xxTimer *t = &s->timer[i];
571
+
572
+ timer_del(&t->qtimer);
573
+ t->expires_ns = 0;
574
+ t->remaining_ns = 0;
575
+ t->tcsr = 0x00000005;
576
+ t->ticr = 0x00000000;
577
+ }
578
+
579
+ s->tisr = 0x00000000;
580
+ s->wtcr = 0x00000400;
581
+}
582
+
583
+static void npcm7xx_timer_hold_reset(Object *obj)
584
+{
585
+ NPCM7xxTimerCtrlState *s = NPCM7XX_TIMER(obj);
586
+ int i;
587
+
588
+ for (i = 0; i < NPCM7XX_TIMERS_PER_CTRL; i++) {
589
+ qemu_irq_lower(s->timer[i].irq);
590
+ }
591
+}
592
+
593
+static void npcm7xx_timer_realize(DeviceState *dev, Error **errp)
594
+{
595
+ NPCM7xxTimerCtrlState *s = NPCM7XX_TIMER(dev);
596
+ SysBusDevice *sbd = &s->parent;
597
+ int i;
598
+
599
+ for (i = 0; i < NPCM7XX_TIMERS_PER_CTRL; i++) {
600
+ NPCM7xxTimer *t = &s->timer[i];
601
+ t->ctrl = s;
602
+ timer_init_ns(&t->qtimer, QEMU_CLOCK_VIRTUAL, npcm7xx_timer_expired, t);
603
+ sysbus_init_irq(sbd, &t->irq);
604
+ }
605
+
606
+ memory_region_init_io(&s->iomem, OBJECT(s), &npcm7xx_timer_ops, s,
607
+ TYPE_NPCM7XX_TIMER, 4 * KiB);
437
+ sysbus_init_mmio(sbd, &s->iomem);
608
+ sysbus_init_mmio(sbd, &s->iomem);
438
+ sysbus_init_irq(sbd, &s->irq);
609
+}
439
+
610
+
440
+ timer_init_ns(&s->timer, QEMU_CLOCK_VIRTUAL, timer_expire, s);
611
+static const VMStateDescription vmstate_npcm7xx_timer = {
441
+}
612
+ .name = "npcm7xx-timer",
442
+
613
+ .version_id = 0,
443
+static void nrf51_timer_reset(DeviceState *dev)
614
+ .minimum_version_id = 0,
444
+{
445
+ NRF51TimerState *s = NRF51_TIMER(dev);
446
+
447
+ timer_del(&s->timer);
448
+ s->timer_start_ns = 0x00;
449
+ s->update_counter_ns = 0x00;
450
+ s->counter = 0x00;
451
+ s->running = false;
452
+
453
+ memset(s->events_compare, 0x00, sizeof(s->events_compare));
454
+ memset(s->cc, 0x00, sizeof(s->cc));
455
+
456
+ s->shorts = 0x00;
457
+ s->inten = 0x00;
458
+ s->mode = 0x00;
459
+ s->bitmode = 0x00;
460
+ s->prescaler = 0x00;
461
+}
462
+
463
+static int nrf51_timer_post_load(void *opaque, int version_id)
464
+{
465
+ NRF51TimerState *s = NRF51_TIMER(opaque);
466
+
467
+ if (s->running && s->mode == NRF51_TIMER_TIMER) {
468
+ timer_expire(s);
469
+ }
470
+ return 0;
471
+}
472
+
473
+static const VMStateDescription vmstate_nrf51_timer = {
474
+ .name = TYPE_NRF51_TIMER,
475
+ .version_id = 1,
476
+ .post_load = nrf51_timer_post_load,
477
+ .fields = (VMStateField[]) {
615
+ .fields = (VMStateField[]) {
478
+ VMSTATE_TIMER(timer, NRF51TimerState),
616
+ VMSTATE_TIMER(qtimer, NPCM7xxTimer),
479
+ VMSTATE_INT64(timer_start_ns, NRF51TimerState),
617
+ VMSTATE_INT64(expires_ns, NPCM7xxTimer),
480
+ VMSTATE_INT64(update_counter_ns, NRF51TimerState),
618
+ VMSTATE_INT64(remaining_ns, NPCM7xxTimer),
481
+ VMSTATE_UINT32(counter, NRF51TimerState),
619
+ VMSTATE_UINT32(tcsr, NPCM7xxTimer),
482
+ VMSTATE_BOOL(running, NRF51TimerState),
620
+ VMSTATE_UINT32(ticr, NPCM7xxTimer),
483
+ VMSTATE_UINT8_ARRAY(events_compare, NRF51TimerState,
621
+ VMSTATE_END_OF_LIST(),
484
+ NRF51_TIMER_REG_COUNT),
622
+ },
485
+ VMSTATE_UINT32_ARRAY(cc, NRF51TimerState, NRF51_TIMER_REG_COUNT),
486
+ VMSTATE_UINT32(shorts, NRF51TimerState),
487
+ VMSTATE_UINT32(inten, NRF51TimerState),
488
+ VMSTATE_UINT32(mode, NRF51TimerState),
489
+ VMSTATE_UINT32(bitmode, NRF51TimerState),
490
+ VMSTATE_UINT32(prescaler, NRF51TimerState),
491
+ VMSTATE_END_OF_LIST()
492
+ }
493
+};
623
+};
494
+
624
+
495
+static void nrf51_timer_class_init(ObjectClass *klass, void *data)
625
+static const VMStateDescription vmstate_npcm7xx_timer_ctrl = {
496
+{
626
+ .name = "npcm7xx-timer-ctrl",
627
+ .version_id = 0,
628
+ .minimum_version_id = 0,
629
+ .fields = (VMStateField[]) {
630
+ VMSTATE_UINT32(tisr, NPCM7xxTimerCtrlState),
631
+ VMSTATE_UINT32(wtcr, NPCM7xxTimerCtrlState),
632
+ VMSTATE_STRUCT_ARRAY(timer, NPCM7xxTimerCtrlState,
633
+ NPCM7XX_TIMERS_PER_CTRL, 0, vmstate_npcm7xx_timer,
634
+ NPCM7xxTimer),
635
+ VMSTATE_END_OF_LIST(),
636
+ },
637
+};
638
+
639
+static void npcm7xx_timer_class_init(ObjectClass *klass, void *data)
640
+{
641
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
497
+ DeviceClass *dc = DEVICE_CLASS(klass);
642
+ DeviceClass *dc = DEVICE_CLASS(klass);
498
+
643
+
499
+ dc->reset = nrf51_timer_reset;
644
+ QEMU_BUILD_BUG_ON(NPCM7XX_TIMER_REGS_END > NPCM7XX_TIMER_NR_REGS);
500
+ dc->vmsd = &vmstate_nrf51_timer;
645
+
501
+}
646
+ dc->desc = "NPCM7xx Timer Controller";
502
+
647
+ dc->realize = npcm7xx_timer_realize;
503
+static const TypeInfo nrf51_timer_info = {
648
+ dc->vmsd = &vmstate_npcm7xx_timer_ctrl;
504
+ .name = TYPE_NRF51_TIMER,
649
+ rc->phases.enter = npcm7xx_timer_enter_reset;
505
+ .parent = TYPE_SYS_BUS_DEVICE,
650
+ rc->phases.hold = npcm7xx_timer_hold_reset;
506
+ .instance_size = sizeof(NRF51TimerState),
651
+}
507
+ .instance_init = nrf51_timer_init,
652
+
508
+ .class_init = nrf51_timer_class_init
653
+static const TypeInfo npcm7xx_timer_info = {
654
+ .name = TYPE_NPCM7XX_TIMER,
655
+ .parent = TYPE_SYS_BUS_DEVICE,
656
+ .instance_size = sizeof(NPCM7xxTimerCtrlState),
657
+ .class_init = npcm7xx_timer_class_init,
509
+};
658
+};
510
+
659
+
511
+static void nrf51_timer_register_types(void)
660
+static void npcm7xx_timer_register_type(void)
512
+{
661
+{
513
+ type_register_static(&nrf51_timer_info);
662
+ type_register_static(&npcm7xx_timer_info);
514
+}
663
+}
515
+
664
+type_init(npcm7xx_timer_register_type);
516
+type_init(nrf51_timer_register_types)
665
diff --git a/hw/timer/meson.build b/hw/timer/meson.build
666
index XXXXXXX..XXXXXXX 100644
667
--- a/hw/timer/meson.build
668
+++ b/hw/timer/meson.build
669
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_LM32', if_true: files('lm32_timer.c'))
670
softmmu_ss.add(when: 'CONFIG_MILKYMIST', if_true: files('milkymist-sysctl.c'))
671
softmmu_ss.add(when: 'CONFIG_MIPS_CPS', if_true: files('mips_gictimer.c'))
672
softmmu_ss.add(when: 'CONFIG_MSF2', if_true: files('mss-timer.c'))
673
+softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_timer.c'))
674
softmmu_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_timer.c'))
675
softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_gptimer.c'))
676
softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_synctimer.c'))
517
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
677
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
518
index XXXXXXX..XXXXXXX 100644
678
index XXXXXXX..XXXXXXX 100644
519
--- a/hw/timer/trace-events
679
--- a/hw/timer/trace-events
520
+++ b/hw/timer/trace-events
680
+++ b/hw/timer/trace-events
521
@@ -XXX,XX +XXX,XX @@ sun4v_rtc_write(uint64_t addr, uint64_t value) "write: addr 0x%" PRIx64 " value
681
@@ -XXX,XX +XXX,XX @@ cmsdk_apb_dualtimer_read(uint64_t offset, uint64_t data, unsigned size) "CMSDK A
522
682
cmsdk_apb_dualtimer_write(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB dualtimer write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
523
# hw/timer/xlnx-zynqmp-rtc.c
683
cmsdk_apb_dualtimer_reset(void) "CMSDK APB dualtimer: reset"
524
xlnx_zynqmp_rtc_gettime(int year, int month, int day, int hour, int min, int sec) "Get time from host: %d-%d-%d %2d:%02d:%02d"
684
525
+
685
+# npcm7xx_timer.c
526
+# hw/timer/nrf51_timer.c
686
+npcm7xx_timer_read(const char *id, uint64_t offset, uint64_t value) " %s offset: 0x%04" PRIx64 " value 0x%08" PRIx64
527
+nrf51_timer_read(uint64_t addr, uint32_t value, unsigned size) "read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
687
+npcm7xx_timer_write(const char *id, uint64_t offset, uint64_t value) "%s offset: 0x%04" PRIx64 " value 0x%08" PRIx64
528
+nrf51_timer_write(uint64_t addr, uint32_t value, unsigned size) "write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
688
+npcm7xx_timer_irq(const char *id, int timer, int state) "%s timer %d state %d"
529
+
689
+
690
# nrf51_timer.c
691
nrf51_timer_read(uint8_t timer_id, uint64_t addr, uint32_t value, unsigned size) "timer %u read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
692
nrf51_timer_write(uint8_t timer_id, uint64_t addr, uint32_t value, unsigned size) "timer %u write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
530
--
693
--
531
2.19.2
694
2.20.1
532
695
533
696
diff view generated by jsdifflib
1
From: Steffen Görtz <contrib@steffen-goertz.de>
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
2
3
Instantiates TIMER0 - TIMER2
3
The Nuvoton NPCM7xx SoC family are used to implement Baseboard
4
4
Management Controllers in servers. While the family includes four SoCs,
5
Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
5
this patch implements limited support for two of them: NPCM730 (targeted
6
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
for Data Center applications) and NPCM750 (targeted for Enterprise
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
applications).
8
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
8
9
Message-id: 20190103091119.9367-10-stefanha@redhat.com
9
This patch includes little more than the bare minimum needed to boot a
10
Linux kernel built with NPCM7xx support in direct-kernel mode:
11
12
- Two Cortex-A9 CPU cores with built-in periperhals.
13
- Global Configuration Registers.
14
- Clock Management.
15
- 3 Timer Modules with 5 timers each.
16
- 4 serial ports.
17
18
The chips themselves have a lot more features, some of which will be
19
added to the model at a later stage.
20
21
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
22
Reviewed-by: Joel Stanley <joel@jms.id.au>
23
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
24
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
25
Tested-by: Alexander Bulekov <alxndr@bu.edu>
26
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
27
Message-id: 20200911052101.2602693-5-hskinnemoen@google.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
28
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
29
---
12
include/hw/arm/nrf51_soc.h | 4 ++++
30
include/hw/arm/npcm7xx.h | 85 ++++++++
13
hw/arm/nrf51_soc.c | 26 ++++++++++++++++++++++++++
31
hw/arm/npcm7xx.c | 407 +++++++++++++++++++++++++++++++++++++++
14
2 files changed, 30 insertions(+)
32
hw/arm/Kconfig | 5 +
15
33
hw/arm/meson.build | 1 +
16
diff --git a/include/hw/arm/nrf51_soc.h b/include/hw/arm/nrf51_soc.h
34
4 files changed, 498 insertions(+)
17
index XXXXXXX..XXXXXXX 100644
35
create mode 100644 include/hw/arm/npcm7xx.h
18
--- a/include/hw/arm/nrf51_soc.h
36
create mode 100644 hw/arm/npcm7xx.c
19
+++ b/include/hw/arm/nrf51_soc.h
37
38
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
39
new file mode 100644
40
index XXXXXXX..XXXXXXX
41
--- /dev/null
42
+++ b/include/hw/arm/npcm7xx.h
20
@@ -XXX,XX +XXX,XX @@
43
@@ -XXX,XX +XXX,XX @@
21
#include "hw/char/nrf51_uart.h"
44
+/*
22
#include "hw/misc/nrf51_rng.h"
45
+ * Nuvoton NPCM7xx SoC family.
23
#include "hw/gpio/nrf51_gpio.h"
46
+ *
24
+#include "hw/timer/nrf51_timer.h"
47
+ * Copyright 2020 Google LLC
25
48
+ *
26
#define TYPE_NRF51_SOC "nrf51-soc"
49
+ * This program is free software; you can redistribute it and/or modify it
27
#define NRF51_SOC(obj) \
50
+ * under the terms of the GNU General Public License as published by the
28
OBJECT_CHECK(NRF51State, (obj), TYPE_NRF51_SOC)
51
+ * Free Software Foundation; either version 2 of the License, or
29
52
+ * (at your option) any later version.
30
+#define NRF51_NUM_TIMERS 3
53
+ *
31
+
54
+ * This program is distributed in the hope that it will be useful, but WITHOUT
32
typedef struct NRF51State {
55
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
33
/*< private >*/
56
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
34
SysBusDevice parent_obj;
57
+ * for more details.
35
@@ -XXX,XX +XXX,XX @@ typedef struct NRF51State {
58
+ */
36
NRF51UARTState uart;
59
+#ifndef NPCM7XX_H
37
NRF51RNGState rng;
60
+#define NPCM7XX_H
38
NRF51GPIOState gpio;
61
+
39
+ NRF51TimerState timer[NRF51_NUM_TIMERS];
62
+#include "hw/boards.h"
40
63
+#include "hw/cpu/a9mpcore.h"
41
MemoryRegion iomem;
64
+#include "hw/misc/npcm7xx_clk.h"
42
MemoryRegion sram;
65
+#include "hw/misc/npcm7xx_gcr.h"
43
diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c
66
+#include "hw/timer/npcm7xx_timer.h"
44
index XXXXXXX..XXXXXXX 100644
67
+#include "target/arm/cpu.h"
45
--- a/hw/arm/nrf51_soc.c
68
+
46
+++ b/hw/arm/nrf51_soc.c
69
+#define NPCM7XX_MAX_NUM_CPUS (2)
47
@@ -XXX,XX +XXX,XX @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
70
+
48
NRF51State *s = NRF51_SOC(dev_soc);
71
+/* The first half of the address space is reserved for DDR4 DRAM. */
49
MemoryRegion *mr;
72
+#define NPCM7XX_DRAM_BA (0x00000000)
50
Error *err = NULL;
73
+#define NPCM7XX_DRAM_SZ (2 * GiB)
51
+ uint8_t i = 0;
74
+
52
+ hwaddr base_addr = 0;
75
+/* Magic addresses for setting up direct kernel booting and SMP boot stubs. */
53
76
+#define NPCM7XX_LOADER_START (0x00000000) /* Start of SDRAM */
54
if (!s->board_memory) {
77
+#define NPCM7XX_SMP_LOADER_START (0xffff0000) /* Boot ROM */
55
error_setg(errp, "memory property was not set");
78
+#define NPCM7XX_SMP_BOOTREG_ADDR (0xf080013c) /* GCR.SCRPAD */
56
@@ -XXX,XX +XXX,XX @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
79
+#define NPCM7XX_GIC_CPU_IF_ADDR (0xf03fe100) /* GIC within A9 */
57
/* Pass all GPIOs to the SOC layer so they are available to the board */
80
+
58
qdev_pass_gpios(DEVICE(&s->gpio), dev_soc, NULL);
81
+typedef struct NPCM7xxState {
59
82
+ DeviceState parent;
60
+ /* TIMER */
83
+
61
+ for (i = 0; i < NRF51_NUM_TIMERS; i++) {
84
+ ARMCPU cpu[NPCM7XX_MAX_NUM_CPUS];
62
+ object_property_set_bool(OBJECT(&s->timer[i]), true, "realized", &err);
85
+ A9MPPrivState a9mpcore;
63
+ if (err) {
86
+
64
+ error_propagate(errp, err);
87
+ MemoryRegion sram;
88
+ MemoryRegion irom;
89
+ MemoryRegion ram3;
90
+ MemoryRegion *dram;
91
+
92
+ NPCM7xxGCRState gcr;
93
+ NPCM7xxCLKState clk;
94
+ NPCM7xxTimerCtrlState tim[3];
95
+} NPCM7xxState;
96
+
97
+#define TYPE_NPCM7XX "npcm7xx"
98
+#define NPCM7XX(obj) OBJECT_CHECK(NPCM7xxState, (obj), TYPE_NPCM7XX)
99
+
100
+#define TYPE_NPCM730 "npcm730"
101
+#define TYPE_NPCM750 "npcm750"
102
+
103
+typedef struct NPCM7xxClass {
104
+ DeviceClass parent;
105
+
106
+ /* Bitmask of modules that are permanently disabled on this chip. */
107
+ uint32_t disabled_modules;
108
+ /* Number of CPU cores enabled in this SoC class (may be 1 or 2). */
109
+ uint32_t num_cpus;
110
+} NPCM7xxClass;
111
+
112
+#define NPCM7XX_CLASS(klass) \
113
+ OBJECT_CLASS_CHECK(NPCM7xxClass, (klass), TYPE_NPCM7XX)
114
+#define NPCM7XX_GET_CLASS(obj) \
115
+ OBJECT_GET_CLASS(NPCM7xxClass, (obj), TYPE_NPCM7XX)
116
+
117
+/**
118
+ * npcm7xx_load_kernel - Loads memory with everything needed to boot
119
+ * @machine - The machine containing the SoC to be booted.
120
+ * @soc - The SoC containing the CPU to be booted.
121
+ *
122
+ * This will set up the ARM boot info structure for the specific NPCM7xx
123
+ * derivative and call arm_load_kernel() to set up loading of the kernel, etc.
124
+ * into memory, if requested by the user.
125
+ */
126
+void npcm7xx_load_kernel(MachineState *machine, NPCM7xxState *soc);
127
+
128
+#endif /* NPCM7XX_H */
129
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
130
new file mode 100644
131
index XXXXXXX..XXXXXXX
132
--- /dev/null
133
+++ b/hw/arm/npcm7xx.c
134
@@ -XXX,XX +XXX,XX @@
135
+/*
136
+ * Nuvoton NPCM7xx SoC family.
137
+ *
138
+ * Copyright 2020 Google LLC
139
+ *
140
+ * This program is free software; you can redistribute it and/or modify it
141
+ * under the terms of the GNU General Public License as published by the
142
+ * Free Software Foundation; either version 2 of the License, or
143
+ * (at your option) any later version.
144
+ *
145
+ * This program is distributed in the hope that it will be useful, but WITHOUT
146
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
147
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
148
+ * for more details.
149
+ */
150
+
151
+#include "qemu/osdep.h"
152
+
153
+#include "exec/address-spaces.h"
154
+#include "hw/arm/boot.h"
155
+#include "hw/arm/npcm7xx.h"
156
+#include "hw/char/serial.h"
157
+#include "hw/loader.h"
158
+#include "hw/misc/unimp.h"
159
+#include "hw/qdev-properties.h"
160
+#include "qapi/error.h"
161
+#include "qemu/units.h"
162
+#include "sysemu/sysemu.h"
163
+
164
+/*
165
+ * This covers the whole MMIO space. We'll use this to catch any MMIO accesses
166
+ * that aren't handled by any device.
167
+ */
168
+#define NPCM7XX_MMIO_BA (0x80000000)
169
+#define NPCM7XX_MMIO_SZ (0x7ffd0000)
170
+
171
+/* Core system modules. */
172
+#define NPCM7XX_L2C_BA (0xf03fc000)
173
+#define NPCM7XX_CPUP_BA (0xf03fe000)
174
+#define NPCM7XX_GCR_BA (0xf0800000)
175
+#define NPCM7XX_CLK_BA (0xf0801000)
176
+
177
+/* Internal AHB SRAM */
178
+#define NPCM7XX_RAM3_BA (0xc0008000)
179
+#define NPCM7XX_RAM3_SZ (4 * KiB)
180
+
181
+/* Memory blocks at the end of the address space */
182
+#define NPCM7XX_RAM2_BA (0xfffd0000)
183
+#define NPCM7XX_RAM2_SZ (128 * KiB)
184
+#define NPCM7XX_ROM_BA (0xffff0000)
185
+#define NPCM7XX_ROM_SZ (64 * KiB)
186
+
187
+/*
188
+ * Interrupt lines going into the GIC. This does not include internal Cortex-A9
189
+ * interrupts.
190
+ */
191
+enum NPCM7xxInterrupt {
192
+ NPCM7XX_UART0_IRQ = 2,
193
+ NPCM7XX_UART1_IRQ,
194
+ NPCM7XX_UART2_IRQ,
195
+ NPCM7XX_UART3_IRQ,
196
+ NPCM7XX_TIMER0_IRQ = 32, /* Timer Module 0 */
197
+ NPCM7XX_TIMER1_IRQ,
198
+ NPCM7XX_TIMER2_IRQ,
199
+ NPCM7XX_TIMER3_IRQ,
200
+ NPCM7XX_TIMER4_IRQ,
201
+ NPCM7XX_TIMER5_IRQ, /* Timer Module 1 */
202
+ NPCM7XX_TIMER6_IRQ,
203
+ NPCM7XX_TIMER7_IRQ,
204
+ NPCM7XX_TIMER8_IRQ,
205
+ NPCM7XX_TIMER9_IRQ,
206
+ NPCM7XX_TIMER10_IRQ, /* Timer Module 2 */
207
+ NPCM7XX_TIMER11_IRQ,
208
+ NPCM7XX_TIMER12_IRQ,
209
+ NPCM7XX_TIMER13_IRQ,
210
+ NPCM7XX_TIMER14_IRQ,
211
+};
212
+
213
+/* Total number of GIC interrupts, including internal Cortex-A9 interrupts. */
214
+#define NPCM7XX_NUM_IRQ (160)
215
+
216
+/* Register base address for each Timer Module */
217
+static const hwaddr npcm7xx_tim_addr[] = {
218
+ 0xf0008000,
219
+ 0xf0009000,
220
+ 0xf000a000,
221
+};
222
+
223
+/* Register base address for each 16550 UART */
224
+static const hwaddr npcm7xx_uart_addr[] = {
225
+ 0xf0001000,
226
+ 0xf0002000,
227
+ 0xf0003000,
228
+ 0xf0004000,
229
+};
230
+
231
+static void npcm7xx_write_secondary_boot(ARMCPU *cpu,
232
+ const struct arm_boot_info *info)
233
+{
234
+ /*
235
+ * The default smpboot stub halts the secondary CPU with a 'wfi'
236
+ * instruction, but the arch/arm/mach-npcm/platsmp.c in the Linux kernel
237
+ * does not send an IPI to wake it up, so the second CPU fails to boot. So
238
+ * we need to provide our own smpboot stub that can not use 'wfi', it has
239
+ * to spin the secondary CPU until the first CPU writes to the SCRPAD reg.
240
+ */
241
+ uint32_t smpboot[] = {
242
+ 0xe59f2018, /* ldr r2, bootreg_addr */
243
+ 0xe3a00000, /* mov r0, #0 */
244
+ 0xe5820000, /* str r0, [r2] */
245
+ 0xe320f002, /* wfe */
246
+ 0xe5921000, /* ldr r1, [r2] */
247
+ 0xe1110001, /* tst r1, r1 */
248
+ 0x0afffffb, /* beq <wfe> */
249
+ 0xe12fff11, /* bx r1 */
250
+ NPCM7XX_SMP_BOOTREG_ADDR,
251
+ };
252
+ int i;
253
+
254
+ for (i = 0; i < ARRAY_SIZE(smpboot); i++) {
255
+ smpboot[i] = tswap32(smpboot[i]);
256
+ }
257
+
258
+ rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot),
259
+ NPCM7XX_SMP_LOADER_START);
260
+}
261
+
262
+static struct arm_boot_info npcm7xx_binfo = {
263
+ .loader_start = NPCM7XX_LOADER_START,
264
+ .smp_loader_start = NPCM7XX_SMP_LOADER_START,
265
+ .smp_bootreg_addr = NPCM7XX_SMP_BOOTREG_ADDR,
266
+ .gic_cpu_if_addr = NPCM7XX_GIC_CPU_IF_ADDR,
267
+ .write_secondary_boot = npcm7xx_write_secondary_boot,
268
+ .board_id = -1,
269
+};
270
+
271
+void npcm7xx_load_kernel(MachineState *machine, NPCM7xxState *soc)
272
+{
273
+ NPCM7xxClass *sc = NPCM7XX_GET_CLASS(soc);
274
+
275
+ npcm7xx_binfo.ram_size = machine->ram_size;
276
+ npcm7xx_binfo.nb_cpus = sc->num_cpus;
277
+
278
+ arm_load_kernel(&soc->cpu[0], machine, &npcm7xx_binfo);
279
+}
280
+
281
+static qemu_irq npcm7xx_irq(NPCM7xxState *s, int n)
282
+{
283
+ return qdev_get_gpio_in(DEVICE(&s->a9mpcore), n);
284
+}
285
+
286
+static void npcm7xx_init(Object *obj)
287
+{
288
+ NPCM7xxState *s = NPCM7XX(obj);
289
+ int i;
290
+
291
+ for (i = 0; i < NPCM7XX_MAX_NUM_CPUS; i++) {
292
+ object_initialize_child(obj, "cpu[*]", &s->cpu[i],
293
+ ARM_CPU_TYPE_NAME("cortex-a9"));
294
+ }
295
+
296
+ object_initialize_child(obj, "a9mpcore", &s->a9mpcore, TYPE_A9MPCORE_PRIV);
297
+ object_initialize_child(obj, "gcr", &s->gcr, TYPE_NPCM7XX_GCR);
298
+ object_property_add_alias(obj, "power-on-straps", OBJECT(&s->gcr),
299
+ "power-on-straps");
300
+ object_initialize_child(obj, "clk", &s->clk, TYPE_NPCM7XX_CLK);
301
+
302
+ for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
303
+ object_initialize_child(obj, "tim[*]", &s->tim[i], TYPE_NPCM7XX_TIMER);
304
+ }
305
+}
306
+
307
+static void npcm7xx_realize(DeviceState *dev, Error **errp)
308
+{
309
+ NPCM7xxState *s = NPCM7XX(dev);
310
+ NPCM7xxClass *nc = NPCM7XX_GET_CLASS(s);
311
+ int i;
312
+
313
+ if (memory_region_size(s->dram) > NPCM7XX_DRAM_SZ) {
314
+ error_setg(errp, "%s: NPCM7xx cannot address more than %" PRIu64
315
+ " MiB of DRAM", __func__, NPCM7XX_DRAM_SZ / MiB);
316
+ return;
317
+ }
318
+
319
+ /* CPUs */
320
+ for (i = 0; i < nc->num_cpus; i++) {
321
+ object_property_set_int(OBJECT(&s->cpu[i]), "mp-affinity",
322
+ arm_cpu_mp_affinity(i, NPCM7XX_MAX_NUM_CPUS),
323
+ &error_abort);
324
+ object_property_set_int(OBJECT(&s->cpu[i]), "reset-cbar",
325
+ NPCM7XX_GIC_CPU_IF_ADDR, &error_abort);
326
+ object_property_set_bool(OBJECT(&s->cpu[i]), "reset-hivecs", true,
327
+ &error_abort);
328
+
329
+ /* Disable security extensions. */
330
+ object_property_set_bool(OBJECT(&s->cpu[i]), "has_el3", false,
331
+ &error_abort);
332
+
333
+ if (!qdev_realize(DEVICE(&s->cpu[i]), NULL, errp)) {
65
+ return;
334
+ return;
66
+ }
335
+ }
67
+
336
+ }
68
+ base_addr = NRF51_TIMER_BASE + i * NRF51_TIMER_SIZE;
337
+
69
+
338
+ /* A9MPCORE peripherals. Can only fail if we pass bad parameters here. */
70
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->timer[i]), 0, base_addr);
339
+ object_property_set_int(OBJECT(&s->a9mpcore), "num-cpu", nc->num_cpus,
71
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer[i]), 0,
340
+ &error_abort);
72
+ qdev_get_gpio_in(DEVICE(&s->cpu),
341
+ object_property_set_int(OBJECT(&s->a9mpcore), "num-irq", NPCM7XX_NUM_IRQ,
73
+ BASE_TO_IRQ(base_addr)));
342
+ &error_abort);
74
+ }
343
+ sysbus_realize(SYS_BUS_DEVICE(&s->a9mpcore), &error_abort);
75
+
344
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->a9mpcore), 0, NPCM7XX_CPUP_BA);
76
create_unimplemented_device("nrf51_soc.io", NRF51_IOMEM_BASE,
345
+
77
NRF51_IOMEM_SIZE);
346
+ for (i = 0; i < nc->num_cpus; i++) {
78
create_unimplemented_device("nrf51_soc.ficr", NRF51_FICR_BASE,
347
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->a9mpcore), i,
79
@@ -XXX,XX +XXX,XX @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
348
+ qdev_get_gpio_in(DEVICE(&s->cpu[i]), ARM_CPU_IRQ));
80
349
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->a9mpcore), i + nc->num_cpus,
81
static void nrf51_soc_init(Object *obj)
350
+ qdev_get_gpio_in(DEVICE(&s->cpu[i]), ARM_CPU_FIQ));
82
{
351
+ }
83
+ uint8_t i = 0;
352
+
84
+
353
+ /* L2 cache controller */
85
NRF51State *s = NRF51_SOC(obj);
354
+ sysbus_create_simple("l2x0", NPCM7XX_L2C_BA, NULL);
86
355
+
87
memory_region_init(&s->container, obj, "nrf51-container", UINT64_MAX);
356
+ /* System Global Control Registers (GCR). Can fail due to user input. */
88
@@ -XXX,XX +XXX,XX @@ static void nrf51_soc_init(Object *obj)
357
+ object_property_set_int(OBJECT(&s->gcr), "disabled-modules",
89
358
+ nc->disabled_modules, &error_abort);
90
sysbus_init_child_obj(obj, "gpio", &s->gpio, sizeof(s->gpio),
359
+ object_property_add_const_link(OBJECT(&s->gcr), "dram-mr", OBJECT(s->dram));
91
TYPE_NRF51_GPIO);
360
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->gcr), errp)) {
92
+
361
+ return;
93
+ for (i = 0; i < NRF51_NUM_TIMERS; i++) {
362
+ }
94
+ sysbus_init_child_obj(obj, "timer[*]", &s->timer[i],
363
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gcr), 0, NPCM7XX_GCR_BA);
95
+ sizeof(s->timer[i]), TYPE_NRF51_TIMER);
364
+
96
+
365
+ /* Clock Control Registers (CLK). Cannot fail. */
97
+ }
366
+ sysbus_realize(SYS_BUS_DEVICE(&s->clk), &error_abort);
98
}
367
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->clk), 0, NPCM7XX_CLK_BA);
99
368
+
100
static Property nrf51_soc_properties[] = {
369
+ /* Timer Modules (TIM). Cannot fail. */
370
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_tim_addr) != ARRAY_SIZE(s->tim));
371
+ for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
372
+ SysBusDevice *sbd = SYS_BUS_DEVICE(&s->tim[i]);
373
+ int first_irq;
374
+ int j;
375
+
376
+ sysbus_realize(sbd, &error_abort);
377
+ sysbus_mmio_map(sbd, 0, npcm7xx_tim_addr[i]);
378
+
379
+ first_irq = NPCM7XX_TIMER0_IRQ + i * NPCM7XX_TIMERS_PER_CTRL;
380
+ for (j = 0; j < NPCM7XX_TIMERS_PER_CTRL; j++) {
381
+ qemu_irq irq = npcm7xx_irq(s, first_irq + j);
382
+ sysbus_connect_irq(sbd, j, irq);
383
+ }
384
+ }
385
+
386
+ /* UART0..3 (16550 compatible) */
387
+ for (i = 0; i < ARRAY_SIZE(npcm7xx_uart_addr); i++) {
388
+ serial_mm_init(get_system_memory(), npcm7xx_uart_addr[i], 2,
389
+ npcm7xx_irq(s, NPCM7XX_UART0_IRQ + i), 115200,
390
+ serial_hd(i), DEVICE_LITTLE_ENDIAN);
391
+ }
392
+
393
+ /* RAM2 (SRAM) */
394
+ memory_region_init_ram(&s->sram, OBJECT(dev), "ram2",
395
+ NPCM7XX_RAM2_SZ, &error_abort);
396
+ memory_region_add_subregion(get_system_memory(), NPCM7XX_RAM2_BA, &s->sram);
397
+
398
+ /* RAM3 (SRAM) */
399
+ memory_region_init_ram(&s->ram3, OBJECT(dev), "ram3",
400
+ NPCM7XX_RAM3_SZ, &error_abort);
401
+ memory_region_add_subregion(get_system_memory(), NPCM7XX_RAM3_BA, &s->ram3);
402
+
403
+ /* Internal ROM */
404
+ memory_region_init_rom(&s->irom, OBJECT(dev), "irom", NPCM7XX_ROM_SZ,
405
+ &error_abort);
406
+ memory_region_add_subregion(get_system_memory(), NPCM7XX_ROM_BA, &s->irom);
407
+
408
+ create_unimplemented_device("npcm7xx.shm", 0xc0001000, 4 * KiB);
409
+ create_unimplemented_device("npcm7xx.vdmx", 0xe0800000, 4 * KiB);
410
+ create_unimplemented_device("npcm7xx.pcierc", 0xe1000000, 64 * KiB);
411
+ create_unimplemented_device("npcm7xx.kcs", 0xf0007000, 4 * KiB);
412
+ create_unimplemented_device("npcm7xx.rng", 0xf000b000, 4 * KiB);
413
+ create_unimplemented_device("npcm7xx.adc", 0xf000c000, 4 * KiB);
414
+ create_unimplemented_device("npcm7xx.gfxi", 0xf000e000, 4 * KiB);
415
+ create_unimplemented_device("npcm7xx.gpio[0]", 0xf0010000, 4 * KiB);
416
+ create_unimplemented_device("npcm7xx.gpio[1]", 0xf0011000, 4 * KiB);
417
+ create_unimplemented_device("npcm7xx.gpio[2]", 0xf0012000, 4 * KiB);
418
+ create_unimplemented_device("npcm7xx.gpio[3]", 0xf0013000, 4 * KiB);
419
+ create_unimplemented_device("npcm7xx.gpio[4]", 0xf0014000, 4 * KiB);
420
+ create_unimplemented_device("npcm7xx.gpio[5]", 0xf0015000, 4 * KiB);
421
+ create_unimplemented_device("npcm7xx.gpio[6]", 0xf0016000, 4 * KiB);
422
+ create_unimplemented_device("npcm7xx.gpio[7]", 0xf0017000, 4 * KiB);
423
+ create_unimplemented_device("npcm7xx.smbus[0]", 0xf0080000, 4 * KiB);
424
+ create_unimplemented_device("npcm7xx.smbus[1]", 0xf0081000, 4 * KiB);
425
+ create_unimplemented_device("npcm7xx.smbus[2]", 0xf0082000, 4 * KiB);
426
+ create_unimplemented_device("npcm7xx.smbus[3]", 0xf0083000, 4 * KiB);
427
+ create_unimplemented_device("npcm7xx.smbus[4]", 0xf0084000, 4 * KiB);
428
+ create_unimplemented_device("npcm7xx.smbus[5]", 0xf0085000, 4 * KiB);
429
+ create_unimplemented_device("npcm7xx.smbus[6]", 0xf0086000, 4 * KiB);
430
+ create_unimplemented_device("npcm7xx.smbus[7]", 0xf0087000, 4 * KiB);
431
+ create_unimplemented_device("npcm7xx.smbus[8]", 0xf0088000, 4 * KiB);
432
+ create_unimplemented_device("npcm7xx.smbus[9]", 0xf0089000, 4 * KiB);
433
+ create_unimplemented_device("npcm7xx.smbus[10]", 0xf008a000, 4 * KiB);
434
+ create_unimplemented_device("npcm7xx.smbus[11]", 0xf008b000, 4 * KiB);
435
+ create_unimplemented_device("npcm7xx.smbus[12]", 0xf008c000, 4 * KiB);
436
+ create_unimplemented_device("npcm7xx.smbus[13]", 0xf008d000, 4 * KiB);
437
+ create_unimplemented_device("npcm7xx.smbus[14]", 0xf008e000, 4 * KiB);
438
+ create_unimplemented_device("npcm7xx.smbus[15]", 0xf008f000, 4 * KiB);
439
+ create_unimplemented_device("npcm7xx.espi", 0xf009f000, 4 * KiB);
440
+ create_unimplemented_device("npcm7xx.peci", 0xf0100000, 4 * KiB);
441
+ create_unimplemented_device("npcm7xx.siox[1]", 0xf0101000, 4 * KiB);
442
+ create_unimplemented_device("npcm7xx.siox[2]", 0xf0102000, 4 * KiB);
443
+ create_unimplemented_device("npcm7xx.pwm[0]", 0xf0103000, 4 * KiB);
444
+ create_unimplemented_device("npcm7xx.pwm[1]", 0xf0104000, 4 * KiB);
445
+ create_unimplemented_device("npcm7xx.mft[0]", 0xf0180000, 4 * KiB);
446
+ create_unimplemented_device("npcm7xx.mft[1]", 0xf0181000, 4 * KiB);
447
+ create_unimplemented_device("npcm7xx.mft[2]", 0xf0182000, 4 * KiB);
448
+ create_unimplemented_device("npcm7xx.mft[3]", 0xf0183000, 4 * KiB);
449
+ create_unimplemented_device("npcm7xx.mft[4]", 0xf0184000, 4 * KiB);
450
+ create_unimplemented_device("npcm7xx.mft[5]", 0xf0185000, 4 * KiB);
451
+ create_unimplemented_device("npcm7xx.mft[6]", 0xf0186000, 4 * KiB);
452
+ create_unimplemented_device("npcm7xx.mft[7]", 0xf0187000, 4 * KiB);
453
+ create_unimplemented_device("npcm7xx.pspi1", 0xf0200000, 4 * KiB);
454
+ create_unimplemented_device("npcm7xx.pspi2", 0xf0201000, 4 * KiB);
455
+ create_unimplemented_device("npcm7xx.ahbpci", 0xf0400000, 1 * MiB);
456
+ create_unimplemented_device("npcm7xx.mcphy", 0xf05f0000, 64 * KiB);
457
+ create_unimplemented_device("npcm7xx.gmac1", 0xf0802000, 8 * KiB);
458
+ create_unimplemented_device("npcm7xx.gmac2", 0xf0804000, 8 * KiB);
459
+ create_unimplemented_device("npcm7xx.ehci", 0xf0806000, 4 * KiB);
460
+ create_unimplemented_device("npcm7xx.ohci", 0xf0807000, 4 * KiB);
461
+ create_unimplemented_device("npcm7xx.vcd", 0xf0810000, 64 * KiB);
462
+ create_unimplemented_device("npcm7xx.ece", 0xf0820000, 8 * KiB);
463
+ create_unimplemented_device("npcm7xx.vdma", 0xf0822000, 8 * KiB);
464
+ create_unimplemented_device("npcm7xx.emc1", 0xf0825000, 4 * KiB);
465
+ create_unimplemented_device("npcm7xx.emc2", 0xf0826000, 4 * KiB);
466
+ create_unimplemented_device("npcm7xx.usbd[0]", 0xf0830000, 4 * KiB);
467
+ create_unimplemented_device("npcm7xx.usbd[1]", 0xf0831000, 4 * KiB);
468
+ create_unimplemented_device("npcm7xx.usbd[2]", 0xf0832000, 4 * KiB);
469
+ create_unimplemented_device("npcm7xx.usbd[3]", 0xf0833000, 4 * KiB);
470
+ create_unimplemented_device("npcm7xx.usbd[4]", 0xf0834000, 4 * KiB);
471
+ create_unimplemented_device("npcm7xx.usbd[5]", 0xf0835000, 4 * KiB);
472
+ create_unimplemented_device("npcm7xx.usbd[6]", 0xf0836000, 4 * KiB);
473
+ create_unimplemented_device("npcm7xx.usbd[7]", 0xf0837000, 4 * KiB);
474
+ create_unimplemented_device("npcm7xx.usbd[8]", 0xf0838000, 4 * KiB);
475
+ create_unimplemented_device("npcm7xx.usbd[9]", 0xf0839000, 4 * KiB);
476
+ create_unimplemented_device("npcm7xx.sd", 0xf0840000, 8 * KiB);
477
+ create_unimplemented_device("npcm7xx.mmc", 0xf0842000, 8 * KiB);
478
+ create_unimplemented_device("npcm7xx.pcimbx", 0xf0848000, 512 * KiB);
479
+ create_unimplemented_device("npcm7xx.aes", 0xf0858000, 4 * KiB);
480
+ create_unimplemented_device("npcm7xx.des", 0xf0859000, 4 * KiB);
481
+ create_unimplemented_device("npcm7xx.sha", 0xf085a000, 4 * KiB);
482
+ create_unimplemented_device("npcm7xx.secacc", 0xf085b000, 4 * KiB);
483
+ create_unimplemented_device("npcm7xx.spixcs0", 0xf8000000, 16 * MiB);
484
+ create_unimplemented_device("npcm7xx.spixcs1", 0xf9000000, 16 * MiB);
485
+ create_unimplemented_device("npcm7xx.spix", 0xfb001000, 4 * KiB);
486
+}
487
+
488
+static Property npcm7xx_properties[] = {
489
+ DEFINE_PROP_LINK("dram-mr", NPCM7xxState, dram, TYPE_MEMORY_REGION,
490
+ MemoryRegion *),
491
+ DEFINE_PROP_END_OF_LIST(),
492
+};
493
+
494
+static void npcm7xx_class_init(ObjectClass *oc, void *data)
495
+{
496
+ DeviceClass *dc = DEVICE_CLASS(oc);
497
+
498
+ dc->realize = npcm7xx_realize;
499
+ dc->user_creatable = false;
500
+ device_class_set_props(dc, npcm7xx_properties);
501
+}
502
+
503
+static void npcm730_class_init(ObjectClass *oc, void *data)
504
+{
505
+ NPCM7xxClass *nc = NPCM7XX_CLASS(oc);
506
+
507
+ /* NPCM730 is optimized for data center use, so no graphics, etc. */
508
+ nc->disabled_modules = 0x00300395;
509
+ nc->num_cpus = 2;
510
+}
511
+
512
+static void npcm750_class_init(ObjectClass *oc, void *data)
513
+{
514
+ NPCM7xxClass *nc = NPCM7XX_CLASS(oc);
515
+
516
+ /* NPCM750 has 2 cores and a full set of peripherals */
517
+ nc->disabled_modules = 0x00000000;
518
+ nc->num_cpus = 2;
519
+}
520
+
521
+static const TypeInfo npcm7xx_soc_types[] = {
522
+ {
523
+ .name = TYPE_NPCM7XX,
524
+ .parent = TYPE_DEVICE,
525
+ .instance_size = sizeof(NPCM7xxState),
526
+ .instance_init = npcm7xx_init,
527
+ .class_size = sizeof(NPCM7xxClass),
528
+ .class_init = npcm7xx_class_init,
529
+ .abstract = true,
530
+ }, {
531
+ .name = TYPE_NPCM730,
532
+ .parent = TYPE_NPCM7XX,
533
+ .class_init = npcm730_class_init,
534
+ }, {
535
+ .name = TYPE_NPCM750,
536
+ .parent = TYPE_NPCM7XX,
537
+ .class_init = npcm750_class_init,
538
+ },
539
+};
540
+
541
+DEFINE_TYPES(npcm7xx_soc_types);
542
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
543
index XXXXXXX..XXXXXXX 100644
544
--- a/hw/arm/Kconfig
545
+++ b/hw/arm/Kconfig
546
@@ -XXX,XX +XXX,XX @@ config XLNX_VERSAL
547
548
config NPCM7XX
549
bool
550
+ select A9MPCORE
551
+ select ARM_GIC
552
+ select PL310 # cache controller
553
+ select SERIAL
554
+ select UNIMP
555
556
config FSL_IMX25
557
bool
558
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
559
index XXXXXXX..XXXXXXX 100644
560
--- a/hw/arm/meson.build
561
+++ b/hw/arm/meson.build
562
@@ -XXX,XX +XXX,XX @@ arm_ss.add(when: 'CONFIG_MICROBIT', if_true: files('microbit.c'))
563
arm_ss.add(when: 'CONFIG_MUSICPAL', if_true: files('musicpal.c'))
564
arm_ss.add(when: 'CONFIG_NETDUINO2', if_true: files('netduino2.c'))
565
arm_ss.add(when: 'CONFIG_NETDUINOPLUS2', if_true: files('netduinoplus2.c'))
566
+arm_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx.c'))
567
arm_ss.add(when: 'CONFIG_NSERIES', if_true: files('nseries.c'))
568
arm_ss.add(when: 'CONFIG_SX1', if_true: files('omap_sx1.c'))
569
arm_ss.add(when: 'CONFIG_CHEETAH', if_true: files('palm.c'))
101
--
570
--
102
2.19.2
571
2.20.1
103
572
104
573
diff view generated by jsdifflib
1
From: Steffen Görtz <contrib@steffen-goertz.de>
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
2
3
Adds a header that provides definitions that are used
3
This adds two new machines, both supported by OpenBMC:
4
across nRF51 peripherals
4
5
5
- npcm750-evb: Nuvoton NPCM750 Evaluation Board.
6
Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
6
- quanta-gsj: A board with a NPCM730 chip.
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
7
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
They rely on the NPCM7xx SoC device to do the heavy lifting. They are
9
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9
almost completely identical at the moment, apart from the SoC type,
10
Message-id: 20190103091119.9367-3-stefanha@redhat.com
10
which currently only changes the reset contents of one register
11
(GCR.MDLR), but they might grow apart a bit more as more functionality
12
is added.
13
14
Both machines can boot the Linux kernel into /bin/sh.
15
16
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
17
Reviewed-by: Joel Stanley <joel@jms.id.au>
18
Reviewed-by: Cédric Le Goater <clg@kaod.org>
19
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
20
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
21
Tested-by: Alexander Bulekov <alxndr@bu.edu>
22
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
23
Message-id: 20200911052101.2602693-6-hskinnemoen@google.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
25
---
13
include/hw/arm/nrf51.h | 45 ++++++++++++++++++++++++++++++++++++
26
default-configs/arm-softmmu.mak | 1 +
14
include/hw/char/nrf51_uart.h | 1 -
27
include/hw/arm/npcm7xx.h | 19 +++++
15
hw/arm/nrf51_soc.c | 33 ++++++++++----------------
28
hw/arm/npcm7xx_boards.c | 145 ++++++++++++++++++++++++++++++++
16
3 files changed, 57 insertions(+), 22 deletions(-)
29
hw/arm/meson.build | 2 +-
17
create mode 100644 include/hw/arm/nrf51.h
30
4 files changed, 166 insertions(+), 1 deletion(-)
18
31
create mode 100644 hw/arm/npcm7xx_boards.c
19
diff --git a/include/hw/arm/nrf51.h b/include/hw/arm/nrf51.h
32
33
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
34
index XXXXXXX..XXXXXXX 100644
35
--- a/default-configs/arm-softmmu.mak
36
+++ b/default-configs/arm-softmmu.mak
37
@@ -XXX,XX +XXX,XX @@ CONFIG_GUMSTIX=y
38
CONFIG_SPITZ=y
39
CONFIG_TOSA=y
40
CONFIG_Z2=y
41
+CONFIG_NPCM7XX=y
42
CONFIG_COLLIE=y
43
CONFIG_ASPEED_SOC=y
44
CONFIG_NETDUINO2=y
45
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
46
index XXXXXXX..XXXXXXX 100644
47
--- a/include/hw/arm/npcm7xx.h
48
+++ b/include/hw/arm/npcm7xx.h
49
@@ -XXX,XX +XXX,XX @@
50
#define NPCM7XX_SMP_BOOTREG_ADDR (0xf080013c) /* GCR.SCRPAD */
51
#define NPCM7XX_GIC_CPU_IF_ADDR (0xf03fe100) /* GIC within A9 */
52
53
+typedef struct NPCM7xxMachine {
54
+ MachineState parent;
55
+} NPCM7xxMachine;
56
+
57
+#define TYPE_NPCM7XX_MACHINE MACHINE_TYPE_NAME("npcm7xx")
58
+#define NPCM7XX_MACHINE(obj) \
59
+ OBJECT_CHECK(NPCM7xxMachine, (obj), TYPE_NPCM7XX_MACHINE)
60
+
61
+typedef struct NPCM7xxMachineClass {
62
+ MachineClass parent;
63
+
64
+ const char *soc_type;
65
+} NPCM7xxMachineClass;
66
+
67
+#define NPCM7XX_MACHINE_CLASS(klass) \
68
+ OBJECT_CLASS_CHECK(NPCM7xxMachineClass, (klass), TYPE_NPCM7XX_MACHINE)
69
+#define NPCM7XX_MACHINE_GET_CLASS(obj) \
70
+ OBJECT_GET_CLASS(NPCM7xxMachineClass, (obj), TYPE_NPCM7XX_MACHINE)
71
+
72
typedef struct NPCM7xxState {
73
DeviceState parent;
74
75
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
20
new file mode 100644
76
new file mode 100644
21
index XXXXXXX..XXXXXXX
77
index XXXXXXX..XXXXXXX
22
--- /dev/null
78
--- /dev/null
23
+++ b/include/hw/arm/nrf51.h
79
+++ b/hw/arm/npcm7xx_boards.c
24
@@ -XXX,XX +XXX,XX @@
80
@@ -XXX,XX +XXX,XX @@
25
+/*
81
+/*
26
+ * Nordic Semiconductor nRF51 Series SOC Common Defines
82
+ * Machine definitions for boards featuring an NPCM7xx SoC.
27
+ *
83
+ *
28
+ * This file hosts generic defines used in various nRF51 peripheral devices.
84
+ * Copyright 2020 Google LLC
29
+ *
85
+ *
30
+ * Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.pdf
86
+ * This program is free software; you can redistribute it and/or modify it
31
+ * Product Spec: http://infocenter.nordicsemi.com/pdf/nRF51822_PS_v3.1.pdf
87
+ * under the terms of the GNU General Public License as published by the
88
+ * Free Software Foundation; either version 2 of the License, or
89
+ * (at your option) any later version.
32
+ *
90
+ *
33
+ * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
91
+ * This program is distributed in the hope that it will be useful, but WITHOUT
34
+ *
92
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
35
+ * This code is licensed under the GPL version 2 or later. See
93
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
36
+ * the COPYING file in the top-level directory.
94
+ * for more details.
37
+ */
95
+ */
38
+
96
+
39
+#ifndef NRF51_H
97
+#include "qemu/osdep.h"
40
+#define NRF51_H
98
+
41
+
99
+#include "exec/address-spaces.h"
42
+#define NRF51_FLASH_BASE 0x00000000
100
+#include "hw/arm/npcm7xx.h"
43
+#define NRF51_FICR_BASE 0x10000000
101
+#include "hw/core/cpu.h"
44
+#define NRF51_FICR_SIZE 0x00000100
102
+#include "qapi/error.h"
45
+#define NRF51_UICR_BASE 0x10001000
103
+#include "qemu/units.h"
46
+#define NRF51_SRAM_BASE 0x20000000
104
+
47
+
105
+#define NPCM750_EVB_POWER_ON_STRAPS 0x00001ff7
48
+#define NRF51_IOMEM_BASE 0x40000000
106
+#define QUANTA_GSJ_POWER_ON_STRAPS 0x00001fff
49
+#define NRF51_IOMEM_SIZE 0x20000000
107
+
50
+
108
+static void npcm7xx_connect_dram(NPCM7xxState *soc, MemoryRegion *dram)
51
+#define NRF51_UART_BASE 0x40002000
109
+{
52
+#define NRF51_TIMER_BASE 0x40008000
110
+ memory_region_add_subregion(get_system_memory(), NPCM7XX_DRAM_BA, dram);
53
+#define NRF51_TIMER_SIZE 0x00001000
111
+
54
+#define NRF51_RNG_BASE 0x4000D000
112
+ object_property_set_link(OBJECT(soc), "dram-mr", OBJECT(dram),
55
+#define NRF51_NVMC_BASE 0x4001E000
113
+ &error_abort);
56
+#define NRF51_GPIO_BASE 0x50000000
114
+}
57
+
115
+
58
+#define NRF51_PRIVATE_BASE 0xF0000000
116
+static NPCM7xxState *npcm7xx_create_soc(MachineState *machine,
59
+#define NRF51_PRIVATE_SIZE 0x10000000
117
+ uint32_t hw_straps)
60
+
118
+{
61
+#define NRF51_PAGE_SIZE 1024
119
+ NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_GET_CLASS(machine);
62
+
120
+ MachineClass *mc = &nmc->parent;
63
+/* Trigger */
121
+ Object *obj;
64
+#define NRF51_TRIGGER_TASK 0x01
122
+
65
+
123
+ if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
66
+/* Events */
124
+ error_report("This board can only be used with %s",
67
+#define NRF51_EVENT_CLEAR 0x00
125
+ mc->default_cpu_type);
68
+
126
+ exit(1);
69
+#endif
127
+ }
70
diff --git a/include/hw/char/nrf51_uart.h b/include/hw/char/nrf51_uart.h
128
+
129
+ obj = object_new_with_props(nmc->soc_type, OBJECT(machine), "soc",
130
+ &error_abort, NULL);
131
+ object_property_set_uint(obj, "power-on-straps", hw_straps, &error_abort);
132
+
133
+ return NPCM7XX(obj);
134
+}
135
+
136
+static void npcm750_evb_init(MachineState *machine)
137
+{
138
+ NPCM7xxState *soc;
139
+
140
+ soc = npcm7xx_create_soc(machine, NPCM750_EVB_POWER_ON_STRAPS);
141
+ npcm7xx_connect_dram(soc, machine->ram);
142
+ qdev_realize(DEVICE(soc), NULL, &error_fatal);
143
+
144
+ npcm7xx_load_kernel(machine, soc);
145
+}
146
+
147
+static void quanta_gsj_init(MachineState *machine)
148
+{
149
+ NPCM7xxState *soc;
150
+
151
+ soc = npcm7xx_create_soc(machine, QUANTA_GSJ_POWER_ON_STRAPS);
152
+ npcm7xx_connect_dram(soc, machine->ram);
153
+ qdev_realize(DEVICE(soc), NULL, &error_fatal);
154
+
155
+ npcm7xx_load_kernel(machine, soc);
156
+}
157
+
158
+static void npcm7xx_set_soc_type(NPCM7xxMachineClass *nmc, const char *type)
159
+{
160
+ NPCM7xxClass *sc = NPCM7XX_CLASS(object_class_by_name(type));
161
+ MachineClass *mc = MACHINE_CLASS(nmc);
162
+
163
+ nmc->soc_type = type;
164
+ mc->default_cpus = mc->min_cpus = mc->max_cpus = sc->num_cpus;
165
+}
166
+
167
+static void npcm7xx_machine_class_init(ObjectClass *oc, void *data)
168
+{
169
+ MachineClass *mc = MACHINE_CLASS(oc);
170
+
171
+ mc->no_floppy = 1;
172
+ mc->no_cdrom = 1;
173
+ mc->no_parallel = 1;
174
+ mc->default_ram_id = "ram";
175
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a9");
176
+}
177
+
178
+/*
179
+ * Schematics:
180
+ * https://github.com/Nuvoton-Israel/nuvoton-info/blob/master/npcm7xx-poleg/evaluation-board/board_deliverables/NPCM750x_EB_ver.A1.1_COMPLETE.pdf
181
+ */
182
+static void npcm750_evb_machine_class_init(ObjectClass *oc, void *data)
183
+{
184
+ NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_CLASS(oc);
185
+ MachineClass *mc = MACHINE_CLASS(oc);
186
+
187
+ npcm7xx_set_soc_type(nmc, TYPE_NPCM750);
188
+
189
+ mc->desc = "Nuvoton NPCM750 Evaluation Board (Cortex A9)";
190
+ mc->init = npcm750_evb_init;
191
+ mc->default_ram_size = 512 * MiB;
192
+};
193
+
194
+static void gsj_machine_class_init(ObjectClass *oc, void *data)
195
+{
196
+ NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_CLASS(oc);
197
+ MachineClass *mc = MACHINE_CLASS(oc);
198
+
199
+ npcm7xx_set_soc_type(nmc, TYPE_NPCM730);
200
+
201
+ mc->desc = "Quanta GSJ (Cortex A9)";
202
+ mc->init = quanta_gsj_init;
203
+ mc->default_ram_size = 512 * MiB;
204
+};
205
+
206
+static const TypeInfo npcm7xx_machine_types[] = {
207
+ {
208
+ .name = TYPE_NPCM7XX_MACHINE,
209
+ .parent = TYPE_MACHINE,
210
+ .instance_size = sizeof(NPCM7xxMachine),
211
+ .class_size = sizeof(NPCM7xxMachineClass),
212
+ .class_init = npcm7xx_machine_class_init,
213
+ .abstract = true,
214
+ }, {
215
+ .name = MACHINE_TYPE_NAME("npcm750-evb"),
216
+ .parent = TYPE_NPCM7XX_MACHINE,
217
+ .class_init = npcm750_evb_machine_class_init,
218
+ }, {
219
+ .name = MACHINE_TYPE_NAME("quanta-gsj"),
220
+ .parent = TYPE_NPCM7XX_MACHINE,
221
+ .class_init = gsj_machine_class_init,
222
+ },
223
+};
224
+
225
+DEFINE_TYPES(npcm7xx_machine_types)
226
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
71
index XXXXXXX..XXXXXXX 100644
227
index XXXXXXX..XXXXXXX 100644
72
--- a/include/hw/char/nrf51_uart.h
228
--- a/hw/arm/meson.build
73
+++ b/include/hw/char/nrf51_uart.h
229
+++ b/hw/arm/meson.build
74
@@ -XXX,XX +XXX,XX @@
230
@@ -XXX,XX +XXX,XX @@ arm_ss.add(when: 'CONFIG_MICROBIT', if_true: files('microbit.c'))
75
#include "hw/registerfields.h"
231
arm_ss.add(when: 'CONFIG_MUSICPAL', if_true: files('musicpal.c'))
76
232
arm_ss.add(when: 'CONFIG_NETDUINO2', if_true: files('netduino2.c'))
77
#define UART_FIFO_LENGTH 6
233
arm_ss.add(when: 'CONFIG_NETDUINOPLUS2', if_true: files('netduinoplus2.c'))
78
-#define UART_BASE 0x40002000
234
-arm_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx.c'))
79
#define UART_SIZE 0x1000
235
+arm_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx.c', 'npcm7xx_boards.c'))
80
236
arm_ss.add(when: 'CONFIG_NSERIES', if_true: files('nseries.c'))
81
#define TYPE_NRF51_UART "nrf51_soc.uart"
237
arm_ss.add(when: 'CONFIG_SX1', if_true: files('omap_sx1.c'))
82
diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c
238
arm_ss.add(when: 'CONFIG_CHEETAH', if_true: files('palm.c'))
83
index XXXXXXX..XXXXXXX 100644
84
--- a/hw/arm/nrf51_soc.c
85
+++ b/hw/arm/nrf51_soc.c
86
@@ -XXX,XX +XXX,XX @@
87
#include "qemu/log.h"
88
#include "cpu.h"
89
90
+#include "hw/arm/nrf51.h"
91
#include "hw/arm/nrf51_soc.h"
92
93
-#define IOMEM_BASE 0x40000000
94
-#define IOMEM_SIZE 0x20000000
95
-
96
-#define FICR_BASE 0x10000000
97
-#define FICR_SIZE 0x000000fc
98
-
99
-#define FLASH_BASE 0x00000000
100
-#define SRAM_BASE 0x20000000
101
-
102
-#define PRIVATE_BASE 0xF0000000
103
-#define PRIVATE_SIZE 0x10000000
104
-
105
/*
106
* The size and base is for the NRF51822 part. If other parts
107
* are supported in the future, add a sub-class of NRF51SoC for
108
* the specific variants
109
*/
110
-#define NRF51822_FLASH_SIZE (256 * 1024)
111
-#define NRF51822_SRAM_SIZE (16 * 1024)
112
+#define NRF51822_FLASH_SIZE (256 * NRF51_PAGE_SIZE)
113
+#define NRF51822_SRAM_SIZE (16 * NRF51_PAGE_SIZE)
114
115
#define BASE_TO_IRQ(base) ((base >> 12) & 0x1F)
116
117
@@ -XXX,XX +XXX,XX @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
118
error_propagate(errp, err);
119
return;
120
}
121
- memory_region_add_subregion(&s->container, FLASH_BASE, &s->flash);
122
+ memory_region_add_subregion(&s->container, NRF51_FLASH_BASE, &s->flash);
123
124
memory_region_init_ram(&s->sram, NULL, "nrf51.sram", s->sram_size, &err);
125
if (err) {
126
error_propagate(errp, err);
127
return;
128
}
129
- memory_region_add_subregion(&s->container, SRAM_BASE, &s->sram);
130
+ memory_region_add_subregion(&s->container, NRF51_SRAM_BASE, &s->sram);
131
132
/* UART */
133
object_property_set_bool(OBJECT(&s->uart), true, "realized", &err);
134
@@ -XXX,XX +XXX,XX @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
135
return;
136
}
137
mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->uart), 0);
138
- memory_region_add_subregion_overlap(&s->container, UART_BASE, mr, 0);
139
+ memory_region_add_subregion_overlap(&s->container, NRF51_UART_BASE, mr, 0);
140
sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart), 0,
141
qdev_get_gpio_in(DEVICE(&s->cpu),
142
- BASE_TO_IRQ(UART_BASE)));
143
+ BASE_TO_IRQ(NRF51_UART_BASE)));
144
145
- create_unimplemented_device("nrf51_soc.io", IOMEM_BASE, IOMEM_SIZE);
146
- create_unimplemented_device("nrf51_soc.ficr", FICR_BASE, FICR_SIZE);
147
+ create_unimplemented_device("nrf51_soc.io", NRF51_IOMEM_BASE,
148
+ NRF51_IOMEM_SIZE);
149
+ create_unimplemented_device("nrf51_soc.ficr", NRF51_FICR_BASE,
150
+ NRF51_FICR_SIZE);
151
create_unimplemented_device("nrf51_soc.private",
152
- PRIVATE_BASE, PRIVATE_SIZE);
153
+ NRF51_PRIVATE_BASE, NRF51_PRIVATE_SIZE);
154
}
155
156
static void nrf51_soc_init(Object *obj)
157
--
239
--
158
2.19.2
240
2.20.1
159
241
160
242
diff view generated by jsdifflib
1
From: Luc Michel <luc.michel@greensocs.com>
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
2
3
Add support for the '!' extended mode packet. This is required for the
3
This is a minimalistic boot ROM written specifically for use with QEMU.
4
multiprocess extension.
4
It supports loading the second-stage loader from SPI flash into RAM, SMP
5
boot, and not much else.
5
6
6
Signed-off-by: Luc Michel <luc.michel@greensocs.com>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Acked-by: Alistair Francis <alistair.francis@wdc.com>
9
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
9
Message-id: 20181207090135.7651-12-luc.michel@greensocs.com
10
Message-id: 20200911052101.2602693-7-hskinnemoen@google.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
---
12
gdbstub.c | 3 +++
13
.gitmodules | 3 +++
13
1 file changed, 3 insertions(+)
14
MAINTAINERS | 2 ++
15
pc-bios/README | 6 ++++++
16
pc-bios/meson.build | 1 +
17
pc-bios/npcm7xx_bootrom.bin | Bin 0 -> 768 bytes
18
roms/Makefile | 7 +++++++
19
roms/vbootrom | 1 +
20
7 files changed, 20 insertions(+)
21
create mode 100644 pc-bios/npcm7xx_bootrom.bin
22
create mode 160000 roms/vbootrom
14
23
15
diff --git a/gdbstub.c b/gdbstub.c
24
diff --git a/.gitmodules b/.gitmodules
16
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
17
--- a/gdbstub.c
26
--- a/.gitmodules
18
+++ b/gdbstub.c
27
+++ b/.gitmodules
19
@@ -XXX,XX +XXX,XX @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
28
@@ -XXX,XX +XXX,XX @@
20
p = line_buf;
29
[submodule "meson"]
21
ch = *p++;
30
    path = meson
22
switch(ch) {
31
    url = https://github.com/mesonbuild/meson/
23
+ case '!':
32
+[submodule "roms/vbootrom"]
24
+ put_packet(s, "OK");
33
+    path = roms/vbootrom
25
+ break;
34
+    url = https://github.com/google/vbootrom.git
26
case '?':
35
diff --git a/MAINTAINERS b/MAINTAINERS
27
/* TODO: Make this return the correct value for user-mode. */
36
index XXXXXXX..XXXXXXX 100644
28
snprintf(buf, sizeof(buf), "T%02xthread:%s;", GDB_SIGNAL_TRAP,
37
--- a/MAINTAINERS
38
+++ b/MAINTAINERS
39
@@ -XXX,XX +XXX,XX @@ L: qemu-arm@nongnu.org
40
S: Supported
41
F: hw/*/npcm7xx*
42
F: include/hw/*/npcm7xx*
43
+F: pc-bios/npcm7xx_bootrom.bin
44
+F: roms/vbootrom
45
46
nSeries
47
M: Andrzej Zaborowski <balrogg@gmail.com>
48
diff --git a/pc-bios/README b/pc-bios/README
49
index XXXXXXX..XXXXXXX 100644
50
--- a/pc-bios/README
51
+++ b/pc-bios/README
52
@@ -XXX,XX +XXX,XX @@
53
("Simplified BSD License" or "FreeBSD License", SPDX: BSD-2-Clause). OpenSBI
54
source code also contains code reused from other projects desribed here:
55
https://github.com/riscv/opensbi/blob/master/ThirdPartyNotices.md.
56
+
57
+- npcm7xx_bootrom.bin is a simplified, free (Apache 2.0) boot ROM for Nuvoton
58
+ NPCM7xx BMC devices. It currently implements the bare minimum to load, parse,
59
+ initialize and run boot images stored in SPI flash, but may grow more
60
+ features over time as needed. The source code is available at:
61
+ https://github.com/google/vbootrom
62
diff --git a/pc-bios/meson.build b/pc-bios/meson.build
63
index XXXXXXX..XXXXXXX 100644
64
--- a/pc-bios/meson.build
65
+++ b/pc-bios/meson.build
66
@@ -XXX,XX +XXX,XX @@ blobs = files(
67
'opensbi-riscv64-generic-fw_dynamic.bin',
68
'opensbi-riscv32-generic-fw_dynamic.elf',
69
'opensbi-riscv64-generic-fw_dynamic.elf',
70
+ 'npcm7xx_bootrom.bin',
71
)
72
73
if install_blobs
74
diff --git a/pc-bios/npcm7xx_bootrom.bin b/pc-bios/npcm7xx_bootrom.bin
75
new file mode 100644
76
index XXXXXXX..XXXXXXX
77
GIT binary patch
78
literal 768
79
zcmd5)JxClu6n-<aczPbVhZYusb8wKx;7TklHfmuZdYT9pDRLwd1p_t-DFpWpyA+8(
80
zwKtZg3J4a0aCM3_X(ZL&4g;46VVk5e$K;z;L99|b@aE%v^S$rQ8)h(Vm@cB9IYc+2
81
z2SHd4^NwTIGE%w>9S05p1#kf90Sj5Z(jG8}+)IZIp~iXK=T&)dL`%d-q*8aR#mq{7
82
z9`=6;Dr(H0ACe72R5x?!)^86Qj-X%{+!K9iZNA@*wkBAV&iZ(l^I9?!Gz=S2I_*1d
83
zr+tTQDHjvyzKnw(hu00yX`u!Fv<!~XVcX?@kr#<B0(gGU?$W{gSsQa}CF^8Cfzp2X
84
z@P}yDV-bci(K9XL$FU!som2C`c)?Uc&294s^}Wzumap{hg1X^jN|V25M5tQZ=<9lN
85
z%(zKz#t-qCwHKb;HygOCpvCNL_4@1tXV1YGf^XUE_$zr{g8zWh-6gz-teI(eibtxo
86
z?0OZI4%rU0741PgUD`2xq@H|*4=+Rs?%N)Ox5G+q>C;DilBe_YlkeSUVHA-crNk+k
87
jtiF_MudA<CB(}8|fqYwCf3re&=&@_s761P#-ID$TwgmBa
88
89
literal 0
90
HcmV?d00001
91
92
diff --git a/roms/Makefile b/roms/Makefile
93
index XXXXXXX..XXXXXXX 100644
94
--- a/roms/Makefile
95
+++ b/roms/Makefile
96
@@ -XXX,XX +XXX,XX @@ find-cross-gcc = $(firstword $(wildcard $(patsubst %ld,%gcc,$(call find-cross-ld
97
# finally strip off path + toolname so we get the prefix
98
find-cross-prefix = $(subst gcc,,$(notdir $(call find-cross-gcc,$(1))))
99
100
+arm_cross_prefix := $(call find-cross-prefix,arm)
101
powerpc64_cross_prefix := $(call find-cross-prefix,powerpc64)
102
powerpc_cross_prefix := $(call find-cross-prefix,powerpc)
103
x86_64_cross_prefix := $(call find-cross-prefix,x86_64)
104
@@ -XXX,XX +XXX,XX @@ default help:
105
    @echo " skiboot -- update skiboot.lid"
106
    @echo " u-boot.e500 -- update u-boot.e500"
107
    @echo " u-boot.sam460 -- update u-boot.sam460"
108
+    @echo " npcm7xx_bootrom -- update vbootrom for npcm7xx"
109
    @echo " efi -- update UEFI (edk2) platform firmware"
110
    @echo " opensbi32-generic -- update OpenSBI for 32-bit generic machine"
111
    @echo " opensbi64-generic -- update OpenSBI for 64-bit generic machine"
112
@@ -XXX,XX +XXX,XX @@ bios-microvm:
113
    $(MAKE) -C qboot
114
    cp qboot/bios.bin ../pc-bios/bios-microvm.bin
115
116
+npcm7xx_bootrom:
117
+    $(MAKE) -C vbootrom CROSS_COMPILE=$(arm_cross_prefix)
118
+    cp vbootrom/npcm7xx_bootrom.bin ../pc-bios/npcm7xx_bootrom.bin
119
+
120
clean:
121
    rm -rf seabios/.config seabios/out seabios/builds
122
    $(MAKE) -C sgabios clean
123
@@ -XXX,XX +XXX,XX @@ clean:
124
    $(MAKE) -f Makefile.edk2 clean
125
    $(MAKE) -C opensbi clean
126
    $(MAKE) -C qboot clean
127
+    $(MAKE) -C vbootrom clean
128
diff --git a/roms/vbootrom b/roms/vbootrom
129
new file mode 160000
130
index XXXXXXX..XXXXXXX
131
--- /dev/null
132
+++ b/roms/vbootrom
133
@@ -0,0 +1 @@
134
+Subproject commit 0c37a43527f0ee2b9584e7fb2fdc805e902635ac
29
--
135
--
30
2.19.2
136
2.20.1
31
137
32
138
diff view generated by jsdifflib
1
From: Luc Michel <luc.michel@greensocs.com>
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
2
3
The gdb_get_cpu_pid() function does the PID lookup for the given CPU. It
3
If a -bios option is specified on the command line, load the image into
4
checks if the CPU is a direct child of a CPU cluster. If it is, the
4
the internal ROM memory region, which contains the first instructions
5
returned PID is the cluster ID plus one (cluster IDs start at 0, GDB
5
run by the CPU after reset.
6
PIDs at 1). When the CPU is not a child of such a container, the PID of
7
the default process is returned.
8
6
9
The gdb_fmt_thread_id() function generates the string to be used to identify
7
If -bios is not specified, the vbootrom included with qemu is loaded by
10
a given thread, in a response packet for the peer. This function
8
default.
11
supports generating thread IDs when multiprocess mode is enabled (in the
12
form `p<pid>.<tid>').
13
9
14
Use them in the reply to a '?' request.
10
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
15
11
Reviewed-by: Cédric Le Goater <clg@kaod.org>
16
Signed-off-by: Luc Michel <luc.michel@greensocs.com>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Acked-by: Alistair Francis <alistair.francis@wdc.com>
13
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
18
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
14
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
19
Message-id: 20181207090135.7651-4-luc.michel@greensocs.com
15
Message-id: 20200911052101.2602693-8-hskinnemoen@google.com
20
[PMM: fixed checkpatch blockquote style nit]
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
---
17
---
23
gdbstub.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
18
hw/arm/npcm7xx_boards.c | 32 ++++++++++++++++++++++++++++++++
24
1 file changed, 64 insertions(+), 2 deletions(-)
19
1 file changed, 32 insertions(+)
25
20
26
diff --git a/gdbstub.c b/gdbstub.c
21
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
27
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
28
--- a/gdbstub.c
23
--- a/hw/arm/npcm7xx_boards.c
29
+++ b/gdbstub.c
24
+++ b/hw/arm/npcm7xx_boards.c
30
@@ -XXX,XX +XXX,XX @@ static int memtox(char *buf, const char *mem, int len)
25
@@ -XXX,XX +XXX,XX @@
31
return p - buf;
26
#include "exec/address-spaces.h"
32
}
27
#include "hw/arm/npcm7xx.h"
33
28
#include "hw/core/cpu.h"
34
+static uint32_t gdb_get_cpu_pid(const GDBState *s, CPUState *cpu)
29
+#include "hw/loader.h"
30
#include "qapi/error.h"
31
+#include "qemu-common.h"
32
#include "qemu/units.h"
33
+#include "sysemu/sysemu.h"
34
35
#define NPCM750_EVB_POWER_ON_STRAPS 0x00001ff7
36
#define QUANTA_GSJ_POWER_ON_STRAPS 0x00001fff
37
38
+static const char npcm7xx_default_bootrom[] = "npcm7xx_bootrom.bin";
39
+
40
+static void npcm7xx_load_bootrom(MachineState *machine, NPCM7xxState *soc)
35
+{
41
+{
36
+#ifndef CONFIG_USER_ONLY
42
+ g_autofree char *filename = NULL;
37
+ gchar *path, *name = NULL;
43
+ int ret;
38
+ Object *obj;
39
+ CPUClusterState *cluster;
40
+ uint32_t ret;
41
+
44
+
42
+ path = object_get_canonical_path(OBJECT(cpu));
45
+ if (!bios_name) {
43
+
46
+ bios_name = npcm7xx_default_bootrom;
44
+ if (path == NULL) {
45
+ /* Return the default process' PID */
46
+ ret = s->processes[s->process_num - 1].pid;
47
+ goto out;
48
+ }
47
+ }
49
+
48
+
50
+ name = object_get_canonical_path_component(OBJECT(cpu));
49
+ filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
51
+ assert(name != NULL);
50
+ if (!filename) {
52
+
51
+ error_report("Could not find ROM image '%s'", bios_name);
53
+ /*
52
+ if (!machine->kernel_filename) {
54
+ * Retrieve the CPU parent path by removing the last '/' and the CPU name
53
+ /* We can't boot without a bootrom or a kernel image. */
55
+ * from the CPU canonical path.
54
+ exit(1);
56
+ */
55
+ }
57
+ path[strlen(path) - strlen(name) - 1] = '\0';
56
+ return;
58
+
59
+ obj = object_resolve_path_type(path, TYPE_CPU_CLUSTER, NULL);
60
+
61
+ if (obj == NULL) {
62
+ /* Return the default process' PID */
63
+ ret = s->processes[s->process_num - 1].pid;
64
+ goto out;
65
+ }
57
+ }
66
+
58
+ ret = load_image_mr(filename, &soc->irom);
67
+ cluster = CPU_CLUSTER(obj);
59
+ if (ret < 0) {
68
+ ret = cluster->cluster_id + 1;
60
+ error_report("Failed to load ROM image '%s'", filename);
69
+
61
+ exit(1);
70
+out:
62
+ }
71
+ g_free(name);
72
+ g_free(path);
73
+
74
+ return ret;
75
+
76
+#else
77
+ /* TODO: In user mode, we should use the task state PID */
78
+ return s->processes[s->process_num - 1].pid;
79
+#endif
80
+}
63
+}
81
+
64
+
82
static const char *get_feature_xml(const char *p, const char **newp,
65
static void npcm7xx_connect_dram(NPCM7xxState *soc, MemoryRegion *dram)
83
CPUClass *cc)
84
{
66
{
85
@@ -XXX,XX +XXX,XX @@ static CPUState *find_cpu(uint32_t thread_id)
67
memory_region_add_subregion(get_system_memory(), NPCM7XX_DRAM_BA, dram);
86
return NULL;
68
@@ -XXX,XX +XXX,XX @@ static void npcm750_evb_init(MachineState *machine)
69
npcm7xx_connect_dram(soc, machine->ram);
70
qdev_realize(DEVICE(soc), NULL, &error_fatal);
71
72
+ npcm7xx_load_bootrom(machine, soc);
73
npcm7xx_load_kernel(machine, soc);
87
}
74
}
88
75
89
+static char *gdb_fmt_thread_id(const GDBState *s, CPUState *cpu,
76
@@ -XXX,XX +XXX,XX @@ static void quanta_gsj_init(MachineState *machine)
90
+ char *buf, size_t buf_size)
77
npcm7xx_connect_dram(soc, machine->ram);
91
+{
78
qdev_realize(DEVICE(soc), NULL, &error_fatal);
92
+ if (s->multiprocess) {
79
93
+ snprintf(buf, buf_size, "p%02x.%02x",
80
+ npcm7xx_load_bootrom(machine, soc);
94
+ gdb_get_cpu_pid(s, cpu), cpu_gdb_index(cpu));
81
npcm7xx_load_kernel(machine, soc);
95
+ } else {
82
}
96
+ snprintf(buf, buf_size, "%02x", cpu_gdb_index(cpu));
83
97
+ }
98
+
99
+ return buf;
100
+}
101
+
102
static int is_query_packet(const char *p, const char *query, char separator)
103
{
104
unsigned int query_len = strlen(query);
105
@@ -XXX,XX +XXX,XX @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
106
int ch, reg_size, type, res;
107
uint8_t mem_buf[MAX_PACKET_LENGTH];
108
char buf[sizeof(mem_buf) + 1 /* trailing NUL */];
109
+ char thread_id[16];
110
uint8_t *registers;
111
target_ulong addr, len;
112
113
@@ -XXX,XX +XXX,XX @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
114
switch(ch) {
115
case '?':
116
/* TODO: Make this return the correct value for user-mode. */
117
- snprintf(buf, sizeof(buf), "T%02xthread:%02x;", GDB_SIGNAL_TRAP,
118
- cpu_gdb_index(s->c_cpu));
119
+ snprintf(buf, sizeof(buf), "T%02xthread:%s;", GDB_SIGNAL_TRAP,
120
+ gdb_fmt_thread_id(s, s->c_cpu, thread_id, sizeof(thread_id)));
121
put_packet(s, buf);
122
/* Remove all the breakpoints when this query is issued,
123
* because gdb is doing and initial connect and the state
124
--
84
--
125
2.19.2
85
2.20.1
126
86
127
87
diff view generated by jsdifflib
1
From: Steffen Görtz <contrib@steffen-goertz.de>
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
2
3
This adds a model of the nRF51 GPIO peripheral.
3
This supports reading and writing OTP fuses and keys. Only fuse reading
4
has been tested. Protection is not implemented.
4
5
5
Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.pdf
6
Reviewed-by: Avi Fishman <avi.fishman@nuvoton.com>
6
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
The nRF51 series microcontrollers support up to 32 GPIO pins in various configurations.
8
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
The pins can be used as input pins with pull-ups or pull-down.
9
Tested-by: Alexander Bulekov <alxndr@bu.edu>
9
Furthermore, three different output driver modes per level are
10
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
10
available (disconnected, standard, high-current).
11
Message-id: 20200911052101.2602693-9-hskinnemoen@google.com
11
12
The GPIO-Peripheral has a mechanism for detecting level changes which is
13
not featured in this model.
14
15
Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
16
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
17
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
19
Message-id: 20190103091119.9367-6-stefanha@redhat.com
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
---
13
---
22
Makefile.objs | 1 +
14
include/hw/arm/npcm7xx.h | 3 +
23
hw/gpio/Makefile.objs | 1 +
15
include/hw/nvram/npcm7xx_otp.h | 79 ++++++
24
include/hw/gpio/nrf51_gpio.h | 69 ++++++++
16
hw/arm/npcm7xx.c | 29 +++
25
hw/gpio/nrf51_gpio.c | 300 +++++++++++++++++++++++++++++++++++
17
hw/nvram/npcm7xx_otp.c | 440 +++++++++++++++++++++++++++++++++
26
hw/gpio/trace-events | 7 +
18
hw/nvram/meson.build | 1 +
27
5 files changed, 378 insertions(+)
19
5 files changed, 552 insertions(+)
28
create mode 100644 include/hw/gpio/nrf51_gpio.h
20
create mode 100644 include/hw/nvram/npcm7xx_otp.h
29
create mode 100644 hw/gpio/nrf51_gpio.c
21
create mode 100644 hw/nvram/npcm7xx_otp.c
30
create mode 100644 hw/gpio/trace-events
31
22
32
diff --git a/Makefile.objs b/Makefile.objs
23
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
33
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
34
--- a/Makefile.objs
25
--- a/include/hw/arm/npcm7xx.h
35
+++ b/Makefile.objs
26
+++ b/include/hw/arm/npcm7xx.h
36
@@ -XXX,XX +XXX,XX @@ trace-events-subdirs += hw/vfio
27
@@ -XXX,XX +XXX,XX @@
37
trace-events-subdirs += hw/virtio
28
#include "hw/cpu/a9mpcore.h"
38
trace-events-subdirs += hw/watchdog
29
#include "hw/misc/npcm7xx_clk.h"
39
trace-events-subdirs += hw/xen
30
#include "hw/misc/npcm7xx_gcr.h"
40
+trace-events-subdirs += hw/gpio
31
+#include "hw/nvram/npcm7xx_otp.h"
41
trace-events-subdirs += io
32
#include "hw/timer/npcm7xx_timer.h"
42
trace-events-subdirs += linux-user
33
#include "target/arm/cpu.h"
43
trace-events-subdirs += migration
34
44
diff --git a/hw/gpio/Makefile.objs b/hw/gpio/Makefile.objs
35
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
45
index XXXXXXX..XXXXXXX 100644
36
NPCM7xxGCRState gcr;
46
--- a/hw/gpio/Makefile.objs
37
NPCM7xxCLKState clk;
47
+++ b/hw/gpio/Makefile.objs
38
NPCM7xxTimerCtrlState tim[3];
48
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_GPIO_KEY) += gpio_key.o
39
+ NPCM7xxOTPState key_storage;
49
obj-$(CONFIG_OMAP) += omap_gpio.o
40
+ NPCM7xxOTPState fuse_array;
50
obj-$(CONFIG_IMX) += imx_gpio.o
41
} NPCM7xxState;
51
obj-$(CONFIG_RASPI) += bcm2835_gpio.o
42
52
+obj-$(CONFIG_NRF51_SOC) += nrf51_gpio.o
43
#define TYPE_NPCM7XX "npcm7xx"
53
diff --git a/include/hw/gpio/nrf51_gpio.h b/include/hw/gpio/nrf51_gpio.h
44
diff --git a/include/hw/nvram/npcm7xx_otp.h b/include/hw/nvram/npcm7xx_otp.h
54
new file mode 100644
45
new file mode 100644
55
index XXXXXXX..XXXXXXX
46
index XXXXXXX..XXXXXXX
56
--- /dev/null
47
--- /dev/null
57
+++ b/include/hw/gpio/nrf51_gpio.h
48
+++ b/include/hw/nvram/npcm7xx_otp.h
58
@@ -XXX,XX +XXX,XX @@
49
@@ -XXX,XX +XXX,XX @@
59
+/*
50
+/*
60
+ * nRF51 System-on-Chip general purpose input/output register definition
51
+ * Nuvoton NPCM7xx OTP (Fuse Array) Interface
61
+ *
52
+ *
62
+ * QEMU interface:
53
+ * Copyright 2020 Google LLC
63
+ * + sysbus MMIO regions 0: GPIO registers
54
+ *
64
+ * + Unnamed GPIO inputs 0-31: Set tri-state input level for GPIO pin.
55
+ * This program is free software; you can redistribute it and/or modify it
65
+ * Level -1: Externally Disconnected/Floating; Pull-up/down will be regarded
56
+ * under the terms of the GNU General Public License as published by the
66
+ * Level 0: Input externally driven LOW
57
+ * Free Software Foundation; either version 2 of the License, or
67
+ * Level 1: Input externally driven HIGH
58
+ * (at your option) any later version.
68
+ * + Unnamed GPIO outputs 0-31:
59
+ *
69
+ * Level -1: Disconnected/Floating
60
+ * This program is distributed in the hope that it will be useful, but WITHOUT
70
+ * Level 0: Driven LOW
61
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
71
+ * Level 1: Driven HIGH
62
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
72
+ *
63
+ * for more details.
73
+ * Accuracy of the peripheral model:
74
+ * + The nRF51 GPIO output driver supports two modes, standard and high-current
75
+ * mode. These different drive modes are not modeled and handled the same.
76
+ * + Pin SENSEing is not modeled/implemented.
77
+ *
78
+ * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
79
+ *
80
+ * This code is licensed under the GPL version 2 or later. See
81
+ * the COPYING file in the top-level directory.
82
+ *
83
+ */
64
+ */
84
+#ifndef NRF51_GPIO_H
65
+#ifndef NPCM7XX_OTP_H
85
+#define NRF51_GPIO_H
66
+#define NPCM7XX_OTP_H
86
+
67
+
68
+#include "exec/memory.h"
87
+#include "hw/sysbus.h"
69
+#include "hw/sysbus.h"
88
+#define TYPE_NRF51_GPIO "nrf51_soc.gpio"
70
+
89
+#define NRF51_GPIO(obj) OBJECT_CHECK(NRF51GPIOState, (obj), TYPE_NRF51_GPIO)
71
+/* Each OTP module holds 8192 bits of one-time programmable storage */
90
+
72
+#define NPCM7XX_OTP_ARRAY_BITS (8192)
91
+#define NRF51_GPIO_PINS 32
73
+#define NPCM7XX_OTP_ARRAY_BYTES (NPCM7XX_OTP_ARRAY_BITS / BITS_PER_BYTE)
92
+
74
+
93
+#define NRF51_GPIO_SIZE 0x1000
75
+/* Fuse array offsets */
94
+
76
+#define NPCM7XX_FUSE_FUSTRAP (0)
95
+#define NRF51_GPIO_REG_OUT 0x504
77
+#define NPCM7XX_FUSE_CP_FUSTRAP (12)
96
+#define NRF51_GPIO_REG_OUTSET 0x508
78
+#define NPCM7XX_FUSE_DAC_CALIB (16)
97
+#define NRF51_GPIO_REG_OUTCLR 0x50C
79
+#define NPCM7XX_FUSE_ADC_CALIB (24)
98
+#define NRF51_GPIO_REG_IN 0x510
80
+#define NPCM7XX_FUSE_DERIVATIVE (64)
99
+#define NRF51_GPIO_REG_DIR 0x514
81
+#define NPCM7XX_FUSE_TEST_SIG (72)
100
+#define NRF51_GPIO_REG_DIRSET 0x518
82
+#define NPCM7XX_FUSE_DIE_LOCATION (74)
101
+#define NRF51_GPIO_REG_DIRCLR 0x51C
83
+#define NPCM7XX_FUSE_GP1 (80)
102
+#define NRF51_GPIO_REG_CNF_START 0x700
84
+#define NPCM7XX_FUSE_GP2 (128)
103
+#define NRF51_GPIO_REG_CNF_END 0x77F
85
+
104
+
86
+/*
105
+#define NRF51_GPIO_PULLDOWN 1
87
+ * Number of registers in our device state structure. Don't change this without
106
+#define NRF51_GPIO_PULLUP 3
88
+ * incrementing the version_id in the vmstate.
107
+
89
+ */
108
+typedef struct NRF51GPIOState {
90
+#define NPCM7XX_OTP_NR_REGS (0x18 / sizeof(uint32_t))
109
+ SysBusDevice parent_obj;
91
+
92
+/**
93
+ * struct NPCM7xxOTPState - Device state for one OTP module.
94
+ * @parent: System bus device.
95
+ * @mmio: Memory region through which registers are accessed.
96
+ * @regs: Register contents.
97
+ * @array: OTP storage array.
98
+ */
99
+typedef struct NPCM7xxOTPState {
100
+ SysBusDevice parent;
110
+
101
+
111
+ MemoryRegion mmio;
102
+ MemoryRegion mmio;
112
+ qemu_irq irq;
103
+ uint32_t regs[NPCM7XX_OTP_NR_REGS];
113
+
104
+ uint8_t array[NPCM7XX_OTP_ARRAY_BYTES];
114
+ uint32_t out;
105
+} NPCM7xxOTPState;
115
+ uint32_t in;
106
+
116
+ uint32_t in_mask;
107
+#define TYPE_NPCM7XX_OTP "npcm7xx-otp"
117
+ uint32_t dir;
108
+#define NPCM7XX_OTP(obj) OBJECT_CHECK(NPCM7xxOTPState, (obj), TYPE_NPCM7XX_OTP)
118
+ uint32_t cnf[NRF51_GPIO_PINS];
109
+
119
+
110
+#define TYPE_NPCM7XX_KEY_STORAGE "npcm7xx-key-storage"
120
+ uint32_t old_out;
111
+#define TYPE_NPCM7XX_FUSE_ARRAY "npcm7xx-fuse-array"
121
+ uint32_t old_out_connected;
112
+
122
+
113
+typedef struct NPCM7xxOTPClass NPCM7xxOTPClass;
123
+ qemu_irq output[NRF51_GPIO_PINS];
114
+
124
+} NRF51GPIOState;
115
+/**
125
+
116
+ * npcm7xx_otp_array_write - ECC encode and write data to OTP array.
126
+
117
+ * @s: OTP module.
127
+#endif
118
+ * @data: Data to be encoded and written.
128
diff --git a/hw/gpio/nrf51_gpio.c b/hw/gpio/nrf51_gpio.c
119
+ * @offset: Offset of first byte to be written in the OTP array.
120
+ * @len: Number of bytes before ECC encoding.
121
+ *
122
+ * Each nibble of data is encoded into a byte, so the number of bytes written
123
+ * to the array will be @len * 2.
124
+ */
125
+extern void npcm7xx_otp_array_write(NPCM7xxOTPState *s, const void *data,
126
+ unsigned int offset, unsigned int len);
127
+
128
+#endif /* NPCM7XX_OTP_H */
129
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
130
index XXXXXXX..XXXXXXX 100644
131
--- a/hw/arm/npcm7xx.c
132
+++ b/hw/arm/npcm7xx.c
133
@@ -XXX,XX +XXX,XX @@
134
#define NPCM7XX_MMIO_BA (0x80000000)
135
#define NPCM7XX_MMIO_SZ (0x7ffd0000)
136
137
+/* OTP key storage and fuse strap array */
138
+#define NPCM7XX_OTP1_BA (0xf0189000)
139
+#define NPCM7XX_OTP2_BA (0xf018a000)
140
+
141
/* Core system modules. */
142
#define NPCM7XX_L2C_BA (0xf03fc000)
143
#define NPCM7XX_CPUP_BA (0xf03fe000)
144
@@ -XXX,XX +XXX,XX @@ void npcm7xx_load_kernel(MachineState *machine, NPCM7xxState *soc)
145
arm_load_kernel(&soc->cpu[0], machine, &npcm7xx_binfo);
146
}
147
148
+static void npcm7xx_init_fuses(NPCM7xxState *s)
149
+{
150
+ NPCM7xxClass *nc = NPCM7XX_GET_CLASS(s);
151
+ uint32_t value;
152
+
153
+ /*
154
+ * The initial mask of disabled modules indicates the chip derivative (e.g.
155
+ * NPCM750 or NPCM730).
156
+ */
157
+ value = tswap32(nc->disabled_modules);
158
+ npcm7xx_otp_array_write(&s->fuse_array, &value, NPCM7XX_FUSE_DERIVATIVE,
159
+ sizeof(value));
160
+}
161
+
162
static qemu_irq npcm7xx_irq(NPCM7xxState *s, int n)
163
{
164
return qdev_get_gpio_in(DEVICE(&s->a9mpcore), n);
165
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
166
object_property_add_alias(obj, "power-on-straps", OBJECT(&s->gcr),
167
"power-on-straps");
168
object_initialize_child(obj, "clk", &s->clk, TYPE_NPCM7XX_CLK);
169
+ object_initialize_child(obj, "otp1", &s->key_storage,
170
+ TYPE_NPCM7XX_KEY_STORAGE);
171
+ object_initialize_child(obj, "otp2", &s->fuse_array,
172
+ TYPE_NPCM7XX_FUSE_ARRAY);
173
174
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
175
object_initialize_child(obj, "tim[*]", &s->tim[i], TYPE_NPCM7XX_TIMER);
176
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
177
sysbus_realize(SYS_BUS_DEVICE(&s->clk), &error_abort);
178
sysbus_mmio_map(SYS_BUS_DEVICE(&s->clk), 0, NPCM7XX_CLK_BA);
179
180
+ /* OTP key storage and fuse strap array. Cannot fail. */
181
+ sysbus_realize(SYS_BUS_DEVICE(&s->key_storage), &error_abort);
182
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->key_storage), 0, NPCM7XX_OTP1_BA);
183
+ sysbus_realize(SYS_BUS_DEVICE(&s->fuse_array), &error_abort);
184
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->fuse_array), 0, NPCM7XX_OTP2_BA);
185
+ npcm7xx_init_fuses(s);
186
+
187
/* Timer Modules (TIM). Cannot fail. */
188
QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_tim_addr) != ARRAY_SIZE(s->tim));
189
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
190
diff --git a/hw/nvram/npcm7xx_otp.c b/hw/nvram/npcm7xx_otp.c
129
new file mode 100644
191
new file mode 100644
130
index XXXXXXX..XXXXXXX
192
index XXXXXXX..XXXXXXX
131
--- /dev/null
193
--- /dev/null
132
+++ b/hw/gpio/nrf51_gpio.c
194
+++ b/hw/nvram/npcm7xx_otp.c
133
@@ -XXX,XX +XXX,XX @@
195
@@ -XXX,XX +XXX,XX @@
134
+/*
196
+/*
135
+ * nRF51 System-on-Chip general purpose input/output register definition
197
+ * Nuvoton NPCM7xx OTP (Fuse Array) Interface
136
+ *
198
+ *
137
+ * Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.pdf
199
+ * Copyright 2020 Google LLC
138
+ * Product Spec: http://infocenter.nordicsemi.com/pdf/nRF51822_PS_v3.1.pdf
200
+ *
139
+ *
201
+ * This program is free software; you can redistribute it and/or modify it
140
+ * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
202
+ * under the terms of the GNU General Public License as published by the
141
+ *
203
+ * Free Software Foundation; either version 2 of the License, or
142
+ * This code is licensed under the GPL version 2 or later. See
204
+ * (at your option) any later version.
143
+ * the COPYING file in the top-level directory.
205
+ *
206
+ * This program is distributed in the hope that it will be useful, but WITHOUT
207
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
208
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
209
+ * for more details.
144
+ */
210
+ */
145
+
211
+
146
+#include "qemu/osdep.h"
212
+#include "qemu/osdep.h"
213
+
214
+#include "hw/nvram/npcm7xx_otp.h"
215
+#include "migration/vmstate.h"
216
+#include "qapi/error.h"
217
+#include "qemu/bitops.h"
147
+#include "qemu/log.h"
218
+#include "qemu/log.h"
148
+#include "hw/gpio/nrf51_gpio.h"
219
+#include "qemu/module.h"
149
+#include "trace.h"
220
+#include "qemu/units.h"
150
+
221
+
151
+/*
222
+/* Each module has 4 KiB of register space. Only a fraction of it is used. */
152
+ * Check if the output driver is connected to the direction switch
223
+#define NPCM7XX_OTP_REGS_SIZE (4 * KiB)
153
+ * given the current configuration and logic level.
224
+
154
+ * It is not differentiated between standard and "high"(-power) drive modes.
225
+/* 32-bit register indices. */
226
+typedef enum NPCM7xxOTPRegister {
227
+ NPCM7XX_OTP_FST,
228
+ NPCM7XX_OTP_FADDR,
229
+ NPCM7XX_OTP_FDATA,
230
+ NPCM7XX_OTP_FCFG,
231
+ /* Offset 0x10 is FKEYIND in OTP1, FUSTRAP in OTP2 */
232
+ NPCM7XX_OTP_FKEYIND = 0x0010 / sizeof(uint32_t),
233
+ NPCM7XX_OTP_FUSTRAP = 0x0010 / sizeof(uint32_t),
234
+ NPCM7XX_OTP_FCTL,
235
+ NPCM7XX_OTP_REGS_END,
236
+} NPCM7xxOTPRegister;
237
+
238
+/* Register field definitions. */
239
+#define FST_RIEN BIT(2)
240
+#define FST_RDST BIT(1)
241
+#define FST_RDY BIT(0)
242
+#define FST_RO_MASK (FST_RDST | FST_RDY)
243
+
244
+#define FADDR_BYTEADDR(rv) extract32((rv), 0, 10)
245
+#define FADDR_BITPOS(rv) extract32((rv), 10, 3)
246
+
247
+#define FDATA_CLEAR 0x00000001
248
+
249
+#define FCFG_FDIS BIT(31)
250
+#define FCFG_FCFGLK_MASK 0x00ff0000
251
+
252
+#define FCTL_PROG_CMD1 0x00000001
253
+#define FCTL_PROG_CMD2 0xbf79e5d0
254
+#define FCTL_READ_CMD 0x00000002
255
+
256
+/**
257
+ * struct NPCM7xxOTPClass - OTP module class.
258
+ * @parent: System bus device class.
259
+ * @mmio_ops: MMIO register operations for this type of module.
260
+ *
261
+ * The two OTP modules (key-storage and fuse-array) have slightly different
262
+ * behavior, so we give them different MMIO register operations.
155
+ */
263
+ */
156
+static bool is_connected(uint32_t config, uint32_t level)
264
+struct NPCM7xxOTPClass {
157
+{
265
+ SysBusDeviceClass parent;
158
+ bool state;
266
+
159
+ uint32_t drive_config = extract32(config, 8, 3);
267
+ const MemoryRegionOps *mmio_ops;
160
+
268
+};
161
+ switch (drive_config) {
269
+
162
+ case 0 ... 3:
270
+#define NPCM7XX_OTP_CLASS(klass) \
163
+ state = true;
271
+ OBJECT_CLASS_CHECK(NPCM7xxOTPClass, (klass), TYPE_NPCM7XX_OTP)
164
+ break;
272
+#define NPCM7XX_OTP_GET_CLASS(obj) \
165
+ case 4 ... 5:
273
+ OBJECT_GET_CLASS(NPCM7xxOTPClass, (obj), TYPE_NPCM7XX_OTP)
166
+ state = level != 0;
274
+
167
+ break;
275
+static uint8_t ecc_encode_nibble(uint8_t n)
168
+ case 6 ... 7:
276
+{
169
+ state = level == 0;
277
+ uint8_t result = n;
170
+ break;
278
+
279
+ result |= (((n >> 0) & 1) ^ ((n >> 1) & 1)) << 4;
280
+ result |= (((n >> 2) & 1) ^ ((n >> 3) & 1)) << 5;
281
+ result |= (((n >> 0) & 1) ^ ((n >> 2) & 1)) << 6;
282
+ result |= (((n >> 1) & 1) ^ ((n >> 3) & 1)) << 7;
283
+
284
+ return result;
285
+}
286
+
287
+void npcm7xx_otp_array_write(NPCM7xxOTPState *s, const void *data,
288
+ unsigned int offset, unsigned int len)
289
+{
290
+ const uint8_t *src = data;
291
+ uint8_t *dst = &s->array[offset];
292
+
293
+ while (len-- > 0) {
294
+ uint8_t c = *src++;
295
+
296
+ *dst++ = ecc_encode_nibble(extract8(c, 0, 4));
297
+ *dst++ = ecc_encode_nibble(extract8(c, 4, 4));
298
+ }
299
+}
300
+
301
+/* Common register read handler for both OTP classes. */
302
+static uint64_t npcm7xx_otp_read(NPCM7xxOTPState *s, NPCM7xxOTPRegister reg)
303
+{
304
+ uint32_t value = 0;
305
+
306
+ switch (reg) {
307
+ case NPCM7XX_OTP_FST:
308
+ case NPCM7XX_OTP_FADDR:
309
+ case NPCM7XX_OTP_FDATA:
310
+ case NPCM7XX_OTP_FCFG:
311
+ value = s->regs[reg];
312
+ break;
313
+
314
+ case NPCM7XX_OTP_FCTL:
315
+ qemu_log_mask(LOG_GUEST_ERROR,
316
+ "%s: read from write-only FCTL register\n",
317
+ DEVICE(s)->canonical_path);
318
+ break;
319
+
171
+ default:
320
+ default:
172
+ g_assert_not_reached();
321
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: read from invalid offset 0x%zx\n",
322
+ DEVICE(s)->canonical_path, reg * sizeof(uint32_t));
173
+ break;
323
+ break;
174
+ }
324
+ }
175
+
325
+
176
+ return state;
326
+ return value;
177
+}
327
+}
178
+
328
+
179
+static void update_output_irq(NRF51GPIOState *s, size_t i,
329
+/* Read a byte from the OTP array into the data register. */
180
+ bool connected, bool level)
330
+static void npcm7xx_otp_read_array(NPCM7xxOTPState *s)
181
+{
331
+{
182
+ int64_t irq_level = connected ? level : -1;
332
+ uint32_t faddr = s->regs[NPCM7XX_OTP_FADDR];
183
+ bool old_connected = extract32(s->old_out_connected, i, 1);
333
+
184
+ bool old_level = extract32(s->old_out, i, 1);
334
+ s->regs[NPCM7XX_OTP_FDATA] = s->array[FADDR_BYTEADDR(faddr)];
185
+
335
+ s->regs[NPCM7XX_OTP_FST] |= FST_RDST | FST_RDY;
186
+ if ((old_connected != connected) || (old_level != level)) {
336
+}
187
+ qemu_set_irq(s->output[i], irq_level);
337
+
188
+ trace_nrf51_gpio_update_output_irq(i, irq_level);
338
+/* Program a byte from the data register into the OTP array. */
339
+static void npcm7xx_otp_program_array(NPCM7xxOTPState *s)
340
+{
341
+ uint32_t faddr = s->regs[NPCM7XX_OTP_FADDR];
342
+
343
+ /* Bits can only go 0->1, never 1->0. */
344
+ s->array[FADDR_BYTEADDR(faddr)] |= (1U << FADDR_BITPOS(faddr));
345
+ s->regs[NPCM7XX_OTP_FST] |= FST_RDST | FST_RDY;
346
+}
347
+
348
+/* Compute the next value of the FCFG register. */
349
+static uint32_t npcm7xx_otp_compute_fcfg(uint32_t cur_value, uint32_t new_value)
350
+{
351
+ uint32_t lock_mask;
352
+ uint32_t value;
353
+
354
+ /*
355
+ * FCFGLK holds sticky bits 16..23, indicating which bits in FPRGLK (8..15)
356
+ * and FRDLK (0..7) that are read-only.
357
+ */
358
+ lock_mask = (cur_value & FCFG_FCFGLK_MASK) >> 8;
359
+ lock_mask |= lock_mask >> 8;
360
+ /* FDIS and FCFGLK bits are sticky (write 1 to set; can't clear). */
361
+ value = cur_value & (FCFG_FDIS | FCFG_FCFGLK_MASK);
362
+ /* Preserve read-only bits in FPRGLK and FRDLK */
363
+ value |= cur_value & lock_mask;
364
+ /* Set all bits that aren't read-only. */
365
+ value |= new_value & ~lock_mask;
366
+
367
+ return value;
368
+}
369
+
370
+/* Common register write handler for both OTP classes. */
371
+static void npcm7xx_otp_write(NPCM7xxOTPState *s, NPCM7xxOTPRegister reg,
372
+ uint32_t value)
373
+{
374
+ switch (reg) {
375
+ case NPCM7XX_OTP_FST:
376
+ /* RDST is cleared by writing 1 to it. */
377
+ if (value & FST_RDST) {
378
+ s->regs[NPCM7XX_OTP_FST] &= ~FST_RDST;
379
+ }
380
+ /* Preserve read-only and write-one-to-clear bits */
381
+ value &= ~FST_RO_MASK;
382
+ value |= s->regs[NPCM7XX_OTP_FST] & FST_RO_MASK;
383
+ break;
384
+
385
+ case NPCM7XX_OTP_FADDR:
386
+ break;
387
+
388
+ case NPCM7XX_OTP_FDATA:
389
+ /*
390
+ * This register is cleared by writing a magic value to it; no other
391
+ * values can be written.
392
+ */
393
+ if (value == FDATA_CLEAR) {
394
+ value = 0;
395
+ } else {
396
+ value = s->regs[NPCM7XX_OTP_FDATA];
397
+ }
398
+ break;
399
+
400
+ case NPCM7XX_OTP_FCFG:
401
+ value = npcm7xx_otp_compute_fcfg(s->regs[NPCM7XX_OTP_FCFG], value);
402
+ break;
403
+
404
+ case NPCM7XX_OTP_FCTL:
405
+ switch (value) {
406
+ case FCTL_READ_CMD:
407
+ npcm7xx_otp_read_array(s);
408
+ break;
409
+
410
+ case FCTL_PROG_CMD1:
411
+ /*
412
+ * Programming requires writing two separate magic values to this
413
+ * register; this is the first one. Just store it so it can be
414
+ * verified later when the second magic value is received.
415
+ */
416
+ break;
417
+
418
+ case FCTL_PROG_CMD2:
419
+ /*
420
+ * Only initiate programming if we received the first half of the
421
+ * command immediately before this one.
422
+ */
423
+ if (s->regs[NPCM7XX_OTP_FCTL] == FCTL_PROG_CMD1) {
424
+ npcm7xx_otp_program_array(s);
425
+ }
426
+ break;
427
+
428
+ default:
429
+ qemu_log_mask(LOG_GUEST_ERROR,
430
+ "%s: unrecognized FCNTL value 0x%" PRIx32 "\n",
431
+ DEVICE(s)->canonical_path, value);
432
+ break;
433
+ }
434
+ if (value != FCTL_PROG_CMD1) {
435
+ value = 0;
436
+ }
437
+ break;
438
+
439
+ default:
440
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: write to invalid offset 0x%zx\n",
441
+ DEVICE(s)->canonical_path, reg * sizeof(uint32_t));
442
+ return;
189
+ }
443
+ }
190
+
444
+
191
+ s->old_out = deposit32(s->old_out, i, 1, level);
445
+ s->regs[reg] = value;
192
+ s->old_out_connected = deposit32(s->old_out_connected, i, 1, connected);
446
+}
193
+}
447
+
194
+
448
+/* Register read handler specific to the fuse array OTP module. */
195
+static void update_state(NRF51GPIOState *s)
449
+static uint64_t npcm7xx_fuse_array_read(void *opaque, hwaddr addr,
196
+{
450
+ unsigned int size)
197
+ uint32_t pull;
451
+{
198
+ size_t i;
452
+ NPCM7xxOTPRegister reg = addr / sizeof(uint32_t);
199
+ bool connected_out, dir, connected_in, out, input;
453
+ NPCM7xxOTPState *s = opaque;
200
+
454
+ uint32_t value;
201
+ for (i = 0; i < NRF51_GPIO_PINS; i++) {
455
+
202
+ pull = extract32(s->cnf[i], 2, 2);
456
+ /*
203
+ dir = extract32(s->cnf[i], 0, 1);
457
+ * Only the Fuse Strap register needs special handling; all other registers
204
+ connected_in = extract32(s->in_mask, i, 1);
458
+ * work the same way for both kinds of OTP modules.
205
+ out = extract32(s->out, i, 1);
459
+ */
206
+ input = !extract32(s->cnf[i], 1, 1);
460
+ if (reg != NPCM7XX_OTP_FUSTRAP) {
207
+ connected_out = is_connected(s->cnf[i], out) && dir;
461
+ value = npcm7xx_otp_read(s, reg);
208
+
462
+ } else {
209
+ update_output_irq(s, i, connected_out, out);
463
+ /* FUSTRAP is stored as three copies in the OTP array. */
210
+
464
+ uint32_t fustrap[3];
211
+ /* Pin both driven externally and internally */
465
+
212
+ if (connected_out && connected_in) {
466
+ memcpy(fustrap, &s->array[0], sizeof(fustrap));
213
+ qemu_log_mask(LOG_GUEST_ERROR, "GPIO pin %zu short circuited\n", i);
467
+
214
+ }
468
+ /* Determine value by a majority vote on each bit. */
215
+
469
+ value = (fustrap[0] & fustrap[1]) | (fustrap[0] & fustrap[2]) |
216
+ /*
470
+ (fustrap[1] & fustrap[2]);
217
+ * Input buffer disconnected from internal/external drives, so
218
+ * pull-up/pull-down becomes relevant
219
+ */
220
+ if (!input || (input && !connected_in && !connected_out)) {
221
+ if (pull == NRF51_GPIO_PULLDOWN) {
222
+ s->in = deposit32(s->in, i, 1, 0);
223
+ } else if (pull == NRF51_GPIO_PULLUP) {
224
+ s->in = deposit32(s->in, i, 1, 1);
225
+ }
226
+ }
227
+
228
+ /* Self stimulation through internal output driver */
229
+ if (connected_out && !connected_in && input) {
230
+ s->in = deposit32(s->in, i, 1, out);
231
+ }
232
+ }
471
+ }
233
+
472
+
234
+}
473
+ return value;
235
+
474
+}
236
+/*
475
+
237
+ * Direction is exposed in both the DIR register and the DIR bit
476
+/* Register write handler specific to the fuse array OTP module. */
238
+ * of each PINs CNF configuration register. Reflect bits for pins in DIR
477
+static void npcm7xx_fuse_array_write(void *opaque, hwaddr addr, uint64_t v,
239
+ * to individual pin configuration registers.
478
+ unsigned int size)
240
+ */
479
+{
241
+static void reflect_dir_bit_in_cnf(NRF51GPIOState *s)
480
+ NPCM7xxOTPRegister reg = addr / sizeof(uint32_t);
242
+{
481
+ NPCM7xxOTPState *s = opaque;
243
+ size_t i;
482
+
244
+
483
+ /*
245
+ uint32_t value = s->dir;
484
+ * The Fuse Strap register is read-only. Other registers are handled by
246
+
485
+ * common code.
247
+ for (i = 0; i < NRF51_GPIO_PINS; i++) {
486
+ */
248
+ s->cnf[i] = (s->cnf[i] & ~(1UL)) | ((value >> i) & 0x01);
487
+ if (reg != NPCM7XX_OTP_FUSTRAP) {
488
+ npcm7xx_otp_write(s, reg, v);
249
+ }
489
+ }
250
+}
490
+}
251
+
491
+
252
+static uint64_t nrf51_gpio_read(void *opaque, hwaddr offset, unsigned int size)
492
+static const MemoryRegionOps npcm7xx_fuse_array_ops = {
253
+{
493
+ .read = npcm7xx_fuse_array_read,
254
+ NRF51GPIOState *s = NRF51_GPIO(opaque);
494
+ .write = npcm7xx_fuse_array_write,
255
+ uint64_t r = 0;
495
+ .endianness = DEVICE_LITTLE_ENDIAN,
256
+ size_t idx;
496
+ .valid = {
257
+
497
+ .min_access_size = 4,
258
+ switch (offset) {
498
+ .max_access_size = 4,
259
+ case NRF51_GPIO_REG_OUT ... NRF51_GPIO_REG_OUTCLR:
499
+ .unaligned = false,
260
+ r = s->out;
500
+ },
261
+ break;
501
+};
262
+
502
+
263
+ case NRF51_GPIO_REG_IN:
503
+/* Register read handler specific to the key storage OTP module. */
264
+ r = s->in;
504
+static uint64_t npcm7xx_key_storage_read(void *opaque, hwaddr addr,
265
+ break;
505
+ unsigned int size)
266
+
506
+{
267
+ case NRF51_GPIO_REG_DIR ... NRF51_GPIO_REG_DIRCLR:
507
+ NPCM7xxOTPRegister reg = addr / sizeof(uint32_t);
268
+ r = s->dir;
508
+ NPCM7xxOTPState *s = opaque;
269
+ break;
509
+
270
+
510
+ /*
271
+ case NRF51_GPIO_REG_CNF_START ... NRF51_GPIO_REG_CNF_END:
511
+ * Only the Fuse Key Index register needs special handling; all other
272
+ idx = (offset - NRF51_GPIO_REG_CNF_START) / 4;
512
+ * registers work the same way for both kinds of OTP modules.
273
+ r = s->cnf[idx];
513
+ */
274
+ break;
514
+ if (reg != NPCM7XX_OTP_FKEYIND) {
275
+
515
+ return npcm7xx_otp_read(s, reg);
276
+ default:
277
+ qemu_log_mask(LOG_GUEST_ERROR,
278
+ "%s: bad read offset 0x%" HWADDR_PRIx "\n",
279
+ __func__, offset);
280
+ }
516
+ }
281
+
517
+
282
+ trace_nrf51_gpio_read(offset, r);
518
+ qemu_log_mask(LOG_UNIMP, "%s: FKEYIND is not implemented\n", __func__);
283
+
519
+
284
+ return r;
520
+ return s->regs[NPCM7XX_OTP_FKEYIND];
285
+}
521
+}
286
+
522
+
287
+static void nrf51_gpio_write(void *opaque, hwaddr offset,
523
+/* Register write handler specific to the key storage OTP module. */
288
+ uint64_t value, unsigned int size)
524
+static void npcm7xx_key_storage_write(void *opaque, hwaddr addr, uint64_t v,
289
+{
525
+ unsigned int size)
290
+ NRF51GPIOState *s = NRF51_GPIO(opaque);
526
+{
291
+ size_t idx;
527
+ NPCM7xxOTPRegister reg = addr / sizeof(uint32_t);
292
+
528
+ NPCM7xxOTPState *s = opaque;
293
+ trace_nrf51_gpio_write(offset, value);
529
+
294
+
530
+ /*
295
+ switch (offset) {
531
+ * Only the Fuse Key Index register needs special handling; all other
296
+ case NRF51_GPIO_REG_OUT:
532
+ * registers work the same way for both kinds of OTP modules.
297
+ s->out = value;
533
+ */
298
+ break;
534
+ if (reg != NPCM7XX_OTP_FKEYIND) {
299
+
535
+ npcm7xx_otp_write(s, reg, v);
300
+ case NRF51_GPIO_REG_OUTSET:
536
+ return;
301
+ s->out |= value;
302
+ break;
303
+
304
+ case NRF51_GPIO_REG_OUTCLR:
305
+ s->out &= ~value;
306
+ break;
307
+
308
+ case NRF51_GPIO_REG_DIR:
309
+ s->dir = value;
310
+ reflect_dir_bit_in_cnf(s);
311
+ break;
312
+
313
+ case NRF51_GPIO_REG_DIRSET:
314
+ s->dir |= value;
315
+ reflect_dir_bit_in_cnf(s);
316
+ break;
317
+
318
+ case NRF51_GPIO_REG_DIRCLR:
319
+ s->dir &= ~value;
320
+ reflect_dir_bit_in_cnf(s);
321
+ break;
322
+
323
+ case NRF51_GPIO_REG_CNF_START ... NRF51_GPIO_REG_CNF_END:
324
+ idx = (offset - NRF51_GPIO_REG_CNF_START) / 4;
325
+ s->cnf[idx] = value;
326
+ /*
327
+ * direction is exposed in both the DIR register and the DIR bit
328
+ * of each PINs CNF configuration register.
329
+ */
330
+ s->dir = (s->dir & ~(1UL << idx)) | ((value & 0x01) << idx);
331
+ break;
332
+
333
+ default:
334
+ qemu_log_mask(LOG_GUEST_ERROR,
335
+ "%s: bad write offset 0x%" HWADDR_PRIx "\n",
336
+ __func__, offset);
337
+ }
537
+ }
338
+
538
+
339
+ update_state(s);
539
+ qemu_log_mask(LOG_UNIMP, "%s: FKEYIND is not implemented\n", __func__);
340
+}
540
+
341
+
541
+ s->regs[NPCM7XX_OTP_FKEYIND] = v;
342
+static const MemoryRegionOps gpio_ops = {
542
+}
343
+ .read = nrf51_gpio_read,
543
+
344
+ .write = nrf51_gpio_write,
544
+static const MemoryRegionOps npcm7xx_key_storage_ops = {
545
+ .read = npcm7xx_key_storage_read,
546
+ .write = npcm7xx_key_storage_write,
345
+ .endianness = DEVICE_LITTLE_ENDIAN,
547
+ .endianness = DEVICE_LITTLE_ENDIAN,
346
+ .impl.min_access_size = 4,
548
+ .valid = {
347
+ .impl.max_access_size = 4,
549
+ .min_access_size = 4,
550
+ .max_access_size = 4,
551
+ .unaligned = false,
552
+ },
348
+};
553
+};
349
+
554
+
350
+static void nrf51_gpio_set(void *opaque, int line, int value)
555
+static void npcm7xx_otp_enter_reset(Object *obj, ResetType type)
351
+{
556
+{
352
+ NRF51GPIOState *s = NRF51_GPIO(opaque);
557
+ NPCM7xxOTPState *s = NPCM7XX_OTP(obj);
353
+
558
+
354
+ trace_nrf51_gpio_set(line, value);
559
+ memset(s->regs, 0, sizeof(s->regs));
355
+
560
+
356
+ assert(line >= 0 && line < NRF51_GPIO_PINS);
561
+ s->regs[NPCM7XX_OTP_FST] = 0x00000001;
357
+
562
+ s->regs[NPCM7XX_OTP_FCFG] = 0x20000000;
358
+ s->in_mask = deposit32(s->in_mask, line, 1, value >= 0);
563
+}
359
+ if (value >= 0) {
564
+
360
+ s->in = deposit32(s->in, line, 1, value != 0);
565
+static void npcm7xx_otp_realize(DeviceState *dev, Error **errp)
361
+ }
566
+{
362
+
567
+ NPCM7xxOTPClass *oc = NPCM7XX_OTP_GET_CLASS(dev);
363
+ update_state(s);
568
+ NPCM7xxOTPState *s = NPCM7XX_OTP(dev);
364
+}
569
+ SysBusDevice *sbd = &s->parent;
365
+
570
+
366
+static void nrf51_gpio_reset(DeviceState *dev)
571
+ memset(s->array, 0, sizeof(s->array));
367
+{
572
+
368
+ NRF51GPIOState *s = NRF51_GPIO(dev);
573
+ memory_region_init_io(&s->mmio, OBJECT(s), oc->mmio_ops, s, "regs",
369
+ size_t i;
574
+ NPCM7XX_OTP_REGS_SIZE);
370
+
575
+ sysbus_init_mmio(sbd, &s->mmio);
371
+ s->out = 0;
576
+}
372
+ s->old_out = 0;
577
+
373
+ s->old_out_connected = 0;
578
+static const VMStateDescription vmstate_npcm7xx_otp = {
374
+ s->in = 0;
579
+ .name = "npcm7xx-otp",
375
+ s->in_mask = 0;
580
+ .version_id = 0,
376
+ s->dir = 0;
581
+ .minimum_version_id = 0,
377
+
378
+ for (i = 0; i < NRF51_GPIO_PINS; i++) {
379
+ s->cnf[i] = 0x00000002;
380
+ }
381
+}
382
+
383
+static const VMStateDescription vmstate_nrf51_gpio = {
384
+ .name = TYPE_NRF51_GPIO,
385
+ .version_id = 1,
386
+ .minimum_version_id = 1,
387
+ .fields = (VMStateField[]) {
582
+ .fields = (VMStateField[]) {
388
+ VMSTATE_UINT32(out, NRF51GPIOState),
583
+ VMSTATE_UINT32_ARRAY(regs, NPCM7xxOTPState, NPCM7XX_OTP_NR_REGS),
389
+ VMSTATE_UINT32(in, NRF51GPIOState),
584
+ VMSTATE_UINT8_ARRAY(array, NPCM7xxOTPState, NPCM7XX_OTP_ARRAY_BYTES),
390
+ VMSTATE_UINT32(in_mask, NRF51GPIOState),
585
+ VMSTATE_END_OF_LIST(),
391
+ VMSTATE_UINT32(dir, NRF51GPIOState),
586
+ },
392
+ VMSTATE_UINT32_ARRAY(cnf, NRF51GPIOState, NRF51_GPIO_PINS),
393
+ VMSTATE_UINT32(old_out, NRF51GPIOState),
394
+ VMSTATE_UINT32(old_out_connected, NRF51GPIOState),
395
+ VMSTATE_END_OF_LIST()
396
+ }
397
+};
587
+};
398
+
588
+
399
+static void nrf51_gpio_init(Object *obj)
589
+static void npcm7xx_otp_class_init(ObjectClass *klass, void *data)
400
+{
590
+{
401
+ NRF51GPIOState *s = NRF51_GPIO(obj);
591
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
402
+
403
+ memory_region_init_io(&s->mmio, obj, &gpio_ops, s,
404
+ TYPE_NRF51_GPIO, NRF51_GPIO_SIZE);
405
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
406
+
407
+ qdev_init_gpio_in(DEVICE(s), nrf51_gpio_set, NRF51_GPIO_PINS);
408
+ qdev_init_gpio_out(DEVICE(s), s->output, NRF51_GPIO_PINS);
409
+}
410
+
411
+static void nrf51_gpio_class_init(ObjectClass *klass, void *data)
412
+{
413
+ DeviceClass *dc = DEVICE_CLASS(klass);
592
+ DeviceClass *dc = DEVICE_CLASS(klass);
414
+
593
+
415
+ dc->vmsd = &vmstate_nrf51_gpio;
594
+ QEMU_BUILD_BUG_ON(NPCM7XX_OTP_REGS_END > NPCM7XX_OTP_NR_REGS);
416
+ dc->reset = nrf51_gpio_reset;
595
+
417
+ dc->desc = "nRF51 GPIO";
596
+ dc->realize = npcm7xx_otp_realize;
418
+}
597
+ dc->vmsd = &vmstate_npcm7xx_otp;
419
+
598
+ rc->phases.enter = npcm7xx_otp_enter_reset;
420
+static const TypeInfo nrf51_gpio_info = {
599
+}
421
+ .name = TYPE_NRF51_GPIO,
600
+
422
+ .parent = TYPE_SYS_BUS_DEVICE,
601
+static void npcm7xx_key_storage_class_init(ObjectClass *klass, void *data)
423
+ .instance_size = sizeof(NRF51GPIOState),
602
+{
424
+ .instance_init = nrf51_gpio_init,
603
+ NPCM7xxOTPClass *oc = NPCM7XX_OTP_CLASS(klass);
425
+ .class_init = nrf51_gpio_class_init
604
+
605
+ oc->mmio_ops = &npcm7xx_key_storage_ops;
606
+}
607
+
608
+static void npcm7xx_fuse_array_class_init(ObjectClass *klass, void *data)
609
+{
610
+ NPCM7xxOTPClass *oc = NPCM7XX_OTP_CLASS(klass);
611
+
612
+ oc->mmio_ops = &npcm7xx_fuse_array_ops;
613
+}
614
+
615
+static const TypeInfo npcm7xx_otp_types[] = {
616
+ {
617
+ .name = TYPE_NPCM7XX_OTP,
618
+ .parent = TYPE_SYS_BUS_DEVICE,
619
+ .instance_size = sizeof(NPCM7xxOTPState),
620
+ .class_size = sizeof(NPCM7xxOTPClass),
621
+ .class_init = npcm7xx_otp_class_init,
622
+ .abstract = true,
623
+ },
624
+ {
625
+ .name = TYPE_NPCM7XX_KEY_STORAGE,
626
+ .parent = TYPE_NPCM7XX_OTP,
627
+ .class_init = npcm7xx_key_storage_class_init,
628
+ },
629
+ {
630
+ .name = TYPE_NPCM7XX_FUSE_ARRAY,
631
+ .parent = TYPE_NPCM7XX_OTP,
632
+ .class_init = npcm7xx_fuse_array_class_init,
633
+ },
426
+};
634
+};
427
+
635
+DEFINE_TYPES(npcm7xx_otp_types);
428
+static void nrf51_gpio_register_types(void)
636
diff --git a/hw/nvram/meson.build b/hw/nvram/meson.build
429
+{
637
index XXXXXXX..XXXXXXX 100644
430
+ type_register_static(&nrf51_gpio_info);
638
--- a/hw/nvram/meson.build
431
+}
639
+++ b/hw/nvram/meson.build
432
+
640
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_DS1225Y', if_true: files('ds1225y.c'))
433
+type_init(nrf51_gpio_register_types)
641
softmmu_ss.add(when: 'CONFIG_NMC93XX_EEPROM', if_true: files('eeprom93xx.c'))
434
diff --git a/hw/gpio/trace-events b/hw/gpio/trace-events
642
softmmu_ss.add(when: 'CONFIG_AT24C', if_true: files('eeprom_at24c.c'))
435
new file mode 100644
643
softmmu_ss.add(when: 'CONFIG_MAC_NVRAM', if_true: files('mac_nvram.c'))
436
index XXXXXXX..XXXXXXX
644
+softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_otp.c'))
437
--- /dev/null
645
softmmu_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_nvm.c'))
438
+++ b/hw/gpio/trace-events
646
439
@@ -XXX,XX +XXX,XX @@
647
specific_ss.add(when: 'CONFIG_PSERIES', if_true: files('spapr_nvram.c'))
440
+# See docs/devel/tracing.txt for syntax documentation.
441
+
442
+# hw/gpio/nrf51_gpio.c
443
+nrf51_gpio_read(uint64_t offset, uint64_t r) "offset 0x%" PRIx64 " value 0x%" PRIx64
444
+nrf51_gpio_write(uint64_t offset, uint64_t value) "offset 0x%" PRIx64 " value 0x%" PRIx64
445
+nrf51_gpio_set(int64_t line, int64_t value) "line %" PRIi64 " value %" PRIi64
446
+nrf51_gpio_update_output_irq(int64_t line, int64_t value) "line %" PRIi64 " value %" PRIi64
447
\ No newline at end of file
448
--
648
--
449
2.19.2
649
2.20.1
450
650
451
651
diff view generated by jsdifflib
1
From: Luc Michel <luc.michel@greensocs.com>
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
2
3
Add support for multiprocess extension in gdb_vm_state_change()
3
This just implements the bare minimum to cause the boot block to skip
4
function.
4
memory initialization.
5
5
6
Signed-off-by: Luc Michel <luc.michel@greensocs.com>
6
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Reviewed-by: Cédric Le Goater <clg@kaod.org>
8
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Acked-by: Alistair Francis <alistair.francis@wdc.com>
9
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Message-id: 20181207090135.7651-10-luc.michel@greensocs.com
10
Tested-by: Alexander Bulekov <alxndr@bu.edu>
11
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
12
Message-id: 20200911052101.2602693-10-hskinnemoen@google.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
14
---
13
gdbstub.c | 15 ++++++++++++---
15
include/hw/arm/npcm7xx.h | 2 +
14
1 file changed, 12 insertions(+), 3 deletions(-)
16
include/hw/mem/npcm7xx_mc.h | 36 ++++++++++++++++
15
17
hw/arm/npcm7xx.c | 6 +++
16
diff --git a/gdbstub.c b/gdbstub.c
18
hw/mem/npcm7xx_mc.c | 84 +++++++++++++++++++++++++++++++++++++
19
hw/mem/meson.build | 1 +
20
5 files changed, 129 insertions(+)
21
create mode 100644 include/hw/mem/npcm7xx_mc.h
22
create mode 100644 hw/mem/npcm7xx_mc.c
23
24
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
17
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
18
--- a/gdbstub.c
26
--- a/include/hw/arm/npcm7xx.h
19
+++ b/gdbstub.c
27
+++ b/include/hw/arm/npcm7xx.h
20
@@ -XXX,XX +XXX,XX @@ static void gdb_vm_state_change(void *opaque, int running, RunState state)
28
@@ -XXX,XX +XXX,XX @@
21
GDBState *s = gdbserver_state;
29
22
CPUState *cpu = s->c_cpu;
30
#include "hw/boards.h"
23
char buf[256];
31
#include "hw/cpu/a9mpcore.h"
24
+ char thread_id[16];
32
+#include "hw/mem/npcm7xx_mc.h"
25
const char *type;
33
#include "hw/misc/npcm7xx_clk.h"
26
int ret;
34
#include "hw/misc/npcm7xx_gcr.h"
27
35
#include "hw/nvram/npcm7xx_otp.h"
28
@@ -XXX,XX +XXX,XX @@ static void gdb_vm_state_change(void *opaque, int running, RunState state)
36
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
29
put_packet(s, s->syscall_buf);
37
NPCM7xxTimerCtrlState tim[3];
30
return;
38
NPCM7xxOTPState key_storage;
31
}
39
NPCM7xxOTPState fuse_array;
32
+
40
+ NPCM7xxMCState mc;
33
+ if (cpu == NULL) {
41
} NPCM7xxState;
34
+ /* No process attached */
42
35
+ return;
43
#define TYPE_NPCM7XX "npcm7xx"
44
diff --git a/include/hw/mem/npcm7xx_mc.h b/include/hw/mem/npcm7xx_mc.h
45
new file mode 100644
46
index XXXXXXX..XXXXXXX
47
--- /dev/null
48
+++ b/include/hw/mem/npcm7xx_mc.h
49
@@ -XXX,XX +XXX,XX @@
50
+/*
51
+ * Nuvoton NPCM7xx Memory Controller stub
52
+ *
53
+ * Copyright 2020 Google LLC
54
+ *
55
+ * This program is free software; you can redistribute it and/or modify it
56
+ * under the terms of the GNU General Public License as published by the
57
+ * Free Software Foundation; either version 2 of the License, or
58
+ * (at your option) any later version.
59
+ *
60
+ * This program is distributed in the hope that it will be useful, but WITHOUT
61
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
62
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
63
+ * for more details.
64
+ */
65
+#ifndef NPCM7XX_MC_H
66
+#define NPCM7XX_MC_H
67
+
68
+#include "exec/memory.h"
69
+#include "hw/sysbus.h"
70
+
71
+/**
72
+ * struct NPCM7xxMCState - Device state for the memory controller.
73
+ * @parent: System bus device.
74
+ * @mmio: Memory region through which registers are accessed.
75
+ */
76
+typedef struct NPCM7xxMCState {
77
+ SysBusDevice parent;
78
+
79
+ MemoryRegion mmio;
80
+} NPCM7xxMCState;
81
+
82
+#define TYPE_NPCM7XX_MC "npcm7xx-mc"
83
+#define NPCM7XX_MC(obj) OBJECT_CHECK(NPCM7xxMCState, (obj), TYPE_NPCM7XX_MC)
84
+
85
+#endif /* NPCM7XX_MC_H */
86
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
87
index XXXXXXX..XXXXXXX 100644
88
--- a/hw/arm/npcm7xx.c
89
+++ b/hw/arm/npcm7xx.c
90
@@ -XXX,XX +XXX,XX @@
91
#define NPCM7XX_CPUP_BA (0xf03fe000)
92
#define NPCM7XX_GCR_BA (0xf0800000)
93
#define NPCM7XX_CLK_BA (0xf0801000)
94
+#define NPCM7XX_MC_BA (0xf0824000)
95
96
/* Internal AHB SRAM */
97
#define NPCM7XX_RAM3_BA (0xc0008000)
98
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
99
TYPE_NPCM7XX_KEY_STORAGE);
100
object_initialize_child(obj, "otp2", &s->fuse_array,
101
TYPE_NPCM7XX_FUSE_ARRAY);
102
+ object_initialize_child(obj, "mc", &s->mc, TYPE_NPCM7XX_MC);
103
104
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
105
object_initialize_child(obj, "tim[*]", &s->tim[i], TYPE_NPCM7XX_TIMER);
106
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
107
sysbus_mmio_map(SYS_BUS_DEVICE(&s->fuse_array), 0, NPCM7XX_OTP2_BA);
108
npcm7xx_init_fuses(s);
109
110
+ /* Fake Memory Controller (MC). Cannot fail. */
111
+ sysbus_realize(SYS_BUS_DEVICE(&s->mc), &error_abort);
112
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->mc), 0, NPCM7XX_MC_BA);
113
+
114
/* Timer Modules (TIM). Cannot fail. */
115
QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_tim_addr) != ARRAY_SIZE(s->tim));
116
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
117
diff --git a/hw/mem/npcm7xx_mc.c b/hw/mem/npcm7xx_mc.c
118
new file mode 100644
119
index XXXXXXX..XXXXXXX
120
--- /dev/null
121
+++ b/hw/mem/npcm7xx_mc.c
122
@@ -XXX,XX +XXX,XX @@
123
+/*
124
+ * Nuvoton NPCM7xx Memory Controller stub
125
+ *
126
+ * Copyright 2020 Google LLC
127
+ *
128
+ * This program is free software; you can redistribute it and/or modify it
129
+ * under the terms of the GNU General Public License as published by the
130
+ * Free Software Foundation; either version 2 of the License, or
131
+ * (at your option) any later version.
132
+ *
133
+ * This program is distributed in the hope that it will be useful, but WITHOUT
134
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
135
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
136
+ * for more details.
137
+ */
138
+
139
+#include "qemu/osdep.h"
140
+
141
+#include "hw/mem/npcm7xx_mc.h"
142
+#include "qapi/error.h"
143
+#include "qemu/log.h"
144
+#include "qemu/module.h"
145
+#include "qemu/units.h"
146
+
147
+#define NPCM7XX_MC_REGS_SIZE (4 * KiB)
148
+
149
+static uint64_t npcm7xx_mc_read(void *opaque, hwaddr addr, unsigned int size)
150
+{
151
+ /*
152
+ * If bits 8..11 @ offset 0 are not zero, the boot block thinks the memory
153
+ * controller has already been initialized and will skip DDR training.
154
+ */
155
+ if (addr == 0) {
156
+ return 0x100;
36
+ }
157
+ }
37
+
158
+
38
+ gdb_fmt_thread_id(s, cpu, thread_id, sizeof(thread_id));
159
+ qemu_log_mask(LOG_UNIMP, "%s: mostly unimplemented\n", __func__);
39
+
160
+
40
switch (state) {
161
+ return 0;
41
case RUN_STATE_DEBUG:
162
+}
42
if (cpu->watchpoint_hit) {
163
+
43
@@ -XXX,XX +XXX,XX @@ static void gdb_vm_state_change(void *opaque, int running, RunState state)
164
+static void npcm7xx_mc_write(void *opaque, hwaddr addr, uint64_t v,
44
trace_gdbstub_hit_watchpoint(type, cpu_gdb_index(cpu),
165
+ unsigned int size)
45
(target_ulong)cpu->watchpoint_hit->vaddr);
166
+{
46
snprintf(buf, sizeof(buf),
167
+ qemu_log_mask(LOG_UNIMP, "%s: mostly unimplemented\n", __func__);
47
- "T%02xthread:%02x;%swatch:" TARGET_FMT_lx ";",
168
+}
48
- GDB_SIGNAL_TRAP, cpu_gdb_index(cpu), type,
169
+
49
+ "T%02xthread:%s;%swatch:" TARGET_FMT_lx ";",
170
+static const MemoryRegionOps npcm7xx_mc_ops = {
50
+ GDB_SIGNAL_TRAP, thread_id, type,
171
+ .read = npcm7xx_mc_read,
51
(target_ulong)cpu->watchpoint_hit->vaddr);
172
+ .write = npcm7xx_mc_write,
52
cpu->watchpoint_hit = NULL;
173
+ .endianness = DEVICE_LITTLE_ENDIAN,
53
goto send_packet;
174
+ .valid = {
54
@@ -XXX,XX +XXX,XX @@ static void gdb_vm_state_change(void *opaque, int running, RunState state)
175
+ .min_access_size = 4,
55
break;
176
+ .max_access_size = 4,
56
}
177
+ .unaligned = false,
57
gdb_set_stop_cpu(cpu);
178
+ },
58
- snprintf(buf, sizeof(buf), "T%02xthread:%02x;", ret, cpu_gdb_index(cpu));
179
+};
59
+ snprintf(buf, sizeof(buf), "T%02xthread:%s;", ret, thread_id);
180
+
60
181
+static void npcm7xx_mc_realize(DeviceState *dev, Error **errp)
61
send_packet:
182
+{
62
put_packet(s, buf);
183
+ NPCM7xxMCState *s = NPCM7XX_MC(dev);
184
+
185
+ memory_region_init_io(&s->mmio, OBJECT(s), &npcm7xx_mc_ops, s, "regs",
186
+ NPCM7XX_MC_REGS_SIZE);
187
+ sysbus_init_mmio(&s->parent, &s->mmio);
188
+}
189
+
190
+static void npcm7xx_mc_class_init(ObjectClass *klass, void *data)
191
+{
192
+ DeviceClass *dc = DEVICE_CLASS(klass);
193
+
194
+ dc->desc = "NPCM7xx Memory Controller stub";
195
+ dc->realize = npcm7xx_mc_realize;
196
+}
197
+
198
+static const TypeInfo npcm7xx_mc_types[] = {
199
+ {
200
+ .name = TYPE_NPCM7XX_MC,
201
+ .parent = TYPE_SYS_BUS_DEVICE,
202
+ .instance_size = sizeof(NPCM7xxMCState),
203
+ .class_init = npcm7xx_mc_class_init,
204
+ },
205
+};
206
+DEFINE_TYPES(npcm7xx_mc_types);
207
diff --git a/hw/mem/meson.build b/hw/mem/meson.build
208
index XXXXXXX..XXXXXXX 100644
209
--- a/hw/mem/meson.build
210
+++ b/hw/mem/meson.build
211
@@ -XXX,XX +XXX,XX @@
212
mem_ss = ss.source_set()
213
mem_ss.add(files('memory-device.c'))
214
mem_ss.add(when: 'CONFIG_DIMM', if_true: files('pc-dimm.c'))
215
+mem_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_mc.c'))
216
mem_ss.add(when: 'CONFIG_NVDIMM', if_true: files('nvdimm.c'))
217
218
softmmu_ss.add_all(when: 'CONFIG_MEM_DEVICE', if_true: mem_ss)
63
--
219
--
64
2.19.2
220
2.20.1
65
221
66
222
diff view generated by jsdifflib
1
From: Luc Michel <luc.michel@greensocs.com>
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
2
3
Add a couple of helper functions to cope with GDB threads and processes.
3
This implements a device model for the NPCM7xx SPI flash controller.
4
4
5
The gdb_get_process() function looks for a process given a pid.
5
Direct reads and writes, and user-mode transactions have been tested in
6
various modes. Protection features are not implemented yet.
6
7
7
The gdb_get_cpu() function returns the CPU corresponding to the (pid,
8
All the FIU instances are available in the SoC's address space,
8
tid) pair given as parameters.
9
regardless of whether or not they're connected to actual flash chips.
9
10
10
The read_thread_id() function parses the thread-id sent by the peer.
11
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
11
This function supports the multiprocess extension thread-id syntax. The
12
Reviewed-by: Cédric Le Goater <clg@kaod.org>
12
return value specifies if the parsing failed, or if a special case was
13
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
encountered (all processes or all threads).
14
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
15
Tested-by: Alexander Bulekov <alxndr@bu.edu>
15
Use them in 'H' and 'T' packets handling to support the multiprocess
16
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
16
extension.
17
Message-id: 20200911052101.2602693-11-hskinnemoen@google.com
17
18
Signed-off-by: Luc Michel <luc.michel@greensocs.com>
19
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
20
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
21
Acked-by: Alistair Francis <alistair.francis@wdc.com>
22
Message-id: 20181207090135.7651-5-luc.michel@greensocs.com
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
---
19
---
25
gdbstub.c | 154 +++++++++++++++++++++++++++++++++++++++++++++++-------
20
include/hw/arm/npcm7xx.h | 2 +
26
1 file changed, 136 insertions(+), 18 deletions(-)
21
include/hw/ssi/npcm7xx_fiu.h | 73 +++++
22
hw/arm/npcm7xx.c | 58 ++++
23
hw/ssi/npcm7xx_fiu.c | 572 +++++++++++++++++++++++++++++++++++
24
hw/arm/Kconfig | 1 +
25
hw/ssi/meson.build | 1 +
26
hw/ssi/trace-events | 11 +
27
7 files changed, 718 insertions(+)
28
create mode 100644 include/hw/ssi/npcm7xx_fiu.h
29
create mode 100644 hw/ssi/npcm7xx_fiu.c
27
30
28
diff --git a/gdbstub.c b/gdbstub.c
31
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
29
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
30
--- a/gdbstub.c
33
--- a/include/hw/arm/npcm7xx.h
31
+++ b/gdbstub.c
34
+++ b/include/hw/arm/npcm7xx.h
32
@@ -XXX,XX +XXX,XX @@ out:
35
@@ -XXX,XX +XXX,XX @@
33
#endif
36
#include "hw/misc/npcm7xx_gcr.h"
37
#include "hw/nvram/npcm7xx_otp.h"
38
#include "hw/timer/npcm7xx_timer.h"
39
+#include "hw/ssi/npcm7xx_fiu.h"
40
#include "target/arm/cpu.h"
41
42
#define NPCM7XX_MAX_NUM_CPUS (2)
43
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
44
NPCM7xxOTPState key_storage;
45
NPCM7xxOTPState fuse_array;
46
NPCM7xxMCState mc;
47
+ NPCM7xxFIUState fiu[2];
48
} NPCM7xxState;
49
50
#define TYPE_NPCM7XX "npcm7xx"
51
diff --git a/include/hw/ssi/npcm7xx_fiu.h b/include/hw/ssi/npcm7xx_fiu.h
52
new file mode 100644
53
index XXXXXXX..XXXXXXX
54
--- /dev/null
55
+++ b/include/hw/ssi/npcm7xx_fiu.h
56
@@ -XXX,XX +XXX,XX @@
57
+/*
58
+ * Nuvoton NPCM7xx Flash Interface Unit (FIU)
59
+ *
60
+ * Copyright 2020 Google LLC
61
+ *
62
+ * This program is free software; you can redistribute it and/or modify it
63
+ * under the terms of the GNU General Public License as published by the
64
+ * Free Software Foundation; either version 2 of the License, or
65
+ * (at your option) any later version.
66
+ *
67
+ * This program is distributed in the hope that it will be useful, but WITHOUT
68
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
69
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
70
+ * for more details.
71
+ */
72
+#ifndef NPCM7XX_FIU_H
73
+#define NPCM7XX_FIU_H
74
+
75
+#include "hw/ssi/ssi.h"
76
+#include "hw/sysbus.h"
77
+
78
+/*
79
+ * Number of registers in our device state structure. Don't change this without
80
+ * incrementing the version_id in the vmstate.
81
+ */
82
+#define NPCM7XX_FIU_NR_REGS (0x7c / sizeof(uint32_t))
83
+
84
+typedef struct NPCM7xxFIUState NPCM7xxFIUState;
85
+
86
+/**
87
+ * struct NPCM7xxFIUFlash - Per-chipselect flash controller state.
88
+ * @direct_access: Memory region for direct flash access.
89
+ * @fiu: Pointer to flash controller shared state.
90
+ */
91
+typedef struct NPCM7xxFIUFlash {
92
+ MemoryRegion direct_access;
93
+ NPCM7xxFIUState *fiu;
94
+} NPCM7xxFIUFlash;
95
+
96
+/**
97
+ * NPCM7xxFIUState - Device state for one Flash Interface Unit.
98
+ * @parent: System bus device.
99
+ * @mmio: Memory region for register access.
100
+ * @cs_count: Number of flash chips that may be connected to this module.
101
+ * @active_cs: Currently active chip select, or -1 if no chip is selected.
102
+ * @cs_lines: GPIO lines that may be wired to flash chips.
103
+ * @flash: Array of @cs_count per-flash-chip state objects.
104
+ * @spi: The SPI bus mastered by this controller.
105
+ * @regs: Register contents.
106
+ *
107
+ * Each FIU has a shared bank of registers, and controls up to four chip
108
+ * selects. Each chip select has a dedicated memory region which may be used to
109
+ * read and write the flash connected to that chip select as if it were memory.
110
+ */
111
+struct NPCM7xxFIUState {
112
+ SysBusDevice parent;
113
+
114
+ MemoryRegion mmio;
115
+
116
+ int32_t cs_count;
117
+ int32_t active_cs;
118
+ qemu_irq *cs_lines;
119
+ NPCM7xxFIUFlash *flash;
120
+
121
+ SSIBus *spi;
122
+
123
+ uint32_t regs[NPCM7XX_FIU_NR_REGS];
124
+};
125
+
126
+#define TYPE_NPCM7XX_FIU "npcm7xx-fiu"
127
+#define NPCM7XX_FIU(obj) OBJECT_CHECK(NPCM7xxFIUState, (obj), TYPE_NPCM7XX_FIU)
128
+
129
+#endif /* NPCM7XX_FIU_H */
130
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
131
index XXXXXXX..XXXXXXX 100644
132
--- a/hw/arm/npcm7xx.c
133
+++ b/hw/arm/npcm7xx.c
134
@@ -XXX,XX +XXX,XX @@ static const hwaddr npcm7xx_uart_addr[] = {
135
0xf0004000,
136
};
137
138
+/* Direct memory-mapped access to SPI0 CS0-1. */
139
+static const hwaddr npcm7xx_fiu0_flash_addr[] = {
140
+ 0x80000000, /* CS0 */
141
+ 0x88000000, /* CS1 */
142
+};
143
+
144
+/* Direct memory-mapped access to SPI3 CS0-3. */
145
+static const hwaddr npcm7xx_fiu3_flash_addr[] = {
146
+ 0xa0000000, /* CS0 */
147
+ 0xa8000000, /* CS1 */
148
+ 0xb0000000, /* CS2 */
149
+ 0xb8000000, /* CS3 */
150
+};
151
+
152
+static const struct {
153
+ const char *name;
154
+ hwaddr regs_addr;
155
+ int cs_count;
156
+ const hwaddr *flash_addr;
157
+} npcm7xx_fiu[] = {
158
+ {
159
+ .name = "fiu0",
160
+ .regs_addr = 0xfb000000,
161
+ .cs_count = ARRAY_SIZE(npcm7xx_fiu0_flash_addr),
162
+ .flash_addr = npcm7xx_fiu0_flash_addr,
163
+ }, {
164
+ .name = "fiu3",
165
+ .regs_addr = 0xc0000000,
166
+ .cs_count = ARRAY_SIZE(npcm7xx_fiu3_flash_addr),
167
+ .flash_addr = npcm7xx_fiu3_flash_addr,
168
+ },
169
+};
170
+
171
static void npcm7xx_write_secondary_boot(ARMCPU *cpu,
172
const struct arm_boot_info *info)
173
{
174
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
175
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
176
object_initialize_child(obj, "tim[*]", &s->tim[i], TYPE_NPCM7XX_TIMER);
177
}
178
+
179
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_fiu) != ARRAY_SIZE(s->fiu));
180
+ for (i = 0; i < ARRAY_SIZE(s->fiu); i++) {
181
+ object_initialize_child(obj, npcm7xx_fiu[i].name, &s->fiu[i],
182
+ TYPE_NPCM7XX_FIU);
183
+ }
34
}
184
}
35
185
36
+static GDBProcess *gdb_get_process(const GDBState *s, uint32_t pid)
186
static void npcm7xx_realize(DeviceState *dev, Error **errp)
37
+{
187
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
188
serial_hd(i), DEVICE_LITTLE_ENDIAN);
189
}
190
191
+ /*
192
+ * Flash Interface Unit (FIU). Can fail if incorrect number of chip selects
193
+ * specified, but this is a programming error.
194
+ */
195
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_fiu) != ARRAY_SIZE(s->fiu));
196
+ for (i = 0; i < ARRAY_SIZE(s->fiu); i++) {
197
+ SysBusDevice *sbd = SYS_BUS_DEVICE(&s->fiu[i]);
198
+ int j;
199
+
200
+ object_property_set_int(OBJECT(sbd), "cs-count",
201
+ npcm7xx_fiu[i].cs_count, &error_abort);
202
+ sysbus_realize(sbd, &error_abort);
203
+
204
+ sysbus_mmio_map(sbd, 0, npcm7xx_fiu[i].regs_addr);
205
+ for (j = 0; j < npcm7xx_fiu[i].cs_count; j++) {
206
+ sysbus_mmio_map(sbd, j + 1, npcm7xx_fiu[i].flash_addr[j]);
207
+ }
208
+ }
209
+
210
/* RAM2 (SRAM) */
211
memory_region_init_ram(&s->sram, OBJECT(dev), "ram2",
212
NPCM7XX_RAM2_SZ, &error_abort);
213
diff --git a/hw/ssi/npcm7xx_fiu.c b/hw/ssi/npcm7xx_fiu.c
214
new file mode 100644
215
index XXXXXXX..XXXXXXX
216
--- /dev/null
217
+++ b/hw/ssi/npcm7xx_fiu.c
218
@@ -XXX,XX +XXX,XX @@
219
+/*
220
+ * Nuvoton NPCM7xx Flash Interface Unit (FIU)
221
+ *
222
+ * Copyright 2020 Google LLC
223
+ *
224
+ * This program is free software; you can redistribute it and/or modify it
225
+ * under the terms of the GNU General Public License as published by the
226
+ * Free Software Foundation; either version 2 of the License, or
227
+ * (at your option) any later version.
228
+ *
229
+ * This program is distributed in the hope that it will be useful, but WITHOUT
230
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
231
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
232
+ * for more details.
233
+ */
234
+
235
+#include "qemu/osdep.h"
236
+
237
+#include "hw/irq.h"
238
+#include "hw/qdev-properties.h"
239
+#include "hw/ssi/npcm7xx_fiu.h"
240
+#include "migration/vmstate.h"
241
+#include "qapi/error.h"
242
+#include "qemu/error-report.h"
243
+#include "qemu/log.h"
244
+#include "qemu/module.h"
245
+#include "qemu/units.h"
246
+
247
+#include "trace.h"
248
+
249
+/* Up to 128 MiB of flash may be accessed directly as memory. */
250
+#define NPCM7XX_FIU_FLASH_WINDOW_SIZE (128 * MiB)
251
+
252
+/* Each module has 4 KiB of register space. Only a fraction of it is used. */
253
+#define NPCM7XX_FIU_CTRL_REGS_SIZE (4 * KiB)
254
+
255
+/* 32-bit FIU register indices. */
256
+enum NPCM7xxFIURegister {
257
+ NPCM7XX_FIU_DRD_CFG,
258
+ NPCM7XX_FIU_DWR_CFG,
259
+ NPCM7XX_FIU_UMA_CFG,
260
+ NPCM7XX_FIU_UMA_CTS,
261
+ NPCM7XX_FIU_UMA_CMD,
262
+ NPCM7XX_FIU_UMA_ADDR,
263
+ NPCM7XX_FIU_PRT_CFG,
264
+ NPCM7XX_FIU_UMA_DW0 = 0x0020 / sizeof(uint32_t),
265
+ NPCM7XX_FIU_UMA_DW1,
266
+ NPCM7XX_FIU_UMA_DW2,
267
+ NPCM7XX_FIU_UMA_DW3,
268
+ NPCM7XX_FIU_UMA_DR0,
269
+ NPCM7XX_FIU_UMA_DR1,
270
+ NPCM7XX_FIU_UMA_DR2,
271
+ NPCM7XX_FIU_UMA_DR3,
272
+ NPCM7XX_FIU_PRT_CMD0,
273
+ NPCM7XX_FIU_PRT_CMD1,
274
+ NPCM7XX_FIU_PRT_CMD2,
275
+ NPCM7XX_FIU_PRT_CMD3,
276
+ NPCM7XX_FIU_PRT_CMD4,
277
+ NPCM7XX_FIU_PRT_CMD5,
278
+ NPCM7XX_FIU_PRT_CMD6,
279
+ NPCM7XX_FIU_PRT_CMD7,
280
+ NPCM7XX_FIU_PRT_CMD8,
281
+ NPCM7XX_FIU_PRT_CMD9,
282
+ NPCM7XX_FIU_CFG = 0x78 / sizeof(uint32_t),
283
+ NPCM7XX_FIU_REGS_END,
284
+};
285
+
286
+/* FIU_{DRD,DWR,UMA,PTR}_CFG cannot be written when this bit is set. */
287
+#define NPCM7XX_FIU_CFG_LCK BIT(31)
288
+
289
+/* Direct Read configuration register fields. */
290
+#define FIU_DRD_CFG_ADDSIZ(rv) extract32(rv, 16, 2)
291
+#define FIU_ADDSIZ_3BYTES 0
292
+#define FIU_ADDSIZ_4BYTES 1
293
+#define FIU_DRD_CFG_DBW(rv) extract32(rv, 12, 2)
294
+#define FIU_DRD_CFG_ACCTYPE(rv) extract32(rv, 8, 2)
295
+#define FIU_DRD_CFG_RDCMD(rv) extract32(rv, 0, 8)
296
+
297
+/* Direct Write configuration register fields. */
298
+#define FIU_DWR_CFG_ADDSIZ(rv) extract32(rv, 16, 2)
299
+#define FIU_DWR_CFG_WRCMD(rv) extract32(rv, 0, 8)
300
+
301
+/* User-Mode Access register fields. */
302
+
303
+/* Command Mode Lock and the bits protected by it. */
304
+#define FIU_UMA_CFG_CMMLCK BIT(30)
305
+#define FIU_UMA_CFG_CMMLCK_MASK 0x00000403
306
+
307
+#define FIU_UMA_CFG_RDATSIZ(rv) extract32(rv, 24, 5)
308
+#define FIU_UMA_CFG_DBSIZ(rv) extract32(rv, 21, 3)
309
+#define FIU_UMA_CFG_WDATSIZ(rv) extract32(rv, 16, 5)
310
+#define FIU_UMA_CFG_ADDSIZ(rv) extract32(rv, 11, 3)
311
+#define FIU_UMA_CFG_CMDSIZ(rv) extract32(rv, 10, 1)
312
+#define FIU_UMA_CFG_DBPCK(rv) extract32(rv, 6, 2)
313
+
314
+#define FIU_UMA_CTS_RDYIE BIT(25)
315
+#define FIU_UMA_CTS_RDYST BIT(24)
316
+#define FIU_UMA_CTS_SW_CS BIT(16)
317
+#define FIU_UMA_CTS_DEV_NUM(rv) extract32(rv, 8, 2)
318
+#define FIU_UMA_CTS_EXEC_DONE BIT(0)
319
+
320
+/*
321
+ * Returns the index of flash in the fiu->flash array. This corresponds to the
322
+ * chip select ID of the flash.
323
+ */
324
+static int npcm7xx_fiu_cs_index(NPCM7xxFIUState *fiu, NPCM7xxFIUFlash *flash)
325
+{
326
+ int index = flash - fiu->flash;
327
+
328
+ g_assert(index >= 0 && index < fiu->cs_count);
329
+
330
+ return index;
331
+}
332
+
333
+/* Assert the chip select specified in the UMA Control/Status Register. */
334
+static void npcm7xx_fiu_select(NPCM7xxFIUState *s, int cs_id)
335
+{
336
+ trace_npcm7xx_fiu_select(DEVICE(s)->canonical_path, cs_id);
337
+
338
+ if (cs_id < s->cs_count) {
339
+ qemu_irq_lower(s->cs_lines[cs_id]);
340
+ } else {
341
+ qemu_log_mask(LOG_GUEST_ERROR,
342
+ "%s: UMA to CS%d; this module has only %d chip selects",
343
+ DEVICE(s)->canonical_path, cs_id, s->cs_count);
344
+ cs_id = -1;
345
+ }
346
+
347
+ s->active_cs = cs_id;
348
+}
349
+
350
+/* Deassert the currently active chip select. */
351
+static void npcm7xx_fiu_deselect(NPCM7xxFIUState *s)
352
+{
353
+ if (s->active_cs < 0) {
354
+ return;
355
+ }
356
+
357
+ trace_npcm7xx_fiu_deselect(DEVICE(s)->canonical_path, s->active_cs);
358
+
359
+ qemu_irq_raise(s->cs_lines[s->active_cs]);
360
+ s->active_cs = -1;
361
+}
362
+
363
+/* Direct flash memory read handler. */
364
+static uint64_t npcm7xx_fiu_flash_read(void *opaque, hwaddr addr,
365
+ unsigned int size)
366
+{
367
+ NPCM7xxFIUFlash *f = opaque;
368
+ NPCM7xxFIUState *fiu = f->fiu;
369
+ uint64_t value = 0;
370
+ uint32_t drd_cfg;
371
+ int dummy_cycles;
38
+ int i;
372
+ int i;
39
+
373
+
40
+ if (!pid) {
374
+ if (fiu->active_cs != -1) {
41
+ /* 0 means any process, we take the first one */
375
+ qemu_log_mask(LOG_GUEST_ERROR,
42
+ return &s->processes[0];
376
+ "%s: direct flash read with CS%d already active",
43
+ }
377
+ DEVICE(fiu)->canonical_path, fiu->active_cs);
44
+
378
+ }
45
+ for (i = 0; i < s->process_num; i++) {
379
+
46
+ if (s->processes[i].pid == pid) {
380
+ npcm7xx_fiu_select(fiu, npcm7xx_fiu_cs_index(fiu, f));
47
+ return &s->processes[i];
381
+
382
+ drd_cfg = fiu->regs[NPCM7XX_FIU_DRD_CFG];
383
+ ssi_transfer(fiu->spi, FIU_DRD_CFG_RDCMD(drd_cfg));
384
+
385
+ switch (FIU_DRD_CFG_ADDSIZ(drd_cfg)) {
386
+ case FIU_ADDSIZ_4BYTES:
387
+ ssi_transfer(fiu->spi, extract32(addr, 24, 8));
388
+ /* fall through */
389
+ case FIU_ADDSIZ_3BYTES:
390
+ ssi_transfer(fiu->spi, extract32(addr, 16, 8));
391
+ ssi_transfer(fiu->spi, extract32(addr, 8, 8));
392
+ ssi_transfer(fiu->spi, extract32(addr, 0, 8));
393
+ break;
394
+
395
+ default:
396
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: bad address size %d\n",
397
+ DEVICE(fiu)->canonical_path, FIU_DRD_CFG_ADDSIZ(drd_cfg));
398
+ break;
399
+ }
400
+
401
+ /* Flash chip model expects one transfer per dummy bit, not byte */
402
+ dummy_cycles =
403
+ (FIU_DRD_CFG_DBW(drd_cfg) * 8) >> FIU_DRD_CFG_ACCTYPE(drd_cfg);
404
+ for (i = 0; i < dummy_cycles; i++) {
405
+ ssi_transfer(fiu->spi, 0);
406
+ }
407
+
408
+ for (i = 0; i < size; i++) {
409
+ value = deposit64(value, 8 * i, 8, ssi_transfer(fiu->spi, 0));
410
+ }
411
+
412
+ trace_npcm7xx_fiu_flash_read(DEVICE(fiu)->canonical_path, fiu->active_cs,
413
+ addr, size, value);
414
+
415
+ npcm7xx_fiu_deselect(fiu);
416
+
417
+ return value;
418
+}
419
+
420
+/* Direct flash memory write handler. */
421
+static void npcm7xx_fiu_flash_write(void *opaque, hwaddr addr, uint64_t v,
422
+ unsigned int size)
423
+{
424
+ NPCM7xxFIUFlash *f = opaque;
425
+ NPCM7xxFIUState *fiu = f->fiu;
426
+ uint32_t dwr_cfg;
427
+ int cs_id;
428
+ int i;
429
+
430
+ if (fiu->active_cs != -1) {
431
+ qemu_log_mask(LOG_GUEST_ERROR,
432
+ "%s: direct flash write with CS%d already active",
433
+ DEVICE(fiu)->canonical_path, fiu->active_cs);
434
+ }
435
+
436
+ cs_id = npcm7xx_fiu_cs_index(fiu, f);
437
+ trace_npcm7xx_fiu_flash_write(DEVICE(fiu)->canonical_path, cs_id, addr,
438
+ size, v);
439
+ npcm7xx_fiu_select(fiu, cs_id);
440
+
441
+ dwr_cfg = fiu->regs[NPCM7XX_FIU_DWR_CFG];
442
+ ssi_transfer(fiu->spi, FIU_DWR_CFG_WRCMD(dwr_cfg));
443
+
444
+ switch (FIU_DWR_CFG_ADDSIZ(dwr_cfg)) {
445
+ case FIU_ADDSIZ_4BYTES:
446
+ ssi_transfer(fiu->spi, extract32(addr, 24, 8));
447
+ /* fall through */
448
+ case FIU_ADDSIZ_3BYTES:
449
+ ssi_transfer(fiu->spi, extract32(addr, 16, 8));
450
+ ssi_transfer(fiu->spi, extract32(addr, 8, 8));
451
+ ssi_transfer(fiu->spi, extract32(addr, 0, 8));
452
+ break;
453
+
454
+ default:
455
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: bad address size %d\n",
456
+ DEVICE(fiu)->canonical_path, FIU_DWR_CFG_ADDSIZ(dwr_cfg));
457
+ break;
458
+ }
459
+
460
+ for (i = 0; i < size; i++) {
461
+ ssi_transfer(fiu->spi, extract64(v, i * 8, 8));
462
+ }
463
+
464
+ npcm7xx_fiu_deselect(fiu);
465
+}
466
+
467
+static const MemoryRegionOps npcm7xx_fiu_flash_ops = {
468
+ .read = npcm7xx_fiu_flash_read,
469
+ .write = npcm7xx_fiu_flash_write,
470
+ .endianness = DEVICE_LITTLE_ENDIAN,
471
+ .valid = {
472
+ .min_access_size = 1,
473
+ .max_access_size = 8,
474
+ .unaligned = true,
475
+ },
476
+};
477
+
478
+/* Control register read handler. */
479
+static uint64_t npcm7xx_fiu_ctrl_read(void *opaque, hwaddr addr,
480
+ unsigned int size)
481
+{
482
+ hwaddr reg = addr / sizeof(uint32_t);
483
+ NPCM7xxFIUState *s = opaque;
484
+ uint32_t value;
485
+
486
+ if (reg < NPCM7XX_FIU_NR_REGS) {
487
+ value = s->regs[reg];
488
+ } else {
489
+ qemu_log_mask(LOG_GUEST_ERROR,
490
+ "%s: read from invalid offset 0x%" PRIx64 "\n",
491
+ DEVICE(s)->canonical_path, addr);
492
+ value = 0;
493
+ }
494
+
495
+ trace_npcm7xx_fiu_ctrl_read(DEVICE(s)->canonical_path, addr, value);
496
+
497
+ return value;
498
+}
499
+
500
+/* Send the specified number of address bytes from the UMA address register. */
501
+static void send_address(SSIBus *spi, unsigned int addsiz, uint32_t addr)
502
+{
503
+ switch (addsiz) {
504
+ case 4:
505
+ ssi_transfer(spi, extract32(addr, 24, 8));
506
+ /* fall through */
507
+ case 3:
508
+ ssi_transfer(spi, extract32(addr, 16, 8));
509
+ /* fall through */
510
+ case 2:
511
+ ssi_transfer(spi, extract32(addr, 8, 8));
512
+ /* fall through */
513
+ case 1:
514
+ ssi_transfer(spi, extract32(addr, 0, 8));
515
+ /* fall through */
516
+ case 0:
517
+ break;
518
+ }
519
+}
520
+
521
+/* Send the number of dummy bits specified in the UMA config register. */
522
+static void send_dummy_bits(SSIBus *spi, uint32_t uma_cfg, uint32_t uma_cmd)
523
+{
524
+ unsigned int bits_per_clock = 1U << FIU_UMA_CFG_DBPCK(uma_cfg);
525
+ unsigned int i;
526
+
527
+ for (i = 0; i < FIU_UMA_CFG_DBSIZ(uma_cfg); i++) {
528
+ /* Use bytes 0 and 1 first, then keep repeating byte 2 */
529
+ unsigned int field = (i < 2) ? ((i + 1) * 8) : 24;
530
+ unsigned int j;
531
+
532
+ for (j = 0; j < 8; j += bits_per_clock) {
533
+ ssi_transfer(spi, extract32(uma_cmd, field + j, bits_per_clock));
48
+ }
534
+ }
49
+ }
535
+ }
50
+
536
+}
51
+ return NULL;
537
+
52
+}
538
+/* Perform a User-Mode Access transaction. */
53
+
539
+static void npcm7xx_fiu_uma_transaction(NPCM7xxFIUState *s)
54
+static GDBProcess *gdb_get_cpu_process(const GDBState *s, CPUState *cpu)
540
+{
55
+{
541
+ uint32_t uma_cts = s->regs[NPCM7XX_FIU_UMA_CTS];
56
+ return gdb_get_process(s, gdb_get_cpu_pid(s, cpu));
542
+ uint32_t uma_cfg;
57
+}
543
+ unsigned int i;
58
+
544
+
59
+static CPUState *find_cpu(uint32_t thread_id)
545
+ /* SW_CS means the CS is already forced low, so don't touch it. */
60
+{
546
+ if (uma_cts & FIU_UMA_CTS_SW_CS) {
61
+ CPUState *cpu;
547
+ int cs_id = FIU_UMA_CTS_DEV_NUM(s->regs[NPCM7XX_FIU_UMA_CTS]);
62
+
548
+ npcm7xx_fiu_select(s, cs_id);
63
+ CPU_FOREACH(cpu) {
549
+ }
64
+ if (cpu_gdb_index(cpu) == thread_id) {
550
+
65
+ return cpu;
551
+ /* Send command, if present. */
552
+ uma_cfg = s->regs[NPCM7XX_FIU_UMA_CFG];
553
+ if (FIU_UMA_CFG_CMDSIZ(uma_cfg) > 0) {
554
+ ssi_transfer(s->spi, extract32(s->regs[NPCM7XX_FIU_UMA_CMD], 0, 8));
555
+ }
556
+
557
+ /* Send address, if present. */
558
+ send_address(s->spi, FIU_UMA_CFG_ADDSIZ(uma_cfg),
559
+ s->regs[NPCM7XX_FIU_UMA_ADDR]);
560
+
561
+ /* Write data, if present. */
562
+ for (i = 0; i < FIU_UMA_CFG_WDATSIZ(uma_cfg); i++) {
563
+ unsigned int reg =
564
+ (i < 16) ? (NPCM7XX_FIU_UMA_DW0 + i / 4) : NPCM7XX_FIU_UMA_DW3;
565
+ unsigned int field = (i % 4) * 8;
566
+
567
+ ssi_transfer(s->spi, extract32(s->regs[reg], field, 8));
568
+ }
569
+
570
+ /* Send dummy bits, if present. */
571
+ send_dummy_bits(s->spi, uma_cfg, s->regs[NPCM7XX_FIU_UMA_CMD]);
572
+
573
+ /* Read data, if present. */
574
+ for (i = 0; i < FIU_UMA_CFG_RDATSIZ(uma_cfg); i++) {
575
+ unsigned int reg = NPCM7XX_FIU_UMA_DR0 + i / 4;
576
+ unsigned int field = (i % 4) * 8;
577
+ uint8_t c;
578
+
579
+ c = ssi_transfer(s->spi, 0);
580
+ if (reg <= NPCM7XX_FIU_UMA_DR3) {
581
+ s->regs[reg] = deposit32(s->regs[reg], field, 8, c);
66
+ }
582
+ }
67
+ }
583
+ }
68
+
584
+
69
+ return NULL;
585
+ /* Again, don't touch CS if the user is forcing it low. */
70
+}
586
+ if (uma_cts & FIU_UMA_CTS_SW_CS) {
71
+
587
+ npcm7xx_fiu_deselect(s);
72
+static CPUState *gdb_get_cpu(const GDBState *s, uint32_t pid, uint32_t tid)
588
+ }
73
+{
589
+
74
+ GDBProcess *process;
590
+ /* RDYST means a command has completed since it was cleared. */
75
+ CPUState *cpu;
591
+ s->regs[NPCM7XX_FIU_UMA_CTS] |= FIU_UMA_CTS_RDYST;
76
+
592
+ /* EXEC_DONE means Execute Command / Not Done, so clear it here. */
77
+ if (!tid) {
593
+ s->regs[NPCM7XX_FIU_UMA_CTS] &= ~FIU_UMA_CTS_EXEC_DONE;
78
+ /* 0 means any thread, we take the first one */
594
+}
79
+ tid = 1;
595
+
80
+ }
596
+/* Control register write handler. */
81
+
597
+static void npcm7xx_fiu_ctrl_write(void *opaque, hwaddr addr, uint64_t v,
82
+ cpu = find_cpu(tid);
598
+ unsigned int size)
83
+
599
+{
84
+ if (cpu == NULL) {
600
+ hwaddr reg = addr / sizeof(uint32_t);
85
+ return NULL;
601
+ NPCM7xxFIUState *s = opaque;
86
+ }
602
+ uint32_t value = v;
87
+
603
+
88
+ process = gdb_get_cpu_process(s, cpu);
604
+ trace_npcm7xx_fiu_ctrl_write(DEVICE(s)->canonical_path, addr, value);
89
+
605
+
90
+ if (process->pid != pid) {
606
+ switch (reg) {
91
+ return NULL;
607
+ case NPCM7XX_FIU_UMA_CFG:
92
+ }
608
+ if (s->regs[reg] & FIU_UMA_CFG_CMMLCK) {
93
+
609
+ value &= ~FIU_UMA_CFG_CMMLCK_MASK;
94
+ if (!process->attached) {
610
+ value |= (s->regs[reg] & FIU_UMA_CFG_CMMLCK_MASK);
95
+ return NULL;
96
+ }
97
+
98
+ return cpu;
99
+}
100
+
101
static const char *get_feature_xml(const char *p, const char **newp,
102
CPUClass *cc)
103
{
104
@@ -XXX,XX +XXX,XX @@ static void gdb_set_cpu_pc(GDBState *s, target_ulong pc)
105
cpu_set_pc(cpu, pc);
106
}
107
108
-static CPUState *find_cpu(uint32_t thread_id)
109
-{
110
- CPUState *cpu;
111
-
112
- CPU_FOREACH(cpu) {
113
- if (cpu_gdb_index(cpu) == thread_id) {
114
- return cpu;
115
- }
116
- }
117
-
118
- return NULL;
119
-}
120
-
121
static char *gdb_fmt_thread_id(const GDBState *s, CPUState *cpu,
122
char *buf, size_t buf_size)
123
{
124
@@ -XXX,XX +XXX,XX @@ static char *gdb_fmt_thread_id(const GDBState *s, CPUState *cpu,
125
return buf;
126
}
127
128
+typedef enum GDBThreadIdKind {
129
+ GDB_ONE_THREAD = 0,
130
+ GDB_ALL_THREADS, /* One process, all threads */
131
+ GDB_ALL_PROCESSES,
132
+ GDB_READ_THREAD_ERR
133
+} GDBThreadIdKind;
134
+
135
+static GDBThreadIdKind read_thread_id(const char *buf, const char **end_buf,
136
+ uint32_t *pid, uint32_t *tid)
137
+{
138
+ unsigned long p, t;
139
+ int ret;
140
+
141
+ if (*buf == 'p') {
142
+ buf++;
143
+ ret = qemu_strtoul(buf, &buf, 16, &p);
144
+
145
+ if (ret) {
146
+ return GDB_READ_THREAD_ERR;
147
+ }
611
+ }
148
+
612
+ /* fall through */
149
+ /* Skip '.' */
613
+ case NPCM7XX_FIU_DRD_CFG:
150
+ buf++;
614
+ case NPCM7XX_FIU_DWR_CFG:
151
+ } else {
615
+ if (s->regs[reg] & NPCM7XX_FIU_CFG_LCK) {
152
+ p = 1;
616
+ qemu_log_mask(LOG_GUEST_ERROR,
153
+ }
617
+ "%s: write to locked register @ 0x%" PRIx64 "\n",
154
+
618
+ DEVICE(s)->canonical_path, addr);
155
+ ret = qemu_strtoul(buf, &buf, 16, &t);
619
+ return;
156
+
157
+ if (ret) {
158
+ return GDB_READ_THREAD_ERR;
159
+ }
160
+
161
+ *end_buf = buf;
162
+
163
+ if (p == -1) {
164
+ return GDB_ALL_PROCESSES;
165
+ }
166
+
167
+ if (pid) {
168
+ *pid = p;
169
+ }
170
+
171
+ if (t == -1) {
172
+ return GDB_ALL_THREADS;
173
+ }
174
+
175
+ if (tid) {
176
+ *tid = t;
177
+ }
178
+
179
+ return GDB_ONE_THREAD;
180
+}
181
+
182
static int is_query_packet(const char *p, const char *query, char separator)
183
{
184
unsigned int query_len = strlen(query);
185
@@ -XXX,XX +XXX,XX @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
186
CPUClass *cc;
187
const char *p;
188
uint32_t thread;
189
+ uint32_t pid, tid;
190
int ch, reg_size, type, res;
191
uint8_t mem_buf[MAX_PACKET_LENGTH];
192
char buf[sizeof(mem_buf) + 1 /* trailing NUL */];
193
char thread_id[16];
194
uint8_t *registers;
195
target_ulong addr, len;
196
+ GDBThreadIdKind thread_kind;
197
198
trace_gdbstub_io_command(line_buf);
199
200
@@ -XXX,XX +XXX,XX @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
201
break;
202
case 'H':
203
type = *p++;
204
- thread = strtoull(p, (char **)&p, 16);
205
- if (thread == -1 || thread == 0) {
206
+
207
+ thread_kind = read_thread_id(p, &p, &pid, &tid);
208
+ if (thread_kind == GDB_READ_THREAD_ERR) {
209
+ put_packet(s, "E22");
210
+ break;
211
+ }
620
+ }
212
+
621
+ s->regs[reg] = value;
213
+ if (thread_kind != GDB_ONE_THREAD) {
622
+ break;
214
put_packet(s, "OK");
623
+
215
break;
624
+ case NPCM7XX_FIU_UMA_CTS:
216
}
625
+ if (value & FIU_UMA_CTS_RDYST) {
217
- cpu = find_cpu(thread);
626
+ value &= ~FIU_UMA_CTS_RDYST;
218
+ cpu = gdb_get_cpu(s, pid, tid);
627
+ } else {
219
if (cpu == NULL) {
628
+ value |= s->regs[reg] & FIU_UMA_CTS_RDYST;
220
put_packet(s, "E22");
221
break;
222
@@ -XXX,XX +XXX,XX @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
223
}
224
break;
225
case 'T':
226
- thread = strtoull(p, (char **)&p, 16);
227
- cpu = find_cpu(thread);
228
+ thread_kind = read_thread_id(p, &p, &pid, &tid);
229
+ if (thread_kind == GDB_READ_THREAD_ERR) {
230
+ put_packet(s, "E22");
231
+ break;
232
+ }
629
+ }
233
+ cpu = gdb_get_cpu(s, pid, tid);
630
+ if ((s->regs[reg] ^ value) & FIU_UMA_CTS_SW_CS) {
234
631
+ if (value & FIU_UMA_CTS_SW_CS) {
235
if (cpu != NULL) {
632
+ /*
236
put_packet(s, "OK");
633
+ * Don't drop CS if there's a transfer in progress, or we're
634
+ * about to start one.
635
+ */
636
+ if (!((value | s->regs[reg]) & FIU_UMA_CTS_EXEC_DONE)) {
637
+ npcm7xx_fiu_deselect(s);
638
+ }
639
+ } else {
640
+ int cs_id = FIU_UMA_CTS_DEV_NUM(s->regs[NPCM7XX_FIU_UMA_CTS]);
641
+ npcm7xx_fiu_select(s, cs_id);
642
+ }
643
+ }
644
+ s->regs[reg] = value | (s->regs[reg] & FIU_UMA_CTS_EXEC_DONE);
645
+ if (value & FIU_UMA_CTS_EXEC_DONE) {
646
+ npcm7xx_fiu_uma_transaction(s);
647
+ }
648
+ break;
649
+
650
+ case NPCM7XX_FIU_UMA_DR0 ... NPCM7XX_FIU_UMA_DR3:
651
+ qemu_log_mask(LOG_GUEST_ERROR,
652
+ "%s: write to read-only register @ 0x%" PRIx64 "\n",
653
+ DEVICE(s)->canonical_path, addr);
654
+ return;
655
+
656
+ case NPCM7XX_FIU_PRT_CFG:
657
+ case NPCM7XX_FIU_PRT_CMD0 ... NPCM7XX_FIU_PRT_CMD9:
658
+ qemu_log_mask(LOG_UNIMP, "%s: PRT is not implemented\n", __func__);
659
+ break;
660
+
661
+ case NPCM7XX_FIU_UMA_CMD:
662
+ case NPCM7XX_FIU_UMA_ADDR:
663
+ case NPCM7XX_FIU_UMA_DW0 ... NPCM7XX_FIU_UMA_DW3:
664
+ case NPCM7XX_FIU_CFG:
665
+ s->regs[reg] = value;
666
+ break;
667
+
668
+ default:
669
+ qemu_log_mask(LOG_GUEST_ERROR,
670
+ "%s: write to invalid offset 0x%" PRIx64 "\n",
671
+ DEVICE(s)->canonical_path, addr);
672
+ return;
673
+ }
674
+}
675
+
676
+static const MemoryRegionOps npcm7xx_fiu_ctrl_ops = {
677
+ .read = npcm7xx_fiu_ctrl_read,
678
+ .write = npcm7xx_fiu_ctrl_write,
679
+ .endianness = DEVICE_LITTLE_ENDIAN,
680
+ .valid = {
681
+ .min_access_size = 4,
682
+ .max_access_size = 4,
683
+ .unaligned = false,
684
+ },
685
+};
686
+
687
+static void npcm7xx_fiu_enter_reset(Object *obj, ResetType type)
688
+{
689
+ NPCM7xxFIUState *s = NPCM7XX_FIU(obj);
690
+
691
+ trace_npcm7xx_fiu_enter_reset(DEVICE(obj)->canonical_path, type);
692
+
693
+ memset(s->regs, 0, sizeof(s->regs));
694
+
695
+ s->regs[NPCM7XX_FIU_DRD_CFG] = 0x0300100b;
696
+ s->regs[NPCM7XX_FIU_DWR_CFG] = 0x03000002;
697
+ s->regs[NPCM7XX_FIU_UMA_CFG] = 0x00000400;
698
+ s->regs[NPCM7XX_FIU_UMA_CTS] = 0x00010000;
699
+ s->regs[NPCM7XX_FIU_UMA_CMD] = 0x0000000b;
700
+ s->regs[NPCM7XX_FIU_PRT_CFG] = 0x00000400;
701
+ s->regs[NPCM7XX_FIU_CFG] = 0x0000000b;
702
+}
703
+
704
+static void npcm7xx_fiu_hold_reset(Object *obj)
705
+{
706
+ NPCM7xxFIUState *s = NPCM7XX_FIU(obj);
707
+ int i;
708
+
709
+ trace_npcm7xx_fiu_hold_reset(DEVICE(obj)->canonical_path);
710
+
711
+ for (i = 0; i < s->cs_count; i++) {
712
+ qemu_irq_raise(s->cs_lines[i]);
713
+ }
714
+}
715
+
716
+static void npcm7xx_fiu_realize(DeviceState *dev, Error **errp)
717
+{
718
+ NPCM7xxFIUState *s = NPCM7XX_FIU(dev);
719
+ SysBusDevice *sbd = &s->parent;
720
+ int i;
721
+
722
+ if (s->cs_count <= 0) {
723
+ error_setg(errp, "%s: %d chip selects specified, need at least one",
724
+ dev->canonical_path, s->cs_count);
725
+ return;
726
+ }
727
+
728
+ s->spi = ssi_create_bus(dev, "spi");
729
+ s->cs_lines = g_new0(qemu_irq, s->cs_count);
730
+ qdev_init_gpio_out_named(DEVICE(s), s->cs_lines, "cs", s->cs_count);
731
+ s->flash = g_new0(NPCM7xxFIUFlash, s->cs_count);
732
+
733
+ /*
734
+ * Register the control registers region first. It may be followed by one
735
+ * or more direct flash access regions.
736
+ */
737
+ memory_region_init_io(&s->mmio, OBJECT(s), &npcm7xx_fiu_ctrl_ops, s, "ctrl",
738
+ NPCM7XX_FIU_CTRL_REGS_SIZE);
739
+ sysbus_init_mmio(sbd, &s->mmio);
740
+
741
+ for (i = 0; i < s->cs_count; i++) {
742
+ NPCM7xxFIUFlash *flash = &s->flash[i];
743
+ flash->fiu = s;
744
+ memory_region_init_io(&flash->direct_access, OBJECT(s),
745
+ &npcm7xx_fiu_flash_ops, &s->flash[i], "flash",
746
+ NPCM7XX_FIU_FLASH_WINDOW_SIZE);
747
+ sysbus_init_mmio(sbd, &flash->direct_access);
748
+ }
749
+}
750
+
751
+static const VMStateDescription vmstate_npcm7xx_fiu = {
752
+ .name = "npcm7xx-fiu",
753
+ .version_id = 0,
754
+ .minimum_version_id = 0,
755
+ .fields = (VMStateField[]) {
756
+ VMSTATE_INT32(active_cs, NPCM7xxFIUState),
757
+ VMSTATE_UINT32_ARRAY(regs, NPCM7xxFIUState, NPCM7XX_FIU_NR_REGS),
758
+ VMSTATE_END_OF_LIST(),
759
+ },
760
+};
761
+
762
+static Property npcm7xx_fiu_properties[] = {
763
+ DEFINE_PROP_INT32("cs-count", NPCM7xxFIUState, cs_count, 0),
764
+ DEFINE_PROP_END_OF_LIST(),
765
+};
766
+
767
+static void npcm7xx_fiu_class_init(ObjectClass *klass, void *data)
768
+{
769
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
770
+ DeviceClass *dc = DEVICE_CLASS(klass);
771
+
772
+ QEMU_BUILD_BUG_ON(NPCM7XX_FIU_REGS_END > NPCM7XX_FIU_NR_REGS);
773
+
774
+ dc->desc = "NPCM7xx Flash Interface Unit";
775
+ dc->realize = npcm7xx_fiu_realize;
776
+ dc->vmsd = &vmstate_npcm7xx_fiu;
777
+ rc->phases.enter = npcm7xx_fiu_enter_reset;
778
+ rc->phases.hold = npcm7xx_fiu_hold_reset;
779
+ device_class_set_props(dc, npcm7xx_fiu_properties);
780
+}
781
+
782
+static const TypeInfo npcm7xx_fiu_types[] = {
783
+ {
784
+ .name = TYPE_NPCM7XX_FIU,
785
+ .parent = TYPE_SYS_BUS_DEVICE,
786
+ .instance_size = sizeof(NPCM7xxFIUState),
787
+ .class_init = npcm7xx_fiu_class_init,
788
+ },
789
+};
790
+DEFINE_TYPES(npcm7xx_fiu_types);
791
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
792
index XXXXXXX..XXXXXXX 100644
793
--- a/hw/arm/Kconfig
794
+++ b/hw/arm/Kconfig
795
@@ -XXX,XX +XXX,XX @@ config NPCM7XX
796
select ARM_GIC
797
select PL310 # cache controller
798
select SERIAL
799
+ select SSI
800
select UNIMP
801
802
config FSL_IMX25
803
diff --git a/hw/ssi/meson.build b/hw/ssi/meson.build
804
index XXXXXXX..XXXXXXX 100644
805
--- a/hw/ssi/meson.build
806
+++ b/hw/ssi/meson.build
807
@@ -XXX,XX +XXX,XX @@
808
softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_smc.c'))
809
softmmu_ss.add(when: 'CONFIG_MSF2', if_true: files('mss-spi.c'))
810
+softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_fiu.c'))
811
softmmu_ss.add(when: 'CONFIG_PL022', if_true: files('pl022.c'))
812
softmmu_ss.add(when: 'CONFIG_SSI', if_true: files('ssi.c'))
813
softmmu_ss.add(when: 'CONFIG_STM32F2XX_SPI', if_true: files('stm32f2xx_spi.c'))
814
diff --git a/hw/ssi/trace-events b/hw/ssi/trace-events
815
index XXXXXXX..XXXXXXX 100644
816
--- a/hw/ssi/trace-events
817
+++ b/hw/ssi/trace-events
818
@@ -XXX,XX +XXX,XX @@ aspeed_smc_dma_checksum(uint32_t addr, uint32_t data) "0x%08x: 0x%08x"
819
aspeed_smc_dma_rw(const char *dir, uint32_t flash_addr, uint32_t dram_addr, uint32_t size) "%s flash:@0x%08x dram:@0x%08x size:0x%08x"
820
aspeed_smc_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size %u: 0x%" PRIx64
821
aspeed_smc_flash_select(int cs, const char *prefix) "CS%d %sselect"
822
+
823
+# npcm7xx_fiu.c
824
+
825
+npcm7xx_fiu_enter_reset(const char *id, int reset_type) "%s reset type: %d"
826
+npcm7xx_fiu_hold_reset(const char *id) "%s"
827
+npcm7xx_fiu_select(const char *id, int cs) "%s select CS%d"
828
+npcm7xx_fiu_deselect(const char *id, int cs) "%s deselect CS%d"
829
+npcm7xx_fiu_ctrl_read(const char *id, uint64_t addr, uint32_t data) "%s offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
830
+npcm7xx_fiu_ctrl_write(const char *id, uint64_t addr, uint32_t data) "%s offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
831
+npcm7xx_fiu_flash_read(const char *id, int cs, uint64_t addr, unsigned int size, uint64_t value) "%s[%d] offset: 0x%08" PRIx64 " size: %u value: 0x%" PRIx64
832
+npcm7xx_fiu_flash_write(const char *id, int cs, uint64_t addr, unsigned int size, uint64_t value) "%s[%d] offset: 0x%08" PRIx64 " size: %u value: 0x%" PRIx64
237
--
833
--
238
2.19.2
834
2.20.1
239
835
240
836
diff view generated by jsdifflib
1
From: Luc Michel <luc.michel@greensocs.com>
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
2
3
'D' packets are used by GDB to detach from a process. In multiprocess
3
This allows these NPCM7xx-based boards to boot from a flash image, e.g.
4
mode, the PID to detach from is sent in the request.
4
one built with OpenBMC. For example like this:
5
5
6
Signed-off-by: Luc Michel <luc.michel@greensocs.com>
6
IMAGE=${OPENBMC}/build/tmp/deploy/images/gsj/image-bmc
7
qemu-system-arm -machine quanta-gsj -nographic \
8
    -drive file=${IMAGE},if=mtd,bus=0,unit=0,format=raw,snapshot=on
9
10
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
11
Reviewed-by: Cédric Le Goater <clg@kaod.org>
12
Tested-by: Cédric Le Goater <clg@kaod.org>
13
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
16
Message-id: 20200911052101.2602693-12-hskinnemoen@google.com
9
Acked-by: Alistair Francis <alistair.francis@wdc.com>
10
Message-id: 20181207090135.7651-11-luc.michel@greensocs.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
18
---
13
gdbstub.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++-------
19
hw/arm/npcm7xx_boards.c | 20 ++++++++++++++++++++
14
1 file changed, 53 insertions(+), 7 deletions(-)
20
1 file changed, 20 insertions(+)
15
21
16
diff --git a/gdbstub.c b/gdbstub.c
22
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
17
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
18
--- a/gdbstub.c
24
--- a/hw/arm/npcm7xx_boards.c
19
+++ b/gdbstub.c
25
+++ b/hw/arm/npcm7xx_boards.c
20
@@ -XXX,XX +XXX,XX @@ static int gdb_breakpoint_remove(target_ulong addr, target_ulong len, int type)
26
@@ -XXX,XX +XXX,XX @@
27
#include "hw/arm/npcm7xx.h"
28
#include "hw/core/cpu.h"
29
#include "hw/loader.h"
30
+#include "hw/qdev-properties.h"
31
#include "qapi/error.h"
32
#include "qemu-common.h"
33
#include "qemu/units.h"
34
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_load_bootrom(MachineState *machine, NPCM7xxState *soc)
21
}
35
}
22
}
36
}
23
37
24
+static inline void gdb_cpu_breakpoint_remove_all(CPUState *cpu)
38
+static void npcm7xx_connect_flash(NPCM7xxFIUState *fiu, int cs_no,
39
+ const char *flash_type, DriveInfo *dinfo)
25
+{
40
+{
26
+ cpu_breakpoint_remove_all(cpu, BP_GDB);
41
+ DeviceState *flash;
27
+#ifndef CONFIG_USER_ONLY
42
+ qemu_irq flash_cs;
28
+ cpu_watchpoint_remove_all(cpu, BP_GDB);
43
+
29
+#endif
44
+ flash = qdev_new(flash_type);
45
+ if (dinfo) {
46
+ qdev_prop_set_drive(flash, "drive", blk_by_legacy_dinfo(dinfo));
47
+ }
48
+ qdev_realize_and_unref(flash, BUS(fiu->spi), &error_fatal);
49
+
50
+ flash_cs = qdev_get_gpio_in_named(flash, SSI_GPIO_CS, 0);
51
+ qdev_connect_gpio_out_named(DEVICE(fiu), "cs", cs_no, flash_cs);
30
+}
52
+}
31
+
53
+
32
+static void gdb_process_breakpoint_remove_all(const GDBState *s, GDBProcess *p)
54
static void npcm7xx_connect_dram(NPCM7xxState *soc, MemoryRegion *dram)
33
+{
34
+ CPUState *cpu = get_first_cpu_in_process(s, p);
35
+
36
+ while (cpu) {
37
+ gdb_cpu_breakpoint_remove_all(cpu);
38
+ cpu = gdb_next_cpu_in_process(s, cpu);
39
+ }
40
+}
41
+
42
static void gdb_breakpoint_remove_all(void)
43
{
55
{
44
CPUState *cpu;
56
memory_region_add_subregion(get_system_memory(), NPCM7XX_DRAM_BA, dram);
45
@@ -XXX,XX +XXX,XX @@ static void gdb_breakpoint_remove_all(void)
57
@@ -XXX,XX +XXX,XX @@ static void npcm750_evb_init(MachineState *machine)
46
}
58
qdev_realize(DEVICE(soc), NULL, &error_fatal);
47
59
48
CPU_FOREACH(cpu) {
60
npcm7xx_load_bootrom(machine, soc);
49
- cpu_breakpoint_remove_all(cpu, BP_GDB);
61
+ npcm7xx_connect_flash(&soc->fiu[0], 0, "w25q256", drive_get(IF_MTD, 0, 0));
50
-#ifndef CONFIG_USER_ONLY
62
npcm7xx_load_kernel(machine, soc);
51
- cpu_watchpoint_remove_all(cpu, BP_GDB);
52
-#endif
53
+ gdb_cpu_breakpoint_remove_all(cpu);
54
}
55
}
63
}
56
64
57
@@ -XXX,XX +XXX,XX @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
65
@@ -XXX,XX +XXX,XX @@ static void quanta_gsj_init(MachineState *machine)
58
exit(0);
66
qdev_realize(DEVICE(soc), NULL, &error_fatal);
59
case 'D':
67
60
/* Detach packet */
68
npcm7xx_load_bootrom(machine, soc);
61
- gdb_breakpoint_remove_all();
69
+ npcm7xx_connect_flash(&soc->fiu[0], 0, "mx25l25635e",
62
- gdb_syscall_mode = GDB_SYS_DISABLED;
70
+ drive_get(IF_MTD, 0, 0));
63
- gdb_continue(s);
71
npcm7xx_load_kernel(machine, soc);
64
+ pid = 1;
72
}
65
+
73
66
+ if (s->multiprocess) {
67
+ unsigned long lpid;
68
+ if (*p != ';') {
69
+ put_packet(s, "E22");
70
+ break;
71
+ }
72
+
73
+ if (qemu_strtoul(p + 1, &p, 16, &lpid)) {
74
+ put_packet(s, "E22");
75
+ break;
76
+ }
77
+
78
+ pid = lpid;
79
+ }
80
+
81
+ process = gdb_get_process(s, pid);
82
+ gdb_process_breakpoint_remove_all(s, process);
83
+ process->attached = false;
84
+
85
+ if (pid == gdb_get_cpu_pid(s, s->c_cpu)) {
86
+ s->c_cpu = gdb_first_attached_cpu(s);
87
+ }
88
+
89
+ if (pid == gdb_get_cpu_pid(s, s->g_cpu)) {
90
+ s->g_cpu = gdb_first_attached_cpu(s);
91
+ }
92
+
93
+ if (s->c_cpu == NULL) {
94
+ /* No more process attached */
95
+ gdb_syscall_mode = GDB_SYS_DISABLED;
96
+ gdb_continue(s);
97
+ }
98
put_packet(s, "OK");
99
break;
100
case 's':
101
--
74
--
102
2.19.2
75
2.20.1
103
76
104
77
diff view generated by jsdifflib
1
From: Luc Michel <luc.michel@greensocs.com>
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
2
3
Add a structure GDBProcess that represents processes from the GDB
3
When booting directly into a kernel, bypassing the boot loader, the CPU and
4
semantic point of view.
4
UART clocks are not set up correctly. This makes the system appear very
5
slow, and causes the initrd boot test to fail when optimization is off.
5
6
6
CPUs can be split into different processes, by grouping them under
7
The UART clock must run at 24 MHz. The default 25 MHz reference clock
7
different cpu-cluster objects. Each occurrence of a cpu-cluster object
8
cannot achieve this, so switch to PLL2/2 @ 480 MHz, which works
8
implies the existence of the corresponding process in the GDB stub. The
9
perfectly with the default /20 divider.
9
GDB process ID is derived from the corresponding cluster ID as follows:
10
10
11
GDB PID = cluster ID + 1
11
The CPU clock should run at 800 MHz, so switch it to PLL1/2. PLL1 runs
12
at 800 MHz by default, so we need to double the feedback divider as well
13
to make it run at 1600 MHz (so PLL1/2 runs at 800 MHz).
12
14
13
This is because PIDs -1 and 0 are reserved in GDB and cannot be used by
15
We don't bother checking for PLL lock because we know our emulated PLLs
14
processes.
16
lock instantly.
15
17
16
A default process is created to handle CPUs that are not in a cluster.
18
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
This process gets the PID of the last process PID + 1.
19
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
18
20
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
19
Signed-off-by: Luc Michel <luc.michel@greensocs.com>
21
Message-id: 20200911052101.2602693-13-hskinnemoen@google.com
20
Acked-by: Alistair Francis <alistair.francis@wdc.com>
21
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
22
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
23
Message-id: 20181207090135.7651-3-luc.michel@greensocs.com
24
[PMM: fixed checkpatch nit about block comment style]
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
---
23
---
27
gdbstub.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
24
include/hw/arm/npcm7xx.h | 1 +
28
1 file changed, 97 insertions(+)
25
hw/arm/npcm7xx.c | 32 ++++++++++++++++++++++++++++++++
26
2 files changed, 33 insertions(+)
29
27
30
diff --git a/gdbstub.c b/gdbstub.c
28
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
31
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
32
--- a/gdbstub.c
30
--- a/include/hw/arm/npcm7xx.h
33
+++ b/gdbstub.c
31
+++ b/include/hw/arm/npcm7xx.h
34
@@ -XXX,XX +XXX,XX @@
32
@@ -XXX,XX +XXX,XX @@
35
#include "chardev/char-fe.h"
33
#define NPCM7XX_SMP_LOADER_START (0xffff0000) /* Boot ROM */
36
#include "sysemu/sysemu.h"
34
#define NPCM7XX_SMP_BOOTREG_ADDR (0xf080013c) /* GCR.SCRPAD */
37
#include "exec/gdbstub.h"
35
#define NPCM7XX_GIC_CPU_IF_ADDR (0xf03fe100) /* GIC within A9 */
38
+#include "hw/cpu/cluster.h"
36
+#define NPCM7XX_BOARD_SETUP_ADDR (0xffff1000) /* Boot ROM */
39
#endif
37
40
38
typedef struct NPCM7xxMachine {
41
#define MAX_PACKET_LENGTH 4096
39
MachineState parent;
42
@@ -XXX,XX +XXX,XX @@ typedef struct GDBRegisterState {
40
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
43
struct GDBRegisterState *next;
41
index XXXXXXX..XXXXXXX 100644
44
} GDBRegisterState;
42
--- a/hw/arm/npcm7xx.c
45
43
+++ b/hw/arm/npcm7xx.c
46
+typedef struct GDBProcess {
44
@@ -XXX,XX +XXX,XX @@
47
+ uint32_t pid;
45
#define NPCM7XX_ROM_BA (0xffff0000)
48
+ bool attached;
46
#define NPCM7XX_ROM_SZ (64 * KiB)
49
+} GDBProcess;
47
48
+/* Clock configuration values to be fixed up when bypassing bootloader */
50
+
49
+
51
enum RSState {
50
+/* Run PLL1 at 1600 MHz */
52
RS_INACTIVE,
51
+#define NPCM7XX_PLLCON1_FIXUP_VAL (0x00402101)
53
RS_IDLE,
52
+/* Run the CPU from PLL1 and UART from PLL2 */
54
@@ -XXX,XX +XXX,XX @@ typedef struct GDBState {
53
+#define NPCM7XX_CLKSEL_FIXUP_VAL (0x004aaba9)
55
CharBackend chr;
54
+
56
Chardev *mon_chr;
55
/*
57
#endif
56
* Interrupt lines going into the GIC. This does not include internal Cortex-A9
58
+ bool multiprocess;
57
* interrupts.
59
+ GDBProcess *processes;
58
@@ -XXX,XX +XXX,XX @@ static const struct {
60
+ int process_num;
59
},
61
char syscall_buf[256];
60
};
62
gdb_syscall_complete_cb current_syscall_cb;
61
63
} GDBState;
62
+static void npcm7xx_write_board_setup(ARMCPU *cpu,
64
@@ -XXX,XX +XXX,XX @@ void gdb_exit(CPUArchState *env, int code)
63
+ const struct arm_boot_info *info)
65
#endif
66
}
67
68
+/*
69
+ * Create the process that will contain all the "orphan" CPUs (that are not
70
+ * part of a CPU cluster). Note that if this process contains no CPUs, it won't
71
+ * be attachable and thus will be invisible to the user.
72
+ */
73
+static void create_default_process(GDBState *s)
74
+{
64
+{
75
+ GDBProcess *process;
65
+ uint32_t board_setup[] = {
76
+ int max_pid = 0;
66
+ 0xe59f0010, /* ldr r0, clk_base_addr */
67
+ 0xe59f1010, /* ldr r1, pllcon1_value */
68
+ 0xe5801010, /* str r1, [r0, #16] */
69
+ 0xe59f100c, /* ldr r1, clksel_value */
70
+ 0xe5801004, /* str r1, [r0, #4] */
71
+ 0xe12fff1e, /* bx lr */
72
+ NPCM7XX_CLK_BA,
73
+ NPCM7XX_PLLCON1_FIXUP_VAL,
74
+ NPCM7XX_CLKSEL_FIXUP_VAL,
75
+ };
76
+ int i;
77
+
77
+
78
+ if (s->process_num) {
78
+ for (i = 0; i < ARRAY_SIZE(board_setup); i++) {
79
+ max_pid = s->processes[s->process_num - 1].pid;
79
+ board_setup[i] = tswap32(board_setup[i]);
80
+ }
80
+ }
81
+
81
+ rom_add_blob_fixed("board-setup", board_setup, sizeof(board_setup),
82
+ s->processes = g_renew(GDBProcess, s->processes, ++s->process_num);
82
+ info->board_setup_addr);
83
+ process = &s->processes[s->process_num - 1];
84
+
85
+ /* We need an available PID slot for this process */
86
+ assert(max_pid < UINT32_MAX);
87
+
88
+ process->pid = max_pid + 1;
89
+ process->attached = false;
90
+}
83
+}
91
+
84
+
92
#ifdef CONFIG_USER_ONLY
85
static void npcm7xx_write_secondary_boot(ARMCPU *cpu,
93
int
86
const struct arm_boot_info *info)
94
gdb_handlesig(CPUState *cpu, int sig)
87
{
95
@@ -XXX,XX +XXX,XX @@ static bool gdb_accept(void)
88
@@ -XXX,XX +XXX,XX @@ static struct arm_boot_info npcm7xx_binfo = {
96
s = g_malloc0(sizeof(GDBState));
89
.gic_cpu_if_addr = NPCM7XX_GIC_CPU_IF_ADDR,
97
s->c_cpu = first_cpu;
90
.write_secondary_boot = npcm7xx_write_secondary_boot,
98
s->g_cpu = first_cpu;
91
.board_id = -1,
99
+ create_default_process(s);
92
+ .board_setup_addr = NPCM7XX_BOARD_SETUP_ADDR,
100
s->fd = fd;
93
+ .write_board_setup = npcm7xx_write_board_setup,
101
gdb_has_xml = false;
102
103
@@ -XXX,XX +XXX,XX @@ static const TypeInfo char_gdb_type_info = {
104
.class_init = char_gdb_class_init,
105
};
94
};
106
95
107
+static int find_cpu_clusters(Object *child, void *opaque)
96
void npcm7xx_load_kernel(MachineState *machine, NPCM7xxState *soc)
108
+{
109
+ if (object_dynamic_cast(child, TYPE_CPU_CLUSTER)) {
110
+ GDBState *s = (GDBState *) opaque;
111
+ CPUClusterState *cluster = CPU_CLUSTER(child);
112
+ GDBProcess *process;
113
+
114
+ s->processes = g_renew(GDBProcess, s->processes, ++s->process_num);
115
+
116
+ process = &s->processes[s->process_num - 1];
117
+
118
+ /*
119
+ * GDB process IDs -1 and 0 are reserved. To avoid subtle errors at
120
+ * runtime, we enforce here that the machine does not use a cluster ID
121
+ * that would lead to PID 0.
122
+ */
123
+ assert(cluster->cluster_id != UINT32_MAX);
124
+ process->pid = cluster->cluster_id + 1;
125
+ process->attached = false;
126
+
127
+ return 0;
128
+ }
129
+
130
+ return object_child_foreach(child, find_cpu_clusters, opaque);
131
+}
132
+
133
+static int pid_order(const void *a, const void *b)
134
+{
135
+ GDBProcess *pa = (GDBProcess *) a;
136
+ GDBProcess *pb = (GDBProcess *) b;
137
+
138
+ if (pa->pid < pb->pid) {
139
+ return -1;
140
+ } else if (pa->pid > pb->pid) {
141
+ return 1;
142
+ } else {
143
+ return 0;
144
+ }
145
+}
146
+
147
+static void create_processes(GDBState *s)
148
+{
149
+ object_child_foreach(object_get_root(), find_cpu_clusters, s);
150
+
151
+ if (s->processes) {
152
+ /* Sort by PID */
153
+ qsort(s->processes, s->process_num, sizeof(s->processes[0]), pid_order);
154
+ }
155
+
156
+ create_default_process(s);
157
+}
158
+
159
+static void cleanup_processes(GDBState *s)
160
+{
161
+ g_free(s->processes);
162
+ s->process_num = 0;
163
+ s->processes = NULL;
164
+}
165
+
166
int gdbserver_start(const char *device)
167
{
168
trace_gdbstub_op_start(device);
169
@@ -XXX,XX +XXX,XX @@ int gdbserver_start(const char *device)
170
} else {
171
qemu_chr_fe_deinit(&s->chr, true);
172
mon_chr = s->mon_chr;
173
+ cleanup_processes(s);
174
memset(s, 0, sizeof(GDBState));
175
s->mon_chr = mon_chr;
176
}
177
s->c_cpu = first_cpu;
178
s->g_cpu = first_cpu;
179
+
180
+ create_processes(s);
181
+
182
if (chr) {
183
qemu_chr_fe_init(&s->chr, chr, &error_abort);
184
qemu_chr_fe_set_handlers(&s->chr, gdb_chr_can_receive, gdb_chr_receive,
185
--
97
--
186
2.19.2
98
2.20.1
187
99
188
100
diff view generated by jsdifflib
Deleted patch
1
From: Luc Michel <luc.michel@greensocs.com>
2
1
3
Change the sC packet handling to support the multiprocess extension.
4
Instead of returning the first thread, we return the first thread of the
5
current process.
6
7
Signed-off-by: Luc Michel <luc.michel@greensocs.com>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
11
Message-id: 20181207090135.7651-7-luc.michel@greensocs.com
12
[PMM: corrected checkpatch comment style nit]
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
gdbstub.c | 12 +++++++++---
16
1 file changed, 9 insertions(+), 3 deletions(-)
17
18
diff --git a/gdbstub.c b/gdbstub.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/gdbstub.c
21
+++ b/gdbstub.c
22
@@ -XXX,XX +XXX,XX @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
23
put_packet(s, "OK");
24
break;
25
} else if (strcmp(p,"C") == 0) {
26
- /* "Current thread" remains vague in the spec, so always return
27
- * the first CPU (gdb returns the first thread). */
28
- put_packet(s, "QC1");
29
+ /*
30
+ * "Current thread" remains vague in the spec, so always return
31
+ * the first thread of the current process (gdb returns the
32
+ * first thread).
33
+ */
34
+ cpu = get_first_cpu_in_process(s, gdb_get_cpu_process(s, s->g_cpu));
35
+ snprintf(buf, sizeof(buf), "QC%s",
36
+ gdb_fmt_thread_id(s, cpu, thread_id, sizeof(thread_id)));
37
+ put_packet(s, buf);
38
break;
39
} else if (strcmp(p,"fThreadInfo") == 0) {
40
s->query_cpu = first_cpu;
41
--
42
2.19.2
43
44
diff view generated by jsdifflib
1
From: Luc Michel <luc.michel@greensocs.com>
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
2
3
Change the Xfer:features:read: packet handling to support the
3
Reviewed-by: Cédric Le Goater <clg@kaod.org>
4
multiprocess extension. This packet is used to request the XML
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
description of the CPU. In multiprocess mode, different descriptions can
5
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
6
be sent for different processes.
6
Message-id: 20200911052101.2602693-14-hskinnemoen@google.com
7
8
This function now takes the process to send the description for as a
9
parameter, and use a buffer in the process structure to store the
10
generated description.
11
12
It takes the first CPU of the process to generate the description.
13
14
Signed-off-by: Luc Michel <luc.michel@greensocs.com>
15
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
16
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
17
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
18
Message-id: 20181207090135.7651-9-luc.michel@greensocs.com
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
---
8
---
21
gdbstub.c | 52 ++++++++++++++++++++++++++++++----------------------
9
docs/system/arm/nuvoton.rst | 92 +++++++++++++++++++++++++++++++++++++
22
1 file changed, 30 insertions(+), 22 deletions(-)
10
docs/system/target-arm.rst | 1 +
11
2 files changed, 93 insertions(+)
12
create mode 100644 docs/system/arm/nuvoton.rst
23
13
24
diff --git a/gdbstub.c b/gdbstub.c
14
diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
15
new file mode 100644
16
index XXXXXXX..XXXXXXX
17
--- /dev/null
18
+++ b/docs/system/arm/nuvoton.rst
19
@@ -XXX,XX +XXX,XX @@
20
+Nuvoton iBMC boards (``npcm750-evb``, ``quanta-gsj``)
21
+=====================================================
22
+
23
+The `Nuvoton iBMC`_ chips (NPCM7xx) are a family of ARM-based SoCs that are
24
+designed to be used as Baseboard Management Controllers (BMCs) in various
25
+servers. They all feature one or two ARM Cortex A9 CPU cores, as well as an
26
+assortment of peripherals targeted for either Enterprise or Data Center /
27
+Hyperscale applications. The former is a superset of the latter, so NPCM750 has
28
+all the peripherals of NPCM730 and more.
29
+
30
+.. _Nuvoton iBMC: https://www.nuvoton.com/products/cloud-computing/ibmc/
31
+
32
+The NPCM750 SoC has two Cortex A9 cores and is targeted for the Enterprise
33
+segment. The following machines are based on this chip :
34
+
35
+- ``npcm750-evb`` Nuvoton NPCM750 Evaluation board
36
+
37
+The NPCM730 SoC has two Cortex A9 cores and is targeted for Data Center and
38
+Hyperscale applications. The following machines are based on this chip :
39
+
40
+- ``quanta-gsj`` Quanta GSJ server BMC
41
+
42
+There are also two more SoCs, NPCM710 and NPCM705, which are single-core
43
+variants of NPCM750 and NPCM730, respectively. These are currently not
44
+supported by QEMU.
45
+
46
+Supported devices
47
+-----------------
48
+
49
+ * SMP (Dual Core Cortex-A9)
50
+ * Cortex-A9MPCore built-in peripherals: SCU, GIC, Global Timer, Private Timer
51
+ and Watchdog.
52
+ * SRAM, ROM and DRAM mappings
53
+ * System Global Control Registers (GCR)
54
+ * Clock and reset controller (CLK)
55
+ * Timer controller (TIM)
56
+ * Serial ports (16550-based)
57
+ * DDR4 memory controller (dummy interface indicating memory training is done)
58
+ * OTP controllers (no protection features)
59
+ * Flash Interface Unit (FIU; no protection features)
60
+
61
+Missing devices
62
+---------------
63
+
64
+ * GPIO controller
65
+ * LPC/eSPI host-to-BMC interface, including
66
+
67
+ * Keyboard and mouse controller interface (KBCI)
68
+ * Keyboard Controller Style (KCS) channels
69
+ * BIOS POST code FIFO
70
+ * System Wake-up Control (SWC)
71
+ * Shared memory (SHM)
72
+ * eSPI slave interface
73
+
74
+ * Ethernet controllers (GMAC and EMC)
75
+ * USB host (USBH)
76
+ * USB device (USBD)
77
+ * SMBus controller (SMBF)
78
+ * Peripheral SPI controller (PSPI)
79
+ * Analog to Digital Converter (ADC)
80
+ * SD/MMC host
81
+ * Random Number Generator (RNG)
82
+ * PECI interface
83
+ * Pulse Width Modulation (PWM)
84
+ * Tachometer
85
+ * PCI and PCIe root complex and bridges
86
+ * VDM and MCTP support
87
+ * Serial I/O expansion
88
+ * LPC/eSPI host
89
+ * Coprocessor
90
+ * Graphics
91
+ * Video capture
92
+ * Encoding compression engine
93
+ * Security features
94
+
95
+Boot options
96
+------------
97
+
98
+The Nuvoton machines can boot from an OpenBMC firmware image, or directly into
99
+a kernel using the ``-kernel`` option. OpenBMC images for `quanta-gsj` and
100
+possibly others can be downloaded from the OpenPOWER jenkins :
101
+
102
+ https://openpower.xyz/
103
+
104
+The firmware image should be attached as an MTD drive. Example :
105
+
106
+.. code-block:: bash
107
+
108
+ $ qemu-system-arm -machine quanta-gsj -nographic \
109
+ -drive file=image-bmc,if=mtd,bus=0,unit=0,format=raw
110
+
111
+The default root password for test images is usually ``0penBmc``.
112
diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst
25
index XXXXXXX..XXXXXXX 100644
113
index XXXXXXX..XXXXXXX 100644
26
--- a/gdbstub.c
114
--- a/docs/system/target-arm.rst
27
+++ b/gdbstub.c
115
+++ b/docs/system/target-arm.rst
28
@@ -XXX,XX +XXX,XX @@ typedef struct GDBRegisterState {
116
@@ -XXX,XX +XXX,XX @@ undocumented; you can get a complete list by running
29
typedef struct GDBProcess {
117
arm/musicpal
30
uint32_t pid;
118
arm/gumstix
31
bool attached;
119
arm/nseries
32
+
120
+ arm/nuvoton
33
+ char target_xml[1024];
121
arm/orangepi
34
} GDBProcess;
122
arm/palm
35
123
arm/xscale
36
enum RSState {
37
@@ -XXX,XX +XXX,XX @@ static CPUState *gdb_first_attached_cpu(const GDBState *s)
38
return cpu;
39
}
40
41
-static const char *get_feature_xml(const char *p, const char **newp,
42
- CPUClass *cc)
43
+static const char *get_feature_xml(const GDBState *s, const char *p,
44
+ const char **newp, GDBProcess *process)
45
{
46
size_t len;
47
int i;
48
const char *name;
49
- static char target_xml[1024];
50
+ CPUState *cpu = get_first_cpu_in_process(s, process);
51
+ CPUClass *cc = CPU_GET_CLASS(cpu);
52
53
len = 0;
54
while (p[len] && p[len] != ':')
55
@@ -XXX,XX +XXX,XX @@ static const char *get_feature_xml(const char *p, const char **newp,
56
57
name = NULL;
58
if (strncmp(p, "target.xml", len) == 0) {
59
- /* Generate the XML description for this CPU. */
60
- if (!target_xml[0]) {
61
- GDBRegisterState *r;
62
- CPUState *cpu = first_cpu;
63
+ char *buf = process->target_xml;
64
+ const size_t buf_sz = sizeof(process->target_xml);
65
66
- pstrcat(target_xml, sizeof(target_xml),
67
+ /* Generate the XML description for this CPU. */
68
+ if (!buf[0]) {
69
+ GDBRegisterState *r;
70
+
71
+ pstrcat(buf, buf_sz,
72
"<?xml version=\"1.0\"?>"
73
"<!DOCTYPE target SYSTEM \"gdb-target.dtd\">"
74
"<target>");
75
if (cc->gdb_arch_name) {
76
gchar *arch = cc->gdb_arch_name(cpu);
77
- pstrcat(target_xml, sizeof(target_xml), "<architecture>");
78
- pstrcat(target_xml, sizeof(target_xml), arch);
79
- pstrcat(target_xml, sizeof(target_xml), "</architecture>");
80
+ pstrcat(buf, buf_sz, "<architecture>");
81
+ pstrcat(buf, buf_sz, arch);
82
+ pstrcat(buf, buf_sz, "</architecture>");
83
g_free(arch);
84
}
85
- pstrcat(target_xml, sizeof(target_xml), "<xi:include href=\"");
86
- pstrcat(target_xml, sizeof(target_xml), cc->gdb_core_xml_file);
87
- pstrcat(target_xml, sizeof(target_xml), "\"/>");
88
+ pstrcat(buf, buf_sz, "<xi:include href=\"");
89
+ pstrcat(buf, buf_sz, cc->gdb_core_xml_file);
90
+ pstrcat(buf, buf_sz, "\"/>");
91
for (r = cpu->gdb_regs; r; r = r->next) {
92
- pstrcat(target_xml, sizeof(target_xml), "<xi:include href=\"");
93
- pstrcat(target_xml, sizeof(target_xml), r->xml);
94
- pstrcat(target_xml, sizeof(target_xml), "\"/>");
95
+ pstrcat(buf, buf_sz, "<xi:include href=\"");
96
+ pstrcat(buf, buf_sz, r->xml);
97
+ pstrcat(buf, buf_sz, "\"/>");
98
}
99
- pstrcat(target_xml, sizeof(target_xml), "</target>");
100
+ pstrcat(buf, buf_sz, "</target>");
101
}
102
- return target_xml;
103
+ return buf;
104
}
105
if (cc->gdb_get_dynamic_xml) {
106
- CPUState *cpu = first_cpu;
107
char *xmlname = g_strndup(p, len);
108
const char *xml = cc->gdb_get_dynamic_xml(cpu, xmlname);
109
110
@@ -XXX,XX +XXX,XX @@ out:
111
static int gdb_handle_packet(GDBState *s, const char *line_buf)
112
{
113
CPUState *cpu;
114
+ GDBProcess *process;
115
CPUClass *cc;
116
const char *p;
117
uint32_t pid, tid;
118
@@ -XXX,XX +XXX,XX @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
119
const char *xml;
120
target_ulong total_len;
121
122
- cc = CPU_GET_CLASS(first_cpu);
123
+ process = gdb_get_cpu_process(s, s->g_cpu);
124
+ cc = CPU_GET_CLASS(s->g_cpu);
125
if (cc->gdb_core_xml_file == NULL) {
126
goto unknown_command;
127
}
128
129
gdb_has_xml = true;
130
p += 19;
131
- xml = get_feature_xml(p, &p, cc);
132
+ xml = get_feature_xml(s, p, &p, process);
133
if (!xml) {
134
snprintf(buf, sizeof(buf), "E00");
135
put_packet(s, buf);
136
@@ -XXX,XX +XXX,XX @@ static void create_default_process(GDBState *s)
137
138
process->pid = max_pid + 1;
139
process->attached = false;
140
+ process->target_xml[0] = '\0';
141
}
142
143
#ifdef CONFIG_USER_ONLY
144
@@ -XXX,XX +XXX,XX @@ static int find_cpu_clusters(Object *child, void *opaque)
145
assert(cluster->cluster_id != UINT32_MAX);
146
process->pid = cluster->cluster_id + 1;
147
process->attached = false;
148
+ process->target_xml[0] = '\0';
149
150
return 0;
151
}
152
--
124
--
153
2.19.2
125
2.20.1
154
126
155
127
diff view generated by jsdifflib
1
From: Luc Michel <luc.michel@greensocs.com>
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
2
3
Change the thread info related packets handling to support multiprocess
3
This adds two acceptance tests for the quanta-gsj machine.
4
extension.
5
4
6
Add the CPUs class name in the extra info to help differentiate
5
One test downloads a lightly patched openbmc flash image from github and
7
them in multiprocess mode.
6
verifies that it boots all the way to the login prompt.
8
7
9
Signed-off-by: Luc Michel <luc.michel@greensocs.com>
8
The other test downloads a kernel, initrd and dtb built from the same
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
openbmc source and verifies that the kernel detects all CPUs and boots
11
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
10
to the point where it can't find the root filesystem (because we have no
12
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
11
flash image in this case).
13
Message-id: 20181207090135.7651-8-luc.michel@greensocs.com
12
13
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
16
Message-id: 20200911052101.2602693-15-hskinnemoen@google.com
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
18
---
16
gdbstub.c | 37 +++++++++++++++++++++++++++----------
19
tests/acceptance/boot_linux_console.py | 83 ++++++++++++++++++++++++++
17
1 file changed, 27 insertions(+), 10 deletions(-)
20
1 file changed, 83 insertions(+)
18
21
19
diff --git a/gdbstub.c b/gdbstub.c
22
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
20
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
21
--- a/gdbstub.c
24
--- a/tests/acceptance/boot_linux_console.py
22
+++ b/gdbstub.c
25
+++ b/tests/acceptance/boot_linux_console.py
23
@@ -XXX,XX +XXX,XX @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
26
@@ -XXX,XX +XXX,XX @@ class BootLinuxConsole(LinuxKernelTest):
24
CPUState *cpu;
27
'sda')
25
CPUClass *cc;
28
# cubieboard's reboot is not functioning; omit reboot test.
26
const char *p;
29
27
- uint32_t thread;
30
+ def test_arm_quanta_gsj(self):
28
uint32_t pid, tid;
31
+ """
29
int ch, reg_size, type, res;
32
+ :avocado: tags=arch:arm
30
uint8_t mem_buf[MAX_PACKET_LENGTH];
33
+ :avocado: tags=machine:quanta-gsj
31
@@ -XXX,XX +XXX,XX @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
34
+ """
32
put_packet(s, buf);
35
+ # 25 MiB compressed, 32 MiB uncompressed.
33
break;
36
+ image_url = (
34
} else if (strcmp(p,"fThreadInfo") == 0) {
37
+ 'https://github.com/hskinnemoen/openbmc/releases/download/'
35
- s->query_cpu = first_cpu;
38
+ '20200711-gsj-qemu-0/obmc-phosphor-image-gsj.static.mtd.gz')
36
+ s->query_cpu = gdb_first_attached_cpu(s);
39
+ image_hash = '14895e634923345cb5c8776037ff7876df96f6b1'
37
goto report_cpuinfo;
40
+ image_path_gz = self.fetch_asset(image_url, asset_hash=image_hash)
38
} else if (strcmp(p,"sThreadInfo") == 0) {
41
+ image_name = 'obmc.mtd'
39
report_cpuinfo:
42
+ image_path = os.path.join(self.workdir, image_name)
40
if (s->query_cpu) {
43
+ archive.gzip_uncompress(image_path_gz, image_path)
41
- snprintf(buf, sizeof(buf), "m%x", cpu_gdb_index(s->query_cpu));
42
+ snprintf(buf, sizeof(buf), "m%s",
43
+ gdb_fmt_thread_id(s, s->query_cpu,
44
+ thread_id, sizeof(thread_id)));
45
put_packet(s, buf);
46
- s->query_cpu = CPU_NEXT(s->query_cpu);
47
+ s->query_cpu = gdb_next_attached_cpu(s, s->query_cpu);
48
} else
49
put_packet(s, "l");
50
break;
51
} else if (strncmp(p,"ThreadExtraInfo,", 16) == 0) {
52
- thread = strtoull(p+16, (char **)&p, 16);
53
- cpu = find_cpu(thread);
54
+ if (read_thread_id(p + 16, &p, &pid, &tid) == GDB_READ_THREAD_ERR) {
55
+ put_packet(s, "E22");
56
+ break;
57
+ }
58
+ cpu = gdb_get_cpu(s, pid, tid);
59
if (cpu != NULL) {
60
cpu_synchronize_state(cpu);
61
- /* memtohex() doubles the required space */
62
- len = snprintf((char *)mem_buf, sizeof(buf) / 2,
63
- "CPU#%d [%s]", cpu->cpu_index,
64
- cpu->halted ? "halted " : "running");
65
+
44
+
66
+ if (s->multiprocess && (s->process_num > 1)) {
45
+ self.vm.set_console()
67
+ /* Print the CPU model and name in multiprocess mode */
46
+ drive_args = 'file=' + image_path + ',if=mtd,bus=0,unit=0'
68
+ ObjectClass *oc = object_get_class(OBJECT(cpu));
47
+ self.vm.add_args('-drive', drive_args)
69
+ const char *cpu_model = object_class_get_name(oc);
48
+ self.vm.launch()
70
+ char *cpu_name =
49
+
71
+ object_get_canonical_path_component(OBJECT(cpu));
50
+ # Disable drivers and services that stall for a long time during boot,
72
+ len = snprintf((char *)mem_buf, sizeof(buf) / 2,
51
+ # to avoid running past the 90-second timeout. These may be removed
73
+ "%s %s [%s]", cpu_model, cpu_name,
52
+ # as the corresponding device support is added.
74
+ cpu->halted ? "halted " : "running");
53
+ kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + (
75
+ g_free(cpu_name);
54
+ 'console=${console} '
76
+ } else {
55
+ 'mem=${mem} '
77
+ /* memtohex() doubles the required space */
56
+ 'initcall_blacklist=npcm_i2c_bus_driver_init '
78
+ len = snprintf((char *)mem_buf, sizeof(buf) / 2,
57
+ 'systemd.mask=systemd-random-seed.service '
79
+ "CPU#%d [%s]", cpu->cpu_index,
58
+ 'systemd.mask=dropbearkey.service '
80
+ cpu->halted ? "halted " : "running");
59
+ )
81
+ }
60
+
82
trace_gdbstub_op_extra_info((char *)mem_buf);
61
+ self.wait_for_console_pattern('> BootBlock by Nuvoton')
83
memtohex(buf, mem_buf, len);
62
+ self.wait_for_console_pattern('>Device: Poleg BMC NPCM730')
84
put_packet(s, buf);
63
+ self.wait_for_console_pattern('>Skip DDR init.')
64
+ self.wait_for_console_pattern('U-Boot ')
65
+ interrupt_interactive_console_until_pattern(
66
+ self, 'Hit any key to stop autoboot:', 'U-Boot>')
67
+ exec_command_and_wait_for_pattern(
68
+ self, "setenv bootargs ${bootargs} " + kernel_command_line,
69
+ 'U-Boot>')
70
+ exec_command_and_wait_for_pattern(
71
+ self, 'run romboot', 'Booting Kernel from flash')
72
+ self.wait_for_console_pattern('Booting Linux on physical CPU 0x0')
73
+ self.wait_for_console_pattern('CPU1: thread -1, cpu 1, socket 0')
74
+ self.wait_for_console_pattern('OpenBMC Project Reference Distro')
75
+ self.wait_for_console_pattern('gsj login:')
76
+
77
+ def test_arm_quanta_gsj_initrd(self):
78
+ """
79
+ :avocado: tags=arch:arm
80
+ :avocado: tags=machine:quanta-gsj
81
+ """
82
+ initrd_url = (
83
+ 'https://github.com/hskinnemoen/openbmc/releases/download/'
84
+ '20200711-gsj-qemu-0/obmc-phosphor-initramfs-gsj.cpio.xz')
85
+ initrd_hash = '98fefe5d7e56727b1eb17d5c00311b1b5c945300'
86
+ initrd_path = self.fetch_asset(initrd_url, asset_hash=initrd_hash)
87
+ kernel_url = (
88
+ 'https://github.com/hskinnemoen/openbmc/releases/download/'
89
+ '20200711-gsj-qemu-0/uImage-gsj.bin')
90
+ kernel_hash = 'fa67b2f141d56d39b3c54305c0e8a899c99eb2c7'
91
+ kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash)
92
+ dtb_url = (
93
+ 'https://github.com/hskinnemoen/openbmc/releases/download/'
94
+ '20200711-gsj-qemu-0/nuvoton-npcm730-gsj.dtb')
95
+ dtb_hash = '18315f7006d7b688d8312d5c727eecd819aa36a4'
96
+ dtb_path = self.fetch_asset(dtb_url, asset_hash=dtb_hash)
97
+
98
+ self.vm.set_console()
99
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
100
+ 'console=ttyS0,115200n8 '
101
+ 'earlycon=uart8250,mmio32,0xf0001000')
102
+ self.vm.add_args('-kernel', kernel_path,
103
+ '-initrd', initrd_path,
104
+ '-dtb', dtb_path,
105
+ '-append', kernel_command_line)
106
+ self.vm.launch()
107
+
108
+ self.wait_for_console_pattern('Booting Linux on physical CPU 0x0')
109
+ self.wait_for_console_pattern('CPU1: thread -1, cpu 1, socket 0')
110
+ self.wait_for_console_pattern(
111
+ 'Give root password for system maintenance')
112
+
113
def test_arm_orangepi(self):
114
"""
115
:avocado: tags=arch:arm
85
--
116
--
86
2.19.2
117
2.20.1
87
118
88
119
diff view generated by jsdifflib
1
From: Steffen Görtz <contrib@steffen-goertz.de>
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
2
2
3
Add a model of the NRF51 random number generator peripheral.
3
The Xilinx ZynqMP CAN controller is developed based on SocketCAN, QEMU CAN bus
4
This is a simple random generator that continuously generates
4
implementation. Bus connection and socketCAN connection for each CAN module
5
new random values after startup.
5
can be set through command lines.
6
6
7
Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.pdf
7
Example for using single CAN:
8
-object can-bus,id=canbus0 \
9
-machine xlnx-zcu102.canbus0=canbus0 \
10
-object can-host-socketcan,id=socketcan0,if=vcan0,canbus=canbus0
8
11
9
Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
12
Example for connecting both CAN to same virtual CAN on host machine:
10
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
13
-object can-bus,id=canbus0 -object can-bus,id=canbus1 \
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
-machine xlnx-zcu102.canbus0=canbus0 \
12
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
15
-machine xlnx-zcu102.canbus1=canbus1 \
13
Message-id: 20190103091119.9367-4-stefanha@redhat.com
16
-object can-host-socketcan,id=socketcan0,if=vcan0,canbus=canbus0 \
17
-object can-host-socketcan,id=socketcan1,if=vcan0,canbus=canbus1
18
19
To create virtual CAN on the host machine, please check the QEMU CAN docs:
20
https://github.com/qemu/qemu/blob/master/docs/can.txt
21
22
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
23
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
24
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
25
Message-id: 1597278668-339715-2-git-send-email-fnu.vikram@xilinx.com
26
[PMM: updated to meson build system]
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
28
---
16
hw/misc/Makefile.objs | 1 +
29
include/hw/net/xlnx-zynqmp-can.h | 78 ++
17
include/hw/misc/nrf51_rng.h | 83 ++++++++++++
30
hw/net/can/xlnx-zynqmp-can.c | 1165 ++++++++++++++++++++++++++++++
18
hw/misc/nrf51_rng.c | 262 ++++++++++++++++++++++++++++++++++++
31
hw/net/can/meson.build | 1 +
19
3 files changed, 346 insertions(+)
32
3 files changed, 1244 insertions(+)
20
create mode 100644 include/hw/misc/nrf51_rng.h
33
create mode 100644 include/hw/net/xlnx-zynqmp-can.h
21
create mode 100644 hw/misc/nrf51_rng.c
34
create mode 100644 hw/net/can/xlnx-zynqmp-can.c
22
35
23
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
36
diff --git a/include/hw/net/xlnx-zynqmp-can.h b/include/hw/net/xlnx-zynqmp-can.h
24
index XXXXXXX..XXXXXXX 100644
25
--- a/hw/misc/Makefile.objs
26
+++ b/hw/misc/Makefile.objs
27
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_PVPANIC) += pvpanic.o
28
obj-$(CONFIG_AUX) += auxbus.o
29
obj-$(CONFIG_ASPEED_SOC) += aspeed_scu.o aspeed_sdmc.o
30
obj-$(CONFIG_MSF2) += msf2-sysreg.o
31
+obj-$(CONFIG_NRF51_SOC) += nrf51_rng.o
32
diff --git a/include/hw/misc/nrf51_rng.h b/include/hw/misc/nrf51_rng.h
33
new file mode 100644
37
new file mode 100644
34
index XXXXXXX..XXXXXXX
38
index XXXXXXX..XXXXXXX
35
--- /dev/null
39
--- /dev/null
36
+++ b/include/hw/misc/nrf51_rng.h
40
+++ b/include/hw/net/xlnx-zynqmp-can.h
37
@@ -XXX,XX +XXX,XX @@
41
@@ -XXX,XX +XXX,XX @@
38
+/*
42
+/*
39
+ * nRF51 Random Number Generator
43
+ * QEMU model of the Xilinx ZynqMP CAN controller.
40
+ *
44
+ *
41
+ * QEMU interface:
45
+ * Copyright (c) 2020 Xilinx Inc.
42
+ * + Property "period_unfiltered_us": Time between two biased values in
43
+ * microseconds.
44
+ * + Property "period_filtered_us": Time between two unbiased values in
45
+ * microseconds.
46
+ * + sysbus MMIO regions 0: Memory Region with tasks, events and registers
47
+ * to be mapped to the peripherals instance address by the SOC.
48
+ * + Named GPIO output "irq": Interrupt line of the peripheral. Must be
49
+ * connected to the associated peripheral interrupt line of the NVIC.
50
+ * + Named GPIO output "eep_valrdy": Event set when new random value is ready
51
+ * to be read.
52
+ * + Named GPIO input "tep_start": Task that triggers start of continuous
53
+ * generation of random values.
54
+ * + Named GPIO input "tep_stop": Task that ends continuous generation of
55
+ * random values.
56
+ *
46
+ *
57
+ * Accuracy of the peripheral model:
47
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
58
+ * + Stochastic properties of different configurations of the random source
59
+ * are not modeled.
60
+ * + Generation of unfiltered and filtered random values take at least the
61
+ * average generation time stated in the production specification;
62
+ * non-deterministic generation times are not modeled.
63
+ *
48
+ *
64
+ * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
49
+ * Based on QEMU CAN Device emulation implemented by Jin Yang, Deniz Eren and
50
+ * Pavel Pisa.
65
+ *
51
+ *
66
+ * This code is licensed under the GPL version 2 or later. See
52
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
67
+ * the COPYING file in the top-level directory.
53
+ * of this software and associated documentation files (the "Software"), to deal
54
+ * in the Software without restriction, including without limitation the rights
55
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
56
+ * copies of the Software, and to permit persons to whom the Software is
57
+ * furnished to do so, subject to the following conditions:
68
+ *
58
+ *
59
+ * The above copyright notice and this permission notice shall be included in
60
+ * all copies or substantial portions of the Software.
61
+ *
62
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
63
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
64
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
65
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
66
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
67
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
68
+ * THE SOFTWARE.
69
+ */
69
+ */
70
+#ifndef NRF51_RNG_H
70
+
71
+#define NRF51_RNG_H
71
+#ifndef XLNX_ZYNQMP_CAN_H
72
+
72
+#define XLNX_ZYNQMP_CAN_H
73
+#include "hw/sysbus.h"
73
+
74
+#include "qemu/timer.h"
74
+#include "hw/register.h"
75
+#define TYPE_NRF51_RNG "nrf51_soc.rng"
75
+#include "net/can_emu.h"
76
+#define NRF51_RNG(obj) OBJECT_CHECK(NRF51RNGState, (obj), TYPE_NRF51_RNG)
76
+#include "net/can_host.h"
77
+
77
+#include "qemu/fifo32.h"
78
+#define NRF51_RNG_SIZE 0x1000
78
+#include "hw/ptimer.h"
79
+
79
+#include "hw/qdev-clock.h"
80
+#define NRF51_RNG_TASK_START 0x000
80
+
81
+#define NRF51_RNG_TASK_STOP 0x004
81
+#define TYPE_XLNX_ZYNQMP_CAN "xlnx.zynqmp-can"
82
+#define NRF51_RNG_EVENT_VALRDY 0x100
82
+
83
+#define NRF51_RNG_REG_SHORTS 0x200
83
+#define XLNX_ZYNQMP_CAN(obj) \
84
+#define NRF51_RNG_REG_SHORTS_VALRDY_STOP 0
84
+ OBJECT_CHECK(XlnxZynqMPCANState, (obj), TYPE_XLNX_ZYNQMP_CAN)
85
+#define NRF51_RNG_REG_INTEN 0x300
85
+
86
+#define NRF51_RNG_REG_INTEN_VALRDY 0
86
+#define MAX_CAN_CTRLS 2
87
+#define NRF51_RNG_REG_INTENSET 0x304
87
+#define XLNX_ZYNQMP_CAN_R_MAX (0x84 / 4)
88
+#define NRF51_RNG_REG_INTENCLR 0x308
88
+#define MAILBOX_CAPACITY 64
89
+#define NRF51_RNG_REG_CONFIG 0x504
89
+#define CAN_TIMER_MAX 0XFFFFUL
90
+#define NRF51_RNG_REG_CONFIG_DECEN 0
90
+#define CAN_DEFAULT_CLOCK (24 * 1000 * 1000)
91
+#define NRF51_RNG_REG_VALUE 0x508
91
+
92
+
92
+/* Each CAN_FRAME will have 4 * 32bit size. */
93
+typedef struct {
93
+#define CAN_FRAME_SIZE 4
94
+ SysBusDevice parent_obj;
94
+#define RXFIFO_SIZE (MAILBOX_CAPACITY * CAN_FRAME_SIZE)
95
+
95
+
96
+ MemoryRegion mmio;
96
+typedef struct XlnxZynqMPCANState {
97
+ qemu_irq irq;
97
+ SysBusDevice parent_obj;
98
+
98
+ MemoryRegion iomem;
99
+ /* Event End Points */
99
+
100
+ qemu_irq eep_valrdy;
100
+ qemu_irq irq;
101
+
101
+
102
+ QEMUTimer timer;
102
+ CanBusClientState bus_client;
103
+
103
+ CanBusState *canbus;
104
+ /* Time between generation of successive unfiltered values in us */
104
+
105
+ uint16_t period_unfiltered_us;
105
+ struct {
106
+ /* Time between generation of successive filtered values in us */
106
+ uint32_t ext_clk_freq;
107
+ uint16_t period_filtered_us;
107
+ } cfg;
108
+
108
+
109
+ uint8_t value;
109
+ RegisterInfo reg_info[XLNX_ZYNQMP_CAN_R_MAX];
110
+
110
+ uint32_t regs[XLNX_ZYNQMP_CAN_R_MAX];
111
+ uint32_t active;
111
+
112
+ uint32_t event_valrdy;
112
+ Fifo32 rx_fifo;
113
+ uint32_t shortcut_stop_on_valrdy;
113
+ Fifo32 tx_fifo;
114
+ uint32_t interrupt_enabled;
114
+ Fifo32 txhpb_fifo;
115
+ uint32_t filter_enabled;
115
+
116
+
116
+ ptimer_state *can_timer;
117
+} NRF51RNGState;
117
+} XlnxZynqMPCANState;
118
+
118
+
119
+
119
+#endif
120
+#endif /* NRF51_RNG_H_ */
120
diff --git a/hw/net/can/xlnx-zynqmp-can.c b/hw/net/can/xlnx-zynqmp-can.c
121
diff --git a/hw/misc/nrf51_rng.c b/hw/misc/nrf51_rng.c
122
new file mode 100644
121
new file mode 100644
123
index XXXXXXX..XXXXXXX
122
index XXXXXXX..XXXXXXX
124
--- /dev/null
123
--- /dev/null
125
+++ b/hw/misc/nrf51_rng.c
124
+++ b/hw/net/can/xlnx-zynqmp-can.c
126
@@ -XXX,XX +XXX,XX @@
125
@@ -XXX,XX +XXX,XX @@
127
+/*
126
+/*
128
+ * nRF51 Random Number Generator
127
+ * QEMU model of the Xilinx ZynqMP CAN controller.
128
+ * This implementation is based on the following datasheet:
129
+ * https://www.xilinx.com/support/documentation/user_guides/ug1085-zynq-ultrascale-trm.pdf
129
+ *
130
+ *
130
+ * Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.1.pdf
131
+ * Copyright (c) 2020 Xilinx Inc.
131
+ *
132
+ *
132
+ * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
133
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
133
+ *
134
+ *
134
+ * This code is licensed under the GPL version 2 or later. See
135
+ * Based on QEMU CAN Device emulation implemented by Jin Yang, Deniz Eren and
135
+ * the COPYING file in the top-level directory.
136
+ * Pavel Pisa
137
+ *
138
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
139
+ * of this software and associated documentation files (the "Software"), to deal
140
+ * in the Software without restriction, including without limitation the rights
141
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
142
+ * copies of the Software, and to permit persons to whom the Software is
143
+ * furnished to do so, subject to the following conditions:
144
+ *
145
+ * The above copyright notice and this permission notice shall be included in
146
+ * all copies or substantial portions of the Software.
147
+ *
148
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
149
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
150
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
151
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
152
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
153
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
154
+ * THE SOFTWARE.
136
+ */
155
+ */
137
+
156
+
138
+#include "qemu/osdep.h"
157
+#include "qemu/osdep.h"
158
+#include "hw/sysbus.h"
159
+#include "hw/register.h"
160
+#include "hw/irq.h"
161
+#include "qapi/error.h"
162
+#include "qemu/bitops.h"
139
+#include "qemu/log.h"
163
+#include "qemu/log.h"
140
+#include "qapi/error.h"
164
+#include "qemu/cutils.h"
141
+#include "hw/arm/nrf51.h"
165
+#include "sysemu/sysemu.h"
142
+#include "hw/misc/nrf51_rng.h"
166
+#include "migration/vmstate.h"
143
+#include "crypto/random.h"
167
+#include "hw/qdev-properties.h"
144
+
168
+#include "net/can_emu.h"
145
+static void update_irq(NRF51RNGState *s)
169
+#include "net/can_host.h"
146
+{
170
+#include "qemu/event_notifier.h"
147
+ bool irq = s->interrupt_enabled && s->event_valrdy;
171
+#include "qom/object_interfaces.h"
172
+#include "hw/net/xlnx-zynqmp-can.h"
173
+
174
+#ifndef XLNX_ZYNQMP_CAN_ERR_DEBUG
175
+#define XLNX_ZYNQMP_CAN_ERR_DEBUG 0
176
+#endif
177
+
178
+#define DB_PRINT(dev, ...) do { \
179
+ if (XLNX_ZYNQMP_CAN_ERR_DEBUG) { \
180
+ g_autofree char *path = object_get_canonical_path(OBJECT(dev)); \
181
+ qemu_log("%s: %s", path, ## __VA_ARGS__); \
182
+ } \
183
+} while (0)
184
+
185
+#define MAX_DLC 8
186
+#undef ERROR
187
+
188
+REG32(SOFTWARE_RESET_REGISTER, 0x0)
189
+ FIELD(SOFTWARE_RESET_REGISTER, CEN, 1, 1)
190
+ FIELD(SOFTWARE_RESET_REGISTER, SRST, 0, 1)
191
+REG32(MODE_SELECT_REGISTER, 0x4)
192
+ FIELD(MODE_SELECT_REGISTER, SNOOP, 2, 1)
193
+ FIELD(MODE_SELECT_REGISTER, LBACK, 1, 1)
194
+ FIELD(MODE_SELECT_REGISTER, SLEEP, 0, 1)
195
+REG32(ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER, 0x8)
196
+ FIELD(ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER, BRP, 0, 8)
197
+REG32(ARBITRATION_PHASE_BIT_TIMING_REGISTER, 0xc)
198
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, SJW, 7, 2)
199
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, TS2, 4, 3)
200
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, TS1, 0, 4)
201
+REG32(ERROR_COUNTER_REGISTER, 0x10)
202
+ FIELD(ERROR_COUNTER_REGISTER, REC, 8, 8)
203
+ FIELD(ERROR_COUNTER_REGISTER, TEC, 0, 8)
204
+REG32(ERROR_STATUS_REGISTER, 0x14)
205
+ FIELD(ERROR_STATUS_REGISTER, ACKER, 4, 1)
206
+ FIELD(ERROR_STATUS_REGISTER, BERR, 3, 1)
207
+ FIELD(ERROR_STATUS_REGISTER, STER, 2, 1)
208
+ FIELD(ERROR_STATUS_REGISTER, FMER, 1, 1)
209
+ FIELD(ERROR_STATUS_REGISTER, CRCER, 0, 1)
210
+REG32(STATUS_REGISTER, 0x18)
211
+ FIELD(STATUS_REGISTER, SNOOP, 12, 1)
212
+ FIELD(STATUS_REGISTER, ACFBSY, 11, 1)
213
+ FIELD(STATUS_REGISTER, TXFLL, 10, 1)
214
+ FIELD(STATUS_REGISTER, TXBFLL, 9, 1)
215
+ FIELD(STATUS_REGISTER, ESTAT, 7, 2)
216
+ FIELD(STATUS_REGISTER, ERRWRN, 6, 1)
217
+ FIELD(STATUS_REGISTER, BBSY, 5, 1)
218
+ FIELD(STATUS_REGISTER, BIDLE, 4, 1)
219
+ FIELD(STATUS_REGISTER, NORMAL, 3, 1)
220
+ FIELD(STATUS_REGISTER, SLEEP, 2, 1)
221
+ FIELD(STATUS_REGISTER, LBACK, 1, 1)
222
+ FIELD(STATUS_REGISTER, CONFIG, 0, 1)
223
+REG32(INTERRUPT_STATUS_REGISTER, 0x1c)
224
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFEMP, 14, 1)
225
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFWMEMP, 13, 1)
226
+ FIELD(INTERRUPT_STATUS_REGISTER, RXFWMFLL, 12, 1)
227
+ FIELD(INTERRUPT_STATUS_REGISTER, WKUP, 11, 1)
228
+ FIELD(INTERRUPT_STATUS_REGISTER, SLP, 10, 1)
229
+ FIELD(INTERRUPT_STATUS_REGISTER, BSOFF, 9, 1)
230
+ FIELD(INTERRUPT_STATUS_REGISTER, ERROR, 8, 1)
231
+ FIELD(INTERRUPT_STATUS_REGISTER, RXNEMP, 7, 1)
232
+ FIELD(INTERRUPT_STATUS_REGISTER, RXOFLW, 6, 1)
233
+ FIELD(INTERRUPT_STATUS_REGISTER, RXUFLW, 5, 1)
234
+ FIELD(INTERRUPT_STATUS_REGISTER, RXOK, 4, 1)
235
+ FIELD(INTERRUPT_STATUS_REGISTER, TXBFLL, 3, 1)
236
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFLL, 2, 1)
237
+ FIELD(INTERRUPT_STATUS_REGISTER, TXOK, 1, 1)
238
+ FIELD(INTERRUPT_STATUS_REGISTER, ARBLST, 0, 1)
239
+REG32(INTERRUPT_ENABLE_REGISTER, 0x20)
240
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFEMP, 14, 1)
241
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFWMEMP, 13, 1)
242
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXFWMFLL, 12, 1)
243
+ FIELD(INTERRUPT_ENABLE_REGISTER, EWKUP, 11, 1)
244
+ FIELD(INTERRUPT_ENABLE_REGISTER, ESLP, 10, 1)
245
+ FIELD(INTERRUPT_ENABLE_REGISTER, EBSOFF, 9, 1)
246
+ FIELD(INTERRUPT_ENABLE_REGISTER, EERROR, 8, 1)
247
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXNEMP, 7, 1)
248
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXOFLW, 6, 1)
249
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXUFLW, 5, 1)
250
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXOK, 4, 1)
251
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXBFLL, 3, 1)
252
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFLL, 2, 1)
253
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXOK, 1, 1)
254
+ FIELD(INTERRUPT_ENABLE_REGISTER, EARBLST, 0, 1)
255
+REG32(INTERRUPT_CLEAR_REGISTER, 0x24)
256
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFEMP, 14, 1)
257
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFWMEMP, 13, 1)
258
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXFWMFLL, 12, 1)
259
+ FIELD(INTERRUPT_CLEAR_REGISTER, CWKUP, 11, 1)
260
+ FIELD(INTERRUPT_CLEAR_REGISTER, CSLP, 10, 1)
261
+ FIELD(INTERRUPT_CLEAR_REGISTER, CBSOFF, 9, 1)
262
+ FIELD(INTERRUPT_CLEAR_REGISTER, CERROR, 8, 1)
263
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXNEMP, 7, 1)
264
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXOFLW, 6, 1)
265
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXUFLW, 5, 1)
266
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXOK, 4, 1)
267
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXBFLL, 3, 1)
268
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFLL, 2, 1)
269
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXOK, 1, 1)
270
+ FIELD(INTERRUPT_CLEAR_REGISTER, CARBLST, 0, 1)
271
+REG32(TIMESTAMP_REGISTER, 0x28)
272
+ FIELD(TIMESTAMP_REGISTER, CTS, 0, 1)
273
+REG32(WIR, 0x2c)
274
+ FIELD(WIR, EW, 8, 8)
275
+ FIELD(WIR, FW, 0, 8)
276
+REG32(TXFIFO_ID, 0x30)
277
+ FIELD(TXFIFO_ID, IDH, 21, 11)
278
+ FIELD(TXFIFO_ID, SRRRTR, 20, 1)
279
+ FIELD(TXFIFO_ID, IDE, 19, 1)
280
+ FIELD(TXFIFO_ID, IDL, 1, 18)
281
+ FIELD(TXFIFO_ID, RTR, 0, 1)
282
+REG32(TXFIFO_DLC, 0x34)
283
+ FIELD(TXFIFO_DLC, DLC, 28, 4)
284
+REG32(TXFIFO_DATA1, 0x38)
285
+ FIELD(TXFIFO_DATA1, DB0, 24, 8)
286
+ FIELD(TXFIFO_DATA1, DB1, 16, 8)
287
+ FIELD(TXFIFO_DATA1, DB2, 8, 8)
288
+ FIELD(TXFIFO_DATA1, DB3, 0, 8)
289
+REG32(TXFIFO_DATA2, 0x3c)
290
+ FIELD(TXFIFO_DATA2, DB4, 24, 8)
291
+ FIELD(TXFIFO_DATA2, DB5, 16, 8)
292
+ FIELD(TXFIFO_DATA2, DB6, 8, 8)
293
+ FIELD(TXFIFO_DATA2, DB7, 0, 8)
294
+REG32(TXHPB_ID, 0x40)
295
+ FIELD(TXHPB_ID, IDH, 21, 11)
296
+ FIELD(TXHPB_ID, SRRRTR, 20, 1)
297
+ FIELD(TXHPB_ID, IDE, 19, 1)
298
+ FIELD(TXHPB_ID, IDL, 1, 18)
299
+ FIELD(TXHPB_ID, RTR, 0, 1)
300
+REG32(TXHPB_DLC, 0x44)
301
+ FIELD(TXHPB_DLC, DLC, 28, 4)
302
+REG32(TXHPB_DATA1, 0x48)
303
+ FIELD(TXHPB_DATA1, DB0, 24, 8)
304
+ FIELD(TXHPB_DATA1, DB1, 16, 8)
305
+ FIELD(TXHPB_DATA1, DB2, 8, 8)
306
+ FIELD(TXHPB_DATA1, DB3, 0, 8)
307
+REG32(TXHPB_DATA2, 0x4c)
308
+ FIELD(TXHPB_DATA2, DB4, 24, 8)
309
+ FIELD(TXHPB_DATA2, DB5, 16, 8)
310
+ FIELD(TXHPB_DATA2, DB6, 8, 8)
311
+ FIELD(TXHPB_DATA2, DB7, 0, 8)
312
+REG32(RXFIFO_ID, 0x50)
313
+ FIELD(RXFIFO_ID, IDH, 21, 11)
314
+ FIELD(RXFIFO_ID, SRRRTR, 20, 1)
315
+ FIELD(RXFIFO_ID, IDE, 19, 1)
316
+ FIELD(RXFIFO_ID, IDL, 1, 18)
317
+ FIELD(RXFIFO_ID, RTR, 0, 1)
318
+REG32(RXFIFO_DLC, 0x54)
319
+ FIELD(RXFIFO_DLC, DLC, 28, 4)
320
+ FIELD(RXFIFO_DLC, RXT, 0, 16)
321
+REG32(RXFIFO_DATA1, 0x58)
322
+ FIELD(RXFIFO_DATA1, DB0, 24, 8)
323
+ FIELD(RXFIFO_DATA1, DB1, 16, 8)
324
+ FIELD(RXFIFO_DATA1, DB2, 8, 8)
325
+ FIELD(RXFIFO_DATA1, DB3, 0, 8)
326
+REG32(RXFIFO_DATA2, 0x5c)
327
+ FIELD(RXFIFO_DATA2, DB4, 24, 8)
328
+ FIELD(RXFIFO_DATA2, DB5, 16, 8)
329
+ FIELD(RXFIFO_DATA2, DB6, 8, 8)
330
+ FIELD(RXFIFO_DATA2, DB7, 0, 8)
331
+REG32(AFR, 0x60)
332
+ FIELD(AFR, UAF4, 3, 1)
333
+ FIELD(AFR, UAF3, 2, 1)
334
+ FIELD(AFR, UAF2, 1, 1)
335
+ FIELD(AFR, UAF1, 0, 1)
336
+REG32(AFMR1, 0x64)
337
+ FIELD(AFMR1, AMIDH, 21, 11)
338
+ FIELD(AFMR1, AMSRR, 20, 1)
339
+ FIELD(AFMR1, AMIDE, 19, 1)
340
+ FIELD(AFMR1, AMIDL, 1, 18)
341
+ FIELD(AFMR1, AMRTR, 0, 1)
342
+REG32(AFIR1, 0x68)
343
+ FIELD(AFIR1, AIIDH, 21, 11)
344
+ FIELD(AFIR1, AISRR, 20, 1)
345
+ FIELD(AFIR1, AIIDE, 19, 1)
346
+ FIELD(AFIR1, AIIDL, 1, 18)
347
+ FIELD(AFIR1, AIRTR, 0, 1)
348
+REG32(AFMR2, 0x6c)
349
+ FIELD(AFMR2, AMIDH, 21, 11)
350
+ FIELD(AFMR2, AMSRR, 20, 1)
351
+ FIELD(AFMR2, AMIDE, 19, 1)
352
+ FIELD(AFMR2, AMIDL, 1, 18)
353
+ FIELD(AFMR2, AMRTR, 0, 1)
354
+REG32(AFIR2, 0x70)
355
+ FIELD(AFIR2, AIIDH, 21, 11)
356
+ FIELD(AFIR2, AISRR, 20, 1)
357
+ FIELD(AFIR2, AIIDE, 19, 1)
358
+ FIELD(AFIR2, AIIDL, 1, 18)
359
+ FIELD(AFIR2, AIRTR, 0, 1)
360
+REG32(AFMR3, 0x74)
361
+ FIELD(AFMR3, AMIDH, 21, 11)
362
+ FIELD(AFMR3, AMSRR, 20, 1)
363
+ FIELD(AFMR3, AMIDE, 19, 1)
364
+ FIELD(AFMR3, AMIDL, 1, 18)
365
+ FIELD(AFMR3, AMRTR, 0, 1)
366
+REG32(AFIR3, 0x78)
367
+ FIELD(AFIR3, AIIDH, 21, 11)
368
+ FIELD(AFIR3, AISRR, 20, 1)
369
+ FIELD(AFIR3, AIIDE, 19, 1)
370
+ FIELD(AFIR3, AIIDL, 1, 18)
371
+ FIELD(AFIR3, AIRTR, 0, 1)
372
+REG32(AFMR4, 0x7c)
373
+ FIELD(AFMR4, AMIDH, 21, 11)
374
+ FIELD(AFMR4, AMSRR, 20, 1)
375
+ FIELD(AFMR4, AMIDE, 19, 1)
376
+ FIELD(AFMR4, AMIDL, 1, 18)
377
+ FIELD(AFMR4, AMRTR, 0, 1)
378
+REG32(AFIR4, 0x80)
379
+ FIELD(AFIR4, AIIDH, 21, 11)
380
+ FIELD(AFIR4, AISRR, 20, 1)
381
+ FIELD(AFIR4, AIIDE, 19, 1)
382
+ FIELD(AFIR4, AIIDL, 1, 18)
383
+ FIELD(AFIR4, AIRTR, 0, 1)
384
+
385
+static void can_update_irq(XlnxZynqMPCANState *s)
386
+{
387
+ uint32_t irq;
388
+
389
+ /* Watermark register interrupts. */
390
+ if ((fifo32_num_free(&s->tx_fifo) / CAN_FRAME_SIZE) >
391
+ ARRAY_FIELD_EX32(s->regs, WIR, EW)) {
392
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXFWMEMP, 1);
393
+ }
394
+
395
+ if ((fifo32_num_used(&s->rx_fifo) / CAN_FRAME_SIZE) >
396
+ ARRAY_FIELD_EX32(s->regs, WIR, FW)) {
397
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXFWMFLL, 1);
398
+ }
399
+
400
+ /* RX Interrupts. */
401
+ if (fifo32_num_used(&s->rx_fifo) >= CAN_FRAME_SIZE) {
402
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXNEMP, 1);
403
+ }
404
+
405
+ /* TX interrupts. */
406
+ if (fifo32_is_empty(&s->tx_fifo)) {
407
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXFEMP, 1);
408
+ }
409
+
410
+ if (fifo32_is_full(&s->tx_fifo)) {
411
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXFLL, 1);
412
+ }
413
+
414
+ if (fifo32_is_full(&s->txhpb_fifo)) {
415
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXBFLL, 1);
416
+ }
417
+
418
+ irq = s->regs[R_INTERRUPT_STATUS_REGISTER];
419
+ irq &= s->regs[R_INTERRUPT_ENABLE_REGISTER];
420
+
148
+ qemu_set_irq(s->irq, irq);
421
+ qemu_set_irq(s->irq, irq);
149
+}
422
+}
150
+
423
+
151
+static uint64_t rng_read(void *opaque, hwaddr offset, unsigned int size)
424
+static void can_ier_post_write(RegisterInfo *reg, uint64_t val64)
152
+{
425
+{
153
+ NRF51RNGState *s = NRF51_RNG(opaque);
426
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
154
+ uint64_t r = 0;
427
+
155
+
428
+ can_update_irq(s);
156
+ switch (offset) {
429
+}
157
+ case NRF51_RNG_EVENT_VALRDY:
430
+
158
+ r = s->event_valrdy;
431
+static uint64_t can_icr_pre_write(RegisterInfo *reg, uint64_t val64)
159
+ break;
432
+{
160
+ case NRF51_RNG_REG_SHORTS:
433
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
161
+ r = s->shortcut_stop_on_valrdy;
434
+ uint32_t val = val64;
162
+ break;
435
+
163
+ case NRF51_RNG_REG_INTEN:
436
+ s->regs[R_INTERRUPT_STATUS_REGISTER] &= ~val;
164
+ case NRF51_RNG_REG_INTENSET:
437
+ can_update_irq(s);
165
+ case NRF51_RNG_REG_INTENCLR:
438
+
166
+ r = s->interrupt_enabled;
439
+ return 0;
167
+ break;
440
+}
168
+ case NRF51_RNG_REG_CONFIG:
441
+
169
+ r = s->filter_enabled;
442
+static void can_config_reset(XlnxZynqMPCANState *s)
170
+ break;
443
+{
171
+ case NRF51_RNG_REG_VALUE:
444
+ /* Reset all the configuration registers. */
172
+ r = s->value;
445
+ register_reset(&s->reg_info[R_SOFTWARE_RESET_REGISTER]);
173
+ break;
446
+ register_reset(&s->reg_info[R_MODE_SELECT_REGISTER]);
174
+
447
+ register_reset(
175
+ default:
448
+ &s->reg_info[R_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER]);
176
+ qemu_log_mask(LOG_GUEST_ERROR,
449
+ register_reset(&s->reg_info[R_ARBITRATION_PHASE_BIT_TIMING_REGISTER]);
177
+ "%s: bad read offset 0x%" HWADDR_PRIx "\n",
450
+ register_reset(&s->reg_info[R_STATUS_REGISTER]);
178
+ __func__, offset);
451
+ register_reset(&s->reg_info[R_INTERRUPT_STATUS_REGISTER]);
179
+ }
452
+ register_reset(&s->reg_info[R_INTERRUPT_ENABLE_REGISTER]);
180
+
453
+ register_reset(&s->reg_info[R_INTERRUPT_CLEAR_REGISTER]);
454
+ register_reset(&s->reg_info[R_WIR]);
455
+}
456
+
457
+static void can_config_mode(XlnxZynqMPCANState *s)
458
+{
459
+ register_reset(&s->reg_info[R_ERROR_COUNTER_REGISTER]);
460
+ register_reset(&s->reg_info[R_ERROR_STATUS_REGISTER]);
461
+
462
+ /* Put XlnxZynqMPCAN in configuration mode. */
463
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, CONFIG, 1);
464
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, WKUP, 0);
465
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, SLP, 0);
466
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, BSOFF, 0);
467
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, ERROR, 0);
468
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOFLW, 0);
469
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 0);
470
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXOK, 0);
471
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, ARBLST, 0);
472
+
473
+ can_update_irq(s);
474
+}
475
+
476
+static void update_status_register_mode_bits(XlnxZynqMPCANState *s)
477
+{
478
+ bool sleep_status = ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP);
479
+ bool sleep_mode = ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SLEEP);
480
+ /* Wake up interrupt bit. */
481
+ bool wakeup_irq_val = sleep_status && (sleep_mode == 0);
482
+ /* Sleep interrupt bit. */
483
+ bool sleep_irq_val = sleep_mode && (sleep_status == 0);
484
+
485
+ /* Clear previous core mode status bits. */
486
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, LBACK, 0);
487
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SLEEP, 0);
488
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SNOOP, 0);
489
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, NORMAL, 0);
490
+
491
+ /* set current mode bit and generate irqs accordingly. */
492
+ if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, LBACK)) {
493
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, LBACK, 1);
494
+ } else if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SLEEP)) {
495
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SLEEP, 1);
496
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, SLP,
497
+ sleep_irq_val);
498
+ } else if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SNOOP)) {
499
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SNOOP, 1);
500
+ } else {
501
+ /*
502
+ * If all bits are zero then XlnxZynqMPCAN is set in normal mode.
503
+ */
504
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, NORMAL, 1);
505
+ /* Set wakeup interrupt bit. */
506
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, WKUP,
507
+ wakeup_irq_val);
508
+ }
509
+
510
+ can_update_irq(s);
511
+}
512
+
513
+static void can_exit_sleep_mode(XlnxZynqMPCANState *s)
514
+{
515
+ ARRAY_FIELD_DP32(s->regs, MODE_SELECT_REGISTER, SLEEP, 0);
516
+ update_status_register_mode_bits(s);
517
+}
518
+
519
+static void generate_frame(qemu_can_frame *frame, uint32_t *data)
520
+{
521
+ frame->can_id = data[0];
522
+ frame->can_dlc = FIELD_EX32(data[1], TXFIFO_DLC, DLC);
523
+
524
+ frame->data[0] = FIELD_EX32(data[2], TXFIFO_DATA1, DB3);
525
+ frame->data[1] = FIELD_EX32(data[2], TXFIFO_DATA1, DB2);
526
+ frame->data[2] = FIELD_EX32(data[2], TXFIFO_DATA1, DB1);
527
+ frame->data[3] = FIELD_EX32(data[2], TXFIFO_DATA1, DB0);
528
+
529
+ frame->data[4] = FIELD_EX32(data[3], TXFIFO_DATA2, DB7);
530
+ frame->data[5] = FIELD_EX32(data[3], TXFIFO_DATA2, DB6);
531
+ frame->data[6] = FIELD_EX32(data[3], TXFIFO_DATA2, DB5);
532
+ frame->data[7] = FIELD_EX32(data[3], TXFIFO_DATA2, DB4);
533
+}
534
+
535
+static bool tx_ready_check(XlnxZynqMPCANState *s)
536
+{
537
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, SRST)) {
538
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
539
+
540
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer data while"
541
+ " data while controller is in reset mode.\n",
542
+ path);
543
+ return false;
544
+ }
545
+
546
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
547
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
548
+
549
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer"
550
+ " data while controller is in configuration mode. Reset"
551
+ " the core so operations can start fresh.\n",
552
+ path);
553
+ return false;
554
+ }
555
+
556
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SNOOP)) {
557
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
558
+
559
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer"
560
+ " data while controller is in SNOOP MODE.\n",
561
+ path);
562
+ return false;
563
+ }
564
+
565
+ return true;
566
+}
567
+
568
+static void transfer_fifo(XlnxZynqMPCANState *s, Fifo32 *fifo)
569
+{
570
+ qemu_can_frame frame;
571
+ uint32_t data[CAN_FRAME_SIZE];
572
+ int i;
573
+ bool can_tx = tx_ready_check(s);
574
+
575
+ if (can_tx) {
576
+ while (!fifo32_is_empty(fifo)) {
577
+ for (i = 0; i < CAN_FRAME_SIZE; i++) {
578
+ data[i] = fifo32_pop(fifo);
579
+ }
580
+
581
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, LBACK)) {
582
+ /*
583
+ * Controller is in loopback. In Loopback mode, the CAN core
584
+ * transmits a recessive bitstream on to the XlnxZynqMPCAN Bus.
585
+ * Any message transmitted is looped back to the RX line and
586
+ * acknowledged. The XlnxZynqMPCAN core receives any message
587
+ * that it transmits.
588
+ */
589
+ if (fifo32_is_full(&s->rx_fifo)) {
590
+ DB_PRINT(s, "Loopback: RX FIFO is full."
591
+ " TX FIFO will be flushed.\n");
592
+
593
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER,
594
+ RXOFLW, 1);
595
+ } else {
596
+ for (i = 0; i < CAN_FRAME_SIZE; i++) {
597
+ fifo32_push(&s->rx_fifo, data[i]);
598
+ }
599
+
600
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER,
601
+ RXOK, 1);
602
+ }
603
+ } else {
604
+ /* Normal mode Tx. */
605
+ generate_frame(&frame, data);
606
+
607
+ can_bus_client_send(&s->bus_client, &frame, 1);
608
+ }
609
+ }
610
+
611
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXOK, 1);
612
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, TXBFLL, 0);
613
+
614
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP)) {
615
+ can_exit_sleep_mode(s);
616
+ }
617
+ } else {
618
+ DB_PRINT(s, "Not enabled for data transfer.\n");
619
+ }
620
+
621
+ can_update_irq(s);
622
+}
623
+
624
+static uint64_t can_srr_pre_write(RegisterInfo *reg, uint64_t val64)
625
+{
626
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
627
+ uint32_t val = val64;
628
+
629
+ ARRAY_FIELD_DP32(s->regs, SOFTWARE_RESET_REGISTER, CEN,
630
+ FIELD_EX32(val, SOFTWARE_RESET_REGISTER, CEN));
631
+
632
+ if (FIELD_EX32(val, SOFTWARE_RESET_REGISTER, SRST)) {
633
+ DB_PRINT(s, "Resetting controller.\n");
634
+
635
+ /* First, core will do software reset then will enter in config mode. */
636
+ can_config_reset(s);
637
+ }
638
+
639
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
640
+ can_config_mode(s);
641
+ } else {
642
+ /*
643
+ * Leave config mode. Now XlnxZynqMPCAN core will enter normal,
644
+ * sleep, snoop or loopback mode depending upon LBACK, SLEEP, SNOOP
645
+ * register states.
646
+ */
647
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, CONFIG, 0);
648
+
649
+ ptimer_transaction_begin(s->can_timer);
650
+ ptimer_set_count(s->can_timer, 0);
651
+ ptimer_transaction_commit(s->can_timer);
652
+
653
+ /* XlnxZynqMPCAN is out of config mode. It will send pending data. */
654
+ transfer_fifo(s, &s->txhpb_fifo);
655
+ transfer_fifo(s, &s->tx_fifo);
656
+ }
657
+
658
+ update_status_register_mode_bits(s);
659
+
660
+ return s->regs[R_SOFTWARE_RESET_REGISTER];
661
+}
662
+
663
+static uint64_t can_msr_pre_write(RegisterInfo *reg, uint64_t val64)
664
+{
665
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
666
+ uint32_t val = val64;
667
+ uint8_t multi_mode;
668
+
669
+ /*
670
+ * Multiple mode set check. This is done to make sure user doesn't set
671
+ * multiple modes.
672
+ */
673
+ multi_mode = FIELD_EX32(val, MODE_SELECT_REGISTER, LBACK) +
674
+ FIELD_EX32(val, MODE_SELECT_REGISTER, SLEEP) +
675
+ FIELD_EX32(val, MODE_SELECT_REGISTER, SNOOP);
676
+
677
+ if (multi_mode > 1) {
678
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
679
+
680
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to config"
681
+ " several modes simultaneously. One mode will be selected"
682
+ " according to their priority: LBACK > SLEEP > SNOOP.\n",
683
+ path);
684
+ }
685
+
686
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
687
+ /* We are in configuration mode, any mode can be selected. */
688
+ s->regs[R_MODE_SELECT_REGISTER] = val;
689
+ } else {
690
+ bool sleep_mode_bit = FIELD_EX32(val, MODE_SELECT_REGISTER, SLEEP);
691
+
692
+ ARRAY_FIELD_DP32(s->regs, MODE_SELECT_REGISTER, SLEEP, sleep_mode_bit);
693
+
694
+ if (FIELD_EX32(val, MODE_SELECT_REGISTER, LBACK)) {
695
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
696
+
697
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to set"
698
+ " LBACK mode without setting CEN bit as 0.\n",
699
+ path);
700
+ } else if (FIELD_EX32(val, MODE_SELECT_REGISTER, SNOOP)) {
701
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
702
+
703
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to set"
704
+ " SNOOP mode without setting CEN bit as 0.\n",
705
+ path);
706
+ }
707
+
708
+ update_status_register_mode_bits(s);
709
+ }
710
+
711
+ return s->regs[R_MODE_SELECT_REGISTER];
712
+}
713
+
714
+static uint64_t can_brpr_pre_write(RegisterInfo *reg, uint64_t val64)
715
+{
716
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
717
+ uint32_t val = val64;
718
+
719
+ /* Only allow writes when in config mode. */
720
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) {
721
+ val = s->regs[R_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER];
722
+ }
723
+
724
+ return val;
725
+}
726
+
727
+static uint64_t can_btr_pre_write(RegisterInfo *reg, uint64_t val64)
728
+{
729
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
730
+ uint32_t val = val64;
731
+
732
+ /* Only allow writes when in config mode. */
733
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) {
734
+ val = s->regs[R_ARBITRATION_PHASE_BIT_TIMING_REGISTER];
735
+ }
736
+
737
+ return val;
738
+}
739
+
740
+static uint64_t can_tcr_pre_write(RegisterInfo *reg, uint64_t val64)
741
+{
742
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
743
+ uint32_t val = val64;
744
+
745
+ if (FIELD_EX32(val, TIMESTAMP_REGISTER, CTS)) {
746
+ ptimer_transaction_begin(s->can_timer);
747
+ ptimer_set_count(s->can_timer, 0);
748
+ ptimer_transaction_commit(s->can_timer);
749
+ }
750
+
751
+ return 0;
752
+}
753
+
754
+static void update_rx_fifo(XlnxZynqMPCANState *s, const qemu_can_frame *frame)
755
+{
756
+ bool filter_pass = false;
757
+ uint16_t timestamp = 0;
758
+
759
+ /* If no filter is enabled. Message will be stored in FIFO. */
760
+ if (!((ARRAY_FIELD_EX32(s->regs, AFR, UAF1)) |
761
+ (ARRAY_FIELD_EX32(s->regs, AFR, UAF2)) |
762
+ (ARRAY_FIELD_EX32(s->regs, AFR, UAF3)) |
763
+ (ARRAY_FIELD_EX32(s->regs, AFR, UAF4)))) {
764
+ filter_pass = true;
765
+ }
766
+
767
+ /*
768
+ * Messages that pass any of the acceptance filters will be stored in
769
+ * the RX FIFO.
770
+ */
771
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF1)) {
772
+ uint32_t id_masked = s->regs[R_AFMR1] & frame->can_id;
773
+ uint32_t filter_id_masked = s->regs[R_AFMR1] & s->regs[R_AFIR1];
774
+
775
+ if (filter_id_masked == id_masked) {
776
+ filter_pass = true;
777
+ }
778
+ }
779
+
780
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF2)) {
781
+ uint32_t id_masked = s->regs[R_AFMR2] & frame->can_id;
782
+ uint32_t filter_id_masked = s->regs[R_AFMR2] & s->regs[R_AFIR2];
783
+
784
+ if (filter_id_masked == id_masked) {
785
+ filter_pass = true;
786
+ }
787
+ }
788
+
789
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF3)) {
790
+ uint32_t id_masked = s->regs[R_AFMR3] & frame->can_id;
791
+ uint32_t filter_id_masked = s->regs[R_AFMR3] & s->regs[R_AFIR3];
792
+
793
+ if (filter_id_masked == id_masked) {
794
+ filter_pass = true;
795
+ }
796
+ }
797
+
798
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF4)) {
799
+ uint32_t id_masked = s->regs[R_AFMR4] & frame->can_id;
800
+ uint32_t filter_id_masked = s->regs[R_AFMR4] & s->regs[R_AFIR4];
801
+
802
+ if (filter_id_masked == id_masked) {
803
+ filter_pass = true;
804
+ }
805
+ }
806
+
807
+ /* Store the message in fifo if it passed through any of the filters. */
808
+ if (filter_pass && frame->can_dlc <= MAX_DLC) {
809
+
810
+ if (fifo32_is_full(&s->rx_fifo)) {
811
+ DB_PRINT(s, "RX FIFO is full.\n");
812
+
813
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOFLW, 1);
814
+ } else {
815
+ timestamp = CAN_TIMER_MAX - ptimer_get_count(s->can_timer);
816
+
817
+ fifo32_push(&s->rx_fifo, frame->can_id);
818
+
819
+ fifo32_push(&s->rx_fifo, deposit32(0, R_RXFIFO_DLC_DLC_SHIFT,
820
+ R_RXFIFO_DLC_DLC_LENGTH,
821
+ frame->can_dlc) |
822
+ deposit32(0, R_RXFIFO_DLC_RXT_SHIFT,
823
+ R_RXFIFO_DLC_RXT_LENGTH,
824
+ timestamp));
825
+
826
+ /* First 32 bit of the data. */
827
+ fifo32_push(&s->rx_fifo, deposit32(0, R_TXFIFO_DATA1_DB3_SHIFT,
828
+ R_TXFIFO_DATA1_DB3_LENGTH,
829
+ frame->data[0]) |
830
+ deposit32(0, R_TXFIFO_DATA1_DB2_SHIFT,
831
+ R_TXFIFO_DATA1_DB2_LENGTH,
832
+ frame->data[1]) |
833
+ deposit32(0, R_TXFIFO_DATA1_DB1_SHIFT,
834
+ R_TXFIFO_DATA1_DB1_LENGTH,
835
+ frame->data[2]) |
836
+ deposit32(0, R_TXFIFO_DATA1_DB0_SHIFT,
837
+ R_TXFIFO_DATA1_DB0_LENGTH,
838
+ frame->data[3]));
839
+ /* Last 32 bit of the data. */
840
+ fifo32_push(&s->rx_fifo, deposit32(0, R_TXFIFO_DATA2_DB7_SHIFT,
841
+ R_TXFIFO_DATA2_DB7_LENGTH,
842
+ frame->data[4]) |
843
+ deposit32(0, R_TXFIFO_DATA2_DB6_SHIFT,
844
+ R_TXFIFO_DATA2_DB6_LENGTH,
845
+ frame->data[5]) |
846
+ deposit32(0, R_TXFIFO_DATA2_DB5_SHIFT,
847
+ R_TXFIFO_DATA2_DB5_LENGTH,
848
+ frame->data[6]) |
849
+ deposit32(0, R_TXFIFO_DATA2_DB4_SHIFT,
850
+ R_TXFIFO_DATA2_DB4_LENGTH,
851
+ frame->data[7]));
852
+
853
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 1);
854
+ }
855
+
856
+ can_update_irq(s);
857
+ } else {
858
+ DB_PRINT(s, "Message didn't pass through any filter or dlc"
859
+ " is not in range.\n");
860
+ }
861
+}
862
+
863
+static uint64_t can_rxfifo_pre_read(RegisterInfo *reg, uint64_t val64)
864
+{
865
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
866
+ uint32_t r = 0;
867
+
868
+ if (!fifo32_is_empty(&s->rx_fifo)) {
869
+ r = fifo32_pop(&s->rx_fifo);
870
+ } else {
871
+ DB_PRINT(s, "No message in RXFIFO.\n");
872
+
873
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXUFLW, 1);
874
+ }
875
+
876
+ can_update_irq(s);
181
+ return r;
877
+ return r;
182
+}
878
+}
183
+
879
+
184
+static int64_t calc_next_timeout(NRF51RNGState *s)
880
+static void can_filter_enable_post_write(RegisterInfo *reg, uint64_t val64)
185
+{
881
+{
186
+ int64_t timeout = qemu_clock_get_us(QEMU_CLOCK_VIRTUAL);
882
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
187
+ if (s->filter_enabled) {
883
+
188
+ timeout += s->period_filtered_us;
884
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF1) &&
885
+ ARRAY_FIELD_EX32(s->regs, AFR, UAF2) &&
886
+ ARRAY_FIELD_EX32(s->regs, AFR, UAF3) &&
887
+ ARRAY_FIELD_EX32(s->regs, AFR, UAF4)) {
888
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, ACFBSY, 1);
189
+ } else {
889
+ } else {
190
+ timeout += s->period_unfiltered_us;
890
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, ACFBSY, 0);
191
+ }
891
+ }
192
+
892
+}
193
+ return timeout;
893
+
194
+}
894
+static uint64_t can_filter_mask_pre_write(RegisterInfo *reg, uint64_t val64)
195
+
895
+{
196
+
896
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
197
+static void rng_update_timer(NRF51RNGState *s)
897
+ uint32_t reg_idx = (reg->access->addr) / 4;
198
+{
898
+ uint32_t val = val64;
199
+ if (s->active) {
899
+ uint32_t filter_number = (reg_idx - R_AFMR1) / 2;
200
+ timer_mod(&s->timer, calc_next_timeout(s));
900
+
901
+ /* modify an acceptance filter, the corresponding UAF bit should be '0.' */
902
+ if (!(s->regs[R_AFR] & (1 << filter_number))) {
903
+ s->regs[reg_idx] = val;
201
+ } else {
904
+ } else {
202
+ timer_del(&s->timer);
905
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
203
+ }
906
+
204
+}
907
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter %d"
205
+
908
+ " mask is not set as corresponding UAF bit is not 0.\n",
206
+
909
+ path, filter_number + 1);
207
+static void rng_write(void *opaque, hwaddr offset,
910
+ }
208
+ uint64_t value, unsigned int size)
911
+
209
+{
912
+ return s->regs[reg_idx];
210
+ NRF51RNGState *s = NRF51_RNG(opaque);
913
+}
211
+
914
+
212
+ switch (offset) {
915
+static uint64_t can_filter_id_pre_write(RegisterInfo *reg, uint64_t val64)
213
+ case NRF51_RNG_TASK_START:
916
+{
214
+ if (value == NRF51_TRIGGER_TASK) {
917
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
215
+ s->active = 1;
918
+ uint32_t reg_idx = (reg->access->addr) / 4;
216
+ rng_update_timer(s);
919
+ uint32_t val = val64;
920
+ uint32_t filter_number = (reg_idx - R_AFIR1) / 2;
921
+
922
+ if (!(s->regs[R_AFR] & (1 << filter_number))) {
923
+ s->regs[reg_idx] = val;
924
+ } else {
925
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
926
+
927
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter %d"
928
+ " id is not set as corresponding UAF bit is not 0.\n",
929
+ path, filter_number + 1);
930
+ }
931
+
932
+ return s->regs[reg_idx];
933
+}
934
+
935
+static void can_tx_post_write(RegisterInfo *reg, uint64_t val64)
936
+{
937
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
938
+ uint32_t val = val64;
939
+
940
+ bool is_txhpb = reg->access->addr > A_TXFIFO_DATA2;
941
+
942
+ bool initiate_transfer = (reg->access->addr == A_TXFIFO_DATA2) ||
943
+ (reg->access->addr == A_TXHPB_DATA2);
944
+
945
+ Fifo32 *f = is_txhpb ? &s->txhpb_fifo : &s->tx_fifo;
946
+
947
+ DB_PRINT(s, "TX FIFO write.\n");
948
+
949
+ if (!fifo32_is_full(f)) {
950
+ fifo32_push(f, val);
951
+ } else {
952
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
953
+
954
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: TX FIFO is full.\n", path);
955
+ }
956
+
957
+ /* Initiate the message send if TX register is written. */
958
+ if (initiate_transfer &&
959
+ ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) {
960
+ transfer_fifo(s, f);
961
+ }
962
+
963
+ can_update_irq(s);
964
+}
965
+
966
+static const RegisterAccessInfo can_regs_info[] = {
967
+ { .name = "SOFTWARE_RESET_REGISTER",
968
+ .addr = A_SOFTWARE_RESET_REGISTER,
969
+ .rsvd = 0xfffffffc,
970
+ .pre_write = can_srr_pre_write,
971
+ },{ .name = "MODE_SELECT_REGISTER",
972
+ .addr = A_MODE_SELECT_REGISTER,
973
+ .rsvd = 0xfffffff8,
974
+ .pre_write = can_msr_pre_write,
975
+ },{ .name = "ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER",
976
+ .addr = A_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER,
977
+ .rsvd = 0xffffff00,
978
+ .pre_write = can_brpr_pre_write,
979
+ },{ .name = "ARBITRATION_PHASE_BIT_TIMING_REGISTER",
980
+ .addr = A_ARBITRATION_PHASE_BIT_TIMING_REGISTER,
981
+ .rsvd = 0xfffffe00,
982
+ .pre_write = can_btr_pre_write,
983
+ },{ .name = "ERROR_COUNTER_REGISTER",
984
+ .addr = A_ERROR_COUNTER_REGISTER,
985
+ .rsvd = 0xffff0000,
986
+ .ro = 0xffffffff,
987
+ },{ .name = "ERROR_STATUS_REGISTER",
988
+ .addr = A_ERROR_STATUS_REGISTER,
989
+ .rsvd = 0xffffffe0,
990
+ .w1c = 0x1f,
991
+ },{ .name = "STATUS_REGISTER", .addr = A_STATUS_REGISTER,
992
+ .reset = 0x1,
993
+ .rsvd = 0xffffe000,
994
+ .ro = 0x1fff,
995
+ },{ .name = "INTERRUPT_STATUS_REGISTER",
996
+ .addr = A_INTERRUPT_STATUS_REGISTER,
997
+ .reset = 0x6000,
998
+ .rsvd = 0xffff8000,
999
+ .ro = 0x7fff,
1000
+ },{ .name = "INTERRUPT_ENABLE_REGISTER",
1001
+ .addr = A_INTERRUPT_ENABLE_REGISTER,
1002
+ .rsvd = 0xffff8000,
1003
+ .post_write = can_ier_post_write,
1004
+ },{ .name = "INTERRUPT_CLEAR_REGISTER",
1005
+ .addr = A_INTERRUPT_CLEAR_REGISTER,
1006
+ .rsvd = 0xffff8000,
1007
+ .pre_write = can_icr_pre_write,
1008
+ },{ .name = "TIMESTAMP_REGISTER",
1009
+ .addr = A_TIMESTAMP_REGISTER,
1010
+ .rsvd = 0xfffffffe,
1011
+ .pre_write = can_tcr_pre_write,
1012
+ },{ .name = "WIR", .addr = A_WIR,
1013
+ .reset = 0x3f3f,
1014
+ .rsvd = 0xffff0000,
1015
+ },{ .name = "TXFIFO_ID", .addr = A_TXFIFO_ID,
1016
+ .post_write = can_tx_post_write,
1017
+ },{ .name = "TXFIFO_DLC", .addr = A_TXFIFO_DLC,
1018
+ .rsvd = 0xfffffff,
1019
+ .post_write = can_tx_post_write,
1020
+ },{ .name = "TXFIFO_DATA1", .addr = A_TXFIFO_DATA1,
1021
+ .post_write = can_tx_post_write,
1022
+ },{ .name = "TXFIFO_DATA2", .addr = A_TXFIFO_DATA2,
1023
+ .post_write = can_tx_post_write,
1024
+ },{ .name = "TXHPB_ID", .addr = A_TXHPB_ID,
1025
+ .post_write = can_tx_post_write,
1026
+ },{ .name = "TXHPB_DLC", .addr = A_TXHPB_DLC,
1027
+ .rsvd = 0xfffffff,
1028
+ .post_write = can_tx_post_write,
1029
+ },{ .name = "TXHPB_DATA1", .addr = A_TXHPB_DATA1,
1030
+ .post_write = can_tx_post_write,
1031
+ },{ .name = "TXHPB_DATA2", .addr = A_TXHPB_DATA2,
1032
+ .post_write = can_tx_post_write,
1033
+ },{ .name = "RXFIFO_ID", .addr = A_RXFIFO_ID,
1034
+ .ro = 0xffffffff,
1035
+ .post_read = can_rxfifo_pre_read,
1036
+ },{ .name = "RXFIFO_DLC", .addr = A_RXFIFO_DLC,
1037
+ .rsvd = 0xfff0000,
1038
+ .post_read = can_rxfifo_pre_read,
1039
+ },{ .name = "RXFIFO_DATA1", .addr = A_RXFIFO_DATA1,
1040
+ .post_read = can_rxfifo_pre_read,
1041
+ },{ .name = "RXFIFO_DATA2", .addr = A_RXFIFO_DATA2,
1042
+ .post_read = can_rxfifo_pre_read,
1043
+ },{ .name = "AFR", .addr = A_AFR,
1044
+ .rsvd = 0xfffffff0,
1045
+ .post_write = can_filter_enable_post_write,
1046
+ },{ .name = "AFMR1", .addr = A_AFMR1,
1047
+ .pre_write = can_filter_mask_pre_write,
1048
+ },{ .name = "AFIR1", .addr = A_AFIR1,
1049
+ .pre_write = can_filter_id_pre_write,
1050
+ },{ .name = "AFMR2", .addr = A_AFMR2,
1051
+ .pre_write = can_filter_mask_pre_write,
1052
+ },{ .name = "AFIR2", .addr = A_AFIR2,
1053
+ .pre_write = can_filter_id_pre_write,
1054
+ },{ .name = "AFMR3", .addr = A_AFMR3,
1055
+ .pre_write = can_filter_mask_pre_write,
1056
+ },{ .name = "AFIR3", .addr = A_AFIR3,
1057
+ .pre_write = can_filter_id_pre_write,
1058
+ },{ .name = "AFMR4", .addr = A_AFMR4,
1059
+ .pre_write = can_filter_mask_pre_write,
1060
+ },{ .name = "AFIR4", .addr = A_AFIR4,
1061
+ .pre_write = can_filter_id_pre_write,
1062
+ }
1063
+};
1064
+
1065
+static void xlnx_zynqmp_can_ptimer_cb(void *opaque)
1066
+{
1067
+ /* No action required on the timer rollover. */
1068
+}
1069
+
1070
+static const MemoryRegionOps can_ops = {
1071
+ .read = register_read_memory,
1072
+ .write = register_write_memory,
1073
+ .endianness = DEVICE_LITTLE_ENDIAN,
1074
+ .valid = {
1075
+ .min_access_size = 4,
1076
+ .max_access_size = 4,
1077
+ },
1078
+};
1079
+
1080
+static void xlnx_zynqmp_can_reset_init(Object *obj, ResetType type)
1081
+{
1082
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(obj);
1083
+ unsigned int i;
1084
+
1085
+ for (i = R_RXFIFO_ID; i < ARRAY_SIZE(s->reg_info); ++i) {
1086
+ register_reset(&s->reg_info[i]);
1087
+ }
1088
+
1089
+ ptimer_transaction_begin(s->can_timer);
1090
+ ptimer_set_count(s->can_timer, 0);
1091
+ ptimer_transaction_commit(s->can_timer);
1092
+}
1093
+
1094
+static void xlnx_zynqmp_can_reset_hold(Object *obj)
1095
+{
1096
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(obj);
1097
+ unsigned int i;
1098
+
1099
+ for (i = 0; i < R_RXFIFO_ID; ++i) {
1100
+ register_reset(&s->reg_info[i]);
1101
+ }
1102
+
1103
+ /*
1104
+ * Reset FIFOs when CAN model is reset. This will clear the fifo writes
1105
+ * done by post_write which gets called from register_reset function,
1106
+ * post_write handle will not be able to trigger tx because CAN will be
1107
+ * disabled when software_reset_register is cleared first.
1108
+ */
1109
+ fifo32_reset(&s->rx_fifo);
1110
+ fifo32_reset(&s->tx_fifo);
1111
+ fifo32_reset(&s->txhpb_fifo);
1112
+}
1113
+
1114
+static bool xlnx_zynqmp_can_can_receive(CanBusClientState *client)
1115
+{
1116
+ XlnxZynqMPCANState *s = container_of(client, XlnxZynqMPCANState,
1117
+ bus_client);
1118
+
1119
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, SRST)) {
1120
+ DB_PRINT(s, "Controller is in reset.\n");
1121
+ return false;
1122
+ } else if ((ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) == 0) {
1123
+ DB_PRINT(s, "Controller is disabled. Incoming messages"
1124
+ " will be discarded.\n");
1125
+ return false;
1126
+ } else {
1127
+ return true;
1128
+ }
1129
+}
1130
+
1131
+static ssize_t xlnx_zynqmp_can_receive(CanBusClientState *client,
1132
+ const qemu_can_frame *buf, size_t buf_size) {
1133
+ XlnxZynqMPCANState *s = container_of(client, XlnxZynqMPCANState,
1134
+ bus_client);
1135
+ const qemu_can_frame *frame = buf;
1136
+
1137
+ DB_PRINT(s, "Incoming data.\n");
1138
+
1139
+ if (buf_size <= 0) {
1140
+ DB_PRINT(s, "Junk data received.\n");
1141
+ return 0;
1142
+ }
1143
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, LBACK)) {
1144
+ /*
1145
+ * XlnxZynqMPCAN will not participate in normal bus communication
1146
+ * and will not receive any messages transmitted by other CAN nodes.
1147
+ */
1148
+ DB_PRINT(s, "Controller is in loopback mode. It will not"
1149
+ " receive data.\n");
1150
+
1151
+ } else if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SNOOP)) {
1152
+ /* Snoop Mode: Just keep the data. no response back. */
1153
+ update_rx_fifo(s, frame);
1154
+ } else if ((ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP))) {
1155
+ /*
1156
+ * XlnxZynqMPCAN is in sleep mode. Any data on bus will bring it to wake
1157
+ * up state.
1158
+ */
1159
+ can_exit_sleep_mode(s);
1160
+ update_rx_fifo(s, frame);
1161
+ } else if ((ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP)) == 0) {
1162
+ update_rx_fifo(s, frame);
1163
+ } else {
1164
+ DB_PRINT(s, "Cannot receive data as controller is not configured"
1165
+ " correctly.\n");
1166
+ }
1167
+
1168
+ return 1;
1169
+}
1170
+
1171
+static CanBusClientInfo can_xilinx_bus_client_info = {
1172
+ .can_receive = xlnx_zynqmp_can_can_receive,
1173
+ .receive = xlnx_zynqmp_can_receive,
1174
+};
1175
+
1176
+static int xlnx_zynqmp_can_connect_to_bus(XlnxZynqMPCANState *s,
1177
+ CanBusState *bus)
1178
+{
1179
+ s->bus_client.info = &can_xilinx_bus_client_info;
1180
+
1181
+ if (can_bus_insert_client(bus, &s->bus_client) < 0) {
1182
+ return -1;
1183
+ }
1184
+ return 0;
1185
+}
1186
+
1187
+static void xlnx_zynqmp_can_realize(DeviceState *dev, Error **errp)
1188
+{
1189
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(dev);
1190
+
1191
+ if (s->canbus) {
1192
+ if (xlnx_zynqmp_can_connect_to_bus(s, s->canbus) < 0) {
1193
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1194
+
1195
+ error_setg(errp, "%s: xlnx_zynqmp_can_connect_to_bus"
1196
+ " failed.", path);
1197
+ return;
217
+ }
1198
+ }
218
+ break;
1199
+
219
+ case NRF51_RNG_TASK_STOP:
1200
+ } else {
220
+ if (value == NRF51_TRIGGER_TASK) {
1201
+ /* If no bus is set. */
221
+ s->active = 0;
1202
+ DB_PRINT(s, "Canbus property is not set.\n");
222
+ rng_update_timer(s);
1203
+ }
223
+ }
1204
+
224
+ break;
1205
+ /* Create RX FIFO, TXFIFO, TXHPB storage. */
225
+ case NRF51_RNG_EVENT_VALRDY:
1206
+ fifo32_create(&s->rx_fifo, RXFIFO_SIZE);
226
+ if (value == NRF51_EVENT_CLEAR) {
1207
+ fifo32_create(&s->tx_fifo, RXFIFO_SIZE);
227
+ s->event_valrdy = 0;
1208
+ fifo32_create(&s->txhpb_fifo, CAN_FRAME_SIZE);
228
+ }
1209
+
229
+ break;
1210
+ /* Allocate a new timer. */
230
+ case NRF51_RNG_REG_SHORTS:
1211
+ s->can_timer = ptimer_init(xlnx_zynqmp_can_ptimer_cb, s,
231
+ s->shortcut_stop_on_valrdy =
1212
+ PTIMER_POLICY_DEFAULT);
232
+ (value & BIT_MASK(NRF51_RNG_REG_SHORTS_VALRDY_STOP)) ? 1 : 0;
1213
+
233
+ break;
1214
+ ptimer_transaction_begin(s->can_timer);
234
+ case NRF51_RNG_REG_INTEN:
1215
+
235
+ s->interrupt_enabled =
1216
+ ptimer_set_freq(s->can_timer, s->cfg.ext_clk_freq);
236
+ (value & BIT_MASK(NRF51_RNG_REG_INTEN_VALRDY)) ? 1 : 0;
1217
+ ptimer_set_limit(s->can_timer, CAN_TIMER_MAX, 1);
237
+ break;
1218
+ ptimer_run(s->can_timer, 0);
238
+ case NRF51_RNG_REG_INTENSET:
1219
+ ptimer_transaction_commit(s->can_timer);
239
+ if (value & BIT_MASK(NRF51_RNG_REG_INTEN_VALRDY)) {
1220
+}
240
+ s->interrupt_enabled = 1;
1221
+
241
+ }
1222
+static void xlnx_zynqmp_can_init(Object *obj)
242
+ break;
1223
+{
243
+ case NRF51_RNG_REG_INTENCLR:
1224
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(obj);
244
+ if (value & BIT_MASK(NRF51_RNG_REG_INTEN_VALRDY)) {
245
+ s->interrupt_enabled = 0;
246
+ }
247
+ break;
248
+ case NRF51_RNG_REG_CONFIG:
249
+ s->filter_enabled =
250
+ (value & BIT_MASK(NRF51_RNG_REG_CONFIG_DECEN)) ? 1 : 0;
251
+ break;
252
+
253
+ default:
254
+ qemu_log_mask(LOG_GUEST_ERROR,
255
+ "%s: bad write offset 0x%" HWADDR_PRIx "\n",
256
+ __func__, offset);
257
+ }
258
+
259
+ update_irq(s);
260
+}
261
+
262
+static const MemoryRegionOps rng_ops = {
263
+ .read = rng_read,
264
+ .write = rng_write,
265
+ .endianness = DEVICE_LITTLE_ENDIAN,
266
+ .impl.min_access_size = 4,
267
+ .impl.max_access_size = 4
268
+};
269
+
270
+static void nrf51_rng_timer_expire(void *opaque)
271
+{
272
+ NRF51RNGState *s = NRF51_RNG(opaque);
273
+
274
+ qcrypto_random_bytes(&s->value, 1, &error_abort);
275
+
276
+ s->event_valrdy = 1;
277
+ qemu_set_irq(s->eep_valrdy, 1);
278
+
279
+ if (s->shortcut_stop_on_valrdy) {
280
+ s->active = 0;
281
+ }
282
+
283
+ rng_update_timer(s);
284
+ update_irq(s);
285
+}
286
+
287
+static void nrf51_rng_tep_start(void *opaque, int n, int level)
288
+{
289
+ NRF51RNGState *s = NRF51_RNG(opaque);
290
+
291
+ if (level) {
292
+ s->active = 1;
293
+ rng_update_timer(s);
294
+ }
295
+}
296
+
297
+static void nrf51_rng_tep_stop(void *opaque, int n, int level)
298
+{
299
+ NRF51RNGState *s = NRF51_RNG(opaque);
300
+
301
+ if (level) {
302
+ s->active = 0;
303
+ rng_update_timer(s);
304
+ }
305
+}
306
+
307
+
308
+static void nrf51_rng_init(Object *obj)
309
+{
310
+ NRF51RNGState *s = NRF51_RNG(obj);
311
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
1225
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
312
+
1226
+
313
+ memory_region_init_io(&s->mmio, obj, &rng_ops, s,
1227
+ RegisterInfoArray *reg_array;
314
+ TYPE_NRF51_RNG, NRF51_RNG_SIZE);
1228
+
315
+ sysbus_init_mmio(sbd, &s->mmio);
1229
+ memory_region_init(&s->iomem, obj, TYPE_XLNX_ZYNQMP_CAN,
316
+
1230
+ XLNX_ZYNQMP_CAN_R_MAX * 4);
317
+ timer_init_us(&s->timer, QEMU_CLOCK_VIRTUAL, nrf51_rng_timer_expire, s);
1231
+ reg_array = register_init_block32(DEVICE(obj), can_regs_info,
318
+
1232
+ ARRAY_SIZE(can_regs_info),
319
+ sysbus_init_irq(sbd, &s->irq);
1233
+ s->reg_info, s->regs,
320
+
1234
+ &can_ops,
321
+ /* Tasks */
1235
+ XLNX_ZYNQMP_CAN_ERR_DEBUG,
322
+ qdev_init_gpio_in_named(DEVICE(s), nrf51_rng_tep_start, "tep_start", 1);
1236
+ XLNX_ZYNQMP_CAN_R_MAX * 4);
323
+ qdev_init_gpio_in_named(DEVICE(s), nrf51_rng_tep_stop, "tep_stop", 1);
1237
+
324
+
1238
+ memory_region_add_subregion(&s->iomem, 0x00, &reg_array->mem);
325
+ /* Events */
1239
+ sysbus_init_mmio(sbd, &s->iomem);
326
+ qdev_init_gpio_out_named(DEVICE(s), &s->eep_valrdy, "eep_valrdy", 1);
1240
+ sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
327
+}
1241
+}
328
+
1242
+
329
+static void nrf51_rng_reset(DeviceState *dev)
1243
+static const VMStateDescription vmstate_can = {
330
+{
1244
+ .name = TYPE_XLNX_ZYNQMP_CAN,
331
+ NRF51RNGState *s = NRF51_RNG(dev);
332
+
333
+ s->value = 0;
334
+ s->active = 0;
335
+ s->event_valrdy = 0;
336
+ s->shortcut_stop_on_valrdy = 0;
337
+ s->interrupt_enabled = 0;
338
+ s->filter_enabled = 0;
339
+
340
+ rng_update_timer(s);
341
+}
342
+
343
+
344
+static Property nrf51_rng_properties[] = {
345
+ DEFINE_PROP_UINT16("period_unfiltered_us", NRF51RNGState,
346
+ period_unfiltered_us, 167),
347
+ DEFINE_PROP_UINT16("period_filtered_us", NRF51RNGState,
348
+ period_filtered_us, 660),
349
+ DEFINE_PROP_END_OF_LIST(),
350
+};
351
+
352
+static const VMStateDescription vmstate_rng = {
353
+ .name = "nrf51_soc.rng",
354
+ .version_id = 1,
1245
+ .version_id = 1,
355
+ .minimum_version_id = 1,
1246
+ .minimum_version_id = 1,
356
+ .fields = (VMStateField[]) {
1247
+ .fields = (VMStateField[]) {
357
+ VMSTATE_UINT32(active, NRF51RNGState),
1248
+ VMSTATE_FIFO32(rx_fifo, XlnxZynqMPCANState),
358
+ VMSTATE_UINT32(event_valrdy, NRF51RNGState),
1249
+ VMSTATE_FIFO32(tx_fifo, XlnxZynqMPCANState),
359
+ VMSTATE_UINT32(shortcut_stop_on_valrdy, NRF51RNGState),
1250
+ VMSTATE_FIFO32(txhpb_fifo, XlnxZynqMPCANState),
360
+ VMSTATE_UINT32(interrupt_enabled, NRF51RNGState),
1251
+ VMSTATE_UINT32_ARRAY(regs, XlnxZynqMPCANState, XLNX_ZYNQMP_CAN_R_MAX),
361
+ VMSTATE_UINT32(filter_enabled, NRF51RNGState),
1252
+ VMSTATE_PTIMER(can_timer, XlnxZynqMPCANState),
362
+ VMSTATE_END_OF_LIST()
1253
+ VMSTATE_END_OF_LIST(),
363
+ }
1254
+ }
364
+};
1255
+};
365
+
1256
+
366
+static void nrf51_rng_class_init(ObjectClass *klass, void *data)
1257
+static Property xlnx_zynqmp_can_properties[] = {
1258
+ DEFINE_PROP_UINT32("ext_clk_freq", XlnxZynqMPCANState, cfg.ext_clk_freq,
1259
+ CAN_DEFAULT_CLOCK),
1260
+ DEFINE_PROP_LINK("canbus", XlnxZynqMPCANState, canbus, TYPE_CAN_BUS,
1261
+ CanBusState *),
1262
+ DEFINE_PROP_END_OF_LIST(),
1263
+};
1264
+
1265
+static void xlnx_zynqmp_can_class_init(ObjectClass *klass, void *data)
367
+{
1266
+{
368
+ DeviceClass *dc = DEVICE_CLASS(klass);
1267
+ DeviceClass *dc = DEVICE_CLASS(klass);
369
+
1268
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
370
+ dc->props = nrf51_rng_properties;
1269
+
371
+ dc->vmsd = &vmstate_rng;
1270
+ rc->phases.enter = xlnx_zynqmp_can_reset_init;
372
+ dc->reset = nrf51_rng_reset;
1271
+ rc->phases.hold = xlnx_zynqmp_can_reset_hold;
373
+}
1272
+ dc->realize = xlnx_zynqmp_can_realize;
374
+
1273
+ device_class_set_props(dc, xlnx_zynqmp_can_properties);
375
+static const TypeInfo nrf51_rng_info = {
1274
+ dc->vmsd = &vmstate_can;
376
+ .name = TYPE_NRF51_RNG,
1275
+}
377
+ .parent = TYPE_SYS_BUS_DEVICE,
1276
+
378
+ .instance_size = sizeof(NRF51RNGState),
1277
+static const TypeInfo can_info = {
379
+ .instance_init = nrf51_rng_init,
1278
+ .name = TYPE_XLNX_ZYNQMP_CAN,
380
+ .class_init = nrf51_rng_class_init
1279
+ .parent = TYPE_SYS_BUS_DEVICE,
1280
+ .instance_size = sizeof(XlnxZynqMPCANState),
1281
+ .class_init = xlnx_zynqmp_can_class_init,
1282
+ .instance_init = xlnx_zynqmp_can_init,
381
+};
1283
+};
382
+
1284
+
383
+static void nrf51_rng_register_types(void)
1285
+static void can_register_types(void)
384
+{
1286
+{
385
+ type_register_static(&nrf51_rng_info);
1287
+ type_register_static(&can_info);
386
+}
1288
+}
387
+
1289
+
388
+type_init(nrf51_rng_register_types)
1290
+type_init(can_register_types)
1291
diff --git a/hw/net/can/meson.build b/hw/net/can/meson.build
1292
index XXXXXXX..XXXXXXX 100644
1293
--- a/hw/net/can/meson.build
1294
+++ b/hw/net/can/meson.build
1295
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_CAN_SJA1000', if_true: files('can_sja1000.c'))
1296
softmmu_ss.add(when: 'CONFIG_CAN_PCI', if_true: files('can_kvaser_pci.c'))
1297
softmmu_ss.add(when: 'CONFIG_CAN_PCI', if_true: files('can_pcm3680_pci.c'))
1298
softmmu_ss.add(when: 'CONFIG_CAN_PCI', if_true: files('can_mioe3680_pci.c'))
1299
+softmmu_ss.add(when: 'CONFIG_XLNX_ZYNQMP', if_true: files('xlnx-zynqmp-can.c'))
389
--
1300
--
390
2.19.2
1301
2.20.1
391
1302
392
1303
diff view generated by jsdifflib
1
From: Luc Michel <luc.michel@greensocs.com>
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
2
2
3
Create two separate CPU clusters for APUs and RPUs.
3
Connect CAN0 and CAN1 on the ZynqMP.
4
4
5
Signed-off-by: Luc Michel <luc.michel@greensocs.com>
5
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
6
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
6
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Message-id: 1597278668-339715-3-git-send-email-fnu.vikram@xilinx.com
9
Message-id: 20181207090135.7651-17-luc.michel@greensocs.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
10
---
12
include/hw/arm/xlnx-zynqmp.h | 3 +++
11
include/hw/arm/xlnx-zynqmp.h | 8 ++++++++
13
hw/arm/xlnx-zynqmp.c | 23 +++++++++++++++++++----
12
hw/arm/xlnx-zcu102.c | 20 ++++++++++++++++++++
14
2 files changed, 22 insertions(+), 4 deletions(-)
13
hw/arm/xlnx-zynqmp.c | 34 ++++++++++++++++++++++++++++++++++
14
3 files changed, 62 insertions(+)
15
15
16
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
16
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
17
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/xlnx-zynqmp.h
18
--- a/include/hw/arm/xlnx-zynqmp.h
19
+++ b/include/hw/arm/xlnx-zynqmp.h
19
+++ b/include/hw/arm/xlnx-zynqmp.h
20
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@
21
#include "hw/display/xlnx_dp.h"
21
#include "hw/intc/arm_gic.h"
22
#include "hw/intc/xlnx-zynqmp-ipi.h"
22
#include "hw/net/cadence_gem.h"
23
#include "hw/timer/xlnx-zynqmp-rtc.h"
23
#include "hw/char/cadence_uart.h"
24
+#include "hw/cpu/cluster.h"
24
+#include "hw/net/xlnx-zynqmp-can.h"
25
#include "hw/ide/ahci.h"
26
#include "hw/sd/sdhci.h"
27
#include "hw/ssi/xilinx_spips.h"
28
@@ -XXX,XX +XXX,XX @@
29
#include "hw/cpu/cluster.h"
30
#include "target/arm/cpu.h"
31
#include "qom/object.h"
32
+#include "net/can_emu.h"
25
33
26
#define TYPE_XLNX_ZYNQMP "xlnx,zynqmp"
34
#define TYPE_XLNX_ZYNQMP "xlnx,zynqmp"
27
#define XLNX_ZYNQMP(obj) OBJECT_CHECK(XlnxZynqMPState, (obj), \
35
typedef struct XlnxZynqMPState XlnxZynqMPState;
28
@@ -XXX,XX +XXX,XX @@ typedef struct XlnxZynqMPState {
36
@@ -XXX,XX +XXX,XX @@ DECLARE_INSTANCE_CHECKER(XlnxZynqMPState, XLNX_ZYNQMP,
29
DeviceState parent_obj;
37
#define XLNX_ZYNQMP_NUM_RPU_CPUS 2
30
38
#define XLNX_ZYNQMP_NUM_GEMS 4
31
/*< public >*/
39
#define XLNX_ZYNQMP_NUM_UARTS 2
32
+ CPUClusterState apu_cluster;
40
+#define XLNX_ZYNQMP_NUM_CAN 2
33
+ CPUClusterState rpu_cluster;
41
+#define XLNX_ZYNQMP_CAN_REF_CLK (24 * 1000 * 1000)
34
ARMCPU apu_cpu[XLNX_ZYNQMP_NUM_APU_CPUS];
42
#define XLNX_ZYNQMP_NUM_SDHCI 2
35
ARMCPU rpu_cpu[XLNX_ZYNQMP_NUM_RPU_CPUS];
43
#define XLNX_ZYNQMP_NUM_SPIS 2
36
GICState gic;
44
#define XLNX_ZYNQMP_NUM_GDMA_CH 8
45
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
46
47
CadenceGEMState gem[XLNX_ZYNQMP_NUM_GEMS];
48
CadenceUARTState uart[XLNX_ZYNQMP_NUM_UARTS];
49
+ XlnxZynqMPCANState can[XLNX_ZYNQMP_NUM_CAN];
50
SysbusAHCIState sata;
51
SDHCIState sdhci[XLNX_ZYNQMP_NUM_SDHCI];
52
XilinxSPIPS spi[XLNX_ZYNQMP_NUM_SPIS];
53
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
54
bool virt;
55
/* Has the RPU subsystem? */
56
bool has_rpu;
57
+
58
+ /* CAN bus. */
59
+ CanBusState *canbus[XLNX_ZYNQMP_NUM_CAN];
60
};
61
62
#endif
63
diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/hw/arm/xlnx-zcu102.c
66
+++ b/hw/arm/xlnx-zcu102.c
67
@@ -XXX,XX +XXX,XX @@
68
#include "sysemu/qtest.h"
69
#include "sysemu/device_tree.h"
70
#include "qom/object.h"
71
+#include "net/can_emu.h"
72
73
struct XlnxZCU102 {
74
MachineState parent_obj;
75
@@ -XXX,XX +XXX,XX @@ struct XlnxZCU102 {
76
bool secure;
77
bool virt;
78
79
+ CanBusState *canbus[XLNX_ZYNQMP_NUM_CAN];
80
+
81
struct arm_boot_info binfo;
82
};
83
typedef struct XlnxZCU102 XlnxZCU102;
84
@@ -XXX,XX +XXX,XX @@ static void xlnx_zcu102_init(MachineState *machine)
85
object_property_set_bool(OBJECT(&s->soc), "virtualization", s->virt,
86
&error_fatal);
87
88
+ for (i = 0; i < XLNX_ZYNQMP_NUM_CAN; i++) {
89
+ gchar *bus_name = g_strdup_printf("canbus%d", i);
90
+
91
+ object_property_set_link(OBJECT(&s->soc), bus_name,
92
+ OBJECT(s->canbus[i]), &error_fatal);
93
+ g_free(bus_name);
94
+ }
95
+
96
qdev_realize(DEVICE(&s->soc), NULL, &error_fatal);
97
98
/* Create and plug in the SD cards */
99
@@ -XXX,XX +XXX,XX @@ static void xlnx_zcu102_machine_instance_init(Object *obj)
100
"Set on/off to enable/disable emulating a "
101
"guest CPU which implements the ARM "
102
"Virtualization Extensions");
103
+ object_property_add_link(obj, "xlnx-zcu102.canbus0", TYPE_CAN_BUS,
104
+ (Object **)&s->canbus[0],
105
+ object_property_allow_set_link,
106
+ 0);
107
+
108
+ object_property_add_link(obj, "xlnx-zcu102.canbus1", TYPE_CAN_BUS,
109
+ (Object **)&s->canbus[1],
110
+ object_property_allow_set_link,
111
+ 0);
112
}
113
114
static void xlnx_zcu102_machine_class_init(ObjectClass *oc, void *data)
37
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
115
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
38
index XXXXXXX..XXXXXXX 100644
116
index XXXXXXX..XXXXXXX 100644
39
--- a/hw/arm/xlnx-zynqmp.c
117
--- a/hw/arm/xlnx-zynqmp.c
40
+++ b/hw/arm/xlnx-zynqmp.c
118
+++ b/hw/arm/xlnx-zynqmp.c
41
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_create_rpu(XlnxZynqMPState *s, const char *boot_cpu,
119
@@ -XXX,XX +XXX,XX @@ static const int uart_intr[XLNX_ZYNQMP_NUM_UARTS] = {
42
int i;
120
21, 22,
43
int num_rpus = MIN(smp_cpus - XLNX_ZYNQMP_NUM_APU_CPUS, XLNX_ZYNQMP_NUM_RPU_CPUS);
121
};
44
122
45
+ object_initialize_child(OBJECT(s), "rpu-cluster", &s->rpu_cluster,
123
+static const uint64_t can_addr[XLNX_ZYNQMP_NUM_CAN] = {
46
+ sizeof(s->rpu_cluster), TYPE_CPU_CLUSTER,
124
+ 0xFF060000, 0xFF070000,
47
+ &error_abort, NULL);
125
+};
48
+ qdev_prop_set_uint32(DEVICE(&s->rpu_cluster), "cluster-id", 1);
49
+
126
+
50
+ qdev_init_nofail(DEVICE(&s->rpu_cluster));
127
+static const int can_intr[XLNX_ZYNQMP_NUM_CAN] = {
128
+ 23, 24,
129
+};
51
+
130
+
52
for (i = 0; i < num_rpus; i++) {
131
static const uint64_t sdhci_addr[XLNX_ZYNQMP_NUM_SDHCI] = {
53
char *name;
132
0xFF160000, 0xFF170000,
54
133
};
55
object_initialize(&s->rpu_cpu[i], sizeof(s->rpu_cpu[i]),
56
"cortex-r5f-" TYPE_ARM_CPU);
57
- object_property_add_child(OBJECT(s), "rpu-cpu[*]",
58
+ object_property_add_child(OBJECT(&s->rpu_cluster), "rpu-cpu[*]",
59
OBJECT(&s->rpu_cpu[i]), &error_abort);
60
61
name = object_get_canonical_path_component(OBJECT(&s->rpu_cpu[i]));
62
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_init(Object *obj)
134
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_init(Object *obj)
63
int i;
135
TYPE_CADENCE_UART);
64
int num_apus = MIN(smp_cpus, XLNX_ZYNQMP_NUM_APU_CPUS);
136
}
65
137
66
+ object_initialize_child(obj, "apu-cluster", &s->apu_cluster,
138
+ for (i = 0; i < XLNX_ZYNQMP_NUM_CAN; i++) {
67
+ sizeof(s->apu_cluster), TYPE_CPU_CLUSTER,
139
+ object_initialize_child(obj, "can[*]", &s->can[i],
68
+ &error_abort, NULL);
140
+ TYPE_XLNX_ZYNQMP_CAN);
69
+ qdev_prop_set_uint32(DEVICE(&s->apu_cluster), "cluster-id", 0);
141
+ }
70
+
142
+
71
for (i = 0; i < num_apus; i++) {
143
object_initialize_child(obj, "sata", &s->sata, TYPE_SYSBUS_AHCI);
72
- object_initialize_child(obj, "apu-cpu[*]", &s->apu_cpu[i],
144
73
- sizeof(s->apu_cpu[i]),
145
for (i = 0; i < XLNX_ZYNQMP_NUM_SDHCI; i++) {
74
- "cortex-a53-" TYPE_ARM_CPU, &error_abort, NULL);
146
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
75
+ object_initialize_child(OBJECT(&s->apu_cluster), "apu-cpu[*]",
147
gic_spi[uart_intr[i]]);
76
+ &s->apu_cpu[i], sizeof(s->apu_cpu[i]),
77
+ "cortex-a53-" TYPE_ARM_CPU, &error_abort,
78
+ NULL);
79
}
148
}
80
149
81
sysbus_init_child_obj(obj, "gic", &s->gic, sizeof(s->gic),
150
+ for (i = 0; i < XLNX_ZYNQMP_NUM_CAN; i++) {
82
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
151
+ object_property_set_int(OBJECT(&s->can[i]), "ext_clk_freq",
83
qdev_prop_set_bit(DEVICE(&s->gic),
152
+ XLNX_ZYNQMP_CAN_REF_CLK, &error_abort);
84
"has-virtualization-extensions", s->virt);
85
86
+ qdev_init_nofail(DEVICE(&s->apu_cluster));
87
+
153
+
88
/* Realize APUs before realizing the GIC. KVM requires this. */
154
+ object_property_set_link(OBJECT(&s->can[i]), "canbus",
89
for (i = 0; i < num_apus; i++) {
155
+ OBJECT(s->canbus[i]), &error_fatal);
90
char *name;
156
+
157
+ sysbus_realize(SYS_BUS_DEVICE(&s->can[i]), &err);
158
+ if (err) {
159
+ error_propagate(errp, err);
160
+ return;
161
+ }
162
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->can[i]), 0, can_addr[i]);
163
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->can[i]), 0,
164
+ gic_spi[can_intr[i]]);
165
+ }
166
+
167
object_property_set_int(OBJECT(&s->sata), "num-ports", SATA_NUM_PORTS,
168
&error_abort);
169
if (!sysbus_realize(SYS_BUS_DEVICE(&s->sata), errp)) {
170
@@ -XXX,XX +XXX,XX @@ static Property xlnx_zynqmp_props[] = {
171
DEFINE_PROP_BOOL("has_rpu", XlnxZynqMPState, has_rpu, false),
172
DEFINE_PROP_LINK("ddr-ram", XlnxZynqMPState, ddr_ram, TYPE_MEMORY_REGION,
173
MemoryRegion *),
174
+ DEFINE_PROP_LINK("canbus0", XlnxZynqMPState, canbus[0], TYPE_CAN_BUS,
175
+ CanBusState *),
176
+ DEFINE_PROP_LINK("canbus1", XlnxZynqMPState, canbus[1], TYPE_CAN_BUS,
177
+ CanBusState *),
178
DEFINE_PROP_END_OF_LIST()
179
};
180
91
--
181
--
92
2.19.2
182
2.20.1
93
183
94
184
diff view generated by jsdifflib
1
From: Steffen Görtz <contrib@steffen-goertz.de>
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
2
2
3
The test suite for the nRF51 GPIO peripheral for now
3
The QTests perform five tests on the Xilinx ZynqMP CAN controller:
4
only tests initial state. Additionally a set of
4
Tests the CAN controller in loopback, sleep and snoop mode.
5
tests testing an implementation detail of the model
5
Tests filtering of incoming CAN messages.
6
are included.
6
7
7
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
8
Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
8
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Message-id: 1597278668-339715-4-git-send-email-fnu.vikram@xilinx.com
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
10
[PMM: updated to meson build system]
11
Message-id: 20190103091119.9367-8-stefanha@redhat.com
12
[PMM: fixed stray space at start of file]
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
12
---
15
tests/Makefile.include | 2 +
13
tests/qtest/xlnx-can-test.c | 359 ++++++++++++++++++++++++++++++++++++
16
tests/microbit-test.c | 160 +++++++++++++++++++++++++++++++++++++++++
14
tests/qtest/meson.build | 1 +
17
2 files changed, 162 insertions(+)
15
2 files changed, 360 insertions(+)
18
create mode 100644 tests/microbit-test.c
16
create mode 100644 tests/qtest/xlnx-can-test.c
19
17
20
diff --git a/tests/Makefile.include b/tests/Makefile.include
18
diff --git a/tests/qtest/xlnx-can-test.c b/tests/qtest/xlnx-can-test.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/tests/Makefile.include
23
+++ b/tests/Makefile.include
24
@@ -XXX,XX +XXX,XX @@ check-qtest-sparc64-y += tests/boot-serial-test$(EXESUF)
25
check-qtest-arm-y += tests/tmp105-test$(EXESUF)
26
check-qtest-arm-y += tests/pca9552-test$(EXESUF)
27
check-qtest-arm-y += tests/ds1338-test$(EXESUF)
28
+check-qtest-arm-y += tests/microbit-test$(EXESUF)
29
check-qtest-arm-y += tests/m25p80-test$(EXESUF)
30
check-qtest-arm-y += tests/virtio-blk-test$(EXESUF)
31
check-qtest-arm-y += tests/test-arm-mptimer$(EXESUF)
32
@@ -XXX,XX +XXX,XX @@ tests/pxe-test$(EXESUF): tests/pxe-test.o tests/boot-sector.o $(libqos-obj-y)
33
tests/tmp105-test$(EXESUF): tests/tmp105-test.o $(libqos-omap-obj-y)
34
tests/pca9552-test$(EXESUF): tests/pca9552-test.o $(libqos-omap-obj-y)
35
tests/ds1338-test$(EXESUF): tests/ds1338-test.o $(libqos-imx-obj-y)
36
+tests/microbit-test$(EXESUF): tests/microbit-test.o
37
tests/m25p80-test$(EXESUF): tests/m25p80-test.o
38
tests/i440fx-test$(EXESUF): tests/i440fx-test.o $(libqos-pc-obj-y)
39
tests/q35-test$(EXESUF): tests/q35-test.o $(libqos-pc-obj-y)
40
diff --git a/tests/microbit-test.c b/tests/microbit-test.c
41
new file mode 100644
19
new file mode 100644
42
index XXXXXXX..XXXXXXX
20
index XXXXXXX..XXXXXXX
43
--- /dev/null
21
--- /dev/null
44
+++ b/tests/microbit-test.c
22
+++ b/tests/qtest/xlnx-can-test.c
45
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@
46
+/*
24
+/*
47
+ * QTest testcase for Microbit board using the Nordic Semiconductor nRF51 SoC.
25
+ * QTests for the Xilinx ZynqMP CAN controller.
48
+ *
26
+ *
49
+ * nRF51:
27
+ * Copyright (c) 2020 Xilinx Inc.
50
+ * Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.pdf
28
+ *
51
+ * Product Spec: http://infocenter.nordicsemi.com/pdf/nRF51822_PS_v3.1.pdf
29
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
52
+ *
30
+ *
53
+ * Microbit Board: http://microbit.org/
31
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
54
+ *
32
+ * of this software and associated documentation files (the "Software"), to deal
55
+ * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
33
+ * in the Software without restriction, including without limitation the rights
56
+ *
34
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
57
+ * This code is licensed under the GPL version 2 or later. See
35
+ * copies of the Software, and to permit persons to whom the Software is
58
+ * the COPYING file in the top-level directory.
36
+ * furnished to do so, subject to the following conditions:
37
+ *
38
+ * The above copyright notice and this permission notice shall be included in
39
+ * all copies or substantial portions of the Software.
40
+ *
41
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
42
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
43
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
44
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
45
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
46
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
47
+ * THE SOFTWARE.
59
+ */
48
+ */
60
+
49
+
61
+
62
+#include "qemu/osdep.h"
50
+#include "qemu/osdep.h"
63
+#include "exec/hwaddr.h"
51
+#include "libqos/libqtest.h"
64
+#include "libqtest.h"
52
+
65
+
53
+/* Base address. */
66
+#include "hw/arm/nrf51.h"
54
+#define CAN0_BASE_ADDR 0xFF060000
67
+#include "hw/gpio/nrf51_gpio.h"
55
+#define CAN1_BASE_ADDR 0xFF070000
68
+
56
+
69
+static void test_nrf51_gpio(void)
57
+/* Register addresses. */
70
+{
58
+#define R_SRR_OFFSET 0x00
71
+ size_t i;
59
+#define R_MSR_OFFSET 0x04
72
+ uint32_t actual, expected;
60
+#define R_SR_OFFSET 0x18
73
+
61
+#define R_ISR_OFFSET 0x1C
74
+ struct {
62
+#define R_ICR_OFFSET 0x24
75
+ hwaddr addr;
63
+#define R_TXID_OFFSET 0x30
76
+ uint32_t expected;
64
+#define R_TXDLC_OFFSET 0x34
77
+ } const reset_state[] = {
65
+#define R_TXDATA1_OFFSET 0x38
78
+ {NRF51_GPIO_REG_OUT, 0x00000000}, {NRF51_GPIO_REG_OUTSET, 0x00000000},
66
+#define R_TXDATA2_OFFSET 0x3C
79
+ {NRF51_GPIO_REG_OUTCLR, 0x00000000}, {NRF51_GPIO_REG_IN, 0x00000000},
67
+#define R_RXID_OFFSET 0x50
80
+ {NRF51_GPIO_REG_DIR, 0x00000000}, {NRF51_GPIO_REG_DIRSET, 0x00000000},
68
+#define R_RXDLC_OFFSET 0x54
81
+ {NRF51_GPIO_REG_DIRCLR, 0x00000000}
69
+#define R_RXDATA1_OFFSET 0x58
82
+ };
70
+#define R_RXDATA2_OFFSET 0x5C
83
+
71
+#define R_AFR 0x60
84
+ /* Check reset state */
72
+#define R_AFMR1 0x64
85
+ for (i = 0; i < ARRAY_SIZE(reset_state); i++) {
73
+#define R_AFIR1 0x68
86
+ expected = reset_state[i].expected;
74
+#define R_AFMR2 0x6C
87
+ actual = readl(NRF51_GPIO_BASE + reset_state[i].addr);
75
+#define R_AFIR2 0x70
88
+ g_assert_cmpuint(actual, ==, expected);
76
+#define R_AFMR3 0x74
77
+#define R_AFIR3 0x78
78
+#define R_AFMR4 0x7C
79
+#define R_AFIR4 0x80
80
+
81
+/* CAN modes. */
82
+#define CONFIG_MODE 0x00
83
+#define NORMAL_MODE 0x00
84
+#define LOOPBACK_MODE 0x02
85
+#define SNOOP_MODE 0x04
86
+#define SLEEP_MODE 0x01
87
+#define ENABLE_CAN (1 << 1)
88
+#define STATUS_NORMAL_MODE (1 << 3)
89
+#define STATUS_LOOPBACK_MODE (1 << 1)
90
+#define STATUS_SNOOP_MODE (1 << 12)
91
+#define STATUS_SLEEP_MODE (1 << 2)
92
+#define ISR_TXOK (1 << 1)
93
+#define ISR_RXOK (1 << 4)
94
+
95
+static void match_rx_tx_data(uint32_t *buf_tx, uint32_t *buf_rx,
96
+ uint8_t can_timestamp)
97
+{
98
+ uint16_t size = 0;
99
+ uint8_t len = 4;
100
+
101
+ while (size < len) {
102
+ if (R_RXID_OFFSET + 4 * size == R_RXDLC_OFFSET) {
103
+ g_assert_cmpint(buf_rx[size], ==, buf_tx[size] + can_timestamp);
104
+ } else {
105
+ g_assert_cmpint(buf_rx[size], ==, buf_tx[size]);
106
+ }
107
+
108
+ size++;
89
+ }
109
+ }
90
+
110
+}
91
+ for (i = 0; i < NRF51_GPIO_PINS; i++) {
111
+
92
+ expected = 0x00000002;
112
+static void read_data(QTestState *qts, uint64_t can_base_addr, uint32_t *buf_rx)
93
+ actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START + i * 4);
113
+{
94
+ g_assert_cmpuint(actual, ==, expected);
114
+ uint32_t int_status;
95
+ }
115
+
96
+
116
+ /* Read the interrupt on CAN rx. */
97
+ /* Check dir bit consistency between dir and cnf */
117
+ int_status = qtest_readl(qts, can_base_addr + R_ISR_OFFSET) & ISR_RXOK;
98
+ /* Check set via DIRSET */
118
+
99
+ expected = 0x80000001;
119
+ g_assert_cmpint(int_status, ==, ISR_RXOK);
100
+ writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIRSET, expected);
120
+
101
+ actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIR);
121
+ /* Read the RX register data for CAN. */
102
+ g_assert_cmpuint(actual, ==, expected);
122
+ buf_rx[0] = qtest_readl(qts, can_base_addr + R_RXID_OFFSET);
103
+ actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START) & 0x01;
123
+ buf_rx[1] = qtest_readl(qts, can_base_addr + R_RXDLC_OFFSET);
104
+ g_assert_cmpuint(actual, ==, 0x01);
124
+ buf_rx[2] = qtest_readl(qts, can_base_addr + R_RXDATA1_OFFSET);
105
+ actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_END) & 0x01;
125
+ buf_rx[3] = qtest_readl(qts, can_base_addr + R_RXDATA2_OFFSET);
106
+ g_assert_cmpuint(actual, ==, 0x01);
126
+
107
+
127
+ /* Clear the RX interrupt. */
108
+ /* Check clear via DIRCLR */
128
+ qtest_writel(qts, CAN1_BASE_ADDR + R_ICR_OFFSET, ISR_RXOK);
109
+ writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIRCLR, 0x80000001);
129
+}
110
+ actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIR);
130
+
111
+ g_assert_cmpuint(actual, ==, 0x00000000);
131
+static void send_data(QTestState *qts, uint64_t can_base_addr, uint32_t *buf_tx)
112
+ actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START) & 0x01;
132
+{
113
+ g_assert_cmpuint(actual, ==, 0x00);
133
+ uint32_t int_status;
114
+ actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_END) & 0x01;
134
+
115
+ g_assert_cmpuint(actual, ==, 0x00);
135
+ /* Write the TX register data for CAN. */
116
+
136
+ qtest_writel(qts, can_base_addr + R_TXID_OFFSET, buf_tx[0]);
117
+ /* Check set via DIR */
137
+ qtest_writel(qts, can_base_addr + R_TXDLC_OFFSET, buf_tx[1]);
118
+ expected = 0x80000001;
138
+ qtest_writel(qts, can_base_addr + R_TXDATA1_OFFSET, buf_tx[2]);
119
+ writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIR, expected);
139
+ qtest_writel(qts, can_base_addr + R_TXDATA2_OFFSET, buf_tx[3]);
120
+ actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIR);
140
+
121
+ g_assert_cmpuint(actual, ==, expected);
141
+ /* Read the interrupt on CAN for tx. */
122
+ actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START) & 0x01;
142
+ int_status = qtest_readl(qts, can_base_addr + R_ISR_OFFSET) & ISR_TXOK;
123
+ g_assert_cmpuint(actual, ==, 0x01);
143
+
124
+ actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_END) & 0x01;
144
+ g_assert_cmpint(int_status, ==, ISR_TXOK);
125
+ g_assert_cmpuint(actual, ==, 0x01);
145
+
126
+
146
+ /* Clear the interrupt for tx. */
127
+ /* Reset DIR */
147
+ qtest_writel(qts, CAN0_BASE_ADDR + R_ICR_OFFSET, ISR_TXOK);
128
+ writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIR, 0x00000000);
148
+}
129
+
149
+
130
+ /* Check Input propagates */
150
+/*
131
+ writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0x00);
151
+ * This test will be transferring data from CAN0 and CAN1 through canbus. CAN0
132
+ qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, 0);
152
+ * initiate the data transfer to can-bus, CAN1 receives the data. Test compares
133
+ actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
153
+ * the data sent from CAN0 with received on CAN1.
134
+ g_assert_cmpuint(actual, ==, 0x00);
154
+ */
135
+ qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, 1);
155
+static void test_can_bus(void)
136
+ actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
156
+{
137
+ g_assert_cmpuint(actual, ==, 0x01);
157
+ uint32_t buf_tx[4] = { 0xFF, 0x80000000, 0x12345678, 0x87654321 };
138
+ qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, -1);
158
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
139
+ actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
159
+ uint32_t status = 0;
140
+ g_assert_cmpuint(actual, ==, 0x01);
160
+ uint8_t can_timestamp = 1;
141
+ writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0x02);
161
+
142
+
162
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
143
+ /* Check pull-up working */
163
+ " -object can-bus,id=canbus0"
144
+ qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, 0);
164
+ " -machine xlnx-zcu102.canbus0=canbus0"
145
+ writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b0000);
165
+ " -machine xlnx-zcu102.canbus1=canbus0"
146
+ actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
166
+ );
147
+ g_assert_cmpuint(actual, ==, 0x00);
167
+
148
+ writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b1110);
168
+ /* Configure the CAN0 and CAN1. */
149
+ actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
169
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
150
+ g_assert_cmpuint(actual, ==, 0x01);
170
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
151
+ writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0x02);
171
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
152
+
172
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
153
+ /* Check pull-down working */
173
+
154
+ qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, 1);
174
+ /* Check here if CAN0 and CAN1 are in normal mode. */
155
+ writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b0000);
175
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
156
+ actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
176
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
157
+ g_assert_cmpuint(actual, ==, 0x01);
177
+
158
+ writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b0110);
178
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
159
+ actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
179
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
160
+ g_assert_cmpuint(actual, ==, 0x00);
180
+
161
+ writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0x02);
181
+ send_data(qts, CAN0_BASE_ADDR, buf_tx);
162
+ qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, -1);
182
+
163
+
183
+ read_data(qts, CAN1_BASE_ADDR, buf_rx);
164
+ /* Check Output propagates */
184
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
165
+ irq_intercept_out("/machine/nrf51");
185
+
166
+ writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b0011);
186
+ qtest_quit(qts);
167
+ writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_OUTSET, 0x01);
187
+}
168
+ g_assert_true(get_irq(0));
188
+
169
+ writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_OUTCLR, 0x01);
189
+/*
170
+ g_assert_false(get_irq(0));
190
+ * This test is performing loopback mode on CAN0 and CAN1. Data sent from TX of
171
+
191
+ * each CAN0 and CAN1 are compared with RX register data for respective CAN.
172
+ /* Check self-stimulation */
192
+ */
173
+ writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b01);
193
+static void test_can_loopback(void)
174
+ writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_OUTSET, 0x01);
194
+{
175
+ actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
195
+ uint32_t buf_tx[4] = { 0xFF, 0x80000000, 0x12345678, 0x87654321 };
176
+ g_assert_cmpuint(actual, ==, 0x01);
196
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
177
+
197
+ uint32_t status = 0;
178
+ writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_OUTCLR, 0x01);
198
+
179
+ actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
199
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
180
+ g_assert_cmpuint(actual, ==, 0x00);
200
+ " -object can-bus,id=canbus0"
201
+ " -machine xlnx-zcu102.canbus0=canbus0"
202
+ " -machine xlnx-zcu102.canbus1=canbus0"
203
+ );
204
+
205
+ /* Configure the CAN0 in loopback mode. */
206
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
207
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, LOOPBACK_MODE);
208
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
209
+
210
+ /* Check here if CAN0 is set in loopback mode. */
211
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
212
+
213
+ g_assert_cmpint(status, ==, STATUS_LOOPBACK_MODE);
214
+
215
+ send_data(qts, CAN0_BASE_ADDR, buf_tx);
216
+ read_data(qts, CAN0_BASE_ADDR, buf_rx);
217
+ match_rx_tx_data(buf_tx, buf_rx, 0);
218
+
219
+ /* Configure the CAN1 in loopback mode. */
220
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
221
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, LOOPBACK_MODE);
222
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
223
+
224
+ /* Check here if CAN1 is set in loopback mode. */
225
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
226
+
227
+ g_assert_cmpint(status, ==, STATUS_LOOPBACK_MODE);
228
+
229
+ send_data(qts, CAN1_BASE_ADDR, buf_tx);
230
+ read_data(qts, CAN1_BASE_ADDR, buf_rx);
231
+ match_rx_tx_data(buf_tx, buf_rx, 0);
232
+
233
+ qtest_quit(qts);
234
+}
235
+
236
+/*
237
+ * Enable filters for CAN1. This will filter incoming messages with ID. In this
238
+ * test message will pass through filter 2.
239
+ */
240
+static void test_can_filter(void)
241
+{
242
+ uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
243
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
244
+ uint32_t status = 0;
245
+ uint8_t can_timestamp = 1;
246
+
247
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
248
+ " -object can-bus,id=canbus0"
249
+ " -machine xlnx-zcu102.canbus0=canbus0"
250
+ " -machine xlnx-zcu102.canbus1=canbus0"
251
+ );
252
+
253
+ /* Configure the CAN0 and CAN1. */
254
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
255
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
256
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
257
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
258
+
259
+ /* Check here if CAN0 and CAN1 are in normal mode. */
260
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
261
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
262
+
263
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
264
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
265
+
266
+ /* Set filter for CAN1 for incoming messages. */
267
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFR, 0x0);
268
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR1, 0xF7);
269
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR1, 0x121F);
270
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR2, 0x5431);
271
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR2, 0x14);
272
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR3, 0x1234);
273
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR3, 0x5431);
274
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR4, 0xFFF);
275
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR4, 0x1234);
276
+
277
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFR, 0xF);
278
+
279
+ send_data(qts, CAN0_BASE_ADDR, buf_tx);
280
+
281
+ read_data(qts, CAN1_BASE_ADDR, buf_rx);
282
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
283
+
284
+ qtest_quit(qts);
285
+}
286
+
287
+/* Testing sleep mode on CAN0 while CAN1 is in normal mode. */
288
+static void test_can_sleepmode(void)
289
+{
290
+ uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
291
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
292
+ uint32_t status = 0;
293
+ uint8_t can_timestamp = 1;
294
+
295
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
296
+ " -object can-bus,id=canbus0"
297
+ " -machine xlnx-zcu102.canbus0=canbus0"
298
+ " -machine xlnx-zcu102.canbus1=canbus0"
299
+ );
300
+
301
+ /* Configure the CAN0. */
302
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
303
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, SLEEP_MODE);
304
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
305
+
306
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
307
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
308
+
309
+ /* Check here if CAN0 is in SLEEP mode and CAN1 in normal mode. */
310
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
311
+ g_assert_cmpint(status, ==, STATUS_SLEEP_MODE);
312
+
313
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
314
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
315
+
316
+ send_data(qts, CAN1_BASE_ADDR, buf_tx);
181
+
317
+
182
+ /*
318
+ /*
183
+ * Check short-circuit - generates an guest_error which must be checked
319
+ * Once CAN1 sends data on can-bus. CAN0 should exit sleep mode.
184
+ * manually as long as qtest can not scan qemu_log messages
320
+ * Check the CAN0 status now. It should exit the sleep mode and receive the
321
+ * incoming data.
185
+ */
322
+ */
186
+ writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b01);
323
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
187
+ writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_OUTSET, 0x01);
324
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
188
+ qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, 0);
325
+
326
+ read_data(qts, CAN0_BASE_ADDR, buf_rx);
327
+
328
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
329
+
330
+ qtest_quit(qts);
331
+}
332
+
333
+/* Testing Snoop mode on CAN0 while CAN1 is in normal mode. */
334
+static void test_can_snoopmode(void)
335
+{
336
+ uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
337
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
338
+ uint32_t status = 0;
339
+ uint8_t can_timestamp = 1;
340
+
341
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
342
+ " -object can-bus,id=canbus0"
343
+ " -machine xlnx-zcu102.canbus0=canbus0"
344
+ " -machine xlnx-zcu102.canbus1=canbus0"
345
+ );
346
+
347
+ /* Configure the CAN0. */
348
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
349
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, SNOOP_MODE);
350
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
351
+
352
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
353
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
354
+
355
+ /* Check here if CAN0 is in SNOOP mode and CAN1 in normal mode. */
356
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
357
+ g_assert_cmpint(status, ==, STATUS_SNOOP_MODE);
358
+
359
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
360
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
361
+
362
+ send_data(qts, CAN1_BASE_ADDR, buf_tx);
363
+
364
+ read_data(qts, CAN0_BASE_ADDR, buf_rx);
365
+
366
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
367
+
368
+ qtest_quit(qts);
189
+}
369
+}
190
+
370
+
191
+int main(int argc, char **argv)
371
+int main(int argc, char **argv)
192
+{
372
+{
193
+ int ret;
194
+
195
+ g_test_init(&argc, &argv, NULL);
373
+ g_test_init(&argc, &argv, NULL);
196
+
374
+
197
+ global_qtest = qtest_initf("-machine microbit");
375
+ qtest_add_func("/net/can/can_bus", test_can_bus);
198
+
376
+ qtest_add_func("/net/can/can_loopback", test_can_loopback);
199
+ qtest_add_func("/microbit/nrf51/gpio", test_nrf51_gpio);
377
+ qtest_add_func("/net/can/can_filter", test_can_filter);
200
+
378
+ qtest_add_func("/net/can/can_test_snoopmode", test_can_snoopmode);
201
+ ret = g_test_run();
379
+ qtest_add_func("/net/can/can_test_sleepmode", test_can_sleepmode);
202
+
380
+
203
+ qtest_quit(global_qtest);
381
+ return g_test_run();
204
+ return ret;
382
+}
205
+}
383
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
384
index XXXXXXX..XXXXXXX 100644
385
--- a/tests/qtest/meson.build
386
+++ b/tests/qtest/meson.build
387
@@ -XXX,XX +XXX,XX @@ qtests_aarch64 = \
388
(config_all_devices.has_key('CONFIG_TPM_TIS_SYSBUS') ? ['tpm-tis-device-swtpm-test'] : []) + \
389
['numa-test',
390
'boot-serial-test',
391
+ 'xlnx-can-test',
392
'migration-test']
393
394
qtests_s390x = \
206
--
395
--
207
2.19.2
396
2.20.1
208
397
209
398
diff view generated by jsdifflib
1
From: Thomas Huth <thuth@redhat.com>
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
2
2
3
Some of the files in hw/input/, hw/misc/ and hw/timer/ are only
3
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
4
used by one of the ARM machines, so we can assign these files to
4
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
5
the corresponding boards.
5
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
6
6
Message-id: 1597278668-339715-5-git-send-email-fnu.vikram@xilinx.com
7
Signed-off-by: Thomas Huth <thuth@redhat.com>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Message-id: 1546433583-18397-1-git-send-email-thuth@redhat.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
8
---
12
MAINTAINERS | 16 ++++++++++++++--
9
MAINTAINERS | 8 ++++++++
13
1 file changed, 14 insertions(+), 2 deletions(-)
10
1 file changed, 8 insertions(+)
14
11
15
diff --git a/MAINTAINERS b/MAINTAINERS
12
diff --git a/MAINTAINERS b/MAINTAINERS
16
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
17
--- a/MAINTAINERS
14
--- a/MAINTAINERS
18
+++ b/MAINTAINERS
15
+++ b/MAINTAINERS
19
@@ -XXX,XX +XXX,XX @@ F: hw/intc/arm*
16
@@ -XXX,XX +XXX,XX @@ F: hw/net/opencores_eth.c
20
F: hw/intc/gic_internal.h
17
21
F: hw/misc/a9scu.c
18
Devices
22
F: hw/misc/arm11scu.c
19
-------
23
+F: hw/misc/arm_l2x0.c
20
+Xilinx CAN
24
F: hw/timer/a9gtimer*
21
+M: Vikram Garhwal <fnu.vikram@xilinx.com>
25
F: hw/timer/arm*
22
+M: Francisco Iglesias <francisco.iglesias@xilinx.com>
26
F: include/hw/arm/arm*.h
23
+S: Maintained
27
@@ -XXX,XX +XXX,XX @@ L: qemu-arm@nongnu.org
24
+F: hw/net/can/xlnx-*
25
+F: include/hw/net/xlnx-*
26
+F: tests/qtest/xlnx-can-test*
27
+
28
EDU
29
M: Jiri Slaby <jslaby@suse.cz>
28
S: Maintained
30
S: Maintained
29
F: hw/arm/integratorcp.c
30
F: hw/misc/arm_integrator_debug.c
31
+F: include/hw/misc/arm_integrator_debug.h
32
33
MCIMX6UL EVK / i.MX6ul
34
M: Peter Maydell <peter.maydell@linaro.org>
35
@@ -XXX,XX +XXX,XX @@ L: qemu-arm@nongnu.org
36
S: Odd Fixes
37
F: hw/arm/mcimx7d-sabre.c
38
F: hw/arm/fsl-imx7.c
39
+F: hw/misc/imx7_*.c
40
F: include/hw/arm/fsl-imx7.h
41
+F: include/hw/misc/imx7_*.h
42
F: hw/pci-host/designware.c
43
F: include/hw/pci-host/designware.h
44
45
@@ -XXX,XX +XXX,XX @@ M: Peter Maydell <peter.maydell@linaro.org>
46
L: qemu-arm@nongnu.org
47
S: Odd Fixes
48
F: hw/arm/nseries.c
49
+F: hw/input/lm832x.c
50
+F: hw/input/tsc2005.c
51
+F: hw/misc/cbus.c
52
+F: hw/timer/twl92230.c
53
54
Palm
55
M: Andrzej Zaborowski <balrogg@gmail.com>
56
@@ -XXX,XX +XXX,XX @@ M: Peter Maydell <peter.maydell@linaro.org>
57
L: qemu-arm@nongnu.org
58
S: Odd Fixes
59
F: hw/arm/palm.c
60
+F: hw/input/tsc210x.c
61
62
Raspberry Pi
63
M: Peter Maydell <peter.maydell@linaro.org>
64
@@ -XXX,XX +XXX,XX @@ F: hw/display/tc6393xb.c
65
F: hw/gpio/max7310.c
66
F: hw/gpio/zaurus.c
67
F: hw/misc/mst_fpga.c
68
+F: hw/misc/max111x.c
69
F: include/hw/arm/pxa.h
70
F: include/hw/arm/sharpsl.h
71
72
@@ -XXX,XX +XXX,XX @@ L: qemu-arm@nongnu.org
73
S: Odd Fixes
74
F: hw/arm/sabrelite.c
75
F: hw/arm/fsl-imx6.c
76
-F: hw/misc/imx6_src.c
77
+F: hw/misc/imx6_*.c
78
F: hw/ssi/imx_spi.c
79
F: include/hw/arm/fsl-imx6.h
80
-F: include/hw/misc/imx6_src.h
81
+F: include/hw/misc/imx6_*.h
82
F: include/hw/ssi/imx_spi.h
83
84
Sharp SL-5500 (Collie) PDA
85
@@ -XXX,XX +XXX,XX @@ R: Joel Stanley <joel@jms.id.au>
86
L: qemu-arm@nongnu.org
87
S: Maintained
88
F: hw/*/*aspeed*
89
+F: hw/misc/pca9552.c
90
F: include/hw/*/*aspeed*
91
+F: include/hw/misc/pca9552*.h
92
F: hw/net/ftgmac100.c
93
F: include/hw/net/ftgmac100.h
94
95
--
31
--
96
2.19.2
32
2.20.1
97
33
98
34
diff view generated by jsdifflib