1
ARM queue for 2.10: all M profile bugfixes...
1
target-arm queue: the big things here are the new nRF51
2
(microbit) devices and Luc's gdbstub multiprocess work.
2
3
3
thanks
4
thanks
4
-- PMM
5
-- PMM
5
6
6
The following changes since commit 25dd0e77898c3e10796d4cbeb35e8af5ba6ce975:
7
The following changes since commit a29644590f95166c8a13e5797f8e7701134b31d0:
7
8
8
Merge remote-tracking branch 'remotes/mjt/tags/trivial-patches-fetch' into staging (2017-07-31 11:27:43 +0100)
9
Merge remote-tracking branch 'remotes/ericb/tags/pull-nbd-2019-01-05' into staging (2019-01-07 11:55:52 +0000)
9
10
10
are available in the git repository at:
11
are available in the Git repository at:
11
12
12
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20170731
13
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20190107
13
14
14
for you to fetch changes up to 89cbc3778a3d61761e2231e740269218c9a8a41d:
15
for you to fetch changes up to f831f955d420966471f5f8b316ba50d2523b1ff0:
15
16
16
hw/mps2_scc: fix incorrect properties (2017-07-31 13:11:56 +0100)
17
Support u-boot noload images for arm as used by, NetBSD/evbarm GENERIC kernel. (2019-01-07 15:46:20 +0000)
17
18
18
----------------------------------------------------------------
19
----------------------------------------------------------------
19
target-arm queue:
20
target-arm queue:
20
* fix broken properties on MPS2 SCC device
21
* Support u-boot 'noload' images for Arm (as used by NetBSD/evbarm GENERIC kernel)
21
* fix MPU trace handling of write vs exec
22
* hw/misc/tz-mpc: Fix value of BLK_MAX register
22
* fix MPU M profile bugs:
23
* target/arm: Emit barriers for A32/T32 load-acquire/store-release insns
23
- not handling system space or PPB region correctly
24
* nRF51 SoC: add timer, GPIO, RNG peripherals
24
- not resetting state
25
* hw/arm/allwinner-a10: Add the 'A' SRAM and the SRAM controller
25
- not migrating MPU_RNR
26
* cpus.c: Fix race condition in cpu_stop_current()
27
* hw/arm: versal: Plug memory leaks
28
* Allow M profile boards to run even if -kernel not specified
29
* gdbstub: Add multiprocess extension support for use when the
30
board has multiple CPUs of different types (like the Xilinx Zynq boards)
31
* target/arm: Don't decode S bit in SVE brk[ab] merging insns
32
* target/arm: Convert ARM_TBFLAG_* to FIELDs
26
33
27
----------------------------------------------------------------
34
----------------------------------------------------------------
28
Peter Maydell (6):
35
Edgar E. Iglesias (1):
29
target/arm: Correct MPU trace handling of write vs execute
36
hw/arm: versal: Plug memory leaks
30
target/arm: Don't do MPU lookups for addresses in M profile PPB region
37
31
target/arm: Don't allow guest to make System space executable for M profile
38
Luc Michel (16):
32
target/arm: Rename cp15.c6_rgnr to pmsav7.rnr
39
hw/cpu: introduce CPU clusters
33
target/arm: Move PMSAv7 reset into arm_cpu_reset() so M profile MPUs get reset
40
gdbstub: introduce GDB processes
34
target/arm: Migrate MPU_RNR register state for M profile cores
41
gdbstub: add multiprocess support to '?' packets
42
gdbstub: add multiprocess support to 'H' and 'T' packets
43
gdbstub: add multiprocess support to vCont packets
44
gdbstub: add multiprocess support to 'sC' packets
45
gdbstub: add multiprocess support to (f|s)ThreadInfo and ThreadExtraInfo
46
gdbstub: add multiprocess support to Xfer:features:read:
47
gdbstub: add multiprocess support to gdb_vm_state_change()
48
gdbstub: add multiprocess support to 'D' packets
49
gdbstub: add support for extended mode packet
50
gdbstub: add support for vAttach packets
51
gdbstub: processes initialization on new peer connection
52
gdbstub: gdb_set_stop_cpu: ignore request when process is not attached
53
gdbstub: add multiprocess extension support
54
arm/xlnx-zynqmp: put APUs and RPUs in separate CPU clusters
55
56
Nick Hudson (1):
57
Support u-boot noload images for arm as used by, NetBSD/evbarm GENERIC kernel.
58
59
Peter Maydell (3):
60
cpus.c: Fix race condition in cpu_stop_current()
61
target/arm: Emit barriers for A32/T32 load-acquire/store-release insns
62
hw/misc/tz-mpc: Fix value of BLK_MAX register
35
63
36
Philippe Mathieu-Daudé (1):
64
Philippe Mathieu-Daudé (1):
37
hw/mps2_scc: fix incorrect properties
65
hw/arm/allwinner-a10: Add the 'A' SRAM and the SRAM controller
38
66
39
target/arm/cpu.h | 3 +--
67
Richard Henderson (2):
40
hw/intc/armv7m_nvic.c | 14 +++++-----
68
target/arm: Convert ARM_TBFLAG_* to FIELDs
41
hw/misc/mps2-scc.c | 4 +--
69
target/arm: SVE brk[ab] merging does not have s bit
42
target/arm/cpu.c | 14 ++++++++++
43
target/arm/helper.c | 71 ++++++++++++++++++++++++++++++++++-----------------
44
target/arm/machine.c | 30 +++++++++++++++++++++-
45
6 files changed, 101 insertions(+), 35 deletions(-)
46
70
71
Stefan Hajnoczi (1):
72
Revert "armv7m: Guard against no -kernel argument"
73
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
Almost all of the PMSAv7 state is in the pmsav7 substruct of
1
From: Richard Henderson <richard.henderson@linaro.org>
2
the ARM CPU state structure. The exception is the region
2
3
number register, which is in cp15.c6_rgnr. This exception
3
Use "register" TBFLAG_ANY to indicate shared state between
4
is a bit odd for M profile, which otherwise generally does
4
A32 and A64, and "registers" TBFLAG_A32 & TBFLAG_A64 for
5
not store state in the cp15 substruct.
5
fields that are specific to the given cpu state.
6
6
7
Rename cp15.c6_rgnr to pmsav7.rnr accordingly.
7
Move ARM_TBFLAG_BE_DATA to shared state, instead of its current
8
8
placement within "Bit usage when in AArch32 state".
9
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.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>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Message-id: 1501153150-19984-4-git-send-email-peter.maydell@linaro.org
12
---
16
---
13
target/arm/cpu.h | 3 +--
17
target/arm/cpu.h | 102 ++++++++-----------------------------
14
hw/intc/armv7m_nvic.c | 14 +++++++-------
18
target/arm/helper.c | 49 +++++++++---------
15
target/arm/helper.c | 6 +++---
19
target/arm/translate-a64.c | 22 ++++----
16
target/arm/machine.c | 2 +-
20
target/arm/translate.c | 40 ++++++++-------
17
4 files changed, 12 insertions(+), 13 deletions(-)
21
4 files changed, 78 insertions(+), 135 deletions(-)
18
22
19
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
23
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
20
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/cpu.h
25
--- a/target/arm/cpu.h
22
+++ b/target/arm/cpu.h
26
+++ b/target/arm/cpu.h
23
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
27
@@ -XXX,XX +XXX,XX @@ static inline bool arm_cpu_data_is_big_endian(CPUARMState *env)
24
uint64_t par_el[4];
28
* We put flags which are shared between 32 and 64 bit mode at the top
25
};
29
* of the word, and flags which apply to only one mode at the bottom.
26
30
*/
27
- uint32_t c6_rgnr;
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)
28
-
101
-
29
uint32_t c9_insn; /* Cache lockdown registers. */
102
-/* some convenience accessor macros */
30
uint32_t c9_data;
103
-#define ARM_TBFLAG_AARCH64_STATE(F) \
31
uint64_t c9_pmcr; /* performance monitor control register */
104
- (((F) & ARM_TBFLAG_AARCH64_STATE_MASK) >> ARM_TBFLAG_AARCH64_STATE_SHIFT)
32
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
105
-#define ARM_TBFLAG_MMUIDX(F) \
33
uint32_t *drbar;
106
- (((F) & ARM_TBFLAG_MMUIDX_MASK) >> ARM_TBFLAG_MMUIDX_SHIFT)
34
uint32_t *drsr;
107
-#define ARM_TBFLAG_SS_ACTIVE(F) \
35
uint32_t *dracr;
108
- (((F) & ARM_TBFLAG_SS_ACTIVE_MASK) >> ARM_TBFLAG_SS_ACTIVE_SHIFT)
36
+ uint32_t rnr;
109
-#define ARM_TBFLAG_PSTATE_SS(F) \
37
} pmsav7;
110
- (((F) & ARM_TBFLAG_PSTATE_SS_MASK) >> ARM_TBFLAG_PSTATE_SS_SHIFT)
38
111
-#define ARM_TBFLAG_FPEXC_EL(F) \
39
void *nvic;
112
- (((F) & ARM_TBFLAG_FPEXC_EL_MASK) >> ARM_TBFLAG_FPEXC_EL_SHIFT)
40
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
113
-#define ARM_TBFLAG_THUMB(F) \
41
index XXXXXXX..XXXXXXX 100644
114
- (((F) & ARM_TBFLAG_THUMB_MASK) >> ARM_TBFLAG_THUMB_SHIFT)
42
--- a/hw/intc/armv7m_nvic.c
115
-#define ARM_TBFLAG_VECLEN(F) \
43
+++ b/hw/intc/armv7m_nvic.c
116
- (((F) & ARM_TBFLAG_VECLEN_MASK) >> ARM_TBFLAG_VECLEN_SHIFT)
44
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset)
117
-#define ARM_TBFLAG_VECSTRIDE(F) \
45
case 0xd94: /* MPU_CTRL */
118
- (((F) & ARM_TBFLAG_VECSTRIDE_MASK) >> ARM_TBFLAG_VECSTRIDE_SHIFT)
46
return cpu->env.v7m.mpu_ctrl;
119
-#define ARM_TBFLAG_VFPEN(F) \
47
case 0xd98: /* MPU_RNR */
120
- (((F) & ARM_TBFLAG_VFPEN_MASK) >> ARM_TBFLAG_VFPEN_SHIFT)
48
- return cpu->env.cp15.c6_rgnr;
121
-#define ARM_TBFLAG_CONDEXEC(F) \
49
+ return cpu->env.pmsav7.rnr;
122
- (((F) & ARM_TBFLAG_CONDEXEC_MASK) >> ARM_TBFLAG_CONDEXEC_SHIFT)
50
case 0xd9c: /* MPU_RBAR */
123
-#define ARM_TBFLAG_SCTLR_B(F) \
51
case 0xda4: /* MPU_RBAR_A1 */
124
- (((F) & ARM_TBFLAG_SCTLR_B_MASK) >> ARM_TBFLAG_SCTLR_B_SHIFT)
52
case 0xdac: /* MPU_RBAR_A2 */
125
-#define ARM_TBFLAG_XSCALE_CPAR(F) \
53
case 0xdb4: /* MPU_RBAR_A3 */
126
- (((F) & ARM_TBFLAG_XSCALE_CPAR_MASK) >> ARM_TBFLAG_XSCALE_CPAR_SHIFT)
54
{
127
-#define ARM_TBFLAG_NS(F) \
55
- int region = cpu->env.cp15.c6_rgnr;
128
- (((F) & ARM_TBFLAG_NS_MASK) >> ARM_TBFLAG_NS_SHIFT)
56
+ int region = cpu->env.pmsav7.rnr;
129
-#define ARM_TBFLAG_BE_DATA(F) \
57
130
- (((F) & ARM_TBFLAG_BE_DATA_MASK) >> ARM_TBFLAG_BE_DATA_SHIFT)
58
if (region >= cpu->pmsav7_dregion) {
131
-#define ARM_TBFLAG_HANDLER(F) \
59
return 0;
132
- (((F) & ARM_TBFLAG_HANDLER_MASK) >> ARM_TBFLAG_HANDLER_SHIFT)
60
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset)
133
-#define ARM_TBFLAG_STACKCHECK(F) \
61
case 0xdb0: /* MPU_RASR_A2 */
134
- (((F) & ARM_TBFLAG_STACKCHECK_MASK) >> ARM_TBFLAG_STACKCHECK_SHIFT)
62
case 0xdb8: /* MPU_RASR_A3 */
135
-#define ARM_TBFLAG_TBI0(F) \
63
{
136
- (((F) & ARM_TBFLAG_TBI0_MASK) >> ARM_TBFLAG_TBI0_SHIFT)
64
- int region = cpu->env.cp15.c6_rgnr;
137
-#define ARM_TBFLAG_TBI1(F) \
65
+ int region = cpu->env.pmsav7.rnr;
138
- (((F) & ARM_TBFLAG_TBI1_MASK) >> ARM_TBFLAG_TBI1_SHIFT)
66
139
-#define ARM_TBFLAG_SVEEXC_EL(F) \
67
if (region >= cpu->pmsav7_dregion) {
140
- (((F) & ARM_TBFLAG_SVEEXC_EL_MASK) >> ARM_TBFLAG_SVEEXC_EL_SHIFT)
68
return 0;
141
-#define ARM_TBFLAG_ZCR_LEN(F) \
69
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
142
- (((F) & ARM_TBFLAG_ZCR_LEN_MASK) >> ARM_TBFLAG_ZCR_LEN_SHIFT)
70
PRIu32 "/%" PRIu32 "\n",
143
+FIELD(TBFLAG_A64, TBI0, 0, 1)
71
value, cpu->pmsav7_dregion);
144
+FIELD(TBFLAG_A64, TBI1, 1, 1)
72
} else {
145
+FIELD(TBFLAG_A64, SVEEXC_EL, 2, 2)
73
- cpu->env.cp15.c6_rgnr = value;
146
+FIELD(TBFLAG_A64, ZCR_LEN, 4, 4)
74
+ cpu->env.pmsav7.rnr = value;
147
75
}
148
static inline bool bswap_code(bool sctlr_b)
76
break;
149
{
77
case 0xd9c: /* MPU_RBAR */
78
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
79
region, cpu->pmsav7_dregion);
80
return;
81
}
82
- cpu->env.cp15.c6_rgnr = region;
83
+ cpu->env.pmsav7.rnr = region;
84
} else {
85
- region = cpu->env.cp15.c6_rgnr;
86
+ region = cpu->env.pmsav7.rnr;
87
}
88
89
if (region >= cpu->pmsav7_dregion) {
90
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
91
case 0xdb0: /* MPU_RASR_A2 */
92
case 0xdb8: /* MPU_RASR_A3 */
93
{
94
- int region = cpu->env.cp15.c6_rgnr;
95
+ int region = cpu->env.pmsav7.rnr;
96
97
if (region >= cpu->pmsav7_dregion) {
98
return;
99
diff --git a/target/arm/helper.c b/target/arm/helper.c
150
diff --git a/target/arm/helper.c b/target/arm/helper.c
100
index XXXXXXX..XXXXXXX 100644
151
index XXXXXXX..XXXXXXX 100644
101
--- a/target/arm/helper.c
152
--- a/target/arm/helper.c
102
+++ b/target/arm/helper.c
153
+++ b/target/arm/helper.c
103
@@ -XXX,XX +XXX,XX @@ static uint64_t pmsav7_read(CPUARMState *env, const ARMCPRegInfo *ri)
154
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
104
return 0;
155
ARMMMUIdx mmu_idx = core_to_arm_mmu_idx(env, cpu_mmu_index(env, false));
105
}
156
int current_el = arm_current_el(env);
106
157
int fp_el = fp_exception_el(env, current_el);
107
- u32p += env->cp15.c6_rgnr;
158
- uint32_t flags;
108
+ u32p += env->pmsav7.rnr;
159
+ uint32_t flags = 0;
109
return *u32p;
160
110
}
161
if (is_a64(env)) {
111
162
ARMCPU *cpu = arm_env_get_cpu(env);
112
@@ -XXX,XX +XXX,XX @@ static void pmsav7_write(CPUARMState *env, const ARMCPRegInfo *ri,
163
113
return;
164
*pc = env->pc;
114
}
165
- flags = ARM_TBFLAG_AARCH64_STATE_MASK;
115
166
+ flags = FIELD_DP32(flags, TBFLAG_ANY, AARCH64_STATE, 1);
116
- u32p += env->cp15.c6_rgnr;
167
/* Get control bits for tagged addresses */
117
+ u32p += env->pmsav7.rnr;
168
- flags |= (arm_regime_tbi0(env, mmu_idx) << ARM_TBFLAG_TBI0_SHIFT);
118
tlb_flush(CPU(cpu)); /* Mappings may have changed - purge! */
169
- flags |= (arm_regime_tbi1(env, mmu_idx) << ARM_TBFLAG_TBI1_SHIFT);
119
*u32p = value;
170
+ flags = FIELD_DP32(flags, TBFLAG_A64, TBI0,
120
}
171
+ arm_regime_tbi0(env, mmu_idx));
121
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo pmsav7_cp_reginfo[] = {
172
+ flags = FIELD_DP32(flags, TBFLAG_A64, TBI1,
122
.readfn = pmsav7_read, .writefn = pmsav7_write, .resetfn = pmsav7_reset },
173
+ arm_regime_tbi1(env, mmu_idx));
123
{ .name = "RGNR", .cp = 15, .crn = 6, .opc1 = 0, .crm = 2, .opc2 = 0,
174
124
.access = PL1_RW,
175
if (cpu_isar_feature(aa64_sve, cpu)) {
125
- .fieldoffset = offsetof(CPUARMState, cp15.c6_rgnr),
176
int sve_el = sve_exception_el(env, current_el);
126
+ .fieldoffset = offsetof(CPUARMState, pmsav7.rnr),
177
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
127
.writefn = pmsav7_rgnr_write },
178
} else {
128
REGINFO_SENTINEL
179
zcr_len = sve_zcr_len_for_el(env, current_el);
129
};
180
}
130
diff --git a/target/arm/machine.c b/target/arm/machine.c
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
}
186
} else {
187
*pc = env->regs[15];
188
- flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT)
189
- | (env->vfp.vec_len << ARM_TBFLAG_VECLEN_SHIFT)
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
}
211
212
- flags |= (arm_to_core_mmu_idx(mmu_idx) << ARM_TBFLAG_MMUIDX_SHIFT);
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
131
index XXXXXXX..XXXXXXX 100644
258
index XXXXXXX..XXXXXXX 100644
132
--- a/target/arm/machine.c
259
--- a/target/arm/translate-a64.c
133
+++ b/target/arm/machine.c
260
+++ b/target/arm/translate-a64.c
134
@@ -XXX,XX +XXX,XX @@ static bool pmsav7_rgnr_vmstate_validate(void *opaque, int version_id)
261
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
135
{
262
DisasContext *dc = container_of(dcbase, DisasContext, base);
136
ARMCPU *cpu = opaque;
263
CPUARMState *env = cpu->env_ptr;
137
264
ARMCPU *arm_cpu = arm_env_get_cpu(env);
138
- return cpu->env.cp15.c6_rgnr < cpu->pmsav7_dregion;
265
- int bound;
139
+ return cpu->env.pmsav7.rnr < cpu->pmsav7_dregion;
266
+ uint32_t tb_flags = dc->base.tb->flags;
140
}
267
+ int bound, core_mmu_idx;
141
268
142
static const VMStateDescription vmstate_pmsav7 = {
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
143
--
391
--
144
2.7.4
392
2.19.2
145
393
146
394
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
While brk[ab] zeroing has a flags setting option, the merging variant
4
does not. Retain the same argument structure, to share expansion but
5
force the flag zero and do not decode bit 22.
6
7
Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20181226215003.31438-1-richard.henderson@linaro.org
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
target/arm/sve.decode | 5 +++--
14
1 file changed, 3 insertions(+), 2 deletions(-)
15
16
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/sve.decode
19
+++ b/target/arm/sve.decode
20
@@ -XXX,XX +XXX,XX @@
21
22
# Two operand with governing predicate, flags setting
23
@pd_pg_pn_s ........ . s:1 ...... .. pg:4 . rn:4 . rd:4 &rpr_s
24
+@pd_pg_pn_s0 ........ . . ...... .. pg:4 . rn:4 . rd:4 &rpr_s s=0
25
26
# Three operand with unused vector element size
27
@rd_rn_rm_e0 ........ ... rm:5 ... ... rn:5 rd:5 &rrr_esz esz=0
28
@@ -XXX,XX +XXX,XX @@ BRKPB 00100101 0. 00 .... 11 .... 0 .... 1 .... @pd_pg_pn_pm_s
29
# SVE partition break condition
30
BRKA_z 00100101 0. 01000001 .... 0 .... 0 .... @pd_pg_pn_s
31
BRKB_z 00100101 1. 01000001 .... 0 .... 0 .... @pd_pg_pn_s
32
-BRKA_m 00100101 0. 01000001 .... 0 .... 1 .... @pd_pg_pn_s
33
-BRKB_m 00100101 1. 01000001 .... 0 .... 1 .... @pd_pg_pn_s
34
+BRKA_m 00100101 00 01000001 .... 0 .... 1 .... @pd_pg_pn_s0
35
+BRKB_m 00100101 10 01000001 .... 0 .... 1 .... @pd_pg_pn_s0
36
37
# SVE propagate break to next partition
38
BRKN 00100101 0. 01100001 .... 0 .... 0 .... @pd_pg_pn_s
39
--
40
2.19.2
41
42
diff view generated by jsdifflib
New patch
1
From: Luc Michel <luc.michel@greensocs.com>
1
2
3
This commit adds the cpu-cluster type. It aims at gathering CPUs from
4
the same cluster in a machine.
5
6
For now it only has a `cluster-id` property.
7
8
Documentation in cluster.h written with the help of Peter Maydell.
9
10
Signed-off-by: Luc Michel <luc.michel@greensocs.com>
11
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
12
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
13
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
14
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
15
Message-id: 20181207090135.7651-2-luc.michel@greensocs.com
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
hw/cpu/Makefile.objs | 2 +-
19
include/hw/cpu/cluster.h | 58 ++++++++++++++++++++++++++++++++++++++++
20
hw/cpu/cluster.c | 50 ++++++++++++++++++++++++++++++++++
21
MAINTAINERS | 2 ++
22
4 files changed, 111 insertions(+), 1 deletion(-)
23
create mode 100644 include/hw/cpu/cluster.h
24
create mode 100644 hw/cpu/cluster.c
25
26
diff --git a/hw/cpu/Makefile.objs b/hw/cpu/Makefile.objs
27
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/cpu/Makefile.objs
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
38
index XXXXXXX..XXXXXXX
39
--- /dev/null
40
+++ b/include/hw/cpu/cluster.h
41
@@ -XXX,XX +XXX,XX @@
42
+/*
43
+ * QEMU CPU cluster
44
+ *
45
+ * Copyright (c) 2018 GreenSocs SAS
46
+ *
47
+ * This program is free software; you can redistribute it and/or
48
+ * modify it under the terms of the GNU General Public License
49
+ * as published by the Free Software Foundation; either version 2
50
+ * of the License, or (at your option) any later version.
51
+ *
52
+ * This program is distributed in the hope that it will be useful,
53
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
54
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
55
+ * GNU General Public License 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
+ */
61
+#ifndef HW_CPU_CLUSTER_H
62
+#define HW_CPU_CLUSTER_H
63
+
64
+#include "qemu/osdep.h"
65
+#include "hw/qdev.h"
66
+
67
+/*
68
+ * CPU Cluster type
69
+ *
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
+ */
79
+
80
+#define TYPE_CPU_CLUSTER "cpu-cluster"
81
+#define CPU_CLUSTER(obj) \
82
+ OBJECT_CHECK(CPUClusterState, (obj), TYPE_CPU_CLUSTER)
83
+
84
+/**
85
+ * CPUClusterState:
86
+ * @cluster_id: The cluster ID. This value is for internal use only and should
87
+ * not be exposed directly to the user or to the guest.
88
+ *
89
+ * State of a CPU cluster.
90
+ */
91
+typedef struct CPUClusterState {
92
+ /*< private >*/
93
+ DeviceState parent_obj;
94
+
95
+ /*< public >*/
96
+ uint32_t cluster_id;
97
+} CPUClusterState;
98
+
99
+#endif
100
diff --git a/hw/cpu/cluster.c b/hw/cpu/cluster.c
101
new file mode 100644
102
index XXXXXXX..XXXXXXX
103
--- /dev/null
104
+++ b/hw/cpu/cluster.c
105
@@ -XXX,XX +XXX,XX @@
106
+/*
107
+ * QEMU CPU cluster
108
+ *
109
+ * Copyright (c) 2018 GreenSocs SAS
110
+ *
111
+ * This program is free software; you can redistribute it and/or
112
+ * modify it under the terms of the GNU General Public License
113
+ * as published by the Free Software Foundation; either version 2
114
+ * of the License, or (at your option) any later version.
115
+ *
116
+ * This program is distributed in the hope that it will be useful,
117
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
118
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
119
+ * GNU General Public License 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
+ */
125
+
126
+#include "qemu/osdep.h"
127
+#include "hw/cpu/cluster.h"
128
+#include "qapi/error.h"
129
+#include "qemu/module.h"
130
+
131
+static Property cpu_cluster_properties[] = {
132
+ DEFINE_PROP_UINT32("cluster-id", CPUClusterState, cluster_id, 0),
133
+ DEFINE_PROP_END_OF_LIST()
134
+};
135
+
136
+static void cpu_cluster_class_init(ObjectClass *klass, void *data)
137
+{
138
+ DeviceClass *dc = DEVICE_CLASS(klass);
139
+
140
+ dc->props = cpu_cluster_properties;
141
+}
142
+
143
+static const TypeInfo cpu_cluster_type_info = {
144
+ .name = TYPE_CPU_CLUSTER,
145
+ .parent = TYPE_DEVICE,
146
+ .instance_size = sizeof(CPUClusterState),
147
+ .class_init = cpu_cluster_class_init,
148
+};
149
+
150
+static void cpu_cluster_register_types(void)
151
+{
152
+ type_register_static(&cpu_cluster_type_info);
153
+}
154
+
155
+type_init(cpu_cluster_register_types)
156
diff --git a/MAINTAINERS b/MAINTAINERS
157
index XXXXXXX..XXXXXXX 100644
158
--- a/MAINTAINERS
159
+++ b/MAINTAINERS
160
@@ -XXX,XX +XXX,XX @@ M: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
161
S: Supported
162
F: hw/core/machine.c
163
F: hw/core/null-machine.c
164
+F: hw/cpu/cluster.c
165
F: include/hw/boards.h
166
+F: include/hw/cpu/cluster.h
167
T: git https://github.com/ehabkost/qemu.git machine-next
168
169
Xtensa Machines
170
--
171
2.19.2
172
173
diff view generated by jsdifflib
New patch
1
From: Luc Michel <luc.michel@greensocs.com>
1
2
3
Add a structure GDBProcess that represents processes from the GDB
4
semantic point of view.
5
6
CPUs can be split into different processes, by grouping them under
7
different cpu-cluster objects. Each occurrence of a cpu-cluster object
8
implies the existence of the corresponding process in the GDB stub. The
9
GDB process ID is derived from the corresponding cluster ID as follows:
10
11
GDB PID = cluster ID + 1
12
13
This is because PIDs -1 and 0 are reserved in GDB and cannot be used by
14
processes.
15
16
A default process is created to handle CPUs that are not in a cluster.
17
This process gets the PID of the last process PID + 1.
18
19
Signed-off-by: Luc Michel <luc.michel@greensocs.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>
26
---
27
gdbstub.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
28
1 file changed, 97 insertions(+)
29
30
diff --git a/gdbstub.c b/gdbstub.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/gdbstub.c
33
+++ b/gdbstub.c
34
@@ -XXX,XX +XXX,XX @@
35
#include "chardev/char-fe.h"
36
#include "sysemu/sysemu.h"
37
#include "exec/gdbstub.h"
38
+#include "hw/cpu/cluster.h"
39
#endif
40
41
#define MAX_PACKET_LENGTH 4096
42
@@ -XXX,XX +XXX,XX @@ typedef struct GDBRegisterState {
43
struct GDBRegisterState *next;
44
} GDBRegisterState;
45
46
+typedef struct GDBProcess {
47
+ uint32_t pid;
48
+ bool attached;
49
+} GDBProcess;
50
+
51
enum RSState {
52
RS_INACTIVE,
53
RS_IDLE,
54
@@ -XXX,XX +XXX,XX @@ typedef struct GDBState {
55
CharBackend chr;
56
Chardev *mon_chr;
57
#endif
58
+ bool multiprocess;
59
+ GDBProcess *processes;
60
+ int process_num;
61
char syscall_buf[256];
62
gdb_syscall_complete_cb current_syscall_cb;
63
} GDBState;
64
@@ -XXX,XX +XXX,XX @@ void gdb_exit(CPUArchState *env, int code)
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
+{
75
+ GDBProcess *process;
76
+ int max_pid = 0;
77
+
78
+ if (s->process_num) {
79
+ max_pid = s->processes[s->process_num - 1].pid;
80
+ }
81
+
82
+ s->processes = g_renew(GDBProcess, s->processes, ++s->process_num);
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
+}
91
+
92
#ifdef CONFIG_USER_ONLY
93
int
94
gdb_handlesig(CPUState *cpu, int sig)
95
@@ -XXX,XX +XXX,XX @@ static bool gdb_accept(void)
96
s = g_malloc0(sizeof(GDBState));
97
s->c_cpu = first_cpu;
98
s->g_cpu = first_cpu;
99
+ create_default_process(s);
100
s->fd = fd;
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
};
106
107
+static int find_cpu_clusters(Object *child, void *opaque)
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
--
186
2.19.2
187
188
diff view generated by jsdifflib
New patch
1
From: Luc Michel <luc.michel@greensocs.com>
1
2
3
The gdb_get_cpu_pid() function does the PID lookup for the given CPU. It
4
checks if the CPU is a direct child of a CPU cluster. If it is, the
5
returned PID is the cluster ID plus one (cluster IDs start at 0, GDB
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
9
The gdb_fmt_thread_id() function generates the string to be used to identify
10
a given thread, in a response packet for the peer. This function
11
supports generating thread IDs when multiprocess mode is enabled (in the
12
form `p<pid>.<tid>').
13
14
Use them in the reply to a '?' request.
15
16
Signed-off-by: Luc Michel <luc.michel@greensocs.com>
17
Acked-by: Alistair Francis <alistair.francis@wdc.com>
18
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
19
Message-id: 20181207090135.7651-4-luc.michel@greensocs.com
20
[PMM: fixed checkpatch blockquote style nit]
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
---
23
gdbstub.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
24
1 file changed, 64 insertions(+), 2 deletions(-)
25
26
diff --git a/gdbstub.c b/gdbstub.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/gdbstub.c
29
+++ b/gdbstub.c
30
@@ -XXX,XX +XXX,XX @@ static int memtox(char *buf, const char *mem, int len)
31
return p - buf;
32
}
33
34
+static uint32_t gdb_get_cpu_pid(const GDBState *s, CPUState *cpu)
35
+{
36
+#ifndef CONFIG_USER_ONLY
37
+ gchar *path, *name = NULL;
38
+ Object *obj;
39
+ CPUClusterState *cluster;
40
+ uint32_t ret;
41
+
42
+ path = object_get_canonical_path(OBJECT(cpu));
43
+
44
+ if (path == NULL) {
45
+ /* Return the default process' PID */
46
+ ret = s->processes[s->process_num - 1].pid;
47
+ goto out;
48
+ }
49
+
50
+ name = object_get_canonical_path_component(OBJECT(cpu));
51
+ assert(name != NULL);
52
+
53
+ /*
54
+ * Retrieve the CPU parent path by removing the last '/' and the CPU name
55
+ * from the CPU canonical path.
56
+ */
57
+ path[strlen(path) - strlen(name) - 1] = '\0';
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
+ }
66
+
67
+ cluster = CPU_CLUSTER(obj);
68
+ ret = cluster->cluster_id + 1;
69
+
70
+out:
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
+}
81
+
82
static const char *get_feature_xml(const char *p, const char **newp,
83
CPUClass *cc)
84
{
85
@@ -XXX,XX +XXX,XX @@ static CPUState *find_cpu(uint32_t thread_id)
86
return NULL;
87
}
88
89
+static char *gdb_fmt_thread_id(const GDBState *s, CPUState *cpu,
90
+ char *buf, size_t buf_size)
91
+{
92
+ if (s->multiprocess) {
93
+ snprintf(buf, buf_size, "p%02x.%02x",
94
+ gdb_get_cpu_pid(s, cpu), cpu_gdb_index(cpu));
95
+ } else {
96
+ snprintf(buf, buf_size, "%02x", cpu_gdb_index(cpu));
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
--
125
2.19.2
126
127
diff view generated by jsdifflib
New patch
1
1
From: Luc Michel <luc.michel@greensocs.com>
2
3
Add a couple of helper functions to cope with GDB threads and processes.
4
5
The gdb_get_process() function looks for a process given a pid.
6
7
The gdb_get_cpu() function returns the CPU corresponding to the (pid,
8
tid) pair given as parameters.
9
10
The read_thread_id() function parses the thread-id sent by the peer.
11
This function supports the multiprocess extension thread-id syntax. The
12
return value specifies if the parsing failed, or if a special case was
13
encountered (all processes or all threads).
14
15
Use them in 'H' and 'T' packets handling to support the multiprocess
16
extension.
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>
24
---
25
gdbstub.c | 154 +++++++++++++++++++++++++++++++++++++++++++++++-------
26
1 file changed, 136 insertions(+), 18 deletions(-)
27
28
diff --git a/gdbstub.c b/gdbstub.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/gdbstub.c
31
+++ b/gdbstub.c
32
@@ -XXX,XX +XXX,XX @@ out:
33
#endif
34
}
35
36
+static GDBProcess *gdb_get_process(const GDBState *s, uint32_t pid)
37
+{
38
+ int i;
39
+
40
+ if (!pid) {
41
+ /* 0 means any process, we take the first one */
42
+ return &s->processes[0];
43
+ }
44
+
45
+ for (i = 0; i < s->process_num; i++) {
46
+ if (s->processes[i].pid == pid) {
47
+ return &s->processes[i];
48
+ }
49
+ }
50
+
51
+ return NULL;
52
+}
53
+
54
+static GDBProcess *gdb_get_cpu_process(const GDBState *s, CPUState *cpu)
55
+{
56
+ return gdb_get_process(s, gdb_get_cpu_pid(s, cpu));
57
+}
58
+
59
+static CPUState *find_cpu(uint32_t thread_id)
60
+{
61
+ CPUState *cpu;
62
+
63
+ CPU_FOREACH(cpu) {
64
+ if (cpu_gdb_index(cpu) == thread_id) {
65
+ return cpu;
66
+ }
67
+ }
68
+
69
+ return NULL;
70
+}
71
+
72
+static CPUState *gdb_get_cpu(const GDBState *s, uint32_t pid, uint32_t tid)
73
+{
74
+ GDBProcess *process;
75
+ CPUState *cpu;
76
+
77
+ if (!tid) {
78
+ /* 0 means any thread, we take the first one */
79
+ tid = 1;
80
+ }
81
+
82
+ cpu = find_cpu(tid);
83
+
84
+ if (cpu == NULL) {
85
+ return NULL;
86
+ }
87
+
88
+ process = gdb_get_cpu_process(s, cpu);
89
+
90
+ if (process->pid != pid) {
91
+ return NULL;
92
+ }
93
+
94
+ if (!process->attached) {
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
+ }
148
+
149
+ /* Skip '.' */
150
+ buf++;
151
+ } else {
152
+ p = 1;
153
+ }
154
+
155
+ ret = qemu_strtoul(buf, &buf, 16, &t);
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
+ }
212
+
213
+ if (thread_kind != GDB_ONE_THREAD) {
214
put_packet(s, "OK");
215
break;
216
}
217
- cpu = find_cpu(thread);
218
+ cpu = gdb_get_cpu(s, pid, tid);
219
if (cpu == NULL) {
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
+ }
233
+ cpu = gdb_get_cpu(s, pid, tid);
234
235
if (cpu != NULL) {
236
put_packet(s, "OK");
237
--
238
2.19.2
239
240
diff view generated by jsdifflib
New patch
1
From: Luc Michel <luc.michel@greensocs.com>
1
2
3
Add the gdb_first_attached_cpu() and gdb_next_attached_cpu() to iterate
4
over all the CPUs in currently attached processes.
5
6
Add the gdb_first_cpu_in_process() and gdb_next_cpu_in_process() to
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
24
--- a/gdbstub.c
25
+++ b/gdbstub.c
26
@@ -XXX,XX +XXX,XX @@ static CPUState *find_cpu(uint32_t thread_id)
27
return NULL;
28
}
29
30
+static CPUState *get_first_cpu_in_process(const GDBState *s,
31
+ GDBProcess *process)
32
+{
33
+ CPUState *cpu;
34
+
35
+ CPU_FOREACH(cpu) {
36
+ if (gdb_get_cpu_pid(s, cpu) == process->pid) {
37
+ return cpu;
38
+ }
39
+ }
40
+
41
+ return NULL;
42
+}
43
+
44
+static CPUState *gdb_next_cpu_in_process(const GDBState *s, CPUState *cpu)
45
+{
46
+ uint32_t pid = gdb_get_cpu_pid(s, cpu);
47
+ cpu = CPU_NEXT(cpu);
48
+
49
+ while (cpu) {
50
+ if (gdb_get_cpu_pid(s, cpu) == pid) {
51
+ break;
52
+ }
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
{
62
GDBProcess *process;
63
@@ -XXX,XX +XXX,XX @@ static CPUState *gdb_get_cpu(const GDBState *s, uint32_t pid, uint32_t tid)
64
return cpu;
65
}
66
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
--
185
2.19.2
186
187
diff view generated by jsdifflib
New patch
1
From: Luc Michel <luc.michel@greensocs.com>
1
2
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
New patch
1
From: Luc Michel <luc.michel@greensocs.com>
1
2
3
Change the thread info related packets handling to support multiprocess
4
extension.
5
6
Add the CPUs class name in the extra info to help differentiate
7
them in multiprocess mode.
8
9
Signed-off-by: Luc Michel <luc.michel@greensocs.com>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
12
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
13
Message-id: 20181207090135.7651-8-luc.michel@greensocs.com
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
16
gdbstub.c | 37 +++++++++++++++++++++++++++----------
17
1 file changed, 27 insertions(+), 10 deletions(-)
18
19
diff --git a/gdbstub.c b/gdbstub.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/gdbstub.c
22
+++ b/gdbstub.c
23
@@ -XXX,XX +XXX,XX @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
24
CPUState *cpu;
25
CPUClass *cc;
26
const char *p;
27
- uint32_t thread;
28
uint32_t pid, tid;
29
int ch, reg_size, type, res;
30
uint8_t mem_buf[MAX_PACKET_LENGTH];
31
@@ -XXX,XX +XXX,XX @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
32
put_packet(s, buf);
33
break;
34
} else if (strcmp(p,"fThreadInfo") == 0) {
35
- s->query_cpu = first_cpu;
36
+ s->query_cpu = gdb_first_attached_cpu(s);
37
goto report_cpuinfo;
38
} else if (strcmp(p,"sThreadInfo") == 0) {
39
report_cpuinfo:
40
if (s->query_cpu) {
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
+
66
+ if (s->multiprocess && (s->process_num > 1)) {
67
+ /* Print the CPU model and name in multiprocess mode */
68
+ ObjectClass *oc = object_get_class(OBJECT(cpu));
69
+ const char *cpu_model = object_class_get_name(oc);
70
+ char *cpu_name =
71
+ object_get_canonical_path_component(OBJECT(cpu));
72
+ len = snprintf((char *)mem_buf, sizeof(buf) / 2,
73
+ "%s %s [%s]", cpu_model, cpu_name,
74
+ cpu->halted ? "halted " : "running");
75
+ g_free(cpu_name);
76
+ } else {
77
+ /* memtohex() doubles the required space */
78
+ len = snprintf((char *)mem_buf, sizeof(buf) / 2,
79
+ "CPU#%d [%s]", cpu->cpu_index,
80
+ cpu->halted ? "halted " : "running");
81
+ }
82
trace_gdbstub_op_extra_info((char *)mem_buf);
83
memtohex(buf, mem_buf, len);
84
put_packet(s, buf);
85
--
86
2.19.2
87
88
diff view generated by jsdifflib
New patch
1
From: Luc Michel <luc.michel@greensocs.com>
1
2
3
Change the Xfer:features:read: packet handling to support the
4
multiprocess extension. This packet is used to request the XML
5
description of the CPU. In multiprocess mode, different descriptions can
6
be sent for different processes.
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>
20
---
21
gdbstub.c | 52 ++++++++++++++++++++++++++++++----------------------
22
1 file changed, 30 insertions(+), 22 deletions(-)
23
24
diff --git a/gdbstub.c b/gdbstub.c
25
index XXXXXXX..XXXXXXX 100644
26
--- a/gdbstub.c
27
+++ b/gdbstub.c
28
@@ -XXX,XX +XXX,XX @@ typedef struct GDBRegisterState {
29
typedef struct GDBProcess {
30
uint32_t pid;
31
bool attached;
32
+
33
+ char target_xml[1024];
34
} GDBProcess;
35
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
--
153
2.19.2
154
155
diff view generated by jsdifflib
New patch
1
From: Luc Michel <luc.michel@greensocs.com>
1
2
3
Add support for multiprocess extension in gdb_vm_state_change()
4
function.
5
6
Signed-off-by: Luc Michel <luc.michel@greensocs.com>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
9
Acked-by: Alistair Francis <alistair.francis@wdc.com>
10
Message-id: 20181207090135.7651-10-luc.michel@greensocs.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
gdbstub.c | 15 ++++++++++++---
14
1 file changed, 12 insertions(+), 3 deletions(-)
15
16
diff --git a/gdbstub.c b/gdbstub.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/gdbstub.c
19
+++ b/gdbstub.c
20
@@ -XXX,XX +XXX,XX @@ static void gdb_vm_state_change(void *opaque, int running, RunState state)
21
GDBState *s = gdbserver_state;
22
CPUState *cpu = s->c_cpu;
23
char buf[256];
24
+ char thread_id[16];
25
const char *type;
26
int ret;
27
28
@@ -XXX,XX +XXX,XX @@ static void gdb_vm_state_change(void *opaque, int running, RunState state)
29
put_packet(s, s->syscall_buf);
30
return;
31
}
32
+
33
+ if (cpu == NULL) {
34
+ /* No process attached */
35
+ return;
36
+ }
37
+
38
+ gdb_fmt_thread_id(s, cpu, thread_id, sizeof(thread_id));
39
+
40
switch (state) {
41
case RUN_STATE_DEBUG:
42
if (cpu->watchpoint_hit) {
43
@@ -XXX,XX +XXX,XX @@ static void gdb_vm_state_change(void *opaque, int running, RunState state)
44
trace_gdbstub_hit_watchpoint(type, cpu_gdb_index(cpu),
45
(target_ulong)cpu->watchpoint_hit->vaddr);
46
snprintf(buf, sizeof(buf),
47
- "T%02xthread:%02x;%swatch:" TARGET_FMT_lx ";",
48
- GDB_SIGNAL_TRAP, cpu_gdb_index(cpu), type,
49
+ "T%02xthread:%s;%swatch:" TARGET_FMT_lx ";",
50
+ GDB_SIGNAL_TRAP, thread_id, type,
51
(target_ulong)cpu->watchpoint_hit->vaddr);
52
cpu->watchpoint_hit = NULL;
53
goto send_packet;
54
@@ -XXX,XX +XXX,XX @@ static void gdb_vm_state_change(void *opaque, int running, RunState state)
55
break;
56
}
57
gdb_set_stop_cpu(cpu);
58
- snprintf(buf, sizeof(buf), "T%02xthread:%02x;", ret, cpu_gdb_index(cpu));
59
+ snprintf(buf, sizeof(buf), "T%02xthread:%s;", ret, thread_id);
60
61
send_packet:
62
put_packet(s, buf);
63
--
64
2.19.2
65
66
diff view generated by jsdifflib
New patch
1
From: Luc Michel <luc.michel@greensocs.com>
1
2
3
'D' packets are used by GDB to detach from a process. In multiprocess
4
mode, the PID to detach from is sent in the request.
5
6
Signed-off-by: Luc Michel <luc.michel@greensocs.com>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.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>
12
---
13
gdbstub.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++-------
14
1 file changed, 53 insertions(+), 7 deletions(-)
15
16
diff --git a/gdbstub.c b/gdbstub.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/gdbstub.c
19
+++ b/gdbstub.c
20
@@ -XXX,XX +XXX,XX @@ static int gdb_breakpoint_remove(target_ulong addr, target_ulong len, int type)
21
}
22
}
23
24
+static inline void gdb_cpu_breakpoint_remove_all(CPUState *cpu)
25
+{
26
+ cpu_breakpoint_remove_all(cpu, BP_GDB);
27
+#ifndef CONFIG_USER_ONLY
28
+ cpu_watchpoint_remove_all(cpu, BP_GDB);
29
+#endif
30
+}
31
+
32
+static void gdb_process_breakpoint_remove_all(const GDBState *s, GDBProcess *p)
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
{
44
CPUState *cpu;
45
@@ -XXX,XX +XXX,XX @@ static void gdb_breakpoint_remove_all(void)
46
}
47
48
CPU_FOREACH(cpu) {
49
- cpu_breakpoint_remove_all(cpu, BP_GDB);
50
-#ifndef CONFIG_USER_ONLY
51
- cpu_watchpoint_remove_all(cpu, BP_GDB);
52
-#endif
53
+ gdb_cpu_breakpoint_remove_all(cpu);
54
}
55
}
56
57
@@ -XXX,XX +XXX,XX @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
58
exit(0);
59
case 'D':
60
/* Detach packet */
61
- gdb_breakpoint_remove_all();
62
- gdb_syscall_mode = GDB_SYS_DISABLED;
63
- gdb_continue(s);
64
+ pid = 1;
65
+
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
--
102
2.19.2
103
104
diff view generated by jsdifflib
New patch
1
From: Luc Michel <luc.michel@greensocs.com>
1
2
3
Add support for the '!' extended mode packet. This is required for the
4
multiprocess extension.
5
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
Message-id: 20181207090135.7651-12-luc.michel@greensocs.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
gdbstub.c | 3 +++
13
1 file changed, 3 insertions(+)
14
15
diff --git a/gdbstub.c b/gdbstub.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/gdbstub.c
18
+++ b/gdbstub.c
19
@@ -XXX,XX +XXX,XX @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
20
p = line_buf;
21
ch = *p++;
22
switch(ch) {
23
+ case '!':
24
+ put_packet(s, "OK");
25
+ break;
26
case '?':
27
/* TODO: Make this return the correct value for user-mode. */
28
snprintf(buf, sizeof(buf), "T%02xthread:%s;", GDB_SIGNAL_TRAP,
29
--
30
2.19.2
31
32
diff view generated by jsdifflib
New patch
1
From: Luc Michel <luc.michel@greensocs.com>
1
2
3
Add support for the vAttach packets. In multiprocess mode, GDB sends
4
them to attach to additional processes.
5
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>
12
---
13
gdbstub.c | 35 +++++++++++++++++++++++++++++++++++
14
1 file changed, 35 insertions(+)
15
16
diff --git a/gdbstub.c b/gdbstub.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/gdbstub.c
19
+++ b/gdbstub.c
20
@@ -XXX,XX +XXX,XX @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
21
goto unknown_command;
22
}
23
break;
24
+ } else if (strncmp(p, "Attach;", 7) == 0) {
25
+ unsigned long pid;
26
+
27
+ p += 7;
28
+
29
+ if (qemu_strtoul(p, &p, 16, &pid)) {
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
--
63
2.19.2
64
65
diff view generated by jsdifflib
New patch
1
From: Luc Michel <luc.michel@greensocs.com>
1
2
3
When a new connection is established, we set the first process to be
4
attached, and the others detached. The first CPU of the first process
5
is selected as the current CPU.
6
7
Signed-off-by: Luc Michel <luc.michel@greensocs.com>
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
19
--- a/gdbstub.c
20
+++ b/gdbstub.c
21
@@ -XXX,XX +XXX,XX @@ static bool gdb_accept(void)
22
}
23
24
s = g_malloc0(sizeof(GDBState));
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
}
58
- s->c_cpu = first_cpu;
59
- s->g_cpu = first_cpu;
60
61
create_processes(s);
62
63
if (chr) {
64
qemu_chr_fe_init(&s->chr, chr, &error_abort);
65
qemu_chr_fe_set_handlers(&s->chr, gdb_chr_can_receive, gdb_chr_receive,
66
- gdb_chr_event, NULL, NULL, NULL, true);
67
+ gdb_chr_event, NULL, s, NULL, true);
68
}
69
s->state = chr ? RS_IDLE : RS_INACTIVE;
70
s->mon_chr = mon_chr;
71
--
72
2.19.2
73
74
diff view generated by jsdifflib
New patch
1
From: Luc Michel <luc.michel@greensocs.com>
1
2
3
When gdb_set_stop_cpu() is called with a CPU associated to a process
4
currently not attached by the GDB client, return without modifying the
5
stop CPU. Otherwise, GDB gets confused if it receives packets with a
6
thread-id it does not know about.
7
8
Signed-off-by: Luc Michel <luc.michel@greensocs.com>
9
Acked-by: Alistair Francis <alistair.francis@wdc.com>
10
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
11
Message-id: 20181207090135.7651-15-luc.michel@greensocs.com
12
[PMM: fix checkpatch comment style nit]
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
gdbstub.c | 10 ++++++++++
16
1 file changed, 10 insertions(+)
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
24
void gdb_set_stop_cpu(CPUState *cpu)
25
{
26
+ GDBProcess *p = gdb_get_cpu_process(gdbserver_state, cpu);
27
+
28
+ if (!p->attached) {
29
+ /*
30
+ * Having a stop CPU corresponding to a process that is not attached
31
+ * confuses GDB. So we ignore the request.
32
+ */
33
+ return;
34
+ }
35
+
36
gdbserver_state->c_cpu = cpu;
37
gdbserver_state->g_cpu = cpu;
38
}
39
--
40
2.19.2
41
42
diff view generated by jsdifflib
New patch
1
From: Luc Michel <luc.michel@greensocs.com>
1
2
3
Add multiprocess extension support by enabling multiprocess mode when
4
the peer requests it, and by replying that we actually support it in the
5
qSupported reply packet.
6
7
Signed-off-by: Luc Michel <luc.michel@greensocs.com>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Acked-by: Alistair Francis <alistair.francis@wdc.com>
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>
13
---
14
gdbstub.c | 6 ++++++
15
1 file changed, 6 insertions(+)
16
17
diff --git a/gdbstub.c b/gdbstub.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/gdbstub.c
20
+++ b/gdbstub.c
21
@@ -XXX,XX +XXX,XX @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
22
if (cc->gdb_core_xml_file != NULL) {
23
pstrcat(buf, sizeof(buf), ";qXfer:features:read+");
24
}
25
+
26
+ if (strstr(p, "multiprocess+")) {
27
+ s->multiprocess = true;
28
+ }
29
+ pstrcat(buf, sizeof(buf), ";multiprocess+");
30
+
31
put_packet(s, buf);
32
break;
33
}
34
--
35
2.19.2
36
37
diff view generated by jsdifflib
New patch
1
From: Luc Michel <luc.michel@greensocs.com>
1
2
3
Create two separate CPU clusters for APUs and RPUs.
4
5
Signed-off-by: Luc Michel <luc.michel@greensocs.com>
6
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Message-id: 20181207090135.7651-17-luc.michel@greensocs.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
include/hw/arm/xlnx-zynqmp.h | 3 +++
13
hw/arm/xlnx-zynqmp.c | 23 +++++++++++++++++++----
14
2 files changed, 22 insertions(+), 4 deletions(-)
15
16
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/xlnx-zynqmp.h
19
+++ b/include/hw/arm/xlnx-zynqmp.h
20
@@ -XXX,XX +XXX,XX @@
21
#include "hw/display/xlnx_dp.h"
22
#include "hw/intc/xlnx-zynqmp-ipi.h"
23
#include "hw/timer/xlnx-zynqmp-rtc.h"
24
+#include "hw/cpu/cluster.h"
25
26
#define TYPE_XLNX_ZYNQMP "xlnx,zynqmp"
27
#define XLNX_ZYNQMP(obj) OBJECT_CHECK(XlnxZynqMPState, (obj), \
28
@@ -XXX,XX +XXX,XX @@ typedef struct XlnxZynqMPState {
29
DeviceState parent_obj;
30
31
/*< public >*/
32
+ CPUClusterState apu_cluster;
33
+ CPUClusterState rpu_cluster;
34
ARMCPU apu_cpu[XLNX_ZYNQMP_NUM_APU_CPUS];
35
ARMCPU rpu_cpu[XLNX_ZYNQMP_NUM_RPU_CPUS];
36
GICState gic;
37
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/hw/arm/xlnx-zynqmp.c
40
+++ b/hw/arm/xlnx-zynqmp.c
41
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_create_rpu(XlnxZynqMPState *s, const char *boot_cpu,
42
int i;
43
int num_rpus = MIN(smp_cpus - XLNX_ZYNQMP_NUM_APU_CPUS, XLNX_ZYNQMP_NUM_RPU_CPUS);
44
45
+ object_initialize_child(OBJECT(s), "rpu-cluster", &s->rpu_cluster,
46
+ sizeof(s->rpu_cluster), TYPE_CPU_CLUSTER,
47
+ &error_abort, NULL);
48
+ qdev_prop_set_uint32(DEVICE(&s->rpu_cluster), "cluster-id", 1);
49
+
50
+ qdev_init_nofail(DEVICE(&s->rpu_cluster));
51
+
52
for (i = 0; i < num_rpus; i++) {
53
char *name;
54
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)
63
int i;
64
int num_apus = MIN(smp_cpus, XLNX_ZYNQMP_NUM_APU_CPUS);
65
66
+ object_initialize_child(obj, "apu-cluster", &s->apu_cluster,
67
+ sizeof(s->apu_cluster), TYPE_CPU_CLUSTER,
68
+ &error_abort, NULL);
69
+ qdev_prop_set_uint32(DEVICE(&s->apu_cluster), "cluster-id", 0);
70
+
71
for (i = 0; i < num_apus; i++) {
72
- object_initialize_child(obj, "apu-cpu[*]", &s->apu_cpu[i],
73
- sizeof(s->apu_cpu[i]),
74
- "cortex-a53-" TYPE_ARM_CPU, &error_abort, NULL);
75
+ object_initialize_child(OBJECT(&s->apu_cluster), "apu-cpu[*]",
76
+ &s->apu_cpu[i], sizeof(s->apu_cpu[i]),
77
+ "cortex-a53-" TYPE_ARM_CPU, &error_abort,
78
+ NULL);
79
}
80
81
sysbus_init_child_obj(obj, "gic", &s->gic, sizeof(s->gic),
82
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
83
qdev_prop_set_bit(DEVICE(&s->gic),
84
"has-virtualization-extensions", s->virt);
85
86
+ qdev_init_nofail(DEVICE(&s->apu_cluster));
87
+
88
/* Realize APUs before realizing the GIC. KVM requires this. */
89
for (i = 0; i < num_apus; i++) {
90
char *name;
91
--
92
2.19.2
93
94
diff view generated by jsdifflib
New patch
1
From: Stefan Hajnoczi <stefanha@redhat.com>
1
2
3
This reverts commit 01fd41ab3fb69971c24a69ed49cde96086d81278.
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>
17
---
18
hw/arm/armv7m.c | 5 -----
19
1 file changed, 5 deletions(-)
20
21
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/arm/armv7m.c
24
+++ b/hw/arm/armv7m.c
25
@@ -XXX,XX +XXX,XX @@ void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size)
26
big_endian = 0;
27
#endif
28
29
- if (!kernel_filename && !qtest_enabled()) {
30
- error_report("Guest image must be specified (using -kernel)");
31
- exit(1);
32
- }
33
-
34
if (arm_feature(&cpu->env, ARM_FEATURE_EL3)) {
35
asidx = ARMASIdx_S;
36
} else {
37
--
38
2.19.2
39
40
diff view generated by jsdifflib
New patch
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
1
2
3
Plug a couple of "board creation time" memory leaks.
4
5
Fixes: 6f16da53ffe4567 ("hw/arm: versal: Add a virtual Xilinx Versal board")
6
Reported-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.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>
12
---
13
hw/arm/xlnx-versal-virt.c | 2 ++
14
1 file changed, 2 insertions(+)
15
16
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/xlnx-versal-virt.c
19
+++ b/hw/arm/xlnx-versal-virt.c
20
@@ -XXX,XX +XXX,XX @@ static void fdt_add_gic_nodes(VersalVirt *s)
21
2, MM_GIC_APU_REDIST_0_SIZE);
22
qemu_fdt_setprop_cell(s->fdt, nodename, "#interrupt-cells", 3);
23
qemu_fdt_setprop_string(s->fdt, nodename, "compatible", "arm,gic-v3");
24
+ g_free(nodename);
25
}
26
27
static void fdt_add_timer_nodes(VersalVirt *s)
28
@@ -XXX,XX +XXX,XX @@ static void create_virtio_regions(VersalVirt *s)
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
--
37
2.19.2
38
39
diff view generated by jsdifflib
New patch
1
From: Thomas Huth <thuth@redhat.com>
1
2
3
Some of the files in hw/input/, hw/misc/ and hw/timer/ are only
4
used by one of the ARM machines, so we can assign these files to
5
the corresponding boards.
6
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>
11
---
12
MAINTAINERS | 16 ++++++++++++++--
13
1 file changed, 14 insertions(+), 2 deletions(-)
14
15
diff --git a/MAINTAINERS b/MAINTAINERS
16
index XXXXXXX..XXXXXXX 100644
17
--- a/MAINTAINERS
18
+++ b/MAINTAINERS
19
@@ -XXX,XX +XXX,XX @@ F: hw/intc/arm*
20
F: hw/intc/gic_internal.h
21
F: hw/misc/a9scu.c
22
F: hw/misc/arm11scu.c
23
+F: hw/misc/arm_l2x0.c
24
F: hw/timer/a9gtimer*
25
F: hw/timer/arm*
26
F: include/hw/arm/arm*.h
27
@@ -XXX,XX +XXX,XX @@ L: qemu-arm@nongnu.org
28
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
--
96
2.19.2
97
98
diff view generated by jsdifflib
1
The M profile PMSAv7 specification says that if the address being looked
1
We use cpu_stop_current() to ensure the current CPU has stopped
2
up is in the PPB region (0xe0000000 - 0xe00fffff) then we do not use
2
from places like qemu_system_reset_request(). Unfortunately its
3
the MPU regions but always use the default memory map. Implement this
3
current implementation has a race. It calls qemu_cpu_stop(),
4
(we were previously behaving like an R profile PMSAv7, which does not
4
which sets cpu->stopped to true even though the CPU hasn't
5
special case this).
5
actually stopped yet. The main thread will look at the flags
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
11
Instead, just set cpu->stop and call cpu_exit(). This will
12
cause the vcpu to exit back to the top level loop, and there
13
(as part of the wait_io_event code) it will call qemu_cpu_stop().
14
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.
6
18
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
20
Reviewed-by: Emilio G. Cota <cota@braap.org>
9
Message-id: 1501153150-19984-2-git-send-email-peter.maydell@linaro.org
21
Tested-by: Jaap Crezee <jaap@jcz.nl>
22
Message-id: 20181207155911.12710-1-peter.maydell@linaro.org
10
---
23
---
11
target/arm/helper.c | 17 ++++++++++++++++-
24
cpus.c | 3 ++-
12
1 file changed, 16 insertions(+), 1 deletion(-)
25
1 file changed, 2 insertions(+), 1 deletion(-)
13
26
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
27
diff --git a/cpus.c b/cpus.c
15
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
29
--- a/cpus.c
17
+++ b/target/arm/helper.c
30
+++ b/cpus.c
18
@@ -XXX,XX +XXX,XX @@ static bool pmsav7_use_background_region(ARMCPU *cpu,
31
@@ -XXX,XX +XXX,XX @@ void qemu_init_vcpu(CPUState *cpu)
32
void cpu_stop_current(void)
33
{
34
if (current_cpu) {
35
- qemu_cpu_stop(current_cpu, true);
36
+ current_cpu->stop = true;
37
+ cpu_exit(current_cpu);
19
}
38
}
20
}
39
}
21
40
22
+static inline bool m_is_ppb_region(CPUARMState *env, uint32_t address)
23
+{
24
+ /* True if address is in the M profile PPB region 0xe0000000 - 0xe00fffff */
25
+ return arm_feature(env, ARM_FEATURE_M) &&
26
+ extract32(address, 20, 12) == 0xe00;
27
+}
28
+
29
static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address,
30
int access_type, ARMMMUIdx mmu_idx,
31
hwaddr *phys_ptr, int *prot, uint32_t *fsr)
32
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address,
33
*phys_ptr = address;
34
*prot = 0;
35
36
- if (regime_translation_disabled(env, mmu_idx)) { /* MPU disabled */
37
+ if (regime_translation_disabled(env, mmu_idx) ||
38
+ m_is_ppb_region(env, address)) {
39
+ /* MPU disabled or M profile PPB access: use default memory map.
40
+ * The other case which uses the default memory map in the
41
+ * v7M ARM ARM pseudocode is exception vector reads from the vector
42
+ * table. In QEMU those accesses are done in arm_v7m_load_vector(),
43
+ * which always does a direct read using address_space_ldl(), rather
44
+ * than going via this function, so we don't need to check that here.
45
+ */
46
get_phys_addr_pmsav7_default(env, mmu_idx, address, prot);
47
} else { /* MPU enabled */
48
for (n = (int)cpu->pmsav7_dregion - 1; n >= 0; n--) {
49
--
41
--
50
2.7.4
42
2.19.2
51
43
52
44
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:
4
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>
3
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
40
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
Message-id: 20170729234930.725-1-f4bug@amsat.org
41
Message-id: 20190104142921.878-1-f4bug@amsat.org
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
42
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
43
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
44
---
8
hw/misc/mps2-scc.c | 4 ++--
45
include/hw/arm/allwinner-a10.h | 1 +
9
1 file changed, 2 insertions(+), 2 deletions(-)
46
hw/arm/allwinner-a10.c | 6 ++++++
47
2 files changed, 7 insertions(+)
10
48
11
diff --git a/hw/misc/mps2-scc.c b/hw/misc/mps2-scc.c
49
diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h
12
index XXXXXXX..XXXXXXX 100644
50
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/misc/mps2-scc.c
51
--- a/include/hw/arm/allwinner-a10.h
14
+++ b/hw/misc/mps2-scc.c
52
+++ b/include/hw/arm/allwinner-a10.h
15
@@ -XXX,XX +XXX,XX @@ static Property mps2_scc_properties[] = {
53
@@ -XXX,XX +XXX,XX @@ typedef struct AwA10State {
16
/* Values for various read-only ID registers (which are specific
54
AwA10PICState intc;
17
* to the board model or FPGA image)
55
AwEmacState emac;
18
*/
56
AllwinnerAHCIState sata;
19
- DEFINE_PROP_UINT32("scc-cfg4", MPS2SCC, aid, 0),
57
+ MemoryRegion sram_a;
20
+ DEFINE_PROP_UINT32("scc-cfg4", MPS2SCC, cfg4, 0),
58
} AwA10State;
21
DEFINE_PROP_UINT32("scc-aid", MPS2SCC, aid, 0),
59
22
- DEFINE_PROP_UINT32("scc-id", MPS2SCC, aid, 0),
60
#define ALLWINNER_H_
23
+ DEFINE_PROP_UINT32("scc-id", MPS2SCC, id, 0),
61
diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c
24
/* These are the initial settings for the source clocks on the board.
62
index XXXXXXX..XXXXXXX 100644
25
* In hardware they can be configured via a config file read by the
63
--- a/hw/arm/allwinner-a10.c
26
* motherboard configuration controller to suit the FPGA image.
64
+++ b/hw/arm/allwinner-a10.c
65
@@ -XXX,XX +XXX,XX @@
66
#include "hw/sysbus.h"
67
#include "hw/devices.h"
68
#include "hw/arm/allwinner-a10.h"
69
+#include "hw/misc/unimp.h"
70
71
static void aw_a10_init(Object *obj)
72
{
73
@@ -XXX,XX +XXX,XX @@ static void aw_a10_realize(DeviceState *dev, Error **errp)
74
sysbus_connect_irq(sysbusdev, 4, s->irq[67]);
75
sysbus_connect_irq(sysbusdev, 5, s->irq[68]);
76
77
+ memory_region_init_ram(&s->sram_a, OBJECT(dev), "sram A", 48 * KiB,
78
+ &error_fatal);
79
+ memory_region_add_subregion(get_system_memory(), 0x00000000, &s->sram_a);
80
+ create_unimplemented_device("a10-sram-ctrl", 0x01c00000, 4 * KiB);
81
+
82
/* FIXME use qdev NIC properties instead of nd_table[] */
83
if (nd_table[0].used) {
84
qemu_check_nic_model(&nd_table[0], TYPE_AW_EMAC);
27
--
85
--
28
2.7.4
86
2.19.2
29
87
30
88
diff view generated by jsdifflib
New patch
1
From: Steffen Görtz <contrib@steffen-goertz.de>
1
2
3
Adds a new qtest command "set_irq_in" which allows
4
to set qemu gpio lines to a given level.
5
6
Based on https://lists.gnu.org/archive/html/qemu-devel/2012-12/msg02363.html
7
which never got merged.
8
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>
21
---
22
tests/libqtest.h | 13 +++++++++++++
23
qtest.c | 43 +++++++++++++++++++++++++++++++++++++++++++
24
tests/libqtest.c | 10 ++++++++++
25
3 files changed, 66 insertions(+)
26
27
diff --git a/tests/libqtest.h b/tests/libqtest.h
28
index XXXXXXX..XXXXXXX 100644
29
--- a/tests/libqtest.h
30
+++ b/tests/libqtest.h
31
@@ -XXX,XX +XXX,XX @@ void qtest_irq_intercept_in(QTestState *s, const char *string);
32
*/
33
void qtest_irq_intercept_out(QTestState *s, const char *string);
34
35
+/**
36
+ * qtest_set_irq_in:
37
+ * @s: QTestState instance to operate on.
38
+ * @string: QOM path of a device
39
+ * @name: IRQ name
40
+ * @irq: IRQ number
41
+ * @level: IRQ level
42
+ *
43
+ * Force given device/irq GPIO-in pin to the given level.
44
+ */
45
+void qtest_set_irq_in(QTestState *s, const char *string, const char *name,
46
+ int irq, int level);
47
+
48
/**
49
* qtest_outb:
50
* @s: #QTestState instance to operate on.
51
diff --git a/qtest.c b/qtest.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/qtest.c
54
+++ b/qtest.c
55
@@ -XXX,XX +XXX,XX @@ static bool qtest_opened;
56
* where NUM is an IRQ number. For the PC, interrupts can be intercepted
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
}
120
121
+void qtest_set_irq_in(QTestState *s, const char *qom_path, const char *name,
122
+ int num, int level)
123
+{
124
+ if (!name) {
125
+ name = "unnamed-gpio-in";
126
+ }
127
+ qtest_sendf(s, "set_irq_in %s %s %d %d\n", qom_path, name, num, level);
128
+ qtest_rsp(s, 0);
129
+}
130
+
131
static void qtest_out(QTestState *s, const char *cmd, uint16_t addr, uint32_t value)
132
{
133
qtest_sendf(s, "%s 0x%x 0x%x\n", cmd, addr, value);
134
--
135
2.19.2
136
137
diff view generated by jsdifflib
New patch
1
From: Steffen Görtz <contrib@steffen-goertz.de>
1
2
3
Adds a header that provides definitions that are used
4
across nRF51 peripherals
5
6
Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Message-id: 20190103091119.9367-3-stefanha@redhat.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
include/hw/arm/nrf51.h | 45 ++++++++++++++++++++++++++++++++++++
14
include/hw/char/nrf51_uart.h | 1 -
15
hw/arm/nrf51_soc.c | 33 ++++++++++----------------
16
3 files changed, 57 insertions(+), 22 deletions(-)
17
create mode 100644 include/hw/arm/nrf51.h
18
19
diff --git a/include/hw/arm/nrf51.h b/include/hw/arm/nrf51.h
20
new file mode 100644
21
index XXXXXXX..XXXXXXX
22
--- /dev/null
23
+++ b/include/hw/arm/nrf51.h
24
@@ -XXX,XX +XXX,XX @@
25
+/*
26
+ * Nordic Semiconductor nRF51 Series SOC Common Defines
27
+ *
28
+ * This file hosts generic defines used in various nRF51 peripheral devices.
29
+ *
30
+ * Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.pdf
31
+ * Product Spec: http://infocenter.nordicsemi.com/pdf/nRF51822_PS_v3.1.pdf
32
+ *
33
+ * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
34
+ *
35
+ * This code is licensed under the GPL version 2 or later. See
36
+ * the COPYING file in the top-level directory.
37
+ */
38
+
39
+#ifndef NRF51_H
40
+#define NRF51_H
41
+
42
+#define NRF51_FLASH_BASE 0x00000000
43
+#define NRF51_FICR_BASE 0x10000000
44
+#define NRF51_FICR_SIZE 0x00000100
45
+#define NRF51_UICR_BASE 0x10001000
46
+#define NRF51_SRAM_BASE 0x20000000
47
+
48
+#define NRF51_IOMEM_BASE 0x40000000
49
+#define NRF51_IOMEM_SIZE 0x20000000
50
+
51
+#define NRF51_UART_BASE 0x40002000
52
+#define NRF51_TIMER_BASE 0x40008000
53
+#define NRF51_TIMER_SIZE 0x00001000
54
+#define NRF51_RNG_BASE 0x4000D000
55
+#define NRF51_NVMC_BASE 0x4001E000
56
+#define NRF51_GPIO_BASE 0x50000000
57
+
58
+#define NRF51_PRIVATE_BASE 0xF0000000
59
+#define NRF51_PRIVATE_SIZE 0x10000000
60
+
61
+#define NRF51_PAGE_SIZE 1024
62
+
63
+/* Trigger */
64
+#define NRF51_TRIGGER_TASK 0x01
65
+
66
+/* Events */
67
+#define NRF51_EVENT_CLEAR 0x00
68
+
69
+#endif
70
diff --git a/include/hw/char/nrf51_uart.h b/include/hw/char/nrf51_uart.h
71
index XXXXXXX..XXXXXXX 100644
72
--- a/include/hw/char/nrf51_uart.h
73
+++ b/include/hw/char/nrf51_uart.h
74
@@ -XXX,XX +XXX,XX @@
75
#include "hw/registerfields.h"
76
77
#define UART_FIFO_LENGTH 6
78
-#define UART_BASE 0x40002000
79
#define UART_SIZE 0x1000
80
81
#define TYPE_NRF51_UART "nrf51_soc.uart"
82
diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.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
--
158
2.19.2
159
160
diff view generated by jsdifflib
New patch
1
1
From: Steffen Görtz <contrib@steffen-goertz.de>
2
3
Add a model of the NRF51 random number generator peripheral.
4
This is a simple random generator that continuously generates
5
new random values after startup.
6
7
Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.pdf
8
9
Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
10
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
13
Message-id: 20190103091119.9367-4-stefanha@redhat.com
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
16
hw/misc/Makefile.objs | 1 +
17
include/hw/misc/nrf51_rng.h | 83 ++++++++++++
18
hw/misc/nrf51_rng.c | 262 ++++++++++++++++++++++++++++++++++++
19
3 files changed, 346 insertions(+)
20
create mode 100644 include/hw/misc/nrf51_rng.h
21
create mode 100644 hw/misc/nrf51_rng.c
22
23
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
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
34
index XXXXXXX..XXXXXXX
35
--- /dev/null
36
+++ b/include/hw/misc/nrf51_rng.h
37
@@ -XXX,XX +XXX,XX @@
38
+/*
39
+ * nRF51 Random Number Generator
40
+ *
41
+ * QEMU interface:
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
+ *
57
+ * Accuracy of the peripheral model:
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
+ *
64
+ * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
65
+ *
66
+ * This code is licensed under the GPL version 2 or later. See
67
+ * the COPYING file in the top-level directory.
68
+ *
69
+ */
70
+#ifndef NRF51_RNG_H
71
+#define NRF51_RNG_H
72
+
73
+#include "hw/sysbus.h"
74
+#include "qemu/timer.h"
75
+#define TYPE_NRF51_RNG "nrf51_soc.rng"
76
+#define NRF51_RNG(obj) OBJECT_CHECK(NRF51RNGState, (obj), TYPE_NRF51_RNG)
77
+
78
+#define NRF51_RNG_SIZE 0x1000
79
+
80
+#define NRF51_RNG_TASK_START 0x000
81
+#define NRF51_RNG_TASK_STOP 0x004
82
+#define NRF51_RNG_EVENT_VALRDY 0x100
83
+#define NRF51_RNG_REG_SHORTS 0x200
84
+#define NRF51_RNG_REG_SHORTS_VALRDY_STOP 0
85
+#define NRF51_RNG_REG_INTEN 0x300
86
+#define NRF51_RNG_REG_INTEN_VALRDY 0
87
+#define NRF51_RNG_REG_INTENSET 0x304
88
+#define NRF51_RNG_REG_INTENCLR 0x308
89
+#define NRF51_RNG_REG_CONFIG 0x504
90
+#define NRF51_RNG_REG_CONFIG_DECEN 0
91
+#define NRF51_RNG_REG_VALUE 0x508
92
+
93
+typedef struct {
94
+ SysBusDevice parent_obj;
95
+
96
+ MemoryRegion mmio;
97
+ qemu_irq irq;
98
+
99
+ /* Event End Points */
100
+ qemu_irq eep_valrdy;
101
+
102
+ QEMUTimer timer;
103
+
104
+ /* Time between generation of successive unfiltered values in us */
105
+ uint16_t period_unfiltered_us;
106
+ /* Time between generation of successive filtered values in us */
107
+ uint16_t period_filtered_us;
108
+
109
+ uint8_t value;
110
+
111
+ uint32_t active;
112
+ uint32_t event_valrdy;
113
+ uint32_t shortcut_stop_on_valrdy;
114
+ uint32_t interrupt_enabled;
115
+ uint32_t filter_enabled;
116
+
117
+} NRF51RNGState;
118
+
119
+
120
+#endif /* NRF51_RNG_H_ */
121
diff --git a/hw/misc/nrf51_rng.c b/hw/misc/nrf51_rng.c
122
new file mode 100644
123
index XXXXXXX..XXXXXXX
124
--- /dev/null
125
+++ b/hw/misc/nrf51_rng.c
126
@@ -XXX,XX +XXX,XX @@
127
+/*
128
+ * nRF51 Random Number Generator
129
+ *
130
+ * Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.1.pdf
131
+ *
132
+ * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
133
+ *
134
+ * This code is licensed under the GPL version 2 or later. See
135
+ * the COPYING file in the top-level directory.
136
+ */
137
+
138
+#include "qemu/osdep.h"
139
+#include "qemu/log.h"
140
+#include "qapi/error.h"
141
+#include "hw/arm/nrf51.h"
142
+#include "hw/misc/nrf51_rng.h"
143
+#include "crypto/random.h"
144
+
145
+static void update_irq(NRF51RNGState *s)
146
+{
147
+ bool irq = s->interrupt_enabled && s->event_valrdy;
148
+ qemu_set_irq(s->irq, irq);
149
+}
150
+
151
+static uint64_t rng_read(void *opaque, hwaddr offset, unsigned int size)
152
+{
153
+ NRF51RNGState *s = NRF51_RNG(opaque);
154
+ uint64_t r = 0;
155
+
156
+ switch (offset) {
157
+ case NRF51_RNG_EVENT_VALRDY:
158
+ r = s->event_valrdy;
159
+ break;
160
+ case NRF51_RNG_REG_SHORTS:
161
+ r = s->shortcut_stop_on_valrdy;
162
+ break;
163
+ case NRF51_RNG_REG_INTEN:
164
+ case NRF51_RNG_REG_INTENSET:
165
+ case NRF51_RNG_REG_INTENCLR:
166
+ r = s->interrupt_enabled;
167
+ break;
168
+ case NRF51_RNG_REG_CONFIG:
169
+ r = s->filter_enabled;
170
+ break;
171
+ case NRF51_RNG_REG_VALUE:
172
+ r = s->value;
173
+ break;
174
+
175
+ default:
176
+ qemu_log_mask(LOG_GUEST_ERROR,
177
+ "%s: bad read offset 0x%" HWADDR_PRIx "\n",
178
+ __func__, offset);
179
+ }
180
+
181
+ return r;
182
+}
183
+
184
+static int64_t calc_next_timeout(NRF51RNGState *s)
185
+{
186
+ int64_t timeout = qemu_clock_get_us(QEMU_CLOCK_VIRTUAL);
187
+ if (s->filter_enabled) {
188
+ timeout += s->period_filtered_us;
189
+ } else {
190
+ timeout += s->period_unfiltered_us;
191
+ }
192
+
193
+ return timeout;
194
+}
195
+
196
+
197
+static void rng_update_timer(NRF51RNGState *s)
198
+{
199
+ if (s->active) {
200
+ timer_mod(&s->timer, calc_next_timeout(s));
201
+ } else {
202
+ timer_del(&s->timer);
203
+ }
204
+}
205
+
206
+
207
+static void rng_write(void *opaque, hwaddr offset,
208
+ uint64_t value, unsigned int size)
209
+{
210
+ NRF51RNGState *s = NRF51_RNG(opaque);
211
+
212
+ switch (offset) {
213
+ case NRF51_RNG_TASK_START:
214
+ if (value == NRF51_TRIGGER_TASK) {
215
+ s->active = 1;
216
+ rng_update_timer(s);
217
+ }
218
+ break;
219
+ case NRF51_RNG_TASK_STOP:
220
+ if (value == NRF51_TRIGGER_TASK) {
221
+ s->active = 0;
222
+ rng_update_timer(s);
223
+ }
224
+ break;
225
+ case NRF51_RNG_EVENT_VALRDY:
226
+ if (value == NRF51_EVENT_CLEAR) {
227
+ s->event_valrdy = 0;
228
+ }
229
+ break;
230
+ case NRF51_RNG_REG_SHORTS:
231
+ s->shortcut_stop_on_valrdy =
232
+ (value & BIT_MASK(NRF51_RNG_REG_SHORTS_VALRDY_STOP)) ? 1 : 0;
233
+ break;
234
+ case NRF51_RNG_REG_INTEN:
235
+ s->interrupt_enabled =
236
+ (value & BIT_MASK(NRF51_RNG_REG_INTEN_VALRDY)) ? 1 : 0;
237
+ break;
238
+ case NRF51_RNG_REG_INTENSET:
239
+ if (value & BIT_MASK(NRF51_RNG_REG_INTEN_VALRDY)) {
240
+ s->interrupt_enabled = 1;
241
+ }
242
+ break;
243
+ case NRF51_RNG_REG_INTENCLR:
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);
312
+
313
+ memory_region_init_io(&s->mmio, obj, &rng_ops, s,
314
+ TYPE_NRF51_RNG, NRF51_RNG_SIZE);
315
+ sysbus_init_mmio(sbd, &s->mmio);
316
+
317
+ timer_init_us(&s->timer, QEMU_CLOCK_VIRTUAL, nrf51_rng_timer_expire, s);
318
+
319
+ sysbus_init_irq(sbd, &s->irq);
320
+
321
+ /* Tasks */
322
+ qdev_init_gpio_in_named(DEVICE(s), nrf51_rng_tep_start, "tep_start", 1);
323
+ qdev_init_gpio_in_named(DEVICE(s), nrf51_rng_tep_stop, "tep_stop", 1);
324
+
325
+ /* Events */
326
+ qdev_init_gpio_out_named(DEVICE(s), &s->eep_valrdy, "eep_valrdy", 1);
327
+}
328
+
329
+static void nrf51_rng_reset(DeviceState *dev)
330
+{
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,
355
+ .minimum_version_id = 1,
356
+ .fields = (VMStateField[]) {
357
+ VMSTATE_UINT32(active, NRF51RNGState),
358
+ VMSTATE_UINT32(event_valrdy, NRF51RNGState),
359
+ VMSTATE_UINT32(shortcut_stop_on_valrdy, NRF51RNGState),
360
+ VMSTATE_UINT32(interrupt_enabled, NRF51RNGState),
361
+ VMSTATE_UINT32(filter_enabled, NRF51RNGState),
362
+ VMSTATE_END_OF_LIST()
363
+ }
364
+};
365
+
366
+static void nrf51_rng_class_init(ObjectClass *klass, void *data)
367
+{
368
+ DeviceClass *dc = DEVICE_CLASS(klass);
369
+
370
+ dc->props = nrf51_rng_properties;
371
+ dc->vmsd = &vmstate_rng;
372
+ dc->reset = nrf51_rng_reset;
373
+}
374
+
375
+static const TypeInfo nrf51_rng_info = {
376
+ .name = TYPE_NRF51_RNG,
377
+ .parent = TYPE_SYS_BUS_DEVICE,
378
+ .instance_size = sizeof(NRF51RNGState),
379
+ .instance_init = nrf51_rng_init,
380
+ .class_init = nrf51_rng_class_init
381
+};
382
+
383
+static void nrf51_rng_register_types(void)
384
+{
385
+ type_register_static(&nrf51_rng_info);
386
+}
387
+
388
+type_init(nrf51_rng_register_types)
389
--
390
2.19.2
391
392
diff view generated by jsdifflib
New patch
1
From: Steffen Görtz <contrib@steffen-goertz.de>
1
2
3
Use RNG in SOC.
4
5
Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
6
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Message-id: 20190103091119.9367-5-stefanha@redhat.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
include/hw/arm/nrf51_soc.h | 2 ++
13
hw/arm/nrf51_soc.c | 16 ++++++++++++++++
14
2 files changed, 18 insertions(+)
15
16
diff --git a/include/hw/arm/nrf51_soc.h b/include/hw/arm/nrf51_soc.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/nrf51_soc.h
19
+++ b/include/hw/arm/nrf51_soc.h
20
@@ -XXX,XX +XXX,XX @@
21
#include "hw/sysbus.h"
22
#include "hw/arm/armv7m.h"
23
#include "hw/char/nrf51_uart.h"
24
+#include "hw/misc/nrf51_rng.h"
25
26
#define TYPE_NRF51_SOC "nrf51-soc"
27
#define NRF51_SOC(obj) \
28
@@ -XXX,XX +XXX,XX @@ typedef struct NRF51State {
29
ARMv7MState cpu;
30
31
NRF51UARTState uart;
32
+ NRF51RNGState rng;
33
34
MemoryRegion iomem;
35
MemoryRegion sram;
36
diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/hw/arm/nrf51_soc.c
39
+++ b/hw/arm/nrf51_soc.c
40
@@ -XXX,XX +XXX,XX @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
41
qdev_get_gpio_in(DEVICE(&s->cpu),
42
BASE_TO_IRQ(NRF51_UART_BASE)));
43
44
+ /* RNG */
45
+ object_property_set_bool(OBJECT(&s->rng), true, "realized", &err);
46
+ if (err) {
47
+ error_propagate(errp, err);
48
+ return;
49
+ }
50
+
51
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->rng), 0);
52
+ memory_region_add_subregion_overlap(&s->container, NRF51_RNG_BASE, mr, 0);
53
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->rng), 0,
54
+ qdev_get_gpio_in(DEVICE(&s->cpu),
55
+ BASE_TO_IRQ(NRF51_RNG_BASE)));
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
TYPE_NRF51_UART);
62
object_property_add_alias(obj, "serial0", OBJECT(&s->uart), "chardev",
63
&error_abort);
64
+
65
+ sysbus_init_child_obj(obj, "rng", &s->rng, sizeof(s->rng),
66
+ TYPE_NRF51_RNG);
67
}
68
69
static Property nrf51_soc_properties[] = {
70
--
71
2.19.2
72
73
diff view generated by jsdifflib
New patch
1
1
From: Steffen Görtz <contrib@steffen-goertz.de>
2
3
This adds a model of the nRF51 GPIO peripheral.
4
5
Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.pdf
6
7
The nRF51 series microcontrollers support up to 32 GPIO pins in various configurations.
8
The pins can be used as input pins with pull-ups or pull-down.
9
Furthermore, three different output driver modes per level are
10
available (disconnected, standard, high-current).
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>
21
---
22
Makefile.objs | 1 +
23
hw/gpio/Makefile.objs | 1 +
24
include/hw/gpio/nrf51_gpio.h | 69 ++++++++
25
hw/gpio/nrf51_gpio.c | 300 +++++++++++++++++++++++++++++++++++
26
hw/gpio/trace-events | 7 +
27
5 files changed, 378 insertions(+)
28
create mode 100644 include/hw/gpio/nrf51_gpio.h
29
create mode 100644 hw/gpio/nrf51_gpio.c
30
create mode 100644 hw/gpio/trace-events
31
32
diff --git a/Makefile.objs b/Makefile.objs
33
index XXXXXXX..XXXXXXX 100644
34
--- a/Makefile.objs
35
+++ b/Makefile.objs
36
@@ -XXX,XX +XXX,XX @@ trace-events-subdirs += hw/vfio
37
trace-events-subdirs += hw/virtio
38
trace-events-subdirs += hw/watchdog
39
trace-events-subdirs += hw/xen
40
+trace-events-subdirs += hw/gpio
41
trace-events-subdirs += io
42
trace-events-subdirs += linux-user
43
trace-events-subdirs += migration
44
diff --git a/hw/gpio/Makefile.objs b/hw/gpio/Makefile.objs
45
index XXXXXXX..XXXXXXX 100644
46
--- a/hw/gpio/Makefile.objs
47
+++ b/hw/gpio/Makefile.objs
48
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_GPIO_KEY) += gpio_key.o
49
obj-$(CONFIG_OMAP) += omap_gpio.o
50
obj-$(CONFIG_IMX) += imx_gpio.o
51
obj-$(CONFIG_RASPI) += bcm2835_gpio.o
52
+obj-$(CONFIG_NRF51_SOC) += nrf51_gpio.o
53
diff --git a/include/hw/gpio/nrf51_gpio.h b/include/hw/gpio/nrf51_gpio.h
54
new file mode 100644
55
index XXXXXXX..XXXXXXX
56
--- /dev/null
57
+++ b/include/hw/gpio/nrf51_gpio.h
58
@@ -XXX,XX +XXX,XX @@
59
+/*
60
+ * nRF51 System-on-Chip general purpose input/output register definition
61
+ *
62
+ * QEMU interface:
63
+ * + sysbus MMIO regions 0: GPIO registers
64
+ * + Unnamed GPIO inputs 0-31: Set tri-state input level for GPIO pin.
65
+ * Level -1: Externally Disconnected/Floating; Pull-up/down will be regarded
66
+ * Level 0: Input externally driven LOW
67
+ * Level 1: Input externally driven HIGH
68
+ * + Unnamed GPIO outputs 0-31:
69
+ * Level -1: Disconnected/Floating
70
+ * Level 0: Driven LOW
71
+ * Level 1: Driven HIGH
72
+ *
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
+ */
84
+#ifndef NRF51_GPIO_H
85
+#define NRF51_GPIO_H
86
+
87
+#include "hw/sysbus.h"
88
+#define TYPE_NRF51_GPIO "nrf51_soc.gpio"
89
+#define NRF51_GPIO(obj) OBJECT_CHECK(NRF51GPIOState, (obj), TYPE_NRF51_GPIO)
90
+
91
+#define NRF51_GPIO_PINS 32
92
+
93
+#define NRF51_GPIO_SIZE 0x1000
94
+
95
+#define NRF51_GPIO_REG_OUT 0x504
96
+#define NRF51_GPIO_REG_OUTSET 0x508
97
+#define NRF51_GPIO_REG_OUTCLR 0x50C
98
+#define NRF51_GPIO_REG_IN 0x510
99
+#define NRF51_GPIO_REG_DIR 0x514
100
+#define NRF51_GPIO_REG_DIRSET 0x518
101
+#define NRF51_GPIO_REG_DIRCLR 0x51C
102
+#define NRF51_GPIO_REG_CNF_START 0x700
103
+#define NRF51_GPIO_REG_CNF_END 0x77F
104
+
105
+#define NRF51_GPIO_PULLDOWN 1
106
+#define NRF51_GPIO_PULLUP 3
107
+
108
+typedef struct NRF51GPIOState {
109
+ SysBusDevice parent_obj;
110
+
111
+ MemoryRegion mmio;
112
+ qemu_irq irq;
113
+
114
+ uint32_t out;
115
+ uint32_t in;
116
+ uint32_t in_mask;
117
+ uint32_t dir;
118
+ uint32_t cnf[NRF51_GPIO_PINS];
119
+
120
+ uint32_t old_out;
121
+ uint32_t old_out_connected;
122
+
123
+ qemu_irq output[NRF51_GPIO_PINS];
124
+} NRF51GPIOState;
125
+
126
+
127
+#endif
128
diff --git a/hw/gpio/nrf51_gpio.c b/hw/gpio/nrf51_gpio.c
129
new file mode 100644
130
index XXXXXXX..XXXXXXX
131
--- /dev/null
132
+++ b/hw/gpio/nrf51_gpio.c
133
@@ -XXX,XX +XXX,XX @@
134
+/*
135
+ * nRF51 System-on-Chip general purpose input/output register definition
136
+ *
137
+ * Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.pdf
138
+ * Product Spec: http://infocenter.nordicsemi.com/pdf/nRF51822_PS_v3.1.pdf
139
+ *
140
+ * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
141
+ *
142
+ * This code is licensed under the GPL version 2 or later. See
143
+ * the COPYING file in the top-level directory.
144
+ */
145
+
146
+#include "qemu/osdep.h"
147
+#include "qemu/log.h"
148
+#include "hw/gpio/nrf51_gpio.h"
149
+#include "trace.h"
150
+
151
+/*
152
+ * Check if the output driver is connected to the direction switch
153
+ * given the current configuration and logic level.
154
+ * It is not differentiated between standard and "high"(-power) drive modes.
155
+ */
156
+static bool is_connected(uint32_t config, uint32_t level)
157
+{
158
+ bool state;
159
+ uint32_t drive_config = extract32(config, 8, 3);
160
+
161
+ switch (drive_config) {
162
+ case 0 ... 3:
163
+ state = true;
164
+ break;
165
+ case 4 ... 5:
166
+ state = level != 0;
167
+ break;
168
+ case 6 ... 7:
169
+ state = level == 0;
170
+ break;
171
+ default:
172
+ g_assert_not_reached();
173
+ break;
174
+ }
175
+
176
+ return state;
177
+}
178
+
179
+static void update_output_irq(NRF51GPIOState *s, size_t i,
180
+ bool connected, bool level)
181
+{
182
+ int64_t irq_level = connected ? level : -1;
183
+ bool old_connected = extract32(s->old_out_connected, i, 1);
184
+ bool old_level = extract32(s->old_out, i, 1);
185
+
186
+ if ((old_connected != connected) || (old_level != level)) {
187
+ qemu_set_irq(s->output[i], irq_level);
188
+ trace_nrf51_gpio_update_output_irq(i, irq_level);
189
+ }
190
+
191
+ s->old_out = deposit32(s->old_out, i, 1, level);
192
+ s->old_out_connected = deposit32(s->old_out_connected, i, 1, connected);
193
+}
194
+
195
+static void update_state(NRF51GPIOState *s)
196
+{
197
+ uint32_t pull;
198
+ size_t i;
199
+ bool connected_out, dir, connected_in, out, input;
200
+
201
+ for (i = 0; i < NRF51_GPIO_PINS; i++) {
202
+ pull = extract32(s->cnf[i], 2, 2);
203
+ dir = extract32(s->cnf[i], 0, 1);
204
+ connected_in = extract32(s->in_mask, i, 1);
205
+ out = extract32(s->out, i, 1);
206
+ input = !extract32(s->cnf[i], 1, 1);
207
+ connected_out = is_connected(s->cnf[i], out) && dir;
208
+
209
+ update_output_irq(s, i, connected_out, out);
210
+
211
+ /* Pin both driven externally and internally */
212
+ if (connected_out && connected_in) {
213
+ qemu_log_mask(LOG_GUEST_ERROR, "GPIO pin %zu short circuited\n", i);
214
+ }
215
+
216
+ /*
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
+ }
233
+
234
+}
235
+
236
+/*
237
+ * Direction is exposed in both the DIR register and the DIR bit
238
+ * of each PINs CNF configuration register. Reflect bits for pins in DIR
239
+ * to individual pin configuration registers.
240
+ */
241
+static void reflect_dir_bit_in_cnf(NRF51GPIOState *s)
242
+{
243
+ size_t i;
244
+
245
+ uint32_t value = s->dir;
246
+
247
+ for (i = 0; i < NRF51_GPIO_PINS; i++) {
248
+ s->cnf[i] = (s->cnf[i] & ~(1UL)) | ((value >> i) & 0x01);
249
+ }
250
+}
251
+
252
+static uint64_t nrf51_gpio_read(void *opaque, hwaddr offset, unsigned int size)
253
+{
254
+ NRF51GPIOState *s = NRF51_GPIO(opaque);
255
+ uint64_t r = 0;
256
+ size_t idx;
257
+
258
+ switch (offset) {
259
+ case NRF51_GPIO_REG_OUT ... NRF51_GPIO_REG_OUTCLR:
260
+ r = s->out;
261
+ break;
262
+
263
+ case NRF51_GPIO_REG_IN:
264
+ r = s->in;
265
+ break;
266
+
267
+ case NRF51_GPIO_REG_DIR ... NRF51_GPIO_REG_DIRCLR:
268
+ r = s->dir;
269
+ break;
270
+
271
+ case NRF51_GPIO_REG_CNF_START ... NRF51_GPIO_REG_CNF_END:
272
+ idx = (offset - NRF51_GPIO_REG_CNF_START) / 4;
273
+ r = s->cnf[idx];
274
+ break;
275
+
276
+ default:
277
+ qemu_log_mask(LOG_GUEST_ERROR,
278
+ "%s: bad read offset 0x%" HWADDR_PRIx "\n",
279
+ __func__, offset);
280
+ }
281
+
282
+ trace_nrf51_gpio_read(offset, r);
283
+
284
+ return r;
285
+}
286
+
287
+static void nrf51_gpio_write(void *opaque, hwaddr offset,
288
+ uint64_t value, unsigned int size)
289
+{
290
+ NRF51GPIOState *s = NRF51_GPIO(opaque);
291
+ size_t idx;
292
+
293
+ trace_nrf51_gpio_write(offset, value);
294
+
295
+ switch (offset) {
296
+ case NRF51_GPIO_REG_OUT:
297
+ s->out = value;
298
+ break;
299
+
300
+ case NRF51_GPIO_REG_OUTSET:
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
+ }
338
+
339
+ update_state(s);
340
+}
341
+
342
+static const MemoryRegionOps gpio_ops = {
343
+ .read = nrf51_gpio_read,
344
+ .write = nrf51_gpio_write,
345
+ .endianness = DEVICE_LITTLE_ENDIAN,
346
+ .impl.min_access_size = 4,
347
+ .impl.max_access_size = 4,
348
+};
349
+
350
+static void nrf51_gpio_set(void *opaque, int line, int value)
351
+{
352
+ NRF51GPIOState *s = NRF51_GPIO(opaque);
353
+
354
+ trace_nrf51_gpio_set(line, value);
355
+
356
+ assert(line >= 0 && line < NRF51_GPIO_PINS);
357
+
358
+ s->in_mask = deposit32(s->in_mask, line, 1, value >= 0);
359
+ if (value >= 0) {
360
+ s->in = deposit32(s->in, line, 1, value != 0);
361
+ }
362
+
363
+ update_state(s);
364
+}
365
+
366
+static void nrf51_gpio_reset(DeviceState *dev)
367
+{
368
+ NRF51GPIOState *s = NRF51_GPIO(dev);
369
+ size_t i;
370
+
371
+ s->out = 0;
372
+ s->old_out = 0;
373
+ s->old_out_connected = 0;
374
+ s->in = 0;
375
+ s->in_mask = 0;
376
+ s->dir = 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[]) {
388
+ VMSTATE_UINT32(out, NRF51GPIOState),
389
+ VMSTATE_UINT32(in, NRF51GPIOState),
390
+ VMSTATE_UINT32(in_mask, NRF51GPIOState),
391
+ VMSTATE_UINT32(dir, NRF51GPIOState),
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
+};
398
+
399
+static void nrf51_gpio_init(Object *obj)
400
+{
401
+ NRF51GPIOState *s = NRF51_GPIO(obj);
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);
414
+
415
+ dc->vmsd = &vmstate_nrf51_gpio;
416
+ dc->reset = nrf51_gpio_reset;
417
+ dc->desc = "nRF51 GPIO";
418
+}
419
+
420
+static const TypeInfo nrf51_gpio_info = {
421
+ .name = TYPE_NRF51_GPIO,
422
+ .parent = TYPE_SYS_BUS_DEVICE,
423
+ .instance_size = sizeof(NRF51GPIOState),
424
+ .instance_init = nrf51_gpio_init,
425
+ .class_init = nrf51_gpio_class_init
426
+};
427
+
428
+static void nrf51_gpio_register_types(void)
429
+{
430
+ type_register_static(&nrf51_gpio_info);
431
+}
432
+
433
+type_init(nrf51_gpio_register_types)
434
diff --git a/hw/gpio/trace-events b/hw/gpio/trace-events
435
new file mode 100644
436
index XXXXXXX..XXXXXXX
437
--- /dev/null
438
+++ b/hw/gpio/trace-events
439
@@ -XXX,XX +XXX,XX @@
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
--
449
2.19.2
450
451
diff view generated by jsdifflib
New patch
1
From: Steffen Görtz <contrib@steffen-goertz.de>
1
2
3
Instantiates GPIO peripheral model
4
5
Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
6
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Message-id: 20190103091119.9367-7-stefanha@redhat.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
include/hw/arm/nrf51_soc.h | 2 ++
13
hw/arm/nrf51_soc.c | 16 ++++++++++++++++
14
2 files changed, 18 insertions(+)
15
16
diff --git a/include/hw/arm/nrf51_soc.h b/include/hw/arm/nrf51_soc.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/nrf51_soc.h
19
+++ b/include/hw/arm/nrf51_soc.h
20
@@ -XXX,XX +XXX,XX @@
21
#include "hw/arm/armv7m.h"
22
#include "hw/char/nrf51_uart.h"
23
#include "hw/misc/nrf51_rng.h"
24
+#include "hw/gpio/nrf51_gpio.h"
25
26
#define TYPE_NRF51_SOC "nrf51-soc"
27
#define NRF51_SOC(obj) \
28
@@ -XXX,XX +XXX,XX @@ typedef struct NRF51State {
29
30
NRF51UARTState uart;
31
NRF51RNGState rng;
32
+ NRF51GPIOState gpio;
33
34
MemoryRegion iomem;
35
MemoryRegion sram;
36
diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/hw/arm/nrf51_soc.c
39
+++ b/hw/arm/nrf51_soc.c
40
@@ -XXX,XX +XXX,XX @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
41
qdev_get_gpio_in(DEVICE(&s->cpu),
42
BASE_TO_IRQ(NRF51_RNG_BASE)));
43
44
+ /* GPIO */
45
+ object_property_set_bool(OBJECT(&s->gpio), true, "realized", &err);
46
+ if (err) {
47
+ error_propagate(errp, err);
48
+ return;
49
+ }
50
+
51
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->gpio), 0);
52
+ memory_region_add_subregion_overlap(&s->container, NRF51_GPIO_BASE, mr, 0);
53
+
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
}
68
69
static Property nrf51_soc_properties[] = {
70
--
71
2.19.2
72
73
diff view generated by jsdifflib
New patch
1
1
From: Steffen Görtz <contrib@steffen-goertz.de>
2
3
The test suite for the nRF51 GPIO peripheral for now
4
only tests initial state. Additionally a set of
5
tests testing an implementation detail of the model
6
are included.
7
8
Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
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>
14
---
15
tests/Makefile.include | 2 +
16
tests/microbit-test.c | 160 +++++++++++++++++++++++++++++++++++++++++
17
2 files changed, 162 insertions(+)
18
create mode 100644 tests/microbit-test.c
19
20
diff --git a/tests/Makefile.include b/tests/Makefile.include
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
42
index XXXXXXX..XXXXXXX
43
--- /dev/null
44
+++ b/tests/microbit-test.c
45
@@ -XXX,XX +XXX,XX @@
46
+/*
47
+ * QTest testcase for Microbit board using the Nordic Semiconductor nRF51 SoC.
48
+ *
49
+ * nRF51:
50
+ * Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.pdf
51
+ * Product Spec: http://infocenter.nordicsemi.com/pdf/nRF51822_PS_v3.1.pdf
52
+ *
53
+ * Microbit Board: http://microbit.org/
54
+ *
55
+ * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
56
+ *
57
+ * This code is licensed under the GPL version 2 or later. See
58
+ * the COPYING file in the top-level directory.
59
+ */
60
+
61
+
62
+#include "qemu/osdep.h"
63
+#include "exec/hwaddr.h"
64
+#include "libqtest.h"
65
+
66
+#include "hw/arm/nrf51.h"
67
+#include "hw/gpio/nrf51_gpio.h"
68
+
69
+static void test_nrf51_gpio(void)
70
+{
71
+ size_t i;
72
+ uint32_t actual, expected;
73
+
74
+ struct {
75
+ hwaddr addr;
76
+ uint32_t expected;
77
+ } const reset_state[] = {
78
+ {NRF51_GPIO_REG_OUT, 0x00000000}, {NRF51_GPIO_REG_OUTSET, 0x00000000},
79
+ {NRF51_GPIO_REG_OUTCLR, 0x00000000}, {NRF51_GPIO_REG_IN, 0x00000000},
80
+ {NRF51_GPIO_REG_DIR, 0x00000000}, {NRF51_GPIO_REG_DIRSET, 0x00000000},
81
+ {NRF51_GPIO_REG_DIRCLR, 0x00000000}
82
+ };
83
+
84
+ /* Check reset state */
85
+ for (i = 0; i < ARRAY_SIZE(reset_state); i++) {
86
+ expected = reset_state[i].expected;
87
+ actual = readl(NRF51_GPIO_BASE + reset_state[i].addr);
88
+ g_assert_cmpuint(actual, ==, expected);
89
+ }
90
+
91
+ for (i = 0; i < NRF51_GPIO_PINS; i++) {
92
+ expected = 0x00000002;
93
+ actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START + i * 4);
94
+ g_assert_cmpuint(actual, ==, expected);
95
+ }
96
+
97
+ /* Check dir bit consistency between dir and cnf */
98
+ /* Check set via DIRSET */
99
+ expected = 0x80000001;
100
+ writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIRSET, expected);
101
+ actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIR);
102
+ g_assert_cmpuint(actual, ==, expected);
103
+ actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START) & 0x01;
104
+ g_assert_cmpuint(actual, ==, 0x01);
105
+ actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_END) & 0x01;
106
+ g_assert_cmpuint(actual, ==, 0x01);
107
+
108
+ /* Check clear via DIRCLR */
109
+ writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIRCLR, 0x80000001);
110
+ actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIR);
111
+ g_assert_cmpuint(actual, ==, 0x00000000);
112
+ actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START) & 0x01;
113
+ g_assert_cmpuint(actual, ==, 0x00);
114
+ actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_END) & 0x01;
115
+ g_assert_cmpuint(actual, ==, 0x00);
116
+
117
+ /* Check set via DIR */
118
+ expected = 0x80000001;
119
+ writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIR, expected);
120
+ actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIR);
121
+ g_assert_cmpuint(actual, ==, expected);
122
+ actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START) & 0x01;
123
+ g_assert_cmpuint(actual, ==, 0x01);
124
+ actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_END) & 0x01;
125
+ g_assert_cmpuint(actual, ==, 0x01);
126
+
127
+ /* Reset DIR */
128
+ writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIR, 0x00000000);
129
+
130
+ /* Check Input propagates */
131
+ writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0x00);
132
+ qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, 0);
133
+ actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
134
+ g_assert_cmpuint(actual, ==, 0x00);
135
+ qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, 1);
136
+ actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
137
+ g_assert_cmpuint(actual, ==, 0x01);
138
+ qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, -1);
139
+ actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
140
+ g_assert_cmpuint(actual, ==, 0x01);
141
+ writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0x02);
142
+
143
+ /* Check pull-up working */
144
+ qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, 0);
145
+ writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b0000);
146
+ actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
147
+ g_assert_cmpuint(actual, ==, 0x00);
148
+ writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b1110);
149
+ actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
150
+ g_assert_cmpuint(actual, ==, 0x01);
151
+ writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0x02);
152
+
153
+ /* Check pull-down working */
154
+ qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, 1);
155
+ writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b0000);
156
+ actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
157
+ g_assert_cmpuint(actual, ==, 0x01);
158
+ writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b0110);
159
+ actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
160
+ g_assert_cmpuint(actual, ==, 0x00);
161
+ writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0x02);
162
+ qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, -1);
163
+
164
+ /* Check Output propagates */
165
+ irq_intercept_out("/machine/nrf51");
166
+ writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b0011);
167
+ writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_OUTSET, 0x01);
168
+ g_assert_true(get_irq(0));
169
+ writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_OUTCLR, 0x01);
170
+ g_assert_false(get_irq(0));
171
+
172
+ /* Check self-stimulation */
173
+ writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b01);
174
+ writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_OUTSET, 0x01);
175
+ actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
176
+ g_assert_cmpuint(actual, ==, 0x01);
177
+
178
+ writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_OUTCLR, 0x01);
179
+ actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
180
+ g_assert_cmpuint(actual, ==, 0x00);
181
+
182
+ /*
183
+ * Check short-circuit - generates an guest_error which must be checked
184
+ * manually as long as qtest can not scan qemu_log messages
185
+ */
186
+ writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b01);
187
+ writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_OUTSET, 0x01);
188
+ qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, 0);
189
+}
190
+
191
+int main(int argc, char **argv)
192
+{
193
+ int ret;
194
+
195
+ g_test_init(&argc, &argv, NULL);
196
+
197
+ global_qtest = qtest_initf("-machine microbit");
198
+
199
+ qtest_add_func("/microbit/nrf51/gpio", test_nrf51_gpio);
200
+
201
+ ret = g_test_run();
202
+
203
+ qtest_quit(global_qtest);
204
+ return ret;
205
+}
206
--
207
2.19.2
208
209
diff view generated by jsdifflib
1
The PMSAv7 region number register is migrated for R profile
1
From: Steffen Görtz <contrib@steffen-goertz.de>
2
cores using the cpreg scheme, but M profile doesn't use
3
cpregs, and so we weren't migrating the MPU_RNR register state
4
at all. Fix that by adding a migration subsection for the
5
M profile case.
6
2
3
This patch adds the model for the nRF51 timer peripheral.
4
Currently, only the TIMER mode is implemented.
5
6
Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
7
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Message-id: 20190103091119.9367-9-stefanha@redhat.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 1501153150-19984-6-git-send-email-peter.maydell@linaro.org
10
---
11
---
11
target/arm/machine.c | 28 ++++++++++++++++++++++++++++
12
hw/timer/Makefile.objs | 1 +
12
1 file changed, 28 insertions(+)
13
include/hw/timer/nrf51_timer.h | 80 +++++++
14
hw/timer/nrf51_timer.c | 393 +++++++++++++++++++++++++++++++++
15
hw/timer/trace-events | 5 +
16
4 files changed, 479 insertions(+)
17
create mode 100644 include/hw/timer/nrf51_timer.h
18
create mode 100644 hw/timer/nrf51_timer.c
13
19
14
diff --git a/target/arm/machine.c b/target/arm/machine.c
20
diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs
15
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/machine.c
22
--- a/hw/timer/Makefile.objs
17
+++ b/target/arm/machine.c
23
+++ b/hw/timer/Makefile.objs
18
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_pmsav7 = {
24
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_IMX) += imx_gpt.o
19
}
25
common-obj-$(CONFIG_LM32) += lm32_timer.o
20
};
26
common-obj-$(CONFIG_MILKYMIST) += milkymist-sysctl.o
21
27
common-obj-$(CONFIG_XLNX_ZYNQMP) += xlnx-zynqmp-rtc.o
22
+static bool pmsav7_rnr_needed(void *opaque)
28
+common-obj-$(CONFIG_NRF51_SOC) += nrf51_timer.o
23
+{
29
24
+ ARMCPU *cpu = opaque;
30
obj-$(CONFIG_ALTERA_TIMER) += altera_timer.o
25
+ CPUARMState *env = &cpu->env;
31
obj-$(CONFIG_EXYNOS4) += exynos4210_mct.o
26
+
32
diff --git a/include/hw/timer/nrf51_timer.h b/include/hw/timer/nrf51_timer.h
27
+ /* For R profile cores pmsav7.rnr is migrated via the cpreg
33
new file mode 100644
28
+ * "RGNR" definition in helper.h. For M profile we have to
34
index XXXXXXX..XXXXXXX
29
+ * migrate it separately.
35
--- /dev/null
30
+ */
36
+++ b/include/hw/timer/nrf51_timer.h
31
+ return arm_feature(env, ARM_FEATURE_M);
37
@@ -XXX,XX +XXX,XX @@
32
+}
38
+/*
33
+
39
+ * nRF51 System-on-Chip Timer peripheral
34
+static const VMStateDescription vmstate_pmsav7_rnr = {
40
+ *
35
+ .name = "cpu/pmsav7-rnr",
41
+ * QEMU interface:
42
+ * + sysbus MMIO regions 0: GPIO registers
43
+ * + sysbus irq
44
+ *
45
+ * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
46
+ *
47
+ * This code is licensed under the GPL version 2 or later. See
48
+ * the COPYING file in the top-level directory.
49
+ */
50
+#ifndef NRF51_TIMER_H
51
+#define NRF51_TIMER_H
52
+
53
+#include "hw/sysbus.h"
54
+#include "qemu/timer.h"
55
+#define TYPE_NRF51_TIMER "nrf51_soc.timer"
56
+#define NRF51_TIMER(obj) OBJECT_CHECK(NRF51TimerState, (obj), TYPE_NRF51_TIMER)
57
+
58
+#define NRF51_TIMER_REG_COUNT 4
59
+
60
+#define NRF51_TIMER_TASK_START 0x000
61
+#define NRF51_TIMER_TASK_STOP 0x004
62
+#define NRF51_TIMER_TASK_COUNT 0x008
63
+#define NRF51_TIMER_TASK_CLEAR 0x00C
64
+#define NRF51_TIMER_TASK_SHUTDOWN 0x010
65
+#define NRF51_TIMER_TASK_CAPTURE_0 0x040
66
+#define NRF51_TIMER_TASK_CAPTURE_3 0x04C
67
+
68
+#define NRF51_TIMER_EVENT_COMPARE_0 0x140
69
+#define NRF51_TIMER_EVENT_COMPARE_1 0x144
70
+#define NRF51_TIMER_EVENT_COMPARE_2 0x148
71
+#define NRF51_TIMER_EVENT_COMPARE_3 0x14C
72
+
73
+#define NRF51_TIMER_REG_SHORTS 0x200
74
+#define NRF51_TIMER_REG_SHORTS_MASK 0xf0f
75
+#define NRF51_TIMER_REG_INTENSET 0x304
76
+#define NRF51_TIMER_REG_INTENCLR 0x308
77
+#define NRF51_TIMER_REG_INTEN_MASK 0xf0000
78
+#define NRF51_TIMER_REG_MODE 0x504
79
+#define NRF51_TIMER_REG_MODE_MASK 0x01
80
+#define NRF51_TIMER_TIMER 0
81
+#define NRF51_TIMER_COUNTER 1
82
+#define NRF51_TIMER_REG_BITMODE 0x508
83
+#define NRF51_TIMER_REG_BITMODE_MASK 0x03
84
+#define NRF51_TIMER_WIDTH_16 0
85
+#define NRF51_TIMER_WIDTH_8 1
86
+#define NRF51_TIMER_WIDTH_24 2
87
+#define NRF51_TIMER_WIDTH_32 3
88
+#define NRF51_TIMER_REG_PRESCALER 0x510
89
+#define NRF51_TIMER_REG_PRESCALER_MASK 0x0F
90
+#define NRF51_TIMER_REG_CC0 0x540
91
+#define NRF51_TIMER_REG_CC3 0x54C
92
+
93
+typedef struct NRF51TimerState {
94
+ SysBusDevice parent_obj;
95
+
96
+ MemoryRegion iomem;
97
+ qemu_irq irq;
98
+
99
+ QEMUTimer timer;
100
+ int64_t timer_start_ns;
101
+ int64_t update_counter_ns;
102
+ uint32_t counter;
103
+
104
+ bool running;
105
+
106
+ uint8_t events_compare[NRF51_TIMER_REG_COUNT];
107
+ uint32_t cc[NRF51_TIMER_REG_COUNT];
108
+ uint32_t shorts;
109
+ uint32_t inten;
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
120
index XXXXXXX..XXXXXXX
121
--- /dev/null
122
+++ b/hw/timer/nrf51_timer.c
123
@@ -XXX,XX +XXX,XX @@
124
+/*
125
+ * nRF51 System-on-Chip Timer peripheral
126
+ *
127
+ * Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.pdf
128
+ * Product Spec: http://infocenter.nordicsemi.com/pdf/nRF51822_PS_v3.1.pdf
129
+ *
130
+ * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
131
+ * Copyright (c) 2019 Red Hat, Inc.
132
+ *
133
+ * This code is licensed under the GPL version 2 or later. See
134
+ * the COPYING file in the top-level directory.
135
+ */
136
+
137
+#include "qemu/osdep.h"
138
+#include "qemu/log.h"
139
+#include "hw/arm/nrf51.h"
140
+#include "hw/timer/nrf51_timer.h"
141
+#include "trace.h"
142
+
143
+#define TIMER_CLK_FREQ 16000000UL
144
+
145
+static uint32_t const bitwidths[] = {16, 8, 24, 32};
146
+
147
+static uint32_t ns_to_ticks(NRF51TimerState *s, int64_t ns)
148
+{
149
+ uint32_t freq = TIMER_CLK_FREQ >> s->prescaler;
150
+
151
+ return muldiv64(ns, freq, NANOSECONDS_PER_SECOND);
152
+}
153
+
154
+static int64_t ticks_to_ns(NRF51TimerState *s, uint32_t ticks)
155
+{
156
+ uint32_t freq = TIMER_CLK_FREQ >> s->prescaler;
157
+
158
+ return muldiv64(ticks, NANOSECONDS_PER_SECOND, freq);
159
+}
160
+
161
+/* Returns number of ticks since last call */
162
+static uint32_t update_counter(NRF51TimerState *s, int64_t now)
163
+{
164
+ uint32_t ticks = ns_to_ticks(s, now - s->update_counter_ns);
165
+
166
+ s->counter = (s->counter + ticks) % BIT(bitwidths[s->bitmode]);
167
+ s->update_counter_ns = now;
168
+ return ticks;
169
+}
170
+
171
+/* Assumes s->counter is up-to-date */
172
+static void rearm_timer(NRF51TimerState *s, int64_t now)
173
+{
174
+ int64_t min_ns = INT64_MAX;
175
+ size_t i;
176
+
177
+ for (i = 0; i < NRF51_TIMER_REG_COUNT; i++) {
178
+ int64_t delta_ns;
179
+
180
+ if (s->events_compare[i]) {
181
+ continue; /* already expired, ignore it for now */
182
+ }
183
+
184
+ if (s->cc[i] <= s->counter) {
185
+ delta_ns = ticks_to_ns(s, BIT(bitwidths[s->bitmode]) -
186
+ s->counter + s->cc[i]);
187
+ } else {
188
+ delta_ns = ticks_to_ns(s, s->cc[i] - s->counter);
189
+ }
190
+
191
+ if (delta_ns < min_ns) {
192
+ min_ns = delta_ns;
193
+ }
194
+ }
195
+
196
+ if (min_ns != INT64_MAX) {
197
+ timer_mod_ns(&s->timer, now + min_ns);
198
+ }
199
+}
200
+
201
+static void update_irq(NRF51TimerState *s)
202
+{
203
+ bool flag = false;
204
+ size_t i;
205
+
206
+ for (i = 0; i < NRF51_TIMER_REG_COUNT; i++) {
207
+ flag |= s->events_compare[i] && extract32(s->inten, 16 + i, 1);
208
+ }
209
+ qemu_set_irq(s->irq, flag);
210
+}
211
+
212
+static void timer_expire(void *opaque)
213
+{
214
+ NRF51TimerState *s = NRF51_TIMER(opaque);
215
+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
216
+ uint32_t cc_remaining[NRF51_TIMER_REG_COUNT];
217
+ bool should_stop = false;
218
+ uint32_t ticks;
219
+ size_t i;
220
+
221
+ for (i = 0; i < NRF51_TIMER_REG_COUNT; i++) {
222
+ if (s->cc[i] > s->counter) {
223
+ cc_remaining[i] = s->cc[i] - s->counter;
224
+ } else {
225
+ cc_remaining[i] = BIT(bitwidths[s->bitmode]) -
226
+ s->counter + s->cc[i];
227
+ }
228
+ }
229
+
230
+ ticks = update_counter(s, now);
231
+
232
+ for (i = 0; i < NRF51_TIMER_REG_COUNT; i++) {
233
+ if (cc_remaining[i] <= ticks) {
234
+ s->events_compare[i] = 1;
235
+
236
+ if (s->shorts & BIT(i)) {
237
+ s->timer_start_ns = now;
238
+ s->update_counter_ns = s->timer_start_ns;
239
+ s->counter = 0;
240
+ }
241
+
242
+ should_stop |= s->shorts & BIT(i + 8);
243
+ }
244
+ }
245
+
246
+ update_irq(s);
247
+
248
+ if (should_stop) {
249
+ s->running = false;
250
+ timer_del(&s->timer);
251
+ } else {
252
+ rearm_timer(s, now);
253
+ }
254
+}
255
+
256
+static void counter_compare(NRF51TimerState *s)
257
+{
258
+ uint32_t counter = s->counter;
259
+ size_t i;
260
+
261
+ for (i = 0; i < NRF51_TIMER_REG_COUNT; i++) {
262
+ if (counter == s->cc[i]) {
263
+ s->events_compare[i] = 1;
264
+
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;
281
+ case NRF51_TIMER_REG_SHORTS:
282
+ r = s->shorts;
283
+ break;
284
+ case NRF51_TIMER_REG_INTENSET:
285
+ r = s->inten;
286
+ break;
287
+ case NRF51_TIMER_REG_INTENCLR:
288
+ r = s->inten;
289
+ break;
290
+ case NRF51_TIMER_REG_MODE:
291
+ r = s->mode;
292
+ break;
293
+ case NRF51_TIMER_REG_BITMODE:
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:
303
+ qemu_log_mask(LOG_GUEST_ERROR,
304
+ "%s: bad read offset 0x%" HWADDR_PRIx "\n",
305
+ __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;
331
+ case NRF51_TIMER_TASK_STOP:
332
+ case NRF51_TIMER_TASK_SHUTDOWN:
333
+ if (value == NRF51_TRIGGER_TASK) {
334
+ s->running = false;
335
+ timer_del(&s->timer);
336
+ }
337
+ break;
338
+ case NRF51_TIMER_TASK_COUNT:
339
+ if (value == NRF51_TRIGGER_TASK && s->mode == NRF51_TIMER_COUNTER) {
340
+ s->counter = (s->counter + 1) % BIT(bitwidths[s->bitmode]);
341
+ counter_compare(s);
342
+ }
343
+ break;
344
+ case NRF51_TIMER_TASK_CLEAR:
345
+ if (value == NRF51_TRIGGER_TASK) {
346
+ s->timer_start_ns = now;
347
+ s->update_counter_ns = s->timer_start_ns;
348
+ s->counter = 0;
349
+ if (s->running) {
350
+ rearm_timer(s, now);
351
+ }
352
+ }
353
+ break;
354
+ case NRF51_TIMER_TASK_CAPTURE_0 ... NRF51_TIMER_TASK_CAPTURE_3:
355
+ if (value == NRF51_TRIGGER_TASK) {
356
+ if (s->running) {
357
+ timer_expire(s); /* update counter and all state */
358
+ }
359
+
360
+ idx = (offset - NRF51_TIMER_TASK_CAPTURE_0) / 4;
361
+ s->cc[idx] = s->counter;
362
+ }
363
+ break;
364
+ case NRF51_TIMER_EVENT_COMPARE_0 ... NRF51_TIMER_EVENT_COMPARE_3:
365
+ if (value == NRF51_EVENT_CLEAR) {
366
+ s->events_compare[(offset - NRF51_TIMER_EVENT_COMPARE_0) / 4] = 0;
367
+
368
+ if (s->running) {
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,
415
+ "%s: bad write offset 0x%" HWADDR_PRIx "\n",
416
+ __func__, offset);
417
+ }
418
+
419
+ update_irq(s);
420
+}
421
+
422
+static const MemoryRegionOps rng_ops = {
423
+ .read = nrf51_timer_read,
424
+ .write = nrf51_timer_write,
425
+ .endianness = DEVICE_LITTLE_ENDIAN,
426
+ .impl.min_access_size = 4,
427
+ .impl.max_access_size = 4,
428
+};
429
+
430
+static void nrf51_timer_init(Object *obj)
431
+{
432
+ NRF51TimerState *s = NRF51_TIMER(obj);
433
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
434
+
435
+ memory_region_init_io(&s->iomem, obj, &rng_ops, s,
436
+ TYPE_NRF51_TIMER, NRF51_TIMER_SIZE);
437
+ sysbus_init_mmio(sbd, &s->iomem);
438
+ sysbus_init_irq(sbd, &s->irq);
439
+
440
+ timer_init_ns(&s->timer, QEMU_CLOCK_VIRTUAL, timer_expire, s);
441
+}
442
+
443
+static void nrf51_timer_reset(DeviceState *dev)
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,
36
+ .version_id = 1,
475
+ .version_id = 1,
37
+ .minimum_version_id = 1,
476
+ .post_load = nrf51_timer_post_load,
38
+ .needed = pmsav7_rnr_needed,
39
+ .fields = (VMStateField[]) {
477
+ .fields = (VMStateField[]) {
40
+ VMSTATE_UINT32(env.pmsav7.rnr, ARMCPU),
478
+ VMSTATE_TIMER(timer, NRF51TimerState),
479
+ VMSTATE_INT64(timer_start_ns, NRF51TimerState),
480
+ VMSTATE_INT64(update_counter_ns, NRF51TimerState),
481
+ VMSTATE_UINT32(counter, NRF51TimerState),
482
+ VMSTATE_BOOL(running, NRF51TimerState),
483
+ VMSTATE_UINT8_ARRAY(events_compare, NRF51TimerState,
484
+ NRF51_TIMER_REG_COUNT),
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),
41
+ VMSTATE_END_OF_LIST()
491
+ VMSTATE_END_OF_LIST()
42
+ }
492
+ }
43
+};
493
+};
44
+
494
+
45
static int get_cpsr(QEMUFile *f, void *opaque, size_t size,
495
+static void nrf51_timer_class_init(ObjectClass *klass, void *data)
46
VMStateField *field)
496
+{
47
{
497
+ DeviceClass *dc = DEVICE_CLASS(klass);
48
@@ -XXX,XX +XXX,XX @@ const VMStateDescription vmstate_arm_cpu = {
498
+
49
&vmstate_iwmmxt,
499
+ dc->reset = nrf51_timer_reset;
50
&vmstate_m,
500
+ dc->vmsd = &vmstate_nrf51_timer;
51
&vmstate_thumb2ee,
501
+}
52
+ /* pmsav7_rnr must come before pmsav7 so that we have the
502
+
53
+ * region number before we test it in the VMSTATE_VALIDATE
503
+static const TypeInfo nrf51_timer_info = {
54
+ * in vmstate_pmsav7.
504
+ .name = TYPE_NRF51_TIMER,
55
+ */
505
+ .parent = TYPE_SYS_BUS_DEVICE,
56
+ &vmstate_pmsav7_rnr,
506
+ .instance_size = sizeof(NRF51TimerState),
57
&vmstate_pmsav7,
507
+ .instance_init = nrf51_timer_init,
58
NULL
508
+ .class_init = nrf51_timer_class_init
59
}
509
+};
510
+
511
+static void nrf51_timer_register_types(void)
512
+{
513
+ type_register_static(&nrf51_timer_info);
514
+}
515
+
516
+type_init(nrf51_timer_register_types)
517
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
518
index XXXXXXX..XXXXXXX 100644
519
--- a/hw/timer/trace-events
520
+++ b/hw/timer/trace-events
521
@@ -XXX,XX +XXX,XX @@ sun4v_rtc_write(uint64_t addr, uint64_t value) "write: addr 0x%" PRIx64 " value
522
523
# hw/timer/xlnx-zynqmp-rtc.c
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"
525
+
526
+# hw/timer/nrf51_timer.c
527
+nrf51_timer_read(uint64_t addr, uint32_t value, unsigned size) "read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
528
+nrf51_timer_write(uint64_t addr, uint32_t value, unsigned size) "write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
529
+
60
--
530
--
61
2.7.4
531
2.19.2
62
532
63
533
diff view generated by jsdifflib
1
When the PMSAv7 implementation was originally added it was for R profile
1
From: Steffen Görtz <contrib@steffen-goertz.de>
2
CPUs only, and reset was handled using the cpreg .resetfn hooks.
3
Unfortunately for M profile cores this doesn't work, because they do
4
not register any cpregs. Move the reset handling into arm_cpu_reset(),
5
where it will work for both R profile and M profile cores.
6
2
3
Instantiates TIMER0 - TIMER2
4
5
Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
6
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Message-id: 20190103091119.9367-10-stefanha@redhat.com
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 1501153150-19984-5-git-send-email-peter.maydell@linaro.org
10
---
11
---
11
target/arm/cpu.c | 14 ++++++++++++++
12
include/hw/arm/nrf51_soc.h | 4 ++++
12
target/arm/helper.c | 28 ++++++++++++----------------
13
hw/arm/nrf51_soc.c | 26 ++++++++++++++++++++++++++
13
2 files changed, 26 insertions(+), 16 deletions(-)
14
2 files changed, 30 insertions(+)
14
15
15
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
16
diff --git a/include/hw/arm/nrf51_soc.h b/include/hw/arm/nrf51_soc.h
16
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/cpu.c
18
--- a/include/hw/arm/nrf51_soc.h
18
+++ b/target/arm/cpu.c
19
+++ b/include/hw/arm/nrf51_soc.h
19
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
20
@@ -XXX,XX +XXX,XX @@
20
21
#include "hw/char/nrf51_uart.h"
21
env->vfp.xregs[ARM_VFP_FPEXC] = 0;
22
#include "hw/misc/nrf51_rng.h"
22
#endif
23
#include "hw/gpio/nrf51_gpio.h"
24
+#include "hw/timer/nrf51_timer.h"
25
26
#define TYPE_NRF51_SOC "nrf51-soc"
27
#define NRF51_SOC(obj) \
28
OBJECT_CHECK(NRF51State, (obj), TYPE_NRF51_SOC)
29
30
+#define NRF51_NUM_TIMERS 3
23
+
31
+
24
+ if (arm_feature(env, ARM_FEATURE_PMSA) &&
32
typedef struct NRF51State {
25
+ arm_feature(env, ARM_FEATURE_V7)) {
33
/*< private >*/
26
+ if (cpu->pmsav7_dregion > 0) {
34
SysBusDevice parent_obj;
27
+ memset(env->pmsav7.drbar, 0,
35
@@ -XXX,XX +XXX,XX @@ typedef struct NRF51State {
28
+ sizeof(*env->pmsav7.drbar) * cpu->pmsav7_dregion);
36
NRF51UARTState uart;
29
+ memset(env->pmsav7.drsr, 0,
37
NRF51RNGState rng;
30
+ sizeof(*env->pmsav7.drsr) * cpu->pmsav7_dregion);
38
NRF51GPIOState gpio;
31
+ memset(env->pmsav7.dracr, 0,
39
+ NRF51TimerState timer[NRF51_NUM_TIMERS];
32
+ sizeof(*env->pmsav7.dracr) * cpu->pmsav7_dregion);
40
41
MemoryRegion iomem;
42
MemoryRegion sram;
43
diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/hw/arm/nrf51_soc.c
46
+++ b/hw/arm/nrf51_soc.c
47
@@ -XXX,XX +XXX,XX @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
48
NRF51State *s = NRF51_SOC(dev_soc);
49
MemoryRegion *mr;
50
Error *err = NULL;
51
+ uint8_t i = 0;
52
+ hwaddr base_addr = 0;
53
54
if (!s->board_memory) {
55
error_setg(errp, "memory property was not set");
56
@@ -XXX,XX +XXX,XX @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
57
/* Pass all GPIOs to the SOC layer so they are available to the board */
58
qdev_pass_gpios(DEVICE(&s->gpio), dev_soc, NULL);
59
60
+ /* TIMER */
61
+ for (i = 0; i < NRF51_NUM_TIMERS; i++) {
62
+ object_property_set_bool(OBJECT(&s->timer[i]), true, "realized", &err);
63
+ if (err) {
64
+ error_propagate(errp, err);
65
+ return;
33
+ }
66
+ }
34
+ env->pmsav7.rnr = 0;
67
+
68
+ base_addr = NRF51_TIMER_BASE + i * NRF51_TIMER_SIZE;
69
+
70
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->timer[i]), 0, base_addr);
71
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer[i]), 0,
72
+ qdev_get_gpio_in(DEVICE(&s->cpu),
73
+ BASE_TO_IRQ(base_addr)));
35
+ }
74
+ }
36
+
75
+
37
set_flush_to_zero(1, &env->vfp.standard_fp_status);
76
create_unimplemented_device("nrf51_soc.io", NRF51_IOMEM_BASE,
38
set_flush_inputs_to_zero(1, &env->vfp.standard_fp_status);
77
NRF51_IOMEM_SIZE);
39
set_default_nan_mode(1, &env->vfp.standard_fp_status);
78
create_unimplemented_device("nrf51_soc.ficr", NRF51_FICR_BASE,
40
diff --git a/target/arm/helper.c b/target/arm/helper.c
79
@@ -XXX,XX +XXX,XX @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
41
index XXXXXXX..XXXXXXX 100644
80
42
--- a/target/arm/helper.c
81
static void nrf51_soc_init(Object *obj)
43
+++ b/target/arm/helper.c
82
{
44
@@ -XXX,XX +XXX,XX @@ static void pmsav7_write(CPUARMState *env, const ARMCPRegInfo *ri,
83
+ uint8_t i = 0;
45
*u32p = value;
84
+
85
NRF51State *s = NRF51_SOC(obj);
86
87
memory_region_init(&s->container, obj, "nrf51-container", UINT64_MAX);
88
@@ -XXX,XX +XXX,XX @@ static void nrf51_soc_init(Object *obj)
89
90
sysbus_init_child_obj(obj, "gpio", &s->gpio, sizeof(s->gpio),
91
TYPE_NRF51_GPIO);
92
+
93
+ for (i = 0; i < NRF51_NUM_TIMERS; i++) {
94
+ sysbus_init_child_obj(obj, "timer[*]", &s->timer[i],
95
+ sizeof(s->timer[i]), TYPE_NRF51_TIMER);
96
+
97
+ }
46
}
98
}
47
99
48
-static void pmsav7_reset(CPUARMState *env, const ARMCPRegInfo *ri)
100
static Property nrf51_soc_properties[] = {
49
-{
50
- ARMCPU *cpu = arm_env_get_cpu(env);
51
- uint32_t *u32p = *(uint32_t **)raw_ptr(env, ri);
52
-
53
- if (!u32p) {
54
- return;
55
- }
56
-
57
- memset(u32p, 0, sizeof(*u32p) * cpu->pmsav7_dregion);
58
-}
59
-
60
static void pmsav7_rgnr_write(CPUARMState *env, const ARMCPRegInfo *ri,
61
uint64_t value)
62
{
63
@@ -XXX,XX +XXX,XX @@ static void pmsav7_rgnr_write(CPUARMState *env, const ARMCPRegInfo *ri,
64
}
65
66
static const ARMCPRegInfo pmsav7_cp_reginfo[] = {
67
+ /* Reset for all these registers is handled in arm_cpu_reset(),
68
+ * because the PMSAv7 is also used by M-profile CPUs, which do
69
+ * not register cpregs but still need the state to be reset.
70
+ */
71
{ .name = "DRBAR", .cp = 15, .crn = 6, .opc1 = 0, .crm = 1, .opc2 = 0,
72
.access = PL1_RW, .type = ARM_CP_NO_RAW,
73
.fieldoffset = offsetof(CPUARMState, pmsav7.drbar),
74
- .readfn = pmsav7_read, .writefn = pmsav7_write, .resetfn = pmsav7_reset },
75
+ .readfn = pmsav7_read, .writefn = pmsav7_write,
76
+ .resetfn = arm_cp_reset_ignore },
77
{ .name = "DRSR", .cp = 15, .crn = 6, .opc1 = 0, .crm = 1, .opc2 = 2,
78
.access = PL1_RW, .type = ARM_CP_NO_RAW,
79
.fieldoffset = offsetof(CPUARMState, pmsav7.drsr),
80
- .readfn = pmsav7_read, .writefn = pmsav7_write, .resetfn = pmsav7_reset },
81
+ .readfn = pmsav7_read, .writefn = pmsav7_write,
82
+ .resetfn = arm_cp_reset_ignore },
83
{ .name = "DRACR", .cp = 15, .crn = 6, .opc1 = 0, .crm = 1, .opc2 = 4,
84
.access = PL1_RW, .type = ARM_CP_NO_RAW,
85
.fieldoffset = offsetof(CPUARMState, pmsav7.dracr),
86
- .readfn = pmsav7_read, .writefn = pmsav7_write, .resetfn = pmsav7_reset },
87
+ .readfn = pmsav7_read, .writefn = pmsav7_write,
88
+ .resetfn = arm_cp_reset_ignore },
89
{ .name = "RGNR", .cp = 15, .crn = 6, .opc1 = 0, .crm = 2, .opc2 = 0,
90
.access = PL1_RW,
91
.fieldoffset = offsetof(CPUARMState, pmsav7.rnr),
92
- .writefn = pmsav7_rgnr_write },
93
+ .writefn = pmsav7_rgnr_write,
94
+ .resetfn = arm_cp_reset_ignore },
95
REGINFO_SENTINEL
96
};
97
98
--
101
--
99
2.7.4
102
2.19.2
100
103
101
104
diff view generated by jsdifflib
1
For an M profile v7PMSA, the system space (0xe0000000 - 0xffffffff) can
1
From: Steffen Görtz <contrib@steffen-goertz.de>
2
never be executable, even if the guest tries to set the MPU registers
3
up that way. Enforce this restriction.
4
2
3
Basic tests for nRF51 Timer Peripheral.
4
5
Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
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
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 1501153150-19984-3-git-send-email-peter.maydell@linaro.org
8
---
10
---
9
target/arm/helper.c | 16 +++++++++++++++-
11
tests/microbit-test.c | 95 +++++++++++++++++++++++++++++++++++++++++++
10
1 file changed, 15 insertions(+), 1 deletion(-)
12
1 file changed, 95 insertions(+)
11
13
12
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
diff --git a/tests/microbit-test.c b/tests/microbit-test.c
13
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/helper.c
16
--- a/tests/microbit-test.c
15
+++ b/target/arm/helper.c
17
+++ b/tests/microbit-test.c
16
@@ -XXX,XX +XXX,XX @@ static inline bool m_is_ppb_region(CPUARMState *env, uint32_t address)
18
@@ -XXX,XX +XXX,XX @@
17
extract32(address, 20, 12) == 0xe00;
19
20
#include "hw/arm/nrf51.h"
21
#include "hw/gpio/nrf51_gpio.h"
22
+#include "hw/timer/nrf51_timer.h"
23
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);
18
}
28
}
19
29
20
+static inline bool m_is_system_region(CPUARMState *env, uint32_t address)
30
+static void timer_task(hwaddr task)
21
+{
31
+{
22
+ /* True if address is in the M profile system region
32
+ writel(NRF51_TIMER_BASE + task, NRF51_TRIGGER_TASK);
23
+ * 0xe0000000 - 0xffffffff
24
+ */
25
+ return arm_feature(env, ARM_FEATURE_M) && extract32(address, 29, 3) == 0x7;
26
+}
33
+}
27
+
34
+
28
static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address,
35
+static void timer_clear_event(hwaddr event)
29
int access_type, ARMMMUIdx mmu_idx,
36
+{
30
hwaddr *phys_ptr, int *prot, uint32_t *fsr)
37
+ writel(NRF51_TIMER_BASE + event, NRF51_EVENT_CLEAR);
31
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address,
38
+}
32
get_phys_addr_pmsav7_default(env, mmu_idx, address, prot);
33
} else { /* a MPU hit! */
34
uint32_t ap = extract32(env->pmsav7.dracr[n], 8, 3);
35
+ uint32_t xn = extract32(env->pmsav7.dracr[n], 12, 1);
36
+
39
+
37
+ if (m_is_system_region(env, address)) {
40
+static void timer_set_bitmode(uint8_t mode)
38
+ /* System space is always execute never */
41
+{
39
+ xn = 1;
42
+ writel(NRF51_TIMER_BASE + NRF51_TIMER_REG_BITMODE, mode);
40
+ }
43
+}
41
44
+
42
if (is_user) { /* User mode AP bit decoding */
45
+static void timer_set_prescaler(uint8_t prescaler)
43
switch (ap) {
46
+{
44
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address,
47
+ writel(NRF51_TIMER_BASE + NRF51_TIMER_REG_PRESCALER, prescaler);
45
}
48
+}
46
49
+
47
/* execute never */
50
+static void timer_set_cc(size_t idx, uint32_t value)
48
- if (env->pmsav7.dracr[n] & (1 << 12)) {
51
+{
49
+ if (xn) {
52
+ writel(NRF51_TIMER_BASE + NRF51_TIMER_REG_CC0 + idx * 4, value);
50
*prot &= ~PAGE_EXEC;
53
+}
51
}
54
+
52
}
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
53
--
134
--
54
2.7.4
135
2.19.2
55
136
56
137
diff view generated by jsdifflib
New patch
1
From: Steffen Görtz <contrib@steffen-goertz.de>
1
2
3
This stubs enables the microbit-micropython firmware to run
4
on the microbit machine.
5
6
Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
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
18
--- a/include/hw/arm/nrf51_soc.h
19
+++ b/include/hw/arm/nrf51_soc.h
20
@@ -XXX,XX +XXX,XX @@ typedef struct NRF51State {
21
MemoryRegion iomem;
22
MemoryRegion sram;
23
MemoryRegion flash;
24
+ MemoryRegion clock;
25
26
uint32_t sram_size;
27
uint32_t flash_size;
28
diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/hw/arm/nrf51_soc.c
31
+++ b/hw/arm/nrf51_soc.c
32
@@ -XXX,XX +XXX,XX @@
33
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
}
62
63
+ /* STUB Peripherals */
64
+ memory_region_init_io(&s->clock, NULL, &clock_ops, NULL,
65
+ "nrf51_soc.clock", 0x1000);
66
+ memory_region_add_subregion_overlap(&s->container,
67
+ NRF51_IOMEM_BASE, &s->clock, -1);
68
+
69
create_unimplemented_device("nrf51_soc.io", NRF51_IOMEM_BASE,
70
NRF51_IOMEM_SIZE);
71
create_unimplemented_device("nrf51_soc.ficr", NRF51_FICR_BASE,
72
--
73
2.19.2
74
75
diff view generated by jsdifflib
1
Correct off-by-one bug in the PSMAv7 MPU tracing where it would print
1
Now that MTTCG is here, the comment in the 32-bit Arm decoder that
2
a write access as "reading", an insn fetch as "writing", and a read
2
"Since the emulation does not have barriers, the acquire/release
3
access as "execute".
3
semantics need no special handling" is no longer true. Emit the
4
4
correct barriers for the load-acquire/store-release insns, as
5
Since we have an MMUAccessType enum now, we can make the code clearer
5
we already do in the A64 decoder.
6
in the process by using that rather than the raw 0/1/2 values.
7
6
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <rth@twiddle.net>
8
Tested-by: Alex Bennée <alex.bennee@linaro.org>
10
Message-id: 1500906792-18010-1-git-send-email-peter.maydell@linaro.org
9
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
11
---
10
---
12
target/arm/helper.c | 4 ++--
11
target/arm/translate.c | 33 ++++++++++++++++++++++++++-------
13
1 file changed, 2 insertions(+), 2 deletions(-)
12
1 file changed, 26 insertions(+), 7 deletions(-)
14
13
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
diff --git a/target/arm/translate.c b/target/arm/translate.c
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.c
16
--- a/target/arm/translate.c
18
+++ b/target/arm/helper.c
17
+++ b/target/arm/translate.c
19
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr(CPUARMState *env, target_ulong address,
18
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
20
phys_ptr, prot, fsr);
19
rd = (insn >> 12) & 0xf;
21
qemu_log_mask(CPU_LOG_MMU, "PMSAv7 MPU lookup for %s at 0x%08" PRIx32
20
if (insn & (1 << 23)) {
22
" mmu_idx %u -> %s (prot %c%c%c)\n",
21
/* load/store exclusive */
23
- access_type == 1 ? "reading" :
22
+ bool is_ld = extract32(insn, 20, 1);
24
- (access_type == 2 ? "writing" : "execute"),
23
+ bool is_lasr = !extract32(insn, 8, 1);
25
+ access_type == MMU_DATA_LOAD ? "reading" :
24
int op2 = (insn >> 8) & 3;
26
+ (access_type == MMU_DATA_STORE ? "writing" : "execute"),
25
op1 = (insn >> 21) & 0x3;
27
(uint32_t)address, mmu_idx,
26
28
ret ? "Miss" : "Hit",
27
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
29
*prot & PAGE_READ ? 'r' : '-',
28
addr = tcg_temp_local_new_i32();
29
load_reg_var(s, addr, rn);
30
31
- /* Since the emulation does not have barriers,
32
- the acquire/release semantics need no special
33
- handling */
34
+ if (is_lasr && !is_ld) {
35
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
36
+ }
37
+
38
if (op2 == 0) {
39
- if (insn & (1 << 20)) {
40
+ if (is_ld) {
41
tmp = tcg_temp_new_i32();
42
switch (op1) {
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. */
30
--
111
--
31
2.7.4
112
2.19.2
32
113
33
114
diff view generated by jsdifflib
New patch
1
In the TZ Memory Protection Controller, the BLK_MAX register is supposed
2
to return the maximum permitted value of the BLK_IDX register. Our
3
implementation incorrectly returned max+1 (ie the total number of
4
valid index values, since BLK_IDX is zero-based).
1
5
6
Correct this off-by-one error. Since we consistently initialize
7
and use s->blk_max throughout the implementation as the 'size'
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
12
Fixes: https://bugs.launchpad.net/qemu/+bug/1806824
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20181213183249.3468-1-peter.maydell@linaro.org
16
---
17
hw/misc/tz-mpc.c | 2 +-
18
1 file changed, 1 insertion(+), 1 deletion(-)
19
20
diff --git a/hw/misc/tz-mpc.c b/hw/misc/tz-mpc.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/misc/tz-mpc.c
23
+++ b/hw/misc/tz-mpc.c
24
@@ -XXX,XX +XXX,XX @@ static MemTxResult tz_mpc_reg_read(void *opaque, hwaddr addr,
25
r = s->ctrl;
26
break;
27
case A_BLK_MAX:
28
- r = s->blk_max;
29
+ r = s->blk_max - 1;
30
break;
31
case A_BLK_CFG:
32
/* We are never in "init in progress state", so this just indicates
33
--
34
2.19.2
35
36
diff view generated by jsdifflib
New patch
1
From: Nick Hudson <nick.hudson@gmx.co.uk>
1
2
3
noload kernels are loaded with the u-boot image header and as a result
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
8
The default location for the uboot file is 32MiB above bottom of DRAM.
9
This matches the recommendation in Documentation/arm/Booting.
10
11
Clarify the load_uimage API to state the passing of a load address when an
12
image doesn't specify one, or when loading a ramdisk is expected.
13
14
Adjust callers of load_uimage, etc.
15
16
Signed-off-by: Nick Hudson <skrll@netbsd.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>
20
---
21
hw/core/uboot_image.h | 1 +
22
include/hw/loader.h | 7 ++++++-
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
32
diff --git a/hw/core/uboot_image.h b/hw/core/uboot_image.h
33
index XXXXXXX..XXXXXXX 100644
34
--- a/hw/core/uboot_image.h
35
+++ b/hw/core/uboot_image.h
36
@@ -XXX,XX +XXX,XX @@
37
#define IH_TYPE_SCRIPT        6    /* Script file            */
38
#define IH_TYPE_FILESYSTEM    7    /* Filesystem Image (any type)    */
39
#define IH_TYPE_FLATDT        8    /* Binary Flat Device Tree Blob    */
40
+#define IH_TYPE_KERNEL_NOLOAD 14    /* OS Kernel Image (noload)    */
41
42
/*
43
* Compression Types
44
diff --git a/include/hw/loader.h b/include/hw/loader.h
45
index XXXXXXX..XXXXXXX 100644
46
--- a/include/hw/loader.h
47
+++ b/include/hw/loader.h
48
@@ -XXX,XX +XXX,XX @@ void load_elf_hdr(const char *filename, void *hdr, bool *is64, Error **errp);
49
int load_aout(const char *filename, hwaddr addr, int max_sz,
50
int bswap_needed, hwaddr target_page_size);
51
52
+#define LOAD_UIMAGE_LOADADDR_INVALID (-1)
53
+
54
/** load_uimage_as:
55
* @filename: Path of uimage file
56
* @ep: Populated with program entry point. Ignored if NULL.
57
- * @loadaddr: Populated with the load address. Ignored if NULL.
58
+ * @loadaddr: load address if none specified in the image or when loading a
59
+ * ramdisk. Populated with the load address. Ignored if NULL or
60
+ * LOAD_UIMAGE_LOADADDR_INVALID (images which do not specify a load
61
+ * address will not be loadable).
62
* @is_linux: Is set to true if the image loaded is Linux. Ignored if NULL.
63
* @translate_fn: optional function to translate load addresses
64
* @translate_opaque: opaque data passed to @translate_fn
65
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
66
index XXXXXXX..XXXXXXX 100644
67
--- a/hw/arm/boot.c
68
+++ b/hw/arm/boot.c
69
@@ -XXX,XX +XXX,XX @@
70
* Documentation/arm/Booting and Documentation/arm64/booting.txt
71
* They have different preferred image load offsets from system RAM base.
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
--
190
2.19.2
191
192
diff view generated by jsdifflib