1
Second lot of ARM changes to sneak in before freeze:
1
Last minute pullreq for arm related patches; quite large because
2
* fixed version of the raspi2 sd controller patches
2
there were several series that only just made it through code review
3
* GICv3 save/restore
3
in time.
4
* v7M QOMify
5
6
I've also included the Linux header update patches stolen
7
from Paolo's pullreq since it hasn't quite hit master yet.
8
4
9
thanks
5
thanks
10
-- PMM
6
-- PMM
11
7
12
The following changes since commit 1bbe5dc66b770d7bedd1d51d7935da948a510dd6:
8
The following changes since commit 091e3e3dbc499d84c004e1c50bc9870af37f6e99:
13
9
14
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20170228' into staging (2017-02-28 14:50:17 +0000)
10
Merge remote-tracking branch 'remotes/ericb/tags/pull-bitmaps-2020-10-26' into staging (2020-10-26 22:36:35 +0000)
15
11
16
are available in the git repository at:
12
are available in the Git repository at:
17
13
18
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20170228-1
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20201027-1
19
15
20
for you to fetch changes up to 1eeb5c7deacbfb4d4cad17590a16a99f3d85eabb:
16
for you to fetch changes up to 32bd322a0134ed89db00f2b9b3894982db3dedcb:
21
17
22
bcm2835: add sdhost and gpio controllers (2017-02-28 17:10:00 +0000)
18
hw/timer/armv7m_systick: Rewrite to use ptimers (2020-10-27 11:15:31 +0000)
23
19
24
----------------------------------------------------------------
20
----------------------------------------------------------------
25
target-arm queue:
21
target-arm queue:
26
* raspi2: add gpio controller and sdhost controller, with
22
* raspi: add model of cprman clock manager
27
the wiring so the guest can switch which controller the
23
* sbsa-ref: add an SBSA generic watchdog device
28
SD card is attached to
24
* arm/trace: Fix hex printing
29
(this is sufficient to get raspbian kernels to boot)
25
* raspi: Add models of Pi 3 model A+, Pi Zero and Pi A+
30
* GICv3: support state save/restore from KVM
26
* hw/arm/smmuv3: Set the restoration priority of the vSMMUv3 explicitly
31
* update Linux headers to 4.11
27
* Nuvoton NPCM7xx: Add USB, RNG, GPIO and watchdog support
32
* refactor and QOMify the ARMv7M container object
28
* hw/arm: fix min_cpus for xlnx-versal-virt platform
29
* hw/arm/highbank: Silence warnings about missing fallthrough statements
30
* linux-user: Support Aarch64 BTI
31
* Armv7M systick: fix corner case bugs by rewriting to use ptimer
33
32
34
----------------------------------------------------------------
33
----------------------------------------------------------------
35
Clement Deschamps (3):
34
Dr. David Alan Gilbert (1):
36
hw/sd: add card-reparenting function
35
arm/trace: Fix hex printing
37
bcm2835_gpio: add bcm2835 gpio controller
38
bcm2835: add sdhost and gpio controllers
39
36
40
Paolo Bonzini (2):
37
Hao Wu (1):
41
update-linux-headers: update for 4.11
38
hw/timer: Adding watchdog for NPCM7XX Timer.
42
update Linux headers to 4.11
43
39
44
Peter Maydell (12):
40
Havard Skinnemoen (4):
45
armv7m: Abstract out the "load kernel" code
41
Move npcm7xx_timer_reached_zero call out of npcm7xx_timer_pause
46
armv7m: Move NVICState struct definition into header
42
hw/misc: Add npcm7xx random number generator
47
armv7m: QOMify the armv7m container
43
hw/arm/npcm7xx: Add EHCI and OHCI controllers
48
armv7m: Use QOMified armv7m object in armv7m_init()
44
hw/gpio: Add GPIO model for Nuvoton NPCM7xx
49
armv7m: Make ARMv7M object take memory region link
50
armv7m: Make NVIC expose a memory region rather than mapping itself
51
armv7m: Make bitband device take the address space to access
52
armv7m: Don't put core v7M devices under CONFIG_STELLARIS
53
armv7m: Split systick out from NVIC
54
stm32f205: Create armv7m object without using armv7m_init()
55
stm32f205: Rename 'nvic' local to 'armv7m'
56
qdev: Have qdev_set_parent_bus() handle devices already on a bus
57
45
58
Vijaya Kumar K (4):
46
Luc Michel (14):
59
hw/intc/arm_gicv3_kvm: Add ICC_SRE_EL1 register to vmstate
47
hw/core/clock: provide the VMSTATE_ARRAY_CLOCK macro
60
hw/intc/arm_gicv3_kvm: Implement get/put functions
48
hw/core/clock: trace clock values in Hz instead of ns
61
target-arm: Add GICv3CPUState in CPUARMState struct
49
hw/arm/raspi: fix CPRMAN base address
62
hw/intc/arm_gicv3_kvm: Reset GICv3 cpu interface registers
50
hw/arm/raspi: add a skeleton implementation of the CPRMAN
51
hw/misc/bcm2835_cprman: add a PLL skeleton implementation
52
hw/misc/bcm2835_cprman: implement PLLs behaviour
53
hw/misc/bcm2835_cprman: add a PLL channel skeleton implementation
54
hw/misc/bcm2835_cprman: implement PLL channels behaviour
55
hw/misc/bcm2835_cprman: add a clock mux skeleton implementation
56
hw/misc/bcm2835_cprman: implement clock mux behaviour
57
hw/misc/bcm2835_cprman: add the DSI0HSCK multiplexer
58
hw/misc/bcm2835_cprman: add sane reset values to the registers
59
hw/char/pl011: add a clock input
60
hw/arm/bcm2835_peripherals: connect the UART clock
63
61
64
hw/gpio/Makefile.objs | 1 +
62
Pavel Dovgalyuk (1):
65
hw/intc/Makefile.objs | 2 +-
63
hw/arm: fix min_cpus for xlnx-versal-virt platform
66
hw/timer/Makefile.objs | 1 +
67
hw/intc/gicv3_internal.h | 3 +
68
include/hw/arm/arm.h | 12 +
69
include/hw/arm/armv7m.h | 63 +++
70
include/hw/arm/armv7m_nvic.h | 62 ++
71
include/hw/arm/bcm2835_peripherals.h | 4 +
72
include/hw/arm/stm32f205_soc.h | 4 +-
73
include/hw/gpio/bcm2835_gpio.h | 39 ++
74
include/hw/intc/arm_gicv3_common.h | 1 +
75
include/hw/sd/sd.h | 11 +
76
include/hw/timer/armv7m_systick.h | 34 ++
77
include/standard-headers/asm-x86/hyperv.h | 8 +
78
include/standard-headers/linux/input-event-codes.h | 2 +-
79
include/standard-headers/linux/pci_regs.h | 25 +
80
include/standard-headers/linux/virtio_ids.h | 1 +
81
linux-headers/asm-arm/kvm.h | 15 +
82
linux-headers/asm-arm/unistd-common.h | 357 ++++++++++++
83
linux-headers/asm-arm/unistd-eabi.h | 5 +
84
linux-headers/asm-arm/unistd-oabi.h | 17 +
85
linux-headers/asm-arm/unistd.h | 419 +-------------
86
linux-headers/asm-arm64/kvm.h | 13 +
87
linux-headers/asm-powerpc/kvm.h | 27 +
88
linux-headers/asm-powerpc/unistd.h | 1 +
89
linux-headers/asm-x86/kvm_para.h | 13 +-
90
linux-headers/linux/kvm.h | 24 +-
91
linux-headers/linux/kvm_para.h | 2 +
92
linux-headers/linux/userfaultfd.h | 67 ++-
93
linux-headers/linux/vfio.h | 10 +
94
target/arm/cpu.h | 2 +
95
hw/arm/armv7m.c | 379 ++++++++-----
96
hw/arm/bcm2835_peripherals.c | 43 +-
97
hw/arm/netduino2.c | 7 +-
98
hw/arm/stm32f205_soc.c | 28 +-
99
hw/core/qdev.c | 14 +
100
hw/gpio/bcm2835_gpio.c | 353 ++++++++++++
101
hw/intc/arm_gicv3_common.c | 38 ++
102
hw/intc/arm_gicv3_cpuif.c | 8 +
103
hw/intc/arm_gicv3_kvm.c | 629 ++++++++++++++++++++-
104
hw/intc/armv7m_nvic.c | 214 ++-----
105
hw/sd/core.c | 27 +
106
hw/timer/armv7m_systick.c | 240 ++++++++
107
default-configs/arm-softmmu.mak | 2 +
108
hw/timer/trace-events | 6 +
109
scripts/update-linux-headers.sh | 13 +-
110
46 files changed, 2479 insertions(+), 767 deletions(-)
111
create mode 100644 include/hw/arm/armv7m.h
112
create mode 100644 include/hw/arm/armv7m_nvic.h
113
create mode 100644 include/hw/gpio/bcm2835_gpio.h
114
create mode 100644 include/hw/timer/armv7m_systick.h
115
create mode 100644 linux-headers/asm-arm/unistd-common.h
116
create mode 100644 linux-headers/asm-arm/unistd-eabi.h
117
create mode 100644 linux-headers/asm-arm/unistd-oabi.h
118
create mode 100644 hw/gpio/bcm2835_gpio.c
119
create mode 100644 hw/timer/armv7m_systick.c
120
64
65
Peter Maydell (2):
66
hw/core/ptimer: Support ptimer being disabled by timer callback
67
hw/timer/armv7m_systick: Rewrite to use ptimers
68
69
Philippe Mathieu-Daudé (10):
70
linux-user/elfload: Avoid leaking interp_name using GLib memory API
71
hw/arm/bcm2836: Restrict BCM283XInfo declaration to C source
72
hw/arm/bcm2836: QOM'ify more by adding class_init() to each SoC type
73
hw/arm/bcm2836: Introduce BCM283XClass::core_count
74
hw/arm/bcm2836: Only provide "enabled-cpus" property to multicore SoCs
75
hw/arm/bcm2836: Split out common realize() code
76
hw/arm/bcm2836: Introduce the BCM2835 SoC
77
hw/arm/raspi: Add the Raspberry Pi A+ machine
78
hw/arm/raspi: Add the Raspberry Pi Zero machine
79
hw/arm/raspi: Add the Raspberry Pi 3 model A+
80
81
Richard Henderson (11):
82
linux-user/aarch64: Reset btype for signals
83
linux-user: Set PAGE_TARGET_1 for TARGET_PROT_BTI
84
include/elf: Add defines related to GNU property notes for AArch64
85
linux-user/elfload: Fix coding style in load_elf_image
86
linux-user/elfload: Adjust iteration over phdr
87
linux-user/elfload: Move PT_INTERP detection to first loop
88
linux-user/elfload: Use Error for load_elf_image
89
linux-user/elfload: Use Error for load_elf_interp
90
linux-user/elfload: Parse NT_GNU_PROPERTY_TYPE_0 notes
91
linux-user/elfload: Parse GNU_PROPERTY_AARCH64_FEATURE_1_AND
92
tests/tcg/aarch64: Add bti smoke tests
93
94
Shashi Mallela (2):
95
hw/watchdog: Implement SBSA watchdog device
96
hw/arm/sbsa-ref: add SBSA watchdog device
97
98
Thomas Huth (1):
99
hw/arm/highbank: Silence warnings about missing fallthrough statements
100
101
Zenghui Yu (1):
102
hw/arm/smmuv3: Set the restoration priority of the vSMMUv3 explicitly
103
104
docs/system/arm/nuvoton.rst | 6 +-
105
hw/usb/hcd-ehci.h | 1 +
106
include/elf.h | 22 +
107
include/exec/cpu-all.h | 2 +
108
include/hw/arm/bcm2835_peripherals.h | 5 +-
109
include/hw/arm/bcm2836.h | 9 +-
110
include/hw/arm/npcm7xx.h | 8 +
111
include/hw/arm/raspi_platform.h | 5 +-
112
include/hw/char/pl011.h | 1 +
113
include/hw/clock.h | 5 +
114
include/hw/gpio/npcm7xx_gpio.h | 55 ++
115
include/hw/misc/bcm2835_cprman.h | 210 ++++++
116
include/hw/misc/bcm2835_cprman_internals.h | 1019 ++++++++++++++++++++++++++++
117
include/hw/misc/npcm7xx_clk.h | 2 +
118
include/hw/misc/npcm7xx_rng.h | 34 +
119
include/hw/timer/armv7m_systick.h | 3 +-
120
include/hw/timer/npcm7xx_timer.h | 48 +-
121
include/hw/watchdog/sbsa_gwdt.h | 79 +++
122
linux-user/qemu.h | 4 +
123
linux-user/syscall_defs.h | 4 +
124
target/arm/cpu.h | 5 +
125
hw/arm/bcm2835_peripherals.c | 15 +-
126
hw/arm/bcm2836.c | 182 +++--
127
hw/arm/highbank.c | 2 +
128
hw/arm/npcm7xx.c | 126 +++-
129
hw/arm/raspi.c | 41 ++
130
hw/arm/sbsa-ref.c | 23 +
131
hw/arm/smmuv3.c | 1 +
132
hw/arm/xlnx-versal-virt.c | 1 +
133
hw/char/pl011.c | 45 ++
134
hw/core/clock.c | 6 +-
135
hw/core/ptimer.c | 4 +
136
hw/gpio/npcm7xx_gpio.c | 424 ++++++++++++
137
hw/misc/bcm2835_cprman.c | 808 ++++++++++++++++++++++
138
hw/misc/npcm7xx_clk.c | 28 +
139
hw/misc/npcm7xx_rng.c | 180 +++++
140
hw/timer/armv7m_systick.c | 124 ++--
141
hw/timer/npcm7xx_timer.c | 270 ++++++--
142
hw/usb/hcd-ehci-sysbus.c | 19 +
143
hw/watchdog/sbsa_gwdt.c | 293 ++++++++
144
linux-user/aarch64/signal.c | 10 +-
145
linux-user/elfload.c | 326 +++++++--
146
linux-user/mmap.c | 16 +
147
target/arm/translate-a64.c | 6 +-
148
tests/qtest/npcm7xx_gpio-test.c | 385 +++++++++++
149
tests/qtest/npcm7xx_rng-test.c | 278 ++++++++
150
tests/qtest/npcm7xx_watchdog_timer-test.c | 319 +++++++++
151
tests/tcg/aarch64/bti-1.c | 62 ++
152
tests/tcg/aarch64/bti-2.c | 116 ++++
153
tests/tcg/aarch64/bti-crt.inc.c | 51 ++
154
MAINTAINERS | 1 +
155
hw/arm/Kconfig | 1 +
156
hw/arm/trace-events | 2 +-
157
hw/char/trace-events | 1 +
158
hw/core/trace-events | 4 +-
159
hw/gpio/meson.build | 1 +
160
hw/gpio/trace-events | 7 +
161
hw/misc/meson.build | 2 +
162
hw/misc/trace-events | 9 +
163
hw/watchdog/Kconfig | 3 +
164
hw/watchdog/meson.build | 1 +
165
tests/qtest/meson.build | 6 +-
166
tests/tcg/aarch64/Makefile.target | 10 +
167
tests/tcg/configure.sh | 4 +
168
64 files changed, 5461 insertions(+), 279 deletions(-)
169
create mode 100644 include/hw/gpio/npcm7xx_gpio.h
170
create mode 100644 include/hw/misc/bcm2835_cprman.h
171
create mode 100644 include/hw/misc/bcm2835_cprman_internals.h
172
create mode 100644 include/hw/misc/npcm7xx_rng.h
173
create mode 100644 include/hw/watchdog/sbsa_gwdt.h
174
create mode 100644 hw/gpio/npcm7xx_gpio.c
175
create mode 100644 hw/misc/bcm2835_cprman.c
176
create mode 100644 hw/misc/npcm7xx_rng.c
177
create mode 100644 hw/watchdog/sbsa_gwdt.c
178
create mode 100644 tests/qtest/npcm7xx_gpio-test.c
179
create mode 100644 tests/qtest/npcm7xx_rng-test.c
180
create mode 100644 tests/qtest/npcm7xx_watchdog_timer-test.c
181
create mode 100644 tests/tcg/aarch64/bti-1.c
182
create mode 100644 tests/tcg/aarch64/bti-2.c
183
create mode 100644 tests/tcg/aarch64/bti-crt.inc.c
184
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
The kernel sets btype for the signal handler as if for a call.
4
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20201021173749.111103-2-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
linux-user/aarch64/signal.c | 10 ++++++++--
11
1 file changed, 8 insertions(+), 2 deletions(-)
12
13
diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/linux-user/aarch64/signal.c
16
+++ b/linux-user/aarch64/signal.c
17
@@ -XXX,XX +XXX,XX @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
18
+ offsetof(struct target_rt_frame_record, tramp);
19
}
20
env->xregs[0] = usig;
21
- env->xregs[31] = frame_addr;
22
env->xregs[29] = frame_addr + fr_ofs;
23
- env->pc = ka->_sa_handler;
24
env->xregs[30] = return_addr;
25
+ env->xregs[31] = frame_addr;
26
+ env->pc = ka->_sa_handler;
27
+
28
+ /* Invoke the signal handler as if by indirect call. */
29
+ if (cpu_isar_feature(aa64_bti, env_archcpu(env))) {
30
+ env->btype = 2;
31
+ }
32
+
33
if (info) {
34
tswap_siginfo(&frame->info, info);
35
env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info);
36
--
37
2.20.1
38
39
diff view generated by jsdifflib
1
From: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Add gicv3state void pointer to CPUARMState struct
3
Transform the prot bit to a qemu internal page bit, and save
4
to store GICv3CPUState.
4
it in the page tables.
5
5
6
In case of usecase like CPU reset, we need to reset
7
GICv3CPUState of the CPU. In such scenario, this pointer
8
becomes handy.
9
10
Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Eric Auger <eric.auger@redhat.com>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 1487850673-26455-5-git-send-email-vijay.kilari@gmail.com
8
Message-id: 20201021173749.111103-3-richard.henderson@linaro.org
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
10
---
16
hw/intc/gicv3_internal.h | 2 ++
11
include/exec/cpu-all.h | 2 ++
17
target/arm/cpu.h | 2 ++
12
linux-user/syscall_defs.h | 4 ++++
18
hw/intc/arm_gicv3_common.c | 2 ++
13
target/arm/cpu.h | 5 +++++
19
hw/intc/arm_gicv3_cpuif.c | 8 ++++++++
14
linux-user/mmap.c | 16 ++++++++++++++++
20
4 files changed, 14 insertions(+)
15
target/arm/translate-a64.c | 6 +++---
16
5 files changed, 30 insertions(+), 3 deletions(-)
21
17
22
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
18
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
23
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
24
--- a/hw/intc/gicv3_internal.h
20
--- a/include/exec/cpu-all.h
25
+++ b/hw/intc/gicv3_internal.h
21
+++ b/include/exec/cpu-all.h
26
@@ -XXX,XX +XXX,XX @@ static inline void gicv3_cache_all_target_cpustates(GICv3State *s)
22
@@ -XXX,XX +XXX,XX @@ extern intptr_t qemu_host_page_mask;
27
}
23
/* FIXME: Code that sets/uses this is broken and needs to go away. */
28
}
24
#define PAGE_RESERVED 0x0020
29
25
#endif
30
+void gicv3_set_gicv3state(CPUState *cpu, GICv3CPUState *s);
26
+/* Target-specific bits that will be used via page_get_flags(). */
27
+#define PAGE_TARGET_1 0x0080
28
29
#if defined(CONFIG_USER_ONLY)
30
void page_dump(FILE *f);
31
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
32
index XXXXXXX..XXXXXXX 100644
33
--- a/linux-user/syscall_defs.h
34
+++ b/linux-user/syscall_defs.h
35
@@ -XXX,XX +XXX,XX @@ struct target_winsize {
36
#define TARGET_PROT_SEM 0x08
37
#endif
38
39
+#ifdef TARGET_AARCH64
40
+#define TARGET_PROT_BTI 0x10
41
+#endif
31
+
42
+
32
#endif /* QEMU_ARM_GICV3_INTERNAL_H */
43
/* Common */
44
#define TARGET_MAP_SHARED    0x01        /* Share changes */
45
#define TARGET_MAP_PRIVATE    0x02        /* Changes are private */
33
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
46
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
34
index XXXXXXX..XXXXXXX 100644
47
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/cpu.h
48
--- a/target/arm/cpu.h
36
+++ b/target/arm/cpu.h
49
+++ b/target/arm/cpu.h
37
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
50
@@ -XXX,XX +XXX,XX @@ static inline MemTxAttrs *typecheck_memtxattrs(MemTxAttrs *x)
38
51
#define arm_tlb_bti_gp(x) (typecheck_memtxattrs(x)->target_tlb_bit0)
39
void *nvic;
52
#define arm_tlb_mte_tagged(x) (typecheck_memtxattrs(x)->target_tlb_bit1)
40
const struct arm_boot_info *boot_info;
53
41
+ /* Store GICv3CPUState to access from this struct */
54
+/*
42
+ void *gicv3state;
55
+ * AArch64 usage of the PAGE_TARGET_* bits for linux-user.
43
} CPUARMState;
56
+ */
44
57
+#define PAGE_BTI PAGE_TARGET_1
45
/**
58
+
46
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
59
/*
60
* Naming convention for isar_feature functions:
61
* Functions which test 32-bit ID registers should have _aa32_ in
62
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
47
index XXXXXXX..XXXXXXX 100644
63
index XXXXXXX..XXXXXXX 100644
48
--- a/hw/intc/arm_gicv3_common.c
64
--- a/linux-user/mmap.c
49
+++ b/hw/intc/arm_gicv3_common.c
65
+++ b/linux-user/mmap.c
50
@@ -XXX,XX +XXX,XX @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
66
@@ -XXX,XX +XXX,XX @@ static int validate_prot_to_pageflags(int *host_prot, int prot)
51
67
*host_prot = (prot & (PROT_READ | PROT_WRITE))
52
s->cpu[i].cpu = cpu;
68
| (prot & PROT_EXEC ? PROT_READ : 0);
53
s->cpu[i].gic = s;
69
54
+ /* Store GICv3CPUState in CPUARMState gicv3state pointer */
70
+#ifdef TARGET_AARCH64
55
+ gicv3_set_gicv3state(cpu, &s->cpu[i]);
71
+ /*
56
72
+ * The PROT_BTI bit is only accepted if the cpu supports the feature.
57
/* Pre-construct the GICR_TYPER:
73
+ * Since this is the unusual case, don't bother checking unless
58
* For our implementation:
74
+ * the bit has been requested. If set and valid, record the bit
59
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
75
+ * within QEMU's page_flags.
76
+ */
77
+ if (prot & TARGET_PROT_BTI) {
78
+ ARMCPU *cpu = ARM_CPU(thread_cpu);
79
+ if (cpu_isar_feature(aa64_bti, cpu)) {
80
+ valid |= TARGET_PROT_BTI;
81
+ page_flags |= PAGE_BTI;
82
+ }
83
+ }
84
+#endif
85
+
86
return prot & ~valid ? 0 : page_flags;
87
}
88
89
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
60
index XXXXXXX..XXXXXXX 100644
90
index XXXXXXX..XXXXXXX 100644
61
--- a/hw/intc/arm_gicv3_cpuif.c
91
--- a/target/arm/translate-a64.c
62
+++ b/hw/intc/arm_gicv3_cpuif.c
92
+++ b/target/arm/translate-a64.c
63
@@ -XXX,XX +XXX,XX @@
93
@@ -XXX,XX +XXX,XX @@ static void disas_data_proc_simd_fp(DisasContext *s, uint32_t insn)
64
#include "gicv3_internal.h"
94
*/
65
#include "cpu.h"
95
static bool is_guarded_page(CPUARMState *env, DisasContext *s)
66
67
+void gicv3_set_gicv3state(CPUState *cpu, GICv3CPUState *s)
68
+{
69
+ ARMCPU *arm_cpu = ARM_CPU(cpu);
70
+ CPUARMState *env = &arm_cpu->env;
71
+
72
+ env->gicv3state = (void *)s;
73
+};
74
+
75
static GICv3CPUState *icc_cs_from_env(CPUARMState *env)
76
{
96
{
77
/* Given the CPU, find the right GICv3CPUState struct.
97
-#ifdef CONFIG_USER_ONLY
98
- return false; /* FIXME */
99
-#else
100
uint64_t addr = s->base.pc_first;
101
+#ifdef CONFIG_USER_ONLY
102
+ return page_get_flags(addr) & PAGE_BTI;
103
+#else
104
int mmu_idx = arm_to_core_mmu_idx(s->mmu_idx);
105
unsigned int index = tlb_index(env, mmu_idx, addr);
106
CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
78
--
107
--
79
2.7.4
108
2.20.1
80
109
81
110
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
These are all of the defines required to parse
4
GNU_PROPERTY_AARCH64_FEATURE_1_AND, copied from binutils.
5
Other missing defines related to other GNU program headers
6
and notes are elided for now.
7
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20201021173749.111103-4-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
include/elf.h | 22 ++++++++++++++++++++++
14
1 file changed, 22 insertions(+)
15
16
diff --git a/include/elf.h b/include/elf.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/elf.h
19
+++ b/include/elf.h
20
@@ -XXX,XX +XXX,XX @@ typedef int64_t Elf64_Sxword;
21
#define PT_NOTE 4
22
#define PT_SHLIB 5
23
#define PT_PHDR 6
24
+#define PT_LOOS 0x60000000
25
+#define PT_HIOS 0x6fffffff
26
#define PT_LOPROC 0x70000000
27
#define PT_HIPROC 0x7fffffff
28
29
+#define PT_GNU_PROPERTY (PT_LOOS + 0x474e553)
30
+
31
#define PT_MIPS_REGINFO 0x70000000
32
#define PT_MIPS_RTPROC 0x70000001
33
#define PT_MIPS_OPTIONS 0x70000002
34
@@ -XXX,XX +XXX,XX @@ typedef struct elf64_shdr {
35
#define NT_ARM_SYSTEM_CALL 0x404 /* ARM system call number */
36
#define NT_ARM_SVE 0x405 /* ARM Scalable Vector Extension regs */
37
38
+/* Defined note types for GNU systems. */
39
+
40
+#define NT_GNU_PROPERTY_TYPE_0 5 /* Program property */
41
+
42
+/* Values used in GNU .note.gnu.property notes (NT_GNU_PROPERTY_TYPE_0). */
43
+
44
+#define GNU_PROPERTY_STACK_SIZE 1
45
+#define GNU_PROPERTY_NO_COPY_ON_PROTECTED 2
46
+
47
+#define GNU_PROPERTY_LOPROC 0xc0000000
48
+#define GNU_PROPERTY_HIPROC 0xdfffffff
49
+#define GNU_PROPERTY_LOUSER 0xe0000000
50
+#define GNU_PROPERTY_HIUSER 0xffffffff
51
+
52
+#define GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000
53
+#define GNU_PROPERTY_AARCH64_FEATURE_1_BTI (1u << 0)
54
+#define GNU_PROPERTY_AARCH64_FEATURE_1_PAC (1u << 1)
55
+
56
/*
57
* Physical entry point into the kernel.
58
*
59
--
60
2.20.1
61
62
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
2
3
Fix an unlikely memory leak in load_elf_image().
4
5
Fixes: bf858897b7 ("linux-user: Re-use load_elf_image for the main binary.")
6
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20201021173749.111103-5-richard.henderson@linaro.org
9
Message-Id: <20201003174944.1972444-1-f4bug@amsat.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
linux-user/elfload.c | 8 ++++----
15
1 file changed, 4 insertions(+), 4 deletions(-)
16
17
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/linux-user/elfload.c
20
+++ b/linux-user/elfload.c
21
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
22
info->brk = vaddr_em;
23
}
24
} else if (eppnt->p_type == PT_INTERP && pinterp_name) {
25
- char *interp_name;
26
+ g_autofree char *interp_name = NULL;
27
28
if (*pinterp_name) {
29
errmsg = "Multiple PT_INTERP entries";
30
goto exit_errmsg;
31
}
32
- interp_name = malloc(eppnt->p_filesz);
33
+ interp_name = g_malloc(eppnt->p_filesz);
34
if (!interp_name) {
35
goto exit_perror;
36
}
37
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
38
errmsg = "Invalid PT_INTERP entry";
39
goto exit_errmsg;
40
}
41
- *pinterp_name = interp_name;
42
+ *pinterp_name = g_steal_pointer(&interp_name);
43
#ifdef TARGET_MIPS
44
} else if (eppnt->p_type == PT_MIPS_ABIFLAGS) {
45
Mips_elf_abiflags_v0 abiflags;
46
@@ -XXX,XX +XXX,XX @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
47
if (elf_interpreter) {
48
info->load_bias = interp_info.load_bias;
49
info->entry = interp_info.entry;
50
- free(elf_interpreter);
51
+ g_free(elf_interpreter);
52
}
53
54
#ifdef USE_ELF_CORE_DUMP
55
--
56
2.20.1
57
58
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
Fixing this now will clarify following patches.
4
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20201021173749.111103-6-richard.henderson@linaro.org
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
linux-user/elfload.c | 12 +++++++++---
11
1 file changed, 9 insertions(+), 3 deletions(-)
12
13
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/linux-user/elfload.c
16
+++ b/linux-user/elfload.c
17
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
18
abi_ulong vaddr, vaddr_po, vaddr_ps, vaddr_ef, vaddr_em, vaddr_len;
19
int elf_prot = 0;
20
21
- if (eppnt->p_flags & PF_R) elf_prot = PROT_READ;
22
- if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
23
- if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
24
+ if (eppnt->p_flags & PF_R) {
25
+ elf_prot |= PROT_READ;
26
+ }
27
+ if (eppnt->p_flags & PF_W) {
28
+ elf_prot |= PROT_WRITE;
29
+ }
30
+ if (eppnt->p_flags & PF_X) {
31
+ elf_prot |= PROT_EXEC;
32
+ }
33
34
vaddr = load_bias + eppnt->p_vaddr;
35
vaddr_po = TARGET_ELF_PAGEOFFSET(vaddr);
36
--
37
2.20.1
38
39
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
The second loop uses a loop induction variable, and the first
4
does not. Transform the first to match the second, to simplify
5
a following patch moving code between them.
6
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20201021173749.111103-7-richard.henderson@linaro.org
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
linux-user/elfload.c | 9 +++++----
13
1 file changed, 5 insertions(+), 4 deletions(-)
14
15
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/linux-user/elfload.c
18
+++ b/linux-user/elfload.c
19
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
20
loaddr = -1, hiaddr = 0;
21
info->alignment = 0;
22
for (i = 0; i < ehdr->e_phnum; ++i) {
23
- if (phdr[i].p_type == PT_LOAD) {
24
- abi_ulong a = phdr[i].p_vaddr - phdr[i].p_offset;
25
+ struct elf_phdr *eppnt = phdr + i;
26
+ if (eppnt->p_type == PT_LOAD) {
27
+ abi_ulong a = eppnt->p_vaddr - eppnt->p_offset;
28
if (a < loaddr) {
29
loaddr = a;
30
}
31
- a = phdr[i].p_vaddr + phdr[i].p_memsz;
32
+ a = eppnt->p_vaddr + eppnt->p_memsz;
33
if (a > hiaddr) {
34
hiaddr = a;
35
}
36
++info->nsegs;
37
- info->alignment |= phdr[i].p_align;
38
+ info->alignment |= eppnt->p_align;
39
}
40
}
41
42
--
43
2.20.1
44
45
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
For BTI, we need to know if the executable is static or dynamic,
4
which means looking for PT_INTERP earlier.
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20201021173749.111103-8-richard.henderson@linaro.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
linux-user/elfload.c | 60 +++++++++++++++++++++++---------------------
12
1 file changed, 31 insertions(+), 29 deletions(-)
13
14
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/linux-user/elfload.c
17
+++ b/linux-user/elfload.c
18
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
19
20
mmap_lock();
21
22
- /* Find the maximum size of the image and allocate an appropriate
23
- amount of memory to handle that. */
24
+ /*
25
+ * Find the maximum size of the image and allocate an appropriate
26
+ * amount of memory to handle that. Locate the interpreter, if any.
27
+ */
28
loaddr = -1, hiaddr = 0;
29
info->alignment = 0;
30
for (i = 0; i < ehdr->e_phnum; ++i) {
31
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
32
}
33
++info->nsegs;
34
info->alignment |= eppnt->p_align;
35
+ } else if (eppnt->p_type == PT_INTERP && pinterp_name) {
36
+ g_autofree char *interp_name = NULL;
37
+
38
+ if (*pinterp_name) {
39
+ errmsg = "Multiple PT_INTERP entries";
40
+ goto exit_errmsg;
41
+ }
42
+ interp_name = g_malloc(eppnt->p_filesz);
43
+ if (!interp_name) {
44
+ goto exit_perror;
45
+ }
46
+
47
+ if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
48
+ memcpy(interp_name, bprm_buf + eppnt->p_offset,
49
+ eppnt->p_filesz);
50
+ } else {
51
+ retval = pread(image_fd, interp_name, eppnt->p_filesz,
52
+ eppnt->p_offset);
53
+ if (retval != eppnt->p_filesz) {
54
+ goto exit_perror;
55
+ }
56
+ }
57
+ if (interp_name[eppnt->p_filesz - 1] != 0) {
58
+ errmsg = "Invalid PT_INTERP entry";
59
+ goto exit_errmsg;
60
+ }
61
+ *pinterp_name = g_steal_pointer(&interp_name);
62
}
63
}
64
65
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
66
if (vaddr_em > info->brk) {
67
info->brk = vaddr_em;
68
}
69
- } else if (eppnt->p_type == PT_INTERP && pinterp_name) {
70
- g_autofree char *interp_name = NULL;
71
-
72
- if (*pinterp_name) {
73
- errmsg = "Multiple PT_INTERP entries";
74
- goto exit_errmsg;
75
- }
76
- interp_name = g_malloc(eppnt->p_filesz);
77
- if (!interp_name) {
78
- goto exit_perror;
79
- }
80
-
81
- if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
82
- memcpy(interp_name, bprm_buf + eppnt->p_offset,
83
- eppnt->p_filesz);
84
- } else {
85
- retval = pread(image_fd, interp_name, eppnt->p_filesz,
86
- eppnt->p_offset);
87
- if (retval != eppnt->p_filesz) {
88
- goto exit_perror;
89
- }
90
- }
91
- if (interp_name[eppnt->p_filesz - 1] != 0) {
92
- errmsg = "Invalid PT_INTERP entry";
93
- goto exit_errmsg;
94
- }
95
- *pinterp_name = g_steal_pointer(&interp_name);
96
#ifdef TARGET_MIPS
97
} else if (eppnt->p_type == PT_MIPS_ABIFLAGS) {
98
Mips_elf_abiflags_v0 abiflags;
99
--
100
2.20.1
101
102
diff view generated by jsdifflib
1
The local variable 'nvic' in stm32f205_soc_realize() no longer
1
From: Richard Henderson <richard.henderson@linaro.org>
2
holds a direct pointer to the NVIC device; it is a pointer to
3
the ARMv7M container object. Rename it 'armv7m' accordingly.
4
2
3
This is a bit clearer than open-coding some of this
4
with a bare c string.
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20201021173749.111103-9-richard.henderson@linaro.org
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
Message-id: 1487604965-23220-12-git-send-email-peter.maydell@linaro.org
10
---
10
---
11
hw/arm/stm32f205_soc.c | 18 +++++++++---------
11
linux-user/elfload.c | 37 ++++++++++++++++++++-----------------
12
1 file changed, 9 insertions(+), 9 deletions(-)
12
1 file changed, 20 insertions(+), 17 deletions(-)
13
13
14
diff --git a/hw/arm/stm32f205_soc.c b/hw/arm/stm32f205_soc.c
14
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/stm32f205_soc.c
16
--- a/linux-user/elfload.c
17
+++ b/hw/arm/stm32f205_soc.c
17
+++ b/linux-user/elfload.c
18
@@ -XXX,XX +XXX,XX @@ static void stm32f205_soc_initfn(Object *obj)
18
@@ -XXX,XX +XXX,XX @@
19
static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp)
19
#include "qemu/guest-random.h"
20
{
20
#include "qemu/units.h"
21
STM32F205State *s = STM32F205_SOC(dev_soc);
21
#include "qemu/selfmap.h"
22
- DeviceState *dev, *nvic;
22
+#include "qapi/error.h"
23
+ DeviceState *dev, *armv7m;
23
24
SysBusDevice *busdev;
24
#ifdef _ARCH_PPC64
25
Error *err = NULL;
25
#undef ARCH_DLINFO
26
int i;
26
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
27
@@ -XXX,XX +XXX,XX @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp)
27
struct elf_phdr *phdr;
28
vmstate_register_ram_global(sram);
28
abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
29
memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, sram);
29
int i, retval;
30
30
- const char *errmsg;
31
- nvic = DEVICE(&s->armv7m);
31
+ Error *err = NULL;
32
- qdev_prop_set_uint32(nvic, "num-irq", 96);
32
33
- qdev_prop_set_string(nvic, "cpu-model", s->cpu_model);
33
/* First of all, some simple consistency checks */
34
+ armv7m = DEVICE(&s->armv7m);
34
- errmsg = "Invalid ELF image for this architecture";
35
+ qdev_prop_set_uint32(armv7m, "num-irq", 96);
35
if (!elf_check_ident(ehdr)) {
36
+ qdev_prop_set_string(armv7m, "cpu-model", s->cpu_model);
36
+ error_setg(&err, "Invalid ELF image for this architecture");
37
object_property_set_link(OBJECT(&s->armv7m), OBJECT(get_system_memory()),
37
goto exit_errmsg;
38
"memory", &error_abort);
39
object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err);
40
@@ -XXX,XX +XXX,XX @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp)
41
}
38
}
42
busdev = SYS_BUS_DEVICE(dev);
39
bswap_ehdr(ehdr);
43
sysbus_mmio_map(busdev, 0, 0x40013800);
40
if (!elf_check_ehdr(ehdr)) {
44
- sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(nvic, 71));
41
+ error_setg(&err, "Invalid ELF image for this architecture");
45
+ sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, 71));
42
goto exit_errmsg;
46
47
/* Attach UART (uses USART registers) and USART controllers */
48
for (i = 0; i < STM_NUM_USARTS; i++) {
49
@@ -XXX,XX +XXX,XX @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp)
50
}
51
busdev = SYS_BUS_DEVICE(dev);
52
sysbus_mmio_map(busdev, 0, usart_addr[i]);
53
- sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(nvic, usart_irq[i]));
54
+ sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, usart_irq[i]));
55
}
43
}
56
44
57
/* Timer 2 to 5 */
45
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
58
@@ -XXX,XX +XXX,XX @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp)
46
g_autofree char *interp_name = NULL;
59
}
47
60
busdev = SYS_BUS_DEVICE(dev);
48
if (*pinterp_name) {
61
sysbus_mmio_map(busdev, 0, timer_addr[i]);
49
- errmsg = "Multiple PT_INTERP entries";
62
- sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(nvic, timer_irq[i]));
50
+ error_setg(&err, "Multiple PT_INTERP entries");
63
+ sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, timer_irq[i]));
51
goto exit_errmsg;
52
}
53
+
54
interp_name = g_malloc(eppnt->p_filesz);
55
- if (!interp_name) {
56
- goto exit_perror;
57
- }
58
59
if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
60
memcpy(interp_name, bprm_buf + eppnt->p_offset,
61
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
62
retval = pread(image_fd, interp_name, eppnt->p_filesz,
63
eppnt->p_offset);
64
if (retval != eppnt->p_filesz) {
65
- goto exit_perror;
66
+ goto exit_read;
67
}
68
}
69
if (interp_name[eppnt->p_filesz - 1] != 0) {
70
- errmsg = "Invalid PT_INTERP entry";
71
+ error_setg(&err, "Invalid PT_INTERP entry");
72
goto exit_errmsg;
73
}
74
*pinterp_name = g_steal_pointer(&interp_name);
75
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
76
(ehdr->e_type == ET_EXEC ? MAP_FIXED : 0),
77
-1, 0);
78
if (load_addr == -1) {
79
- goto exit_perror;
80
+ goto exit_mmap;
64
}
81
}
65
82
load_bias = load_addr - loaddr;
66
/* ADC 1 to 3 */
83
67
@@ -XXX,XX +XXX,XX @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp)
84
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
68
return;
85
image_fd, eppnt->p_offset - vaddr_po);
86
87
if (error == -1) {
88
- goto exit_perror;
89
+ goto exit_mmap;
90
}
91
}
92
93
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
94
} else if (eppnt->p_type == PT_MIPS_ABIFLAGS) {
95
Mips_elf_abiflags_v0 abiflags;
96
if (eppnt->p_filesz < sizeof(Mips_elf_abiflags_v0)) {
97
- errmsg = "Invalid PT_MIPS_ABIFLAGS entry";
98
+ error_setg(&err, "Invalid PT_MIPS_ABIFLAGS entry");
99
goto exit_errmsg;
100
}
101
if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
102
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
103
retval = pread(image_fd, &abiflags, sizeof(Mips_elf_abiflags_v0),
104
eppnt->p_offset);
105
if (retval != sizeof(Mips_elf_abiflags_v0)) {
106
- goto exit_perror;
107
+ goto exit_read;
108
}
109
}
110
bswap_mips_abiflags(&abiflags);
111
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
112
113
exit_read:
114
if (retval >= 0) {
115
- errmsg = "Incomplete read of file header";
116
- goto exit_errmsg;
117
+ error_setg(&err, "Incomplete read of file header");
118
+ } else {
119
+ error_setg_errno(&err, errno, "Error reading file header");
69
}
120
}
70
qdev_connect_gpio_out(DEVICE(s->adc_irqs), 0,
121
- exit_perror:
71
- qdev_get_gpio_in(nvic, ADC_IRQ));
122
- errmsg = strerror(errno);
72
+ qdev_get_gpio_in(armv7m, ADC_IRQ));
123
+ goto exit_errmsg;
73
124
+ exit_mmap:
74
for (i = 0; i < STM_NUM_ADCS; i++) {
125
+ error_setg_errno(&err, errno, "Error mapping file");
75
dev = DEVICE(&(s->adc[i]));
126
+ goto exit_errmsg;
76
@@ -XXX,XX +XXX,XX @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp)
127
exit_errmsg:
77
}
128
- fprintf(stderr, "%s: %s\n", image_name, errmsg);
78
busdev = SYS_BUS_DEVICE(dev);
129
+ error_reportf_err(err, "%s: ", image_name);
79
sysbus_mmio_map(busdev, 0, spi_addr[i]);
130
exit(-1);
80
- sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(nvic, spi_irq[i]));
81
+ sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, spi_irq[i]));
82
}
83
}
131
}
84
132
85
--
133
--
86
2.7.4
134
2.20.1
87
135
88
136
diff view generated by jsdifflib
1
Make the NVIC device expose a memory region for its users
1
From: Richard Henderson <richard.henderson@linaro.org>
2
to map, rather than mapping itself into the system memory
3
space on realize, and get the one user (the ARMv7M object)
4
to do this.
5
2
3
This is slightly clearer than just using strerror, though
4
the different forms produced by error_setg_file_open and
5
error_setg_errno isn't entirely convenient.
6
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20201021173749.111103-10-richard.henderson@linaro.org
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Message-id: 1487604965-23220-7-git-send-email-peter.maydell@linaro.org
9
---
11
---
10
hw/arm/armv7m.c | 7 ++++++-
12
linux-user/elfload.c | 15 ++++++++-------
11
hw/intc/armv7m_nvic.c | 7 ++-----
13
1 file changed, 8 insertions(+), 7 deletions(-)
12
2 files changed, 8 insertions(+), 6 deletions(-)
13
14
14
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
15
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/armv7m.c
17
--- a/linux-user/elfload.c
17
+++ b/hw/arm/armv7m.c
18
+++ b/linux-user/elfload.c
18
@@ -XXX,XX +XXX,XX @@ static void armv7m_instance_init(Object *obj)
19
@@ -XXX,XX +XXX,XX @@ static void load_elf_interp(const char *filename, struct image_info *info,
19
static void armv7m_realize(DeviceState *dev, Error **errp)
20
char bprm_buf[BPRM_BUF_SIZE])
20
{
21
{
21
ARMv7MState *s = ARMV7M(dev);
22
int fd, retval;
22
+ SysBusDevice *sbd;
23
+ Error *err = NULL;
23
Error *err = NULL;
24
24
int i;
25
fd = open(path(filename), O_RDONLY);
25
char **cpustr;
26
if (fd < 0) {
26
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
27
- goto exit_perror;
27
qdev_pass_gpios(DEVICE(&s->nvic), dev, "SYSRESETREQ");
28
+ error_setg_file_open(&err, errno, filename);
28
29
+ error_report_err(err);
29
/* Wire the NVIC up to the CPU */
30
+ exit(-1);
30
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->nvic), 0,
31
}
31
+ sbd = SYS_BUS_DEVICE(&s->nvic);
32
32
+ sysbus_connect_irq(sbd, 0,
33
retval = read(fd, bprm_buf, BPRM_BUF_SIZE);
33
qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ));
34
if (retval < 0) {
34
s->cpu->env.nvic = &s->nvic;
35
- goto exit_perror;
35
36
+ error_setg_errno(&err, errno, "Error reading file header");
36
+ memory_region_add_subregion(&s->container, 0xe000e000,
37
+ error_reportf_err(err, "%s: ", filename);
37
+ sysbus_mmio_get_region(sbd, 0));
38
+ exit(-1);
39
}
38
+
40
+
39
for (i = 0; i < ARRAY_SIZE(s->bitband); i++) {
41
if (retval < BPRM_BUF_SIZE) {
40
Object *obj = OBJECT(&s->bitband[i]);
42
memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval);
41
SysBusDevice *sbd = SYS_BUS_DEVICE(&s->bitband[i]);
43
}
42
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
44
43
index XXXXXXX..XXXXXXX 100644
45
load_elf_image(filename, fd, info, NULL, bprm_buf);
44
--- a/hw/intc/armv7m_nvic.c
46
- return;
45
+++ b/hw/intc/armv7m_nvic.c
47
-
46
@@ -XXX,XX +XXX,XX @@
48
- exit_perror:
47
#include "hw/arm/arm.h"
49
- fprintf(stderr, "%s: %s\n", filename, strerror(errno));
48
#include "hw/arm/armv7m_nvic.h"
50
- exit(-1);
49
#include "target/arm/cpu.h"
50
-#include "exec/address-spaces.h"
51
#include "qemu/log.h"
52
#include "trace.h"
53
54
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
55
"nvic_sysregs", 0x1000);
56
memory_region_add_subregion(&s->container, 0, &s->sysregmem);
57
58
- /* Map the whole thing into system memory at the location required
59
- * by the v7M architecture.
60
- */
61
- memory_region_add_subregion(get_system_memory(), 0xe000e000, &s->container);
62
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->container);
63
+
64
s->systick.timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, systick_timer_tick, s);
65
}
51
}
66
52
53
static int symfind(const void *s0, const void *s1)
67
--
54
--
68
2.7.4
55
2.20.1
69
56
70
57
diff view generated by jsdifflib
New patch
1
1
From: Richard Henderson <richard.henderson@linaro.org>
2
3
This is generic support, with the code disabled for all targets.
4
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20201021173749.111103-11-richard.henderson@linaro.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
linux-user/qemu.h | 4 ++
11
linux-user/elfload.c | 157 +++++++++++++++++++++++++++++++++++++++++++
12
2 files changed, 161 insertions(+)
13
14
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/linux-user/qemu.h
17
+++ b/linux-user/qemu.h
18
@@ -XXX,XX +XXX,XX @@ struct image_info {
19
abi_ulong interpreter_loadmap_addr;
20
abi_ulong interpreter_pt_dynamic_addr;
21
struct image_info *other_info;
22
+
23
+ /* For target-specific processing of NT_GNU_PROPERTY_TYPE_0. */
24
+ uint32_t note_flags;
25
+
26
#ifdef TARGET_MIPS
27
int fp_abi;
28
int interp_fp_abi;
29
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/linux-user/elfload.c
32
+++ b/linux-user/elfload.c
33
@@ -XXX,XX +XXX,XX @@ static void elf_core_copy_regs(target_elf_gregset_t *regs,
34
35
#include "elf.h"
36
37
+static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
38
+ const uint32_t *data,
39
+ struct image_info *info,
40
+ Error **errp)
41
+{
42
+ g_assert_not_reached();
43
+}
44
+#define ARCH_USE_GNU_PROPERTY 0
45
+
46
struct exec
47
{
48
unsigned int a_info; /* Use macros N_MAGIC, etc for access */
49
@@ -XXX,XX +XXX,XX @@ void probe_guest_base(const char *image_name, abi_ulong guest_loaddr,
50
"@ 0x%" PRIx64 "\n", (uint64_t)guest_base);
51
}
52
53
+enum {
54
+ /* The string "GNU\0" as a magic number. */
55
+ GNU0_MAGIC = const_le32('G' | 'N' << 8 | 'U' << 16),
56
+ NOTE_DATA_SZ = 1 * KiB,
57
+ NOTE_NAME_SZ = 4,
58
+ ELF_GNU_PROPERTY_ALIGN = ELF_CLASS == ELFCLASS32 ? 4 : 8,
59
+};
60
+
61
+/*
62
+ * Process a single gnu_property entry.
63
+ * Return false for error.
64
+ */
65
+static bool parse_elf_property(const uint32_t *data, int *off, int datasz,
66
+ struct image_info *info, bool have_prev_type,
67
+ uint32_t *prev_type, Error **errp)
68
+{
69
+ uint32_t pr_type, pr_datasz, step;
70
+
71
+ if (*off > datasz || !QEMU_IS_ALIGNED(*off, ELF_GNU_PROPERTY_ALIGN)) {
72
+ goto error_data;
73
+ }
74
+ datasz -= *off;
75
+ data += *off / sizeof(uint32_t);
76
+
77
+ if (datasz < 2 * sizeof(uint32_t)) {
78
+ goto error_data;
79
+ }
80
+ pr_type = data[0];
81
+ pr_datasz = data[1];
82
+ data += 2;
83
+ datasz -= 2 * sizeof(uint32_t);
84
+ step = ROUND_UP(pr_datasz, ELF_GNU_PROPERTY_ALIGN);
85
+ if (step > datasz) {
86
+ goto error_data;
87
+ }
88
+
89
+ /* Properties are supposed to be unique and sorted on pr_type. */
90
+ if (have_prev_type && pr_type <= *prev_type) {
91
+ if (pr_type == *prev_type) {
92
+ error_setg(errp, "Duplicate property in PT_GNU_PROPERTY");
93
+ } else {
94
+ error_setg(errp, "Unsorted property in PT_GNU_PROPERTY");
95
+ }
96
+ return false;
97
+ }
98
+ *prev_type = pr_type;
99
+
100
+ if (!arch_parse_elf_property(pr_type, pr_datasz, data, info, errp)) {
101
+ return false;
102
+ }
103
+
104
+ *off += 2 * sizeof(uint32_t) + step;
105
+ return true;
106
+
107
+ error_data:
108
+ error_setg(errp, "Ill-formed property in PT_GNU_PROPERTY");
109
+ return false;
110
+}
111
+
112
+/* Process NT_GNU_PROPERTY_TYPE_0. */
113
+static bool parse_elf_properties(int image_fd,
114
+ struct image_info *info,
115
+ const struct elf_phdr *phdr,
116
+ char bprm_buf[BPRM_BUF_SIZE],
117
+ Error **errp)
118
+{
119
+ union {
120
+ struct elf_note nhdr;
121
+ uint32_t data[NOTE_DATA_SZ / sizeof(uint32_t)];
122
+ } note;
123
+
124
+ int n, off, datasz;
125
+ bool have_prev_type;
126
+ uint32_t prev_type;
127
+
128
+ /* Unless the arch requires properties, ignore them. */
129
+ if (!ARCH_USE_GNU_PROPERTY) {
130
+ return true;
131
+ }
132
+
133
+ /* If the properties are crazy large, that's too bad. */
134
+ n = phdr->p_filesz;
135
+ if (n > sizeof(note)) {
136
+ error_setg(errp, "PT_GNU_PROPERTY too large");
137
+ return false;
138
+ }
139
+ if (n < sizeof(note.nhdr)) {
140
+ error_setg(errp, "PT_GNU_PROPERTY too small");
141
+ return false;
142
+ }
143
+
144
+ if (phdr->p_offset + n <= BPRM_BUF_SIZE) {
145
+ memcpy(&note, bprm_buf + phdr->p_offset, n);
146
+ } else {
147
+ ssize_t len = pread(image_fd, &note, n, phdr->p_offset);
148
+ if (len != n) {
149
+ error_setg_errno(errp, errno, "Error reading file header");
150
+ return false;
151
+ }
152
+ }
153
+
154
+ /*
155
+ * The contents of a valid PT_GNU_PROPERTY is a sequence
156
+ * of uint32_t -- swap them all now.
157
+ */
158
+#ifdef BSWAP_NEEDED
159
+ for (int i = 0; i < n / 4; i++) {
160
+ bswap32s(note.data + i);
161
+ }
162
+#endif
163
+
164
+ /*
165
+ * Note that nhdr is 3 words, and that the "name" described by namesz
166
+ * immediately follows nhdr and is thus at the 4th word. Further, all
167
+ * of the inputs to the kernel's round_up are multiples of 4.
168
+ */
169
+ if (note.nhdr.n_type != NT_GNU_PROPERTY_TYPE_0 ||
170
+ note.nhdr.n_namesz != NOTE_NAME_SZ ||
171
+ note.data[3] != GNU0_MAGIC) {
172
+ error_setg(errp, "Invalid note in PT_GNU_PROPERTY");
173
+ return false;
174
+ }
175
+ off = sizeof(note.nhdr) + NOTE_NAME_SZ;
176
+
177
+ datasz = note.nhdr.n_descsz + off;
178
+ if (datasz > n) {
179
+ error_setg(errp, "Invalid note size in PT_GNU_PROPERTY");
180
+ return false;
181
+ }
182
+
183
+ have_prev_type = false;
184
+ prev_type = 0;
185
+ while (1) {
186
+ if (off == datasz) {
187
+ return true; /* end, exit ok */
188
+ }
189
+ if (!parse_elf_property(note.data, &off, datasz, info,
190
+ have_prev_type, &prev_type, errp)) {
191
+ return false;
192
+ }
193
+ have_prev_type = true;
194
+ }
195
+}
196
+
197
/* Load an ELF image into the address space.
198
199
IMAGE_NAME is the filename of the image, to use in error messages.
200
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
201
goto exit_errmsg;
202
}
203
*pinterp_name = g_steal_pointer(&interp_name);
204
+ } else if (eppnt->p_type == PT_GNU_PROPERTY) {
205
+ if (!parse_elf_properties(image_fd, info, eppnt, bprm_buf, &err)) {
206
+ goto exit_errmsg;
207
+ }
208
}
209
}
210
211
--
212
2.20.1
213
214
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
Use the new generic support for NT_GNU_PROPERTY_TYPE_0.
4
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20201021173749.111103-12-richard.henderson@linaro.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
linux-user/elfload.c | 48 ++++++++++++++++++++++++++++++++++++++++++--
11
1 file changed, 46 insertions(+), 2 deletions(-)
12
13
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/linux-user/elfload.c
16
+++ b/linux-user/elfload.c
17
@@ -XXX,XX +XXX,XX @@ static void elf_core_copy_regs(target_elf_gregset_t *regs,
18
19
#include "elf.h"
20
21
+/* We must delay the following stanzas until after "elf.h". */
22
+#if defined(TARGET_AARCH64)
23
+
24
+static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
25
+ const uint32_t *data,
26
+ struct image_info *info,
27
+ Error **errp)
28
+{
29
+ if (pr_type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) {
30
+ if (pr_datasz != sizeof(uint32_t)) {
31
+ error_setg(errp, "Ill-formed GNU_PROPERTY_AARCH64_FEATURE_1_AND");
32
+ return false;
33
+ }
34
+ /* We will extract GNU_PROPERTY_AARCH64_FEATURE_1_BTI later. */
35
+ info->note_flags = *data;
36
+ }
37
+ return true;
38
+}
39
+#define ARCH_USE_GNU_PROPERTY 1
40
+
41
+#else
42
+
43
static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
44
const uint32_t *data,
45
struct image_info *info,
46
@@ -XXX,XX +XXX,XX @@ static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
47
}
48
#define ARCH_USE_GNU_PROPERTY 0
49
50
+#endif
51
+
52
struct exec
53
{
54
unsigned int a_info; /* Use macros N_MAGIC, etc for access */
55
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
56
struct elfhdr *ehdr = (struct elfhdr *)bprm_buf;
57
struct elf_phdr *phdr;
58
abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
59
- int i, retval;
60
+ int i, retval, prot_exec;
61
Error *err = NULL;
62
63
/* First of all, some simple consistency checks */
64
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
65
info->brk = 0;
66
info->elf_flags = ehdr->e_flags;
67
68
+ prot_exec = PROT_EXEC;
69
+#ifdef TARGET_AARCH64
70
+ /*
71
+ * If the BTI feature is present, this indicates that the executable
72
+ * pages of the startup binary should be mapped with PROT_BTI, so that
73
+ * branch targets are enforced.
74
+ *
75
+ * The startup binary is either the interpreter or the static executable.
76
+ * The interpreter is responsible for all pages of a dynamic executable.
77
+ *
78
+ * Elf notes are backward compatible to older cpus.
79
+ * Do not enable BTI unless it is supported.
80
+ */
81
+ if ((info->note_flags & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)
82
+ && (pinterp_name == NULL || *pinterp_name == 0)
83
+ && cpu_isar_feature(aa64_bti, ARM_CPU(thread_cpu))) {
84
+ prot_exec |= TARGET_PROT_BTI;
85
+ }
86
+#endif
87
+
88
for (i = 0; i < ehdr->e_phnum; i++) {
89
struct elf_phdr *eppnt = phdr + i;
90
if (eppnt->p_type == PT_LOAD) {
91
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
92
elf_prot |= PROT_WRITE;
93
}
94
if (eppnt->p_flags & PF_X) {
95
- elf_prot |= PROT_EXEC;
96
+ elf_prot |= prot_exec;
97
}
98
99
vaddr = load_bias + eppnt->p_vaddr;
100
--
101
2.20.1
102
103
diff view generated by jsdifflib
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
virtio_mmio.h would be deleted; I am leaving it in though it was a
3
The note test requires gcc 10 for -mbranch-protection=standard.
4
mistake to add it.
4
The mmap test uses PROT_BTI and does not require special compiler support.
5
5
6
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
6
Acked-by: Alex Bennée <alex.bennee@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20201021173749.111103-13-richard.henderson@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
11
---
9
include/standard-headers/asm-x86/hyperv.h | 8 +
12
tests/tcg/aarch64/bti-1.c | 62 ++++++++++++++++
10
include/standard-headers/linux/input-event-codes.h | 2 +-
13
tests/tcg/aarch64/bti-2.c | 116 ++++++++++++++++++++++++++++++
11
include/standard-headers/linux/pci_regs.h | 25 ++
14
tests/tcg/aarch64/bti-crt.inc.c | 51 +++++++++++++
12
include/standard-headers/linux/virtio_ids.h | 1 +
15
tests/tcg/aarch64/Makefile.target | 10 +++
13
linux-headers/asm-arm/kvm.h | 15 +
16
tests/tcg/configure.sh | 4 ++
14
linux-headers/asm-arm/unistd-common.h | 357 ++++++++++++++++++
17
5 files changed, 243 insertions(+)
15
linux-headers/asm-arm/unistd-eabi.h | 5 +
18
create mode 100644 tests/tcg/aarch64/bti-1.c
16
linux-headers/asm-arm/unistd-oabi.h | 17 +
19
create mode 100644 tests/tcg/aarch64/bti-2.c
17
linux-headers/asm-arm/unistd.h | 419 +--------------------
20
create mode 100644 tests/tcg/aarch64/bti-crt.inc.c
18
linux-headers/asm-arm64/kvm.h | 13 +
21
19
linux-headers/asm-powerpc/kvm.h | 27 ++
22
diff --git a/tests/tcg/aarch64/bti-1.c b/tests/tcg/aarch64/bti-1.c
20
linux-headers/asm-powerpc/unistd.h | 1 +
21
linux-headers/asm-x86/kvm_para.h | 13 +-
22
linux-headers/linux/kvm.h | 24 +-
23
linux-headers/linux/kvm_para.h | 2 +
24
linux-headers/linux/userfaultfd.h | 67 +++-
25
linux-headers/linux/vfio.h | 10 +
26
17 files changed, 577 insertions(+), 429 deletions(-)
27
create mode 100644 linux-headers/asm-arm/unistd-common.h
28
create mode 100644 linux-headers/asm-arm/unistd-eabi.h
29
create mode 100644 linux-headers/asm-arm/unistd-oabi.h
30
31
diff --git a/include/standard-headers/asm-x86/hyperv.h b/include/standard-headers/asm-x86/hyperv.h
32
index XXXXXXX..XXXXXXX 100644
33
--- a/include/standard-headers/asm-x86/hyperv.h
34
+++ b/include/standard-headers/asm-x86/hyperv.h
35
@@ -XXX,XX +XXX,XX @@
36
*/
37
#define HV_X64_MSR_STAT_PAGES_AVAILABLE        (1 << 8)
38
39
+/* Crash MSR available */
40
+#define HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE (1 << 10)
41
+
42
/*
43
* Feature identification: EBX indicates which flags were specified at
44
* partition creation. The format is the same as the partition creation
45
@@ -XXX,XX +XXX,XX @@
46
*/
47
#define HV_X64_RELAXED_TIMING_RECOMMENDED    (1 << 5)
48
49
+/*
50
+ * Crash notification flag.
51
+ */
52
+#define HV_CRASH_CTL_CRASH_NOTIFY (1ULL << 63)
53
+
54
/* MSR used to identify the guest OS. */
55
#define HV_X64_MSR_GUEST_OS_ID            0x40000000
56
57
diff --git a/include/standard-headers/linux/input-event-codes.h b/include/standard-headers/linux/input-event-codes.h
58
index XXXXXXX..XXXXXXX 100644
59
--- a/include/standard-headers/linux/input-event-codes.h
60
+++ b/include/standard-headers/linux/input-event-codes.h
61
@@ -XXX,XX +XXX,XX @@
62
* Control a data application associated with the currently viewed channel,
63
* e.g. teletext or data broadcast application (MHEG, MHP, HbbTV, etc.)
64
*/
65
-#define KEY_DATA            0x275
66
+#define KEY_DATA            0x277
67
68
#define BTN_TRIGGER_HAPPY        0x2c0
69
#define BTN_TRIGGER_HAPPY1        0x2c0
70
diff --git a/include/standard-headers/linux/pci_regs.h b/include/standard-headers/linux/pci_regs.h
71
index XXXXXXX..XXXXXXX 100644
72
--- a/include/standard-headers/linux/pci_regs.h
73
+++ b/include/standard-headers/linux/pci_regs.h
74
@@ -XXX,XX +XXX,XX @@
75
#define LINUX_PCI_REGS_H
76
77
/*
78
+ * Conventional PCI and PCI-X Mode 1 devices have 256 bytes of
79
+ * configuration space. PCI-X Mode 2 and PCIe devices have 4096 bytes of
80
+ * configuration space.
81
+ */
82
+#define PCI_CFG_SPACE_SIZE    256
83
+#define PCI_CFG_SPACE_EXP_SIZE    4096
84
+
85
+/*
86
* Under PCI, each device has 256 bytes of configuration address space,
87
* of which the first 64 bytes are standardized as follows:
88
*/
89
@@ -XXX,XX +XXX,XX @@
90
#define PCI_EXT_CAP_ID_PMUX    0x1A    /* Protocol Multiplexing */
91
#define PCI_EXT_CAP_ID_PASID    0x1B    /* Process Address Space ID */
92
#define PCI_EXT_CAP_ID_DPC    0x1D    /* Downstream Port Containment */
93
+#define PCI_EXT_CAP_ID_L1SS    0x1E    /* L1 PM Substates */
94
#define PCI_EXT_CAP_ID_PTM    0x1F    /* Precision Time Measurement */
95
#define PCI_EXT_CAP_ID_MAX    PCI_EXT_CAP_ID_PTM
96
97
@@ -XXX,XX +XXX,XX @@
98
#define PCI_EXP_DPC_STATUS        8    /* DPC Status */
99
#define PCI_EXP_DPC_STATUS_TRIGGER    0x01    /* Trigger Status */
100
#define PCI_EXP_DPC_STATUS_INTERRUPT    0x08    /* Interrupt Status */
101
+#define PCI_EXP_DPC_RP_BUSY        0x10    /* Root Port Busy */
102
103
#define PCI_EXP_DPC_SOURCE_ID        10    /* DPC Source Identifier */
104
105
@@ -XXX,XX +XXX,XX @@
106
#define PCI_PTM_CTRL_ENABLE        0x00000001 /* PTM enable */
107
#define PCI_PTM_CTRL_ROOT        0x00000002 /* Root select */
108
109
+/* L1 PM Substates */
110
+#define PCI_L1SS_CAP         4    /* capability register */
111
+#define PCI_L1SS_CAP_PCIPM_L1_2     1    /* PCI PM L1.2 Support */
112
+#define PCI_L1SS_CAP_PCIPM_L1_1     2    /* PCI PM L1.1 Support */
113
+#define PCI_L1SS_CAP_ASPM_L1_2         4    /* ASPM L1.2 Support */
114
+#define PCI_L1SS_CAP_ASPM_L1_1         8    /* ASPM L1.1 Support */
115
+#define PCI_L1SS_CAP_L1_PM_SS        16    /* L1 PM Substates Support */
116
+#define PCI_L1SS_CTL1         8    /* Control Register 1 */
117
+#define PCI_L1SS_CTL1_PCIPM_L1_2    1    /* PCI PM L1.2 Enable */
118
+#define PCI_L1SS_CTL1_PCIPM_L1_1    2    /* PCI PM L1.1 Support */
119
+#define PCI_L1SS_CTL1_ASPM_L1_2    4    /* ASPM L1.2 Support */
120
+#define PCI_L1SS_CTL1_ASPM_L1_1    8    /* ASPM L1.1 Support */
121
+#define PCI_L1SS_CTL1_L1SS_MASK    0x0000000F
122
+#define PCI_L1SS_CTL2         0xC    /* Control Register 2 */
123
+
124
#endif /* LINUX_PCI_REGS_H */
125
diff --git a/include/standard-headers/linux/virtio_ids.h b/include/standard-headers/linux/virtio_ids.h
126
index XXXXXXX..XXXXXXX 100644
127
--- a/include/standard-headers/linux/virtio_ids.h
128
+++ b/include/standard-headers/linux/virtio_ids.h
129
@@ -XXX,XX +XXX,XX @@
130
#define VIRTIO_ID_INPUT 18 /* virtio input */
131
#define VIRTIO_ID_VSOCK 19 /* virtio vsock transport */
132
#define VIRTIO_ID_CRYPTO 20 /* virtio crypto */
133
+
134
#endif /* _LINUX_VIRTIO_IDS_H */
135
diff --git a/linux-headers/asm-arm/kvm.h b/linux-headers/asm-arm/kvm.h
136
index XXXXXXX..XXXXXXX 100644
137
--- a/linux-headers/asm-arm/kvm.h
138
+++ b/linux-headers/asm-arm/kvm.h
139
@@ -XXX,XX +XXX,XX @@ struct kvm_regs {
140
/* Supported VGICv3 address types */
141
#define KVM_VGIC_V3_ADDR_TYPE_DIST    2
142
#define KVM_VGIC_V3_ADDR_TYPE_REDIST    3
143
+#define KVM_VGIC_ITS_ADDR_TYPE        4
144
145
#define KVM_VGIC_V3_DIST_SIZE        SZ_64K
146
#define KVM_VGIC_V3_REDIST_SIZE        (2 * SZ_64K)
147
+#define KVM_VGIC_V3_ITS_SIZE        (2 * SZ_64K)
148
149
#define KVM_ARM_VCPU_POWER_OFF        0 /* CPU is started in OFF state */
150
#define KVM_ARM_VCPU_PSCI_0_2        1 /* CPU uses PSCI v0.2 */
151
@@ -XXX,XX +XXX,XX @@ struct kvm_arch_memory_slot {
152
#define KVM_DEV_ARM_VGIC_GRP_CPU_REGS    2
153
#define KVM_DEV_ARM_VGIC_CPUID_SHIFT    32
154
#define KVM_DEV_ARM_VGIC_CPUID_MASK    (0xffULL << KVM_DEV_ARM_VGIC_CPUID_SHIFT)
155
+#define KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT 32
156
+#define KVM_DEV_ARM_VGIC_V3_MPIDR_MASK \
157
+            (0xffffffffULL << KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT)
158
#define KVM_DEV_ARM_VGIC_OFFSET_SHIFT    0
159
#define KVM_DEV_ARM_VGIC_OFFSET_MASK    (0xffffffffULL << KVM_DEV_ARM_VGIC_OFFSET_SHIFT)
160
+#define KVM_DEV_ARM_VGIC_SYSREG_INSTR_MASK (0xffff)
161
#define KVM_DEV_ARM_VGIC_GRP_NR_IRQS    3
162
#define KVM_DEV_ARM_VGIC_GRP_CTRL 4
163
+#define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5
164
+#define KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS 6
165
+#define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO 7
166
+#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT    10
167
+#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \
168
+            (0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT)
169
+#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK 0x3ff
170
+#define VGIC_LEVEL_INFO_LINE_LEVEL    0
171
+
172
#define KVM_DEV_ARM_VGIC_CTRL_INIT 0
173
174
/* KVM_IRQ_LINE irq field index values */
175
diff --git a/linux-headers/asm-arm/unistd-common.h b/linux-headers/asm-arm/unistd-common.h
176
new file mode 100644
23
new file mode 100644
177
index XXXXXXX..XXXXXXX
24
index XXXXXXX..XXXXXXX
178
--- /dev/null
25
--- /dev/null
179
+++ b/linux-headers/asm-arm/unistd-common.h
26
+++ b/tests/tcg/aarch64/bti-1.c
180
@@ -XXX,XX +XXX,XX @@
27
@@ -XXX,XX +XXX,XX @@
181
+#ifndef _ASM_ARM_UNISTD_COMMON_H
28
+/*
182
+#define _ASM_ARM_UNISTD_COMMON_H 1
29
+ * Branch target identification, basic notskip cases.
183
+
30
+ */
184
+#define __NR_restart_syscall (__NR_SYSCALL_BASE + 0)
31
+
185
+#define __NR_exit (__NR_SYSCALL_BASE + 1)
32
+#include "bti-crt.inc.c"
186
+#define __NR_fork (__NR_SYSCALL_BASE + 2)
33
+
187
+#define __NR_read (__NR_SYSCALL_BASE + 3)
34
+static void skip2_sigill(int sig, siginfo_t *info, ucontext_t *uc)
188
+#define __NR_write (__NR_SYSCALL_BASE + 4)
35
+{
189
+#define __NR_open (__NR_SYSCALL_BASE + 5)
36
+ uc->uc_mcontext.pc += 8;
190
+#define __NR_close (__NR_SYSCALL_BASE + 6)
37
+ uc->uc_mcontext.pstate = 1;
191
+#define __NR_creat (__NR_SYSCALL_BASE + 8)
38
+}
192
+#define __NR_link (__NR_SYSCALL_BASE + 9)
39
+
193
+#define __NR_unlink (__NR_SYSCALL_BASE + 10)
40
+#define NOP "nop"
194
+#define __NR_execve (__NR_SYSCALL_BASE + 11)
41
+#define BTI_N "hint #32"
195
+#define __NR_chdir (__NR_SYSCALL_BASE + 12)
42
+#define BTI_C "hint #34"
196
+#define __NR_mknod (__NR_SYSCALL_BASE + 14)
43
+#define BTI_J "hint #36"
197
+#define __NR_chmod (__NR_SYSCALL_BASE + 15)
44
+#define BTI_JC "hint #38"
198
+#define __NR_lchown (__NR_SYSCALL_BASE + 16)
45
+
199
+#define __NR_lseek (__NR_SYSCALL_BASE + 19)
46
+#define BTYPE_1(DEST) \
200
+#define __NR_getpid (__NR_SYSCALL_BASE + 20)
47
+ asm("mov %0,#1; adr x16, 1f; br x16; 1: " DEST "; mov %0,#0" \
201
+#define __NR_mount (__NR_SYSCALL_BASE + 21)
48
+ : "=r"(skipped) : : "x16")
202
+#define __NR_setuid (__NR_SYSCALL_BASE + 23)
49
+
203
+#define __NR_getuid (__NR_SYSCALL_BASE + 24)
50
+#define BTYPE_2(DEST) \
204
+#define __NR_ptrace (__NR_SYSCALL_BASE + 26)
51
+ asm("mov %0,#1; adr x16, 1f; blr x16; 1: " DEST "; mov %0,#0" \
205
+#define __NR_pause (__NR_SYSCALL_BASE + 29)
52
+ : "=r"(skipped) : : "x16", "x30")
206
+#define __NR_access (__NR_SYSCALL_BASE + 33)
53
+
207
+#define __NR_nice (__NR_SYSCALL_BASE + 34)
54
+#define BTYPE_3(DEST) \
208
+#define __NR_sync (__NR_SYSCALL_BASE + 36)
55
+ asm("mov %0,#1; adr x15, 1f; br x15; 1: " DEST "; mov %0,#0" \
209
+#define __NR_kill (__NR_SYSCALL_BASE + 37)
56
+ : "=r"(skipped) : : "x15")
210
+#define __NR_rename (__NR_SYSCALL_BASE + 38)
57
+
211
+#define __NR_mkdir (__NR_SYSCALL_BASE + 39)
58
+#define TEST(WHICH, DEST, EXPECT) \
212
+#define __NR_rmdir (__NR_SYSCALL_BASE + 40)
59
+ do { WHICH(DEST); fail += skipped ^ EXPECT; } while (0)
213
+#define __NR_dup (__NR_SYSCALL_BASE + 41)
60
+
214
+#define __NR_pipe (__NR_SYSCALL_BASE + 42)
61
+
215
+#define __NR_times (__NR_SYSCALL_BASE + 43)
62
+int main()
216
+#define __NR_brk (__NR_SYSCALL_BASE + 45)
63
+{
217
+#define __NR_setgid (__NR_SYSCALL_BASE + 46)
64
+ int fail = 0;
218
+#define __NR_getgid (__NR_SYSCALL_BASE + 47)
65
+ int skipped;
219
+#define __NR_geteuid (__NR_SYSCALL_BASE + 49)
66
+
220
+#define __NR_getegid (__NR_SYSCALL_BASE + 50)
67
+ /* Signal-like with SA_SIGINFO. */
221
+#define __NR_acct (__NR_SYSCALL_BASE + 51)
68
+ signal_info(SIGILL, skip2_sigill);
222
+#define __NR_umount2 (__NR_SYSCALL_BASE + 52)
69
+
223
+#define __NR_ioctl (__NR_SYSCALL_BASE + 54)
70
+ TEST(BTYPE_1, NOP, 1);
224
+#define __NR_fcntl (__NR_SYSCALL_BASE + 55)
71
+ TEST(BTYPE_1, BTI_N, 1);
225
+#define __NR_setpgid (__NR_SYSCALL_BASE + 57)
72
+ TEST(BTYPE_1, BTI_C, 0);
226
+#define __NR_umask (__NR_SYSCALL_BASE + 60)
73
+ TEST(BTYPE_1, BTI_J, 0);
227
+#define __NR_chroot (__NR_SYSCALL_BASE + 61)
74
+ TEST(BTYPE_1, BTI_JC, 0);
228
+#define __NR_ustat (__NR_SYSCALL_BASE + 62)
75
+
229
+#define __NR_dup2 (__NR_SYSCALL_BASE + 63)
76
+ TEST(BTYPE_2, NOP, 1);
230
+#define __NR_getppid (__NR_SYSCALL_BASE + 64)
77
+ TEST(BTYPE_2, BTI_N, 1);
231
+#define __NR_getpgrp (__NR_SYSCALL_BASE + 65)
78
+ TEST(BTYPE_2, BTI_C, 0);
232
+#define __NR_setsid (__NR_SYSCALL_BASE + 66)
79
+ TEST(BTYPE_2, BTI_J, 1);
233
+#define __NR_sigaction (__NR_SYSCALL_BASE + 67)
80
+ TEST(BTYPE_2, BTI_JC, 0);
234
+#define __NR_setreuid (__NR_SYSCALL_BASE + 70)
81
+
235
+#define __NR_setregid (__NR_SYSCALL_BASE + 71)
82
+ TEST(BTYPE_3, NOP, 1);
236
+#define __NR_sigsuspend (__NR_SYSCALL_BASE + 72)
83
+ TEST(BTYPE_3, BTI_N, 1);
237
+#define __NR_sigpending (__NR_SYSCALL_BASE + 73)
84
+ TEST(BTYPE_3, BTI_C, 1);
238
+#define __NR_sethostname (__NR_SYSCALL_BASE + 74)
85
+ TEST(BTYPE_3, BTI_J, 0);
239
+#define __NR_setrlimit (__NR_SYSCALL_BASE + 75)
86
+ TEST(BTYPE_3, BTI_JC, 0);
240
+#define __NR_getrusage (__NR_SYSCALL_BASE + 77)
87
+
241
+#define __NR_gettimeofday (__NR_SYSCALL_BASE + 78)
88
+ return fail;
242
+#define __NR_settimeofday (__NR_SYSCALL_BASE + 79)
89
+}
243
+#define __NR_getgroups (__NR_SYSCALL_BASE + 80)
90
diff --git a/tests/tcg/aarch64/bti-2.c b/tests/tcg/aarch64/bti-2.c
244
+#define __NR_setgroups (__NR_SYSCALL_BASE + 81)
245
+#define __NR_symlink (__NR_SYSCALL_BASE + 83)
246
+#define __NR_readlink (__NR_SYSCALL_BASE + 85)
247
+#define __NR_uselib (__NR_SYSCALL_BASE + 86)
248
+#define __NR_swapon (__NR_SYSCALL_BASE + 87)
249
+#define __NR_reboot (__NR_SYSCALL_BASE + 88)
250
+#define __NR_munmap (__NR_SYSCALL_BASE + 91)
251
+#define __NR_truncate (__NR_SYSCALL_BASE + 92)
252
+#define __NR_ftruncate (__NR_SYSCALL_BASE + 93)
253
+#define __NR_fchmod (__NR_SYSCALL_BASE + 94)
254
+#define __NR_fchown (__NR_SYSCALL_BASE + 95)
255
+#define __NR_getpriority (__NR_SYSCALL_BASE + 96)
256
+#define __NR_setpriority (__NR_SYSCALL_BASE + 97)
257
+#define __NR_statfs (__NR_SYSCALL_BASE + 99)
258
+#define __NR_fstatfs (__NR_SYSCALL_BASE + 100)
259
+#define __NR_syslog (__NR_SYSCALL_BASE + 103)
260
+#define __NR_setitimer (__NR_SYSCALL_BASE + 104)
261
+#define __NR_getitimer (__NR_SYSCALL_BASE + 105)
262
+#define __NR_stat (__NR_SYSCALL_BASE + 106)
263
+#define __NR_lstat (__NR_SYSCALL_BASE + 107)
264
+#define __NR_fstat (__NR_SYSCALL_BASE + 108)
265
+#define __NR_vhangup (__NR_SYSCALL_BASE + 111)
266
+#define __NR_wait4 (__NR_SYSCALL_BASE + 114)
267
+#define __NR_swapoff (__NR_SYSCALL_BASE + 115)
268
+#define __NR_sysinfo (__NR_SYSCALL_BASE + 116)
269
+#define __NR_fsync (__NR_SYSCALL_BASE + 118)
270
+#define __NR_sigreturn (__NR_SYSCALL_BASE + 119)
271
+#define __NR_clone (__NR_SYSCALL_BASE + 120)
272
+#define __NR_setdomainname (__NR_SYSCALL_BASE + 121)
273
+#define __NR_uname (__NR_SYSCALL_BASE + 122)
274
+#define __NR_adjtimex (__NR_SYSCALL_BASE + 124)
275
+#define __NR_mprotect (__NR_SYSCALL_BASE + 125)
276
+#define __NR_sigprocmask (__NR_SYSCALL_BASE + 126)
277
+#define __NR_init_module (__NR_SYSCALL_BASE + 128)
278
+#define __NR_delete_module (__NR_SYSCALL_BASE + 129)
279
+#define __NR_quotactl (__NR_SYSCALL_BASE + 131)
280
+#define __NR_getpgid (__NR_SYSCALL_BASE + 132)
281
+#define __NR_fchdir (__NR_SYSCALL_BASE + 133)
282
+#define __NR_bdflush (__NR_SYSCALL_BASE + 134)
283
+#define __NR_sysfs (__NR_SYSCALL_BASE + 135)
284
+#define __NR_personality (__NR_SYSCALL_BASE + 136)
285
+#define __NR_setfsuid (__NR_SYSCALL_BASE + 138)
286
+#define __NR_setfsgid (__NR_SYSCALL_BASE + 139)
287
+#define __NR__llseek (__NR_SYSCALL_BASE + 140)
288
+#define __NR_getdents (__NR_SYSCALL_BASE + 141)
289
+#define __NR__newselect (__NR_SYSCALL_BASE + 142)
290
+#define __NR_flock (__NR_SYSCALL_BASE + 143)
291
+#define __NR_msync (__NR_SYSCALL_BASE + 144)
292
+#define __NR_readv (__NR_SYSCALL_BASE + 145)
293
+#define __NR_writev (__NR_SYSCALL_BASE + 146)
294
+#define __NR_getsid (__NR_SYSCALL_BASE + 147)
295
+#define __NR_fdatasync (__NR_SYSCALL_BASE + 148)
296
+#define __NR__sysctl (__NR_SYSCALL_BASE + 149)
297
+#define __NR_mlock (__NR_SYSCALL_BASE + 150)
298
+#define __NR_munlock (__NR_SYSCALL_BASE + 151)
299
+#define __NR_mlockall (__NR_SYSCALL_BASE + 152)
300
+#define __NR_munlockall (__NR_SYSCALL_BASE + 153)
301
+#define __NR_sched_setparam (__NR_SYSCALL_BASE + 154)
302
+#define __NR_sched_getparam (__NR_SYSCALL_BASE + 155)
303
+#define __NR_sched_setscheduler (__NR_SYSCALL_BASE + 156)
304
+#define __NR_sched_getscheduler (__NR_SYSCALL_BASE + 157)
305
+#define __NR_sched_yield (__NR_SYSCALL_BASE + 158)
306
+#define __NR_sched_get_priority_max (__NR_SYSCALL_BASE + 159)
307
+#define __NR_sched_get_priority_min (__NR_SYSCALL_BASE + 160)
308
+#define __NR_sched_rr_get_interval (__NR_SYSCALL_BASE + 161)
309
+#define __NR_nanosleep (__NR_SYSCALL_BASE + 162)
310
+#define __NR_mremap (__NR_SYSCALL_BASE + 163)
311
+#define __NR_setresuid (__NR_SYSCALL_BASE + 164)
312
+#define __NR_getresuid (__NR_SYSCALL_BASE + 165)
313
+#define __NR_poll (__NR_SYSCALL_BASE + 168)
314
+#define __NR_nfsservctl (__NR_SYSCALL_BASE + 169)
315
+#define __NR_setresgid (__NR_SYSCALL_BASE + 170)
316
+#define __NR_getresgid (__NR_SYSCALL_BASE + 171)
317
+#define __NR_prctl (__NR_SYSCALL_BASE + 172)
318
+#define __NR_rt_sigreturn (__NR_SYSCALL_BASE + 173)
319
+#define __NR_rt_sigaction (__NR_SYSCALL_BASE + 174)
320
+#define __NR_rt_sigprocmask (__NR_SYSCALL_BASE + 175)
321
+#define __NR_rt_sigpending (__NR_SYSCALL_BASE + 176)
322
+#define __NR_rt_sigtimedwait (__NR_SYSCALL_BASE + 177)
323
+#define __NR_rt_sigqueueinfo (__NR_SYSCALL_BASE + 178)
324
+#define __NR_rt_sigsuspend (__NR_SYSCALL_BASE + 179)
325
+#define __NR_pread64 (__NR_SYSCALL_BASE + 180)
326
+#define __NR_pwrite64 (__NR_SYSCALL_BASE + 181)
327
+#define __NR_chown (__NR_SYSCALL_BASE + 182)
328
+#define __NR_getcwd (__NR_SYSCALL_BASE + 183)
329
+#define __NR_capget (__NR_SYSCALL_BASE + 184)
330
+#define __NR_capset (__NR_SYSCALL_BASE + 185)
331
+#define __NR_sigaltstack (__NR_SYSCALL_BASE + 186)
332
+#define __NR_sendfile (__NR_SYSCALL_BASE + 187)
333
+#define __NR_vfork (__NR_SYSCALL_BASE + 190)
334
+#define __NR_ugetrlimit (__NR_SYSCALL_BASE + 191)
335
+#define __NR_mmap2 (__NR_SYSCALL_BASE + 192)
336
+#define __NR_truncate64 (__NR_SYSCALL_BASE + 193)
337
+#define __NR_ftruncate64 (__NR_SYSCALL_BASE + 194)
338
+#define __NR_stat64 (__NR_SYSCALL_BASE + 195)
339
+#define __NR_lstat64 (__NR_SYSCALL_BASE + 196)
340
+#define __NR_fstat64 (__NR_SYSCALL_BASE + 197)
341
+#define __NR_lchown32 (__NR_SYSCALL_BASE + 198)
342
+#define __NR_getuid32 (__NR_SYSCALL_BASE + 199)
343
+#define __NR_getgid32 (__NR_SYSCALL_BASE + 200)
344
+#define __NR_geteuid32 (__NR_SYSCALL_BASE + 201)
345
+#define __NR_getegid32 (__NR_SYSCALL_BASE + 202)
346
+#define __NR_setreuid32 (__NR_SYSCALL_BASE + 203)
347
+#define __NR_setregid32 (__NR_SYSCALL_BASE + 204)
348
+#define __NR_getgroups32 (__NR_SYSCALL_BASE + 205)
349
+#define __NR_setgroups32 (__NR_SYSCALL_BASE + 206)
350
+#define __NR_fchown32 (__NR_SYSCALL_BASE + 207)
351
+#define __NR_setresuid32 (__NR_SYSCALL_BASE + 208)
352
+#define __NR_getresuid32 (__NR_SYSCALL_BASE + 209)
353
+#define __NR_setresgid32 (__NR_SYSCALL_BASE + 210)
354
+#define __NR_getresgid32 (__NR_SYSCALL_BASE + 211)
355
+#define __NR_chown32 (__NR_SYSCALL_BASE + 212)
356
+#define __NR_setuid32 (__NR_SYSCALL_BASE + 213)
357
+#define __NR_setgid32 (__NR_SYSCALL_BASE + 214)
358
+#define __NR_setfsuid32 (__NR_SYSCALL_BASE + 215)
359
+#define __NR_setfsgid32 (__NR_SYSCALL_BASE + 216)
360
+#define __NR_getdents64 (__NR_SYSCALL_BASE + 217)
361
+#define __NR_pivot_root (__NR_SYSCALL_BASE + 218)
362
+#define __NR_mincore (__NR_SYSCALL_BASE + 219)
363
+#define __NR_madvise (__NR_SYSCALL_BASE + 220)
364
+#define __NR_fcntl64 (__NR_SYSCALL_BASE + 221)
365
+#define __NR_gettid (__NR_SYSCALL_BASE + 224)
366
+#define __NR_readahead (__NR_SYSCALL_BASE + 225)
367
+#define __NR_setxattr (__NR_SYSCALL_BASE + 226)
368
+#define __NR_lsetxattr (__NR_SYSCALL_BASE + 227)
369
+#define __NR_fsetxattr (__NR_SYSCALL_BASE + 228)
370
+#define __NR_getxattr (__NR_SYSCALL_BASE + 229)
371
+#define __NR_lgetxattr (__NR_SYSCALL_BASE + 230)
372
+#define __NR_fgetxattr (__NR_SYSCALL_BASE + 231)
373
+#define __NR_listxattr (__NR_SYSCALL_BASE + 232)
374
+#define __NR_llistxattr (__NR_SYSCALL_BASE + 233)
375
+#define __NR_flistxattr (__NR_SYSCALL_BASE + 234)
376
+#define __NR_removexattr (__NR_SYSCALL_BASE + 235)
377
+#define __NR_lremovexattr (__NR_SYSCALL_BASE + 236)
378
+#define __NR_fremovexattr (__NR_SYSCALL_BASE + 237)
379
+#define __NR_tkill (__NR_SYSCALL_BASE + 238)
380
+#define __NR_sendfile64 (__NR_SYSCALL_BASE + 239)
381
+#define __NR_futex (__NR_SYSCALL_BASE + 240)
382
+#define __NR_sched_setaffinity (__NR_SYSCALL_BASE + 241)
383
+#define __NR_sched_getaffinity (__NR_SYSCALL_BASE + 242)
384
+#define __NR_io_setup (__NR_SYSCALL_BASE + 243)
385
+#define __NR_io_destroy (__NR_SYSCALL_BASE + 244)
386
+#define __NR_io_getevents (__NR_SYSCALL_BASE + 245)
387
+#define __NR_io_submit (__NR_SYSCALL_BASE + 246)
388
+#define __NR_io_cancel (__NR_SYSCALL_BASE + 247)
389
+#define __NR_exit_group (__NR_SYSCALL_BASE + 248)
390
+#define __NR_lookup_dcookie (__NR_SYSCALL_BASE + 249)
391
+#define __NR_epoll_create (__NR_SYSCALL_BASE + 250)
392
+#define __NR_epoll_ctl (__NR_SYSCALL_BASE + 251)
393
+#define __NR_epoll_wait (__NR_SYSCALL_BASE + 252)
394
+#define __NR_remap_file_pages (__NR_SYSCALL_BASE + 253)
395
+#define __NR_set_tid_address (__NR_SYSCALL_BASE + 256)
396
+#define __NR_timer_create (__NR_SYSCALL_BASE + 257)
397
+#define __NR_timer_settime (__NR_SYSCALL_BASE + 258)
398
+#define __NR_timer_gettime (__NR_SYSCALL_BASE + 259)
399
+#define __NR_timer_getoverrun (__NR_SYSCALL_BASE + 260)
400
+#define __NR_timer_delete (__NR_SYSCALL_BASE + 261)
401
+#define __NR_clock_settime (__NR_SYSCALL_BASE + 262)
402
+#define __NR_clock_gettime (__NR_SYSCALL_BASE + 263)
403
+#define __NR_clock_getres (__NR_SYSCALL_BASE + 264)
404
+#define __NR_clock_nanosleep (__NR_SYSCALL_BASE + 265)
405
+#define __NR_statfs64 (__NR_SYSCALL_BASE + 266)
406
+#define __NR_fstatfs64 (__NR_SYSCALL_BASE + 267)
407
+#define __NR_tgkill (__NR_SYSCALL_BASE + 268)
408
+#define __NR_utimes (__NR_SYSCALL_BASE + 269)
409
+#define __NR_arm_fadvise64_64 (__NR_SYSCALL_BASE + 270)
410
+#define __NR_pciconfig_iobase (__NR_SYSCALL_BASE + 271)
411
+#define __NR_pciconfig_read (__NR_SYSCALL_BASE + 272)
412
+#define __NR_pciconfig_write (__NR_SYSCALL_BASE + 273)
413
+#define __NR_mq_open (__NR_SYSCALL_BASE + 274)
414
+#define __NR_mq_unlink (__NR_SYSCALL_BASE + 275)
415
+#define __NR_mq_timedsend (__NR_SYSCALL_BASE + 276)
416
+#define __NR_mq_timedreceive (__NR_SYSCALL_BASE + 277)
417
+#define __NR_mq_notify (__NR_SYSCALL_BASE + 278)
418
+#define __NR_mq_getsetattr (__NR_SYSCALL_BASE + 279)
419
+#define __NR_waitid (__NR_SYSCALL_BASE + 280)
420
+#define __NR_socket (__NR_SYSCALL_BASE + 281)
421
+#define __NR_bind (__NR_SYSCALL_BASE + 282)
422
+#define __NR_connect (__NR_SYSCALL_BASE + 283)
423
+#define __NR_listen (__NR_SYSCALL_BASE + 284)
424
+#define __NR_accept (__NR_SYSCALL_BASE + 285)
425
+#define __NR_getsockname (__NR_SYSCALL_BASE + 286)
426
+#define __NR_getpeername (__NR_SYSCALL_BASE + 287)
427
+#define __NR_socketpair (__NR_SYSCALL_BASE + 288)
428
+#define __NR_send (__NR_SYSCALL_BASE + 289)
429
+#define __NR_sendto (__NR_SYSCALL_BASE + 290)
430
+#define __NR_recv (__NR_SYSCALL_BASE + 291)
431
+#define __NR_recvfrom (__NR_SYSCALL_BASE + 292)
432
+#define __NR_shutdown (__NR_SYSCALL_BASE + 293)
433
+#define __NR_setsockopt (__NR_SYSCALL_BASE + 294)
434
+#define __NR_getsockopt (__NR_SYSCALL_BASE + 295)
435
+#define __NR_sendmsg (__NR_SYSCALL_BASE + 296)
436
+#define __NR_recvmsg (__NR_SYSCALL_BASE + 297)
437
+#define __NR_semop (__NR_SYSCALL_BASE + 298)
438
+#define __NR_semget (__NR_SYSCALL_BASE + 299)
439
+#define __NR_semctl (__NR_SYSCALL_BASE + 300)
440
+#define __NR_msgsnd (__NR_SYSCALL_BASE + 301)
441
+#define __NR_msgrcv (__NR_SYSCALL_BASE + 302)
442
+#define __NR_msgget (__NR_SYSCALL_BASE + 303)
443
+#define __NR_msgctl (__NR_SYSCALL_BASE + 304)
444
+#define __NR_shmat (__NR_SYSCALL_BASE + 305)
445
+#define __NR_shmdt (__NR_SYSCALL_BASE + 306)
446
+#define __NR_shmget (__NR_SYSCALL_BASE + 307)
447
+#define __NR_shmctl (__NR_SYSCALL_BASE + 308)
448
+#define __NR_add_key (__NR_SYSCALL_BASE + 309)
449
+#define __NR_request_key (__NR_SYSCALL_BASE + 310)
450
+#define __NR_keyctl (__NR_SYSCALL_BASE + 311)
451
+#define __NR_semtimedop (__NR_SYSCALL_BASE + 312)
452
+#define __NR_vserver (__NR_SYSCALL_BASE + 313)
453
+#define __NR_ioprio_set (__NR_SYSCALL_BASE + 314)
454
+#define __NR_ioprio_get (__NR_SYSCALL_BASE + 315)
455
+#define __NR_inotify_init (__NR_SYSCALL_BASE + 316)
456
+#define __NR_inotify_add_watch (__NR_SYSCALL_BASE + 317)
457
+#define __NR_inotify_rm_watch (__NR_SYSCALL_BASE + 318)
458
+#define __NR_mbind (__NR_SYSCALL_BASE + 319)
459
+#define __NR_get_mempolicy (__NR_SYSCALL_BASE + 320)
460
+#define __NR_set_mempolicy (__NR_SYSCALL_BASE + 321)
461
+#define __NR_openat (__NR_SYSCALL_BASE + 322)
462
+#define __NR_mkdirat (__NR_SYSCALL_BASE + 323)
463
+#define __NR_mknodat (__NR_SYSCALL_BASE + 324)
464
+#define __NR_fchownat (__NR_SYSCALL_BASE + 325)
465
+#define __NR_futimesat (__NR_SYSCALL_BASE + 326)
466
+#define __NR_fstatat64 (__NR_SYSCALL_BASE + 327)
467
+#define __NR_unlinkat (__NR_SYSCALL_BASE + 328)
468
+#define __NR_renameat (__NR_SYSCALL_BASE + 329)
469
+#define __NR_linkat (__NR_SYSCALL_BASE + 330)
470
+#define __NR_symlinkat (__NR_SYSCALL_BASE + 331)
471
+#define __NR_readlinkat (__NR_SYSCALL_BASE + 332)
472
+#define __NR_fchmodat (__NR_SYSCALL_BASE + 333)
473
+#define __NR_faccessat (__NR_SYSCALL_BASE + 334)
474
+#define __NR_pselect6 (__NR_SYSCALL_BASE + 335)
475
+#define __NR_ppoll (__NR_SYSCALL_BASE + 336)
476
+#define __NR_unshare (__NR_SYSCALL_BASE + 337)
477
+#define __NR_set_robust_list (__NR_SYSCALL_BASE + 338)
478
+#define __NR_get_robust_list (__NR_SYSCALL_BASE + 339)
479
+#define __NR_splice (__NR_SYSCALL_BASE + 340)
480
+#define __NR_arm_sync_file_range (__NR_SYSCALL_BASE + 341)
481
+#define __NR_tee (__NR_SYSCALL_BASE + 342)
482
+#define __NR_vmsplice (__NR_SYSCALL_BASE + 343)
483
+#define __NR_move_pages (__NR_SYSCALL_BASE + 344)
484
+#define __NR_getcpu (__NR_SYSCALL_BASE + 345)
485
+#define __NR_epoll_pwait (__NR_SYSCALL_BASE + 346)
486
+#define __NR_kexec_load (__NR_SYSCALL_BASE + 347)
487
+#define __NR_utimensat (__NR_SYSCALL_BASE + 348)
488
+#define __NR_signalfd (__NR_SYSCALL_BASE + 349)
489
+#define __NR_timerfd_create (__NR_SYSCALL_BASE + 350)
490
+#define __NR_eventfd (__NR_SYSCALL_BASE + 351)
491
+#define __NR_fallocate (__NR_SYSCALL_BASE + 352)
492
+#define __NR_timerfd_settime (__NR_SYSCALL_BASE + 353)
493
+#define __NR_timerfd_gettime (__NR_SYSCALL_BASE + 354)
494
+#define __NR_signalfd4 (__NR_SYSCALL_BASE + 355)
495
+#define __NR_eventfd2 (__NR_SYSCALL_BASE + 356)
496
+#define __NR_epoll_create1 (__NR_SYSCALL_BASE + 357)
497
+#define __NR_dup3 (__NR_SYSCALL_BASE + 358)
498
+#define __NR_pipe2 (__NR_SYSCALL_BASE + 359)
499
+#define __NR_inotify_init1 (__NR_SYSCALL_BASE + 360)
500
+#define __NR_preadv (__NR_SYSCALL_BASE + 361)
501
+#define __NR_pwritev (__NR_SYSCALL_BASE + 362)
502
+#define __NR_rt_tgsigqueueinfo (__NR_SYSCALL_BASE + 363)
503
+#define __NR_perf_event_open (__NR_SYSCALL_BASE + 364)
504
+#define __NR_recvmmsg (__NR_SYSCALL_BASE + 365)
505
+#define __NR_accept4 (__NR_SYSCALL_BASE + 366)
506
+#define __NR_fanotify_init (__NR_SYSCALL_BASE + 367)
507
+#define __NR_fanotify_mark (__NR_SYSCALL_BASE + 368)
508
+#define __NR_prlimit64 (__NR_SYSCALL_BASE + 369)
509
+#define __NR_name_to_handle_at (__NR_SYSCALL_BASE + 370)
510
+#define __NR_open_by_handle_at (__NR_SYSCALL_BASE + 371)
511
+#define __NR_clock_adjtime (__NR_SYSCALL_BASE + 372)
512
+#define __NR_syncfs (__NR_SYSCALL_BASE + 373)
513
+#define __NR_sendmmsg (__NR_SYSCALL_BASE + 374)
514
+#define __NR_setns (__NR_SYSCALL_BASE + 375)
515
+#define __NR_process_vm_readv (__NR_SYSCALL_BASE + 376)
516
+#define __NR_process_vm_writev (__NR_SYSCALL_BASE + 377)
517
+#define __NR_kcmp (__NR_SYSCALL_BASE + 378)
518
+#define __NR_finit_module (__NR_SYSCALL_BASE + 379)
519
+#define __NR_sched_setattr (__NR_SYSCALL_BASE + 380)
520
+#define __NR_sched_getattr (__NR_SYSCALL_BASE + 381)
521
+#define __NR_renameat2 (__NR_SYSCALL_BASE + 382)
522
+#define __NR_seccomp (__NR_SYSCALL_BASE + 383)
523
+#define __NR_getrandom (__NR_SYSCALL_BASE + 384)
524
+#define __NR_memfd_create (__NR_SYSCALL_BASE + 385)
525
+#define __NR_bpf (__NR_SYSCALL_BASE + 386)
526
+#define __NR_execveat (__NR_SYSCALL_BASE + 387)
527
+#define __NR_userfaultfd (__NR_SYSCALL_BASE + 388)
528
+#define __NR_membarrier (__NR_SYSCALL_BASE + 389)
529
+#define __NR_mlock2 (__NR_SYSCALL_BASE + 390)
530
+#define __NR_copy_file_range (__NR_SYSCALL_BASE + 391)
531
+#define __NR_preadv2 (__NR_SYSCALL_BASE + 392)
532
+#define __NR_pwritev2 (__NR_SYSCALL_BASE + 393)
533
+#define __NR_pkey_mprotect (__NR_SYSCALL_BASE + 394)
534
+#define __NR_pkey_alloc (__NR_SYSCALL_BASE + 395)
535
+#define __NR_pkey_free (__NR_SYSCALL_BASE + 396)
536
+
537
+#endif /* _ASM_ARM_UNISTD_COMMON_H */
538
diff --git a/linux-headers/asm-arm/unistd-eabi.h b/linux-headers/asm-arm/unistd-eabi.h
539
new file mode 100644
91
new file mode 100644
540
index XXXXXXX..XXXXXXX
92
index XXXXXXX..XXXXXXX
541
--- /dev/null
93
--- /dev/null
542
+++ b/linux-headers/asm-arm/unistd-eabi.h
94
+++ b/tests/tcg/aarch64/bti-2.c
543
@@ -XXX,XX +XXX,XX @@
95
@@ -XXX,XX +XXX,XX @@
544
+#ifndef _ASM_ARM_UNISTD_EABI_H
96
+/*
545
+#define _ASM_ARM_UNISTD_EABI_H 1
97
+ * Branch target identification, basic notskip cases.
546
+
98
+ */
547
+
99
+
548
+#endif /* _ASM_ARM_UNISTD_EABI_H */
100
+#include <stdio.h>
549
diff --git a/linux-headers/asm-arm/unistd-oabi.h b/linux-headers/asm-arm/unistd-oabi.h
101
+#include <signal.h>
102
+#include <string.h>
103
+#include <unistd.h>
104
+#include <sys/mman.h>
105
+
106
+#ifndef PROT_BTI
107
+#define PROT_BTI 0x10
108
+#endif
109
+
110
+static void skip2_sigill(int sig, siginfo_t *info, void *vuc)
111
+{
112
+ ucontext_t *uc = vuc;
113
+ uc->uc_mcontext.pc += 8;
114
+ uc->uc_mcontext.pstate = 1;
115
+}
116
+
117
+#define NOP "nop"
118
+#define BTI_N "hint #32"
119
+#define BTI_C "hint #34"
120
+#define BTI_J "hint #36"
121
+#define BTI_JC "hint #38"
122
+
123
+#define BTYPE_1(DEST) \
124
+ "mov x1, #1\n\t" \
125
+ "adr x16, 1f\n\t" \
126
+ "br x16\n" \
127
+"1: " DEST "\n\t" \
128
+ "mov x1, #0"
129
+
130
+#define BTYPE_2(DEST) \
131
+ "mov x1, #1\n\t" \
132
+ "adr x16, 1f\n\t" \
133
+ "blr x16\n" \
134
+"1: " DEST "\n\t" \
135
+ "mov x1, #0"
136
+
137
+#define BTYPE_3(DEST) \
138
+ "mov x1, #1\n\t" \
139
+ "adr x15, 1f\n\t" \
140
+ "br x15\n" \
141
+"1: " DEST "\n\t" \
142
+ "mov x1, #0"
143
+
144
+#define TEST(WHICH, DEST, EXPECT) \
145
+ WHICH(DEST) "\n" \
146
+ ".if " #EXPECT "\n\t" \
147
+ "eor x1, x1," #EXPECT "\n" \
148
+ ".endif\n\t" \
149
+ "add x0, x0, x1\n\t"
150
+
151
+asm("\n"
152
+"test_begin:\n\t"
153
+ BTI_C "\n\t"
154
+ "mov x2, x30\n\t"
155
+ "mov x0, #0\n\t"
156
+
157
+ TEST(BTYPE_1, NOP, 1)
158
+ TEST(BTYPE_1, BTI_N, 1)
159
+ TEST(BTYPE_1, BTI_C, 0)
160
+ TEST(BTYPE_1, BTI_J, 0)
161
+ TEST(BTYPE_1, BTI_JC, 0)
162
+
163
+ TEST(BTYPE_2, NOP, 1)
164
+ TEST(BTYPE_2, BTI_N, 1)
165
+ TEST(BTYPE_2, BTI_C, 0)
166
+ TEST(BTYPE_2, BTI_J, 1)
167
+ TEST(BTYPE_2, BTI_JC, 0)
168
+
169
+ TEST(BTYPE_3, NOP, 1)
170
+ TEST(BTYPE_3, BTI_N, 1)
171
+ TEST(BTYPE_3, BTI_C, 1)
172
+ TEST(BTYPE_3, BTI_J, 0)
173
+ TEST(BTYPE_3, BTI_JC, 0)
174
+
175
+ "ret x2\n"
176
+"test_end:"
177
+);
178
+
179
+int main()
180
+{
181
+ struct sigaction sa;
182
+ void *tb, *te;
183
+
184
+ void *p = mmap(0, getpagesize(),
185
+ PROT_EXEC | PROT_READ | PROT_WRITE | PROT_BTI,
186
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
187
+ if (p == MAP_FAILED) {
188
+ perror("mmap");
189
+ return 1;
190
+ }
191
+
192
+ memset(&sa, 0, sizeof(sa));
193
+ sa.sa_sigaction = skip2_sigill;
194
+ sa.sa_flags = SA_SIGINFO;
195
+ if (sigaction(SIGILL, &sa, NULL) < 0) {
196
+ perror("sigaction");
197
+ return 1;
198
+ }
199
+
200
+ /*
201
+ * ??? With "extern char test_begin[]", some compiler versions
202
+ * will use :got references, and some linker versions will
203
+ * resolve this reference to a static symbol incorrectly.
204
+ * Bypass this error by using a pc-relative reference directly.
205
+ */
206
+ asm("adr %0, test_begin; adr %1, test_end" : "=r"(tb), "=r"(te));
207
+
208
+ memcpy(p, tb, te - tb);
209
+
210
+ return ((int (*)(void))p)();
211
+}
212
diff --git a/tests/tcg/aarch64/bti-crt.inc.c b/tests/tcg/aarch64/bti-crt.inc.c
550
new file mode 100644
213
new file mode 100644
551
index XXXXXXX..XXXXXXX
214
index XXXXXXX..XXXXXXX
552
--- /dev/null
215
--- /dev/null
553
+++ b/linux-headers/asm-arm/unistd-oabi.h
216
+++ b/tests/tcg/aarch64/bti-crt.inc.c
554
@@ -XXX,XX +XXX,XX @@
217
@@ -XXX,XX +XXX,XX @@
555
+#ifndef _ASM_ARM_UNISTD_OABI_H
218
+/*
556
+#define _ASM_ARM_UNISTD_OABI_H 1
219
+ * Minimal user-environment for testing BTI.
557
+
220
+ *
558
+#define __NR_time (__NR_SYSCALL_BASE + 13)
221
+ * Normal libc is not (yet) built with BTI support enabled,
559
+#define __NR_umount (__NR_SYSCALL_BASE + 22)
222
+ * and so could generate a BTI TRAP before ever reaching main.
560
+#define __NR_stime (__NR_SYSCALL_BASE + 25)
223
+ */
561
+#define __NR_alarm (__NR_SYSCALL_BASE + 27)
224
+
562
+#define __NR_utime (__NR_SYSCALL_BASE + 30)
225
+#include <stdlib.h>
563
+#define __NR_getrlimit (__NR_SYSCALL_BASE + 76)
226
+#include <signal.h>
564
+#define __NR_select (__NR_SYSCALL_BASE + 82)
227
+#include <ucontext.h>
565
+#define __NR_readdir (__NR_SYSCALL_BASE + 89)
228
+#include <asm/unistd.h>
566
+#define __NR_mmap (__NR_SYSCALL_BASE + 90)
229
+
567
+#define __NR_socketcall (__NR_SYSCALL_BASE + 102)
230
+int main(void);
568
+#define __NR_syscall (__NR_SYSCALL_BASE + 113)
231
+
569
+#define __NR_ipc (__NR_SYSCALL_BASE + 117)
232
+void _start(void)
570
+
233
+{
571
+#endif /* _ASM_ARM_UNISTD_OABI_H */
234
+ exit(main());
572
diff --git a/linux-headers/asm-arm/unistd.h b/linux-headers/asm-arm/unistd.h
235
+}
236
+
237
+void exit(int ret)
238
+{
239
+ register int x0 __asm__("x0") = ret;
240
+ register int x8 __asm__("x8") = __NR_exit;
241
+
242
+ asm volatile("svc #0" : : "r"(x0), "r"(x8));
243
+ __builtin_unreachable();
244
+}
245
+
246
+/*
247
+ * Irritatingly, the user API struct sigaction does not match the
248
+ * kernel API struct sigaction. So for simplicity, isolate the
249
+ * kernel ABI here, and make this act like signal.
250
+ */
251
+void signal_info(int sig, void (*fn)(int, siginfo_t *, ucontext_t *))
252
+{
253
+ struct kernel_sigaction {
254
+ void (*handler)(int, siginfo_t *, ucontext_t *);
255
+ unsigned long flags;
256
+ unsigned long restorer;
257
+ unsigned long mask;
258
+ } sa = { fn, SA_SIGINFO, 0, 0 };
259
+
260
+ register int x0 __asm__("x0") = sig;
261
+ register void *x1 __asm__("x1") = &sa;
262
+ register void *x2 __asm__("x2") = 0;
263
+ register int x3 __asm__("x3") = sizeof(unsigned long);
264
+ register int x8 __asm__("x8") = __NR_rt_sigaction;
265
+
266
+ asm volatile("svc #0"
267
+ : : "r"(x0), "r"(x1), "r"(x2), "r"(x3), "r"(x8) : "memory");
268
+}
269
diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
573
index XXXXXXX..XXXXXXX 100644
270
index XXXXXXX..XXXXXXX 100644
574
--- a/linux-headers/asm-arm/unistd.h
271
--- a/tests/tcg/aarch64/Makefile.target
575
+++ b/linux-headers/asm-arm/unistd.h
272
+++ b/tests/tcg/aarch64/Makefile.target
576
@@ -XXX,XX +XXX,XX @@
273
@@ -XXX,XX +XXX,XX @@ run-pauth-%: QEMU_OPTS += -cpu max
577
274
run-plugin-pauth-%: QEMU_OPTS += -cpu max
578
#if defined(__thumb__) || defined(__ARM_EABI__)
275
endif
579
#define __NR_SYSCALL_BASE    0
276
580
+#include <asm/unistd-eabi.h>
277
+# BTI Tests
581
#else
278
+# bti-1 tests the elf notes, so we require special compiler support.
582
#define __NR_SYSCALL_BASE    __NR_OABI_SYSCALL_BASE
279
+ifneq ($(DOCKER_IMAGE)$(CROSS_CC_HAS_ARMV8_BTI),)
583
+#include <asm/unistd-oabi.h>
280
+AARCH64_TESTS += bti-1
584
#endif
281
+bti-1: CFLAGS += -mbranch-protection=standard
585
282
+bti-1: LDFLAGS += -nostdlib
586
-/*
283
+endif
587
- * This file contains the system call numbers.
284
+# bti-2 tests PROT_BTI, so no special compiler support required.
588
- */
285
+AARCH64_TESTS += bti-2
589
-
286
+
590
-#define __NR_restart_syscall        (__NR_SYSCALL_BASE+ 0)
287
# Semihosting smoke test for linux-user
591
-#define __NR_exit            (__NR_SYSCALL_BASE+ 1)
288
AARCH64_TESTS += semihosting
592
-#define __NR_fork            (__NR_SYSCALL_BASE+ 2)
289
run-semihosting: semihosting
593
-#define __NR_read            (__NR_SYSCALL_BASE+ 3)
290
diff --git a/tests/tcg/configure.sh b/tests/tcg/configure.sh
594
-#define __NR_write            (__NR_SYSCALL_BASE+ 4)
291
index XXXXXXX..XXXXXXX 100755
595
-#define __NR_open            (__NR_SYSCALL_BASE+ 5)
292
--- a/tests/tcg/configure.sh
596
-#define __NR_close            (__NR_SYSCALL_BASE+ 6)
293
+++ b/tests/tcg/configure.sh
597
-                    /* 7 was sys_waitpid */
294
@@ -XXX,XX +XXX,XX @@ for target in $target_list; do
598
-#define __NR_creat            (__NR_SYSCALL_BASE+ 8)
295
-march=armv8.3-a -o $TMPE $TMPC; then
599
-#define __NR_link            (__NR_SYSCALL_BASE+ 9)
296
echo "CROSS_CC_HAS_ARMV8_3=y" >> $config_target_mak
600
-#define __NR_unlink            (__NR_SYSCALL_BASE+ 10)
297
fi
601
-#define __NR_execve            (__NR_SYSCALL_BASE+ 11)
298
+ if do_compiler "$target_compiler" $target_compiler_cflags \
602
-#define __NR_chdir            (__NR_SYSCALL_BASE+ 12)
299
+ -mbranch-protection=standard -o $TMPE $TMPC; then
603
-#define __NR_time            (__NR_SYSCALL_BASE+ 13)
300
+ echo "CROSS_CC_HAS_ARMV8_BTI=y" >> $config_target_mak
604
-#define __NR_mknod            (__NR_SYSCALL_BASE+ 14)
301
+ fi
605
-#define __NR_chmod            (__NR_SYSCALL_BASE+ 15)
302
;;
606
-#define __NR_lchown            (__NR_SYSCALL_BASE+ 16)
303
esac
607
-                    /* 17 was sys_break */
304
608
-                    /* 18 was sys_stat */
609
-#define __NR_lseek            (__NR_SYSCALL_BASE+ 19)
610
-#define __NR_getpid            (__NR_SYSCALL_BASE+ 20)
611
-#define __NR_mount            (__NR_SYSCALL_BASE+ 21)
612
-#define __NR_umount            (__NR_SYSCALL_BASE+ 22)
613
-#define __NR_setuid            (__NR_SYSCALL_BASE+ 23)
614
-#define __NR_getuid            (__NR_SYSCALL_BASE+ 24)
615
-#define __NR_stime            (__NR_SYSCALL_BASE+ 25)
616
-#define __NR_ptrace            (__NR_SYSCALL_BASE+ 26)
617
-#define __NR_alarm            (__NR_SYSCALL_BASE+ 27)
618
-                    /* 28 was sys_fstat */
619
-#define __NR_pause            (__NR_SYSCALL_BASE+ 29)
620
-#define __NR_utime            (__NR_SYSCALL_BASE+ 30)
621
-                    /* 31 was sys_stty */
622
-                    /* 32 was sys_gtty */
623
-#define __NR_access            (__NR_SYSCALL_BASE+ 33)
624
-#define __NR_nice            (__NR_SYSCALL_BASE+ 34)
625
-                    /* 35 was sys_ftime */
626
-#define __NR_sync            (__NR_SYSCALL_BASE+ 36)
627
-#define __NR_kill            (__NR_SYSCALL_BASE+ 37)
628
-#define __NR_rename            (__NR_SYSCALL_BASE+ 38)
629
-#define __NR_mkdir            (__NR_SYSCALL_BASE+ 39)
630
-#define __NR_rmdir            (__NR_SYSCALL_BASE+ 40)
631
-#define __NR_dup            (__NR_SYSCALL_BASE+ 41)
632
-#define __NR_pipe            (__NR_SYSCALL_BASE+ 42)
633
-#define __NR_times            (__NR_SYSCALL_BASE+ 43)
634
-                    /* 44 was sys_prof */
635
-#define __NR_brk            (__NR_SYSCALL_BASE+ 45)
636
-#define __NR_setgid            (__NR_SYSCALL_BASE+ 46)
637
-#define __NR_getgid            (__NR_SYSCALL_BASE+ 47)
638
-                    /* 48 was sys_signal */
639
-#define __NR_geteuid            (__NR_SYSCALL_BASE+ 49)
640
-#define __NR_getegid            (__NR_SYSCALL_BASE+ 50)
641
-#define __NR_acct            (__NR_SYSCALL_BASE+ 51)
642
-#define __NR_umount2            (__NR_SYSCALL_BASE+ 52)
643
-                    /* 53 was sys_lock */
644
-#define __NR_ioctl            (__NR_SYSCALL_BASE+ 54)
645
-#define __NR_fcntl            (__NR_SYSCALL_BASE+ 55)
646
-                    /* 56 was sys_mpx */
647
-#define __NR_setpgid            (__NR_SYSCALL_BASE+ 57)
648
-                    /* 58 was sys_ulimit */
649
-                    /* 59 was sys_olduname */
650
-#define __NR_umask            (__NR_SYSCALL_BASE+ 60)
651
-#define __NR_chroot            (__NR_SYSCALL_BASE+ 61)
652
-#define __NR_ustat            (__NR_SYSCALL_BASE+ 62)
653
-#define __NR_dup2            (__NR_SYSCALL_BASE+ 63)
654
-#define __NR_getppid            (__NR_SYSCALL_BASE+ 64)
655
-#define __NR_getpgrp            (__NR_SYSCALL_BASE+ 65)
656
-#define __NR_setsid            (__NR_SYSCALL_BASE+ 66)
657
-#define __NR_sigaction            (__NR_SYSCALL_BASE+ 67)
658
-                    /* 68 was sys_sgetmask */
659
-                    /* 69 was sys_ssetmask */
660
-#define __NR_setreuid            (__NR_SYSCALL_BASE+ 70)
661
-#define __NR_setregid            (__NR_SYSCALL_BASE+ 71)
662
-#define __NR_sigsuspend            (__NR_SYSCALL_BASE+ 72)
663
-#define __NR_sigpending            (__NR_SYSCALL_BASE+ 73)
664
-#define __NR_sethostname        (__NR_SYSCALL_BASE+ 74)
665
-#define __NR_setrlimit            (__NR_SYSCALL_BASE+ 75)
666
-#define __NR_getrlimit            (__NR_SYSCALL_BASE+ 76)    /* Back compat 2GB limited rlimit */
667
-#define __NR_getrusage            (__NR_SYSCALL_BASE+ 77)
668
-#define __NR_gettimeofday        (__NR_SYSCALL_BASE+ 78)
669
-#define __NR_settimeofday        (__NR_SYSCALL_BASE+ 79)
670
-#define __NR_getgroups            (__NR_SYSCALL_BASE+ 80)
671
-#define __NR_setgroups            (__NR_SYSCALL_BASE+ 81)
672
-#define __NR_select            (__NR_SYSCALL_BASE+ 82)
673
-#define __NR_symlink            (__NR_SYSCALL_BASE+ 83)
674
-                    /* 84 was sys_lstat */
675
-#define __NR_readlink            (__NR_SYSCALL_BASE+ 85)
676
-#define __NR_uselib            (__NR_SYSCALL_BASE+ 86)
677
-#define __NR_swapon            (__NR_SYSCALL_BASE+ 87)
678
-#define __NR_reboot            (__NR_SYSCALL_BASE+ 88)
679
-#define __NR_readdir            (__NR_SYSCALL_BASE+ 89)
680
-#define __NR_mmap            (__NR_SYSCALL_BASE+ 90)
681
-#define __NR_munmap            (__NR_SYSCALL_BASE+ 91)
682
-#define __NR_truncate            (__NR_SYSCALL_BASE+ 92)
683
-#define __NR_ftruncate            (__NR_SYSCALL_BASE+ 93)
684
-#define __NR_fchmod            (__NR_SYSCALL_BASE+ 94)
685
-#define __NR_fchown            (__NR_SYSCALL_BASE+ 95)
686
-#define __NR_getpriority        (__NR_SYSCALL_BASE+ 96)
687
-#define __NR_setpriority        (__NR_SYSCALL_BASE+ 97)
688
-                    /* 98 was sys_profil */
689
-#define __NR_statfs            (__NR_SYSCALL_BASE+ 99)
690
-#define __NR_fstatfs            (__NR_SYSCALL_BASE+100)
691
-                    /* 101 was sys_ioperm */
692
-#define __NR_socketcall            (__NR_SYSCALL_BASE+102)
693
-#define __NR_syslog            (__NR_SYSCALL_BASE+103)
694
-#define __NR_setitimer            (__NR_SYSCALL_BASE+104)
695
-#define __NR_getitimer            (__NR_SYSCALL_BASE+105)
696
-#define __NR_stat            (__NR_SYSCALL_BASE+106)
697
-#define __NR_lstat            (__NR_SYSCALL_BASE+107)
698
-#define __NR_fstat            (__NR_SYSCALL_BASE+108)
699
-                    /* 109 was sys_uname */
700
-                    /* 110 was sys_iopl */
701
-#define __NR_vhangup            (__NR_SYSCALL_BASE+111)
702
-                    /* 112 was sys_idle */
703
-#define __NR_syscall            (__NR_SYSCALL_BASE+113) /* syscall to call a syscall! */
704
-#define __NR_wait4            (__NR_SYSCALL_BASE+114)
705
-#define __NR_swapoff            (__NR_SYSCALL_BASE+115)
706
-#define __NR_sysinfo            (__NR_SYSCALL_BASE+116)
707
-#define __NR_ipc            (__NR_SYSCALL_BASE+117)
708
-#define __NR_fsync            (__NR_SYSCALL_BASE+118)
709
-#define __NR_sigreturn            (__NR_SYSCALL_BASE+119)
710
-#define __NR_clone            (__NR_SYSCALL_BASE+120)
711
-#define __NR_setdomainname        (__NR_SYSCALL_BASE+121)
712
-#define __NR_uname            (__NR_SYSCALL_BASE+122)
713
-                    /* 123 was sys_modify_ldt */
714
-#define __NR_adjtimex            (__NR_SYSCALL_BASE+124)
715
-#define __NR_mprotect            (__NR_SYSCALL_BASE+125)
716
-#define __NR_sigprocmask        (__NR_SYSCALL_BASE+126)
717
-                    /* 127 was sys_create_module */
718
-#define __NR_init_module        (__NR_SYSCALL_BASE+128)
719
-#define __NR_delete_module        (__NR_SYSCALL_BASE+129)
720
-                    /* 130 was sys_get_kernel_syms */
721
-#define __NR_quotactl            (__NR_SYSCALL_BASE+131)
722
-#define __NR_getpgid            (__NR_SYSCALL_BASE+132)
723
-#define __NR_fchdir            (__NR_SYSCALL_BASE+133)
724
-#define __NR_bdflush            (__NR_SYSCALL_BASE+134)
725
-#define __NR_sysfs            (__NR_SYSCALL_BASE+135)
726
-#define __NR_personality        (__NR_SYSCALL_BASE+136)
727
-                    /* 137 was sys_afs_syscall */
728
-#define __NR_setfsuid            (__NR_SYSCALL_BASE+138)
729
-#define __NR_setfsgid            (__NR_SYSCALL_BASE+139)
730
-#define __NR__llseek            (__NR_SYSCALL_BASE+140)
731
-#define __NR_getdents            (__NR_SYSCALL_BASE+141)
732
-#define __NR__newselect            (__NR_SYSCALL_BASE+142)
733
-#define __NR_flock            (__NR_SYSCALL_BASE+143)
734
-#define __NR_msync            (__NR_SYSCALL_BASE+144)
735
-#define __NR_readv            (__NR_SYSCALL_BASE+145)
736
-#define __NR_writev            (__NR_SYSCALL_BASE+146)
737
-#define __NR_getsid            (__NR_SYSCALL_BASE+147)
738
-#define __NR_fdatasync            (__NR_SYSCALL_BASE+148)
739
-#define __NR__sysctl            (__NR_SYSCALL_BASE+149)
740
-#define __NR_mlock            (__NR_SYSCALL_BASE+150)
741
-#define __NR_munlock            (__NR_SYSCALL_BASE+151)
742
-#define __NR_mlockall            (__NR_SYSCALL_BASE+152)
743
-#define __NR_munlockall            (__NR_SYSCALL_BASE+153)
744
-#define __NR_sched_setparam        (__NR_SYSCALL_BASE+154)
745
-#define __NR_sched_getparam        (__NR_SYSCALL_BASE+155)
746
-#define __NR_sched_setscheduler        (__NR_SYSCALL_BASE+156)
747
-#define __NR_sched_getscheduler        (__NR_SYSCALL_BASE+157)
748
-#define __NR_sched_yield        (__NR_SYSCALL_BASE+158)
749
-#define __NR_sched_get_priority_max    (__NR_SYSCALL_BASE+159)
750
-#define __NR_sched_get_priority_min    (__NR_SYSCALL_BASE+160)
751
-#define __NR_sched_rr_get_interval    (__NR_SYSCALL_BASE+161)
752
-#define __NR_nanosleep            (__NR_SYSCALL_BASE+162)
753
-#define __NR_mremap            (__NR_SYSCALL_BASE+163)
754
-#define __NR_setresuid            (__NR_SYSCALL_BASE+164)
755
-#define __NR_getresuid            (__NR_SYSCALL_BASE+165)
756
-                    /* 166 was sys_vm86 */
757
-                    /* 167 was sys_query_module */
758
-#define __NR_poll            (__NR_SYSCALL_BASE+168)
759
-#define __NR_nfsservctl            (__NR_SYSCALL_BASE+169)
760
-#define __NR_setresgid            (__NR_SYSCALL_BASE+170)
761
-#define __NR_getresgid            (__NR_SYSCALL_BASE+171)
762
-#define __NR_prctl            (__NR_SYSCALL_BASE+172)
763
-#define __NR_rt_sigreturn        (__NR_SYSCALL_BASE+173)
764
-#define __NR_rt_sigaction        (__NR_SYSCALL_BASE+174)
765
-#define __NR_rt_sigprocmask        (__NR_SYSCALL_BASE+175)
766
-#define __NR_rt_sigpending        (__NR_SYSCALL_BASE+176)
767
-#define __NR_rt_sigtimedwait        (__NR_SYSCALL_BASE+177)
768
-#define __NR_rt_sigqueueinfo        (__NR_SYSCALL_BASE+178)
769
-#define __NR_rt_sigsuspend        (__NR_SYSCALL_BASE+179)
770
-#define __NR_pread64            (__NR_SYSCALL_BASE+180)
771
-#define __NR_pwrite64            (__NR_SYSCALL_BASE+181)
772
-#define __NR_chown            (__NR_SYSCALL_BASE+182)
773
-#define __NR_getcwd            (__NR_SYSCALL_BASE+183)
774
-#define __NR_capget            (__NR_SYSCALL_BASE+184)
775
-#define __NR_capset            (__NR_SYSCALL_BASE+185)
776
-#define __NR_sigaltstack        (__NR_SYSCALL_BASE+186)
777
-#define __NR_sendfile            (__NR_SYSCALL_BASE+187)
778
-                    /* 188 reserved */
779
-                    /* 189 reserved */
780
-#define __NR_vfork            (__NR_SYSCALL_BASE+190)
781
-#define __NR_ugetrlimit            (__NR_SYSCALL_BASE+191)    /* SuS compliant getrlimit */
782
-#define __NR_mmap2            (__NR_SYSCALL_BASE+192)
783
-#define __NR_truncate64            (__NR_SYSCALL_BASE+193)
784
-#define __NR_ftruncate64        (__NR_SYSCALL_BASE+194)
785
-#define __NR_stat64            (__NR_SYSCALL_BASE+195)
786
-#define __NR_lstat64            (__NR_SYSCALL_BASE+196)
787
-#define __NR_fstat64            (__NR_SYSCALL_BASE+197)
788
-#define __NR_lchown32            (__NR_SYSCALL_BASE+198)
789
-#define __NR_getuid32            (__NR_SYSCALL_BASE+199)
790
-#define __NR_getgid32            (__NR_SYSCALL_BASE+200)
791
-#define __NR_geteuid32            (__NR_SYSCALL_BASE+201)
792
-#define __NR_getegid32            (__NR_SYSCALL_BASE+202)
793
-#define __NR_setreuid32            (__NR_SYSCALL_BASE+203)
794
-#define __NR_setregid32            (__NR_SYSCALL_BASE+204)
795
-#define __NR_getgroups32        (__NR_SYSCALL_BASE+205)
796
-#define __NR_setgroups32        (__NR_SYSCALL_BASE+206)
797
-#define __NR_fchown32            (__NR_SYSCALL_BASE+207)
798
-#define __NR_setresuid32        (__NR_SYSCALL_BASE+208)
799
-#define __NR_getresuid32        (__NR_SYSCALL_BASE+209)
800
-#define __NR_setresgid32        (__NR_SYSCALL_BASE+210)
801
-#define __NR_getresgid32        (__NR_SYSCALL_BASE+211)
802
-#define __NR_chown32            (__NR_SYSCALL_BASE+212)
803
-#define __NR_setuid32            (__NR_SYSCALL_BASE+213)
804
-#define __NR_setgid32            (__NR_SYSCALL_BASE+214)
805
-#define __NR_setfsuid32            (__NR_SYSCALL_BASE+215)
806
-#define __NR_setfsgid32            (__NR_SYSCALL_BASE+216)
807
-#define __NR_getdents64            (__NR_SYSCALL_BASE+217)
808
-#define __NR_pivot_root            (__NR_SYSCALL_BASE+218)
809
-#define __NR_mincore            (__NR_SYSCALL_BASE+219)
810
-#define __NR_madvise            (__NR_SYSCALL_BASE+220)
811
-#define __NR_fcntl64            (__NR_SYSCALL_BASE+221)
812
-                    /* 222 for tux */
813
-                    /* 223 is unused */
814
-#define __NR_gettid            (__NR_SYSCALL_BASE+224)
815
-#define __NR_readahead            (__NR_SYSCALL_BASE+225)
816
-#define __NR_setxattr            (__NR_SYSCALL_BASE+226)
817
-#define __NR_lsetxattr            (__NR_SYSCALL_BASE+227)
818
-#define __NR_fsetxattr            (__NR_SYSCALL_BASE+228)
819
-#define __NR_getxattr            (__NR_SYSCALL_BASE+229)
820
-#define __NR_lgetxattr            (__NR_SYSCALL_BASE+230)
821
-#define __NR_fgetxattr            (__NR_SYSCALL_BASE+231)
822
-#define __NR_listxattr            (__NR_SYSCALL_BASE+232)
823
-#define __NR_llistxattr            (__NR_SYSCALL_BASE+233)
824
-#define __NR_flistxattr            (__NR_SYSCALL_BASE+234)
825
-#define __NR_removexattr        (__NR_SYSCALL_BASE+235)
826
-#define __NR_lremovexattr        (__NR_SYSCALL_BASE+236)
827
-#define __NR_fremovexattr        (__NR_SYSCALL_BASE+237)
828
-#define __NR_tkill            (__NR_SYSCALL_BASE+238)
829
-#define __NR_sendfile64            (__NR_SYSCALL_BASE+239)
830
-#define __NR_futex            (__NR_SYSCALL_BASE+240)
831
-#define __NR_sched_setaffinity        (__NR_SYSCALL_BASE+241)
832
-#define __NR_sched_getaffinity        (__NR_SYSCALL_BASE+242)
833
-#define __NR_io_setup            (__NR_SYSCALL_BASE+243)
834
-#define __NR_io_destroy            (__NR_SYSCALL_BASE+244)
835
-#define __NR_io_getevents        (__NR_SYSCALL_BASE+245)
836
-#define __NR_io_submit            (__NR_SYSCALL_BASE+246)
837
-#define __NR_io_cancel            (__NR_SYSCALL_BASE+247)
838
-#define __NR_exit_group            (__NR_SYSCALL_BASE+248)
839
-#define __NR_lookup_dcookie        (__NR_SYSCALL_BASE+249)
840
-#define __NR_epoll_create        (__NR_SYSCALL_BASE+250)
841
-#define __NR_epoll_ctl            (__NR_SYSCALL_BASE+251)
842
-#define __NR_epoll_wait            (__NR_SYSCALL_BASE+252)
843
-#define __NR_remap_file_pages        (__NR_SYSCALL_BASE+253)
844
-                    /* 254 for set_thread_area */
845
-                    /* 255 for get_thread_area */
846
-#define __NR_set_tid_address        (__NR_SYSCALL_BASE+256)
847
-#define __NR_timer_create        (__NR_SYSCALL_BASE+257)
848
-#define __NR_timer_settime        (__NR_SYSCALL_BASE+258)
849
-#define __NR_timer_gettime        (__NR_SYSCALL_BASE+259)
850
-#define __NR_timer_getoverrun        (__NR_SYSCALL_BASE+260)
851
-#define __NR_timer_delete        (__NR_SYSCALL_BASE+261)
852
-#define __NR_clock_settime        (__NR_SYSCALL_BASE+262)
853
-#define __NR_clock_gettime        (__NR_SYSCALL_BASE+263)
854
-#define __NR_clock_getres        (__NR_SYSCALL_BASE+264)
855
-#define __NR_clock_nanosleep        (__NR_SYSCALL_BASE+265)
856
-#define __NR_statfs64            (__NR_SYSCALL_BASE+266)
857
-#define __NR_fstatfs64            (__NR_SYSCALL_BASE+267)
858
-#define __NR_tgkill            (__NR_SYSCALL_BASE+268)
859
-#define __NR_utimes            (__NR_SYSCALL_BASE+269)
860
-#define __NR_arm_fadvise64_64        (__NR_SYSCALL_BASE+270)
861
-#define __NR_pciconfig_iobase        (__NR_SYSCALL_BASE+271)
862
-#define __NR_pciconfig_read        (__NR_SYSCALL_BASE+272)
863
-#define __NR_pciconfig_write        (__NR_SYSCALL_BASE+273)
864
-#define __NR_mq_open            (__NR_SYSCALL_BASE+274)
865
-#define __NR_mq_unlink            (__NR_SYSCALL_BASE+275)
866
-#define __NR_mq_timedsend        (__NR_SYSCALL_BASE+276)
867
-#define __NR_mq_timedreceive        (__NR_SYSCALL_BASE+277)
868
-#define __NR_mq_notify            (__NR_SYSCALL_BASE+278)
869
-#define __NR_mq_getsetattr        (__NR_SYSCALL_BASE+279)
870
-#define __NR_waitid            (__NR_SYSCALL_BASE+280)
871
-#define __NR_socket            (__NR_SYSCALL_BASE+281)
872
-#define __NR_bind            (__NR_SYSCALL_BASE+282)
873
-#define __NR_connect            (__NR_SYSCALL_BASE+283)
874
-#define __NR_listen            (__NR_SYSCALL_BASE+284)
875
-#define __NR_accept            (__NR_SYSCALL_BASE+285)
876
-#define __NR_getsockname        (__NR_SYSCALL_BASE+286)
877
-#define __NR_getpeername        (__NR_SYSCALL_BASE+287)
878
-#define __NR_socketpair            (__NR_SYSCALL_BASE+288)
879
-#define __NR_send            (__NR_SYSCALL_BASE+289)
880
-#define __NR_sendto            (__NR_SYSCALL_BASE+290)
881
-#define __NR_recv            (__NR_SYSCALL_BASE+291)
882
-#define __NR_recvfrom            (__NR_SYSCALL_BASE+292)
883
-#define __NR_shutdown            (__NR_SYSCALL_BASE+293)
884
-#define __NR_setsockopt            (__NR_SYSCALL_BASE+294)
885
-#define __NR_getsockopt            (__NR_SYSCALL_BASE+295)
886
-#define __NR_sendmsg            (__NR_SYSCALL_BASE+296)
887
-#define __NR_recvmsg            (__NR_SYSCALL_BASE+297)
888
-#define __NR_semop            (__NR_SYSCALL_BASE+298)
889
-#define __NR_semget            (__NR_SYSCALL_BASE+299)
890
-#define __NR_semctl            (__NR_SYSCALL_BASE+300)
891
-#define __NR_msgsnd            (__NR_SYSCALL_BASE+301)
892
-#define __NR_msgrcv            (__NR_SYSCALL_BASE+302)
893
-#define __NR_msgget            (__NR_SYSCALL_BASE+303)
894
-#define __NR_msgctl            (__NR_SYSCALL_BASE+304)
895
-#define __NR_shmat            (__NR_SYSCALL_BASE+305)
896
-#define __NR_shmdt            (__NR_SYSCALL_BASE+306)
897
-#define __NR_shmget            (__NR_SYSCALL_BASE+307)
898
-#define __NR_shmctl            (__NR_SYSCALL_BASE+308)
899
-#define __NR_add_key            (__NR_SYSCALL_BASE+309)
900
-#define __NR_request_key        (__NR_SYSCALL_BASE+310)
901
-#define __NR_keyctl            (__NR_SYSCALL_BASE+311)
902
-#define __NR_semtimedop            (__NR_SYSCALL_BASE+312)
903
-#define __NR_vserver            (__NR_SYSCALL_BASE+313)
904
-#define __NR_ioprio_set            (__NR_SYSCALL_BASE+314)
905
-#define __NR_ioprio_get            (__NR_SYSCALL_BASE+315)
906
-#define __NR_inotify_init        (__NR_SYSCALL_BASE+316)
907
-#define __NR_inotify_add_watch        (__NR_SYSCALL_BASE+317)
908
-#define __NR_inotify_rm_watch        (__NR_SYSCALL_BASE+318)
909
-#define __NR_mbind            (__NR_SYSCALL_BASE+319)
910
-#define __NR_get_mempolicy        (__NR_SYSCALL_BASE+320)
911
-#define __NR_set_mempolicy        (__NR_SYSCALL_BASE+321)
912
-#define __NR_openat            (__NR_SYSCALL_BASE+322)
913
-#define __NR_mkdirat            (__NR_SYSCALL_BASE+323)
914
-#define __NR_mknodat            (__NR_SYSCALL_BASE+324)
915
-#define __NR_fchownat            (__NR_SYSCALL_BASE+325)
916
-#define __NR_futimesat            (__NR_SYSCALL_BASE+326)
917
-#define __NR_fstatat64            (__NR_SYSCALL_BASE+327)
918
-#define __NR_unlinkat            (__NR_SYSCALL_BASE+328)
919
-#define __NR_renameat            (__NR_SYSCALL_BASE+329)
920
-#define __NR_linkat            (__NR_SYSCALL_BASE+330)
921
-#define __NR_symlinkat            (__NR_SYSCALL_BASE+331)
922
-#define __NR_readlinkat            (__NR_SYSCALL_BASE+332)
923
-#define __NR_fchmodat            (__NR_SYSCALL_BASE+333)
924
-#define __NR_faccessat            (__NR_SYSCALL_BASE+334)
925
-#define __NR_pselect6            (__NR_SYSCALL_BASE+335)
926
-#define __NR_ppoll            (__NR_SYSCALL_BASE+336)
927
-#define __NR_unshare            (__NR_SYSCALL_BASE+337)
928
-#define __NR_set_robust_list        (__NR_SYSCALL_BASE+338)
929
-#define __NR_get_robust_list        (__NR_SYSCALL_BASE+339)
930
-#define __NR_splice            (__NR_SYSCALL_BASE+340)
931
-#define __NR_arm_sync_file_range    (__NR_SYSCALL_BASE+341)
932
+#include <asm/unistd-common.h>
933
#define __NR_sync_file_range2        __NR_arm_sync_file_range
934
-#define __NR_tee            (__NR_SYSCALL_BASE+342)
935
-#define __NR_vmsplice            (__NR_SYSCALL_BASE+343)
936
-#define __NR_move_pages            (__NR_SYSCALL_BASE+344)
937
-#define __NR_getcpu            (__NR_SYSCALL_BASE+345)
938
-#define __NR_epoll_pwait        (__NR_SYSCALL_BASE+346)
939
-#define __NR_kexec_load            (__NR_SYSCALL_BASE+347)
940
-#define __NR_utimensat            (__NR_SYSCALL_BASE+348)
941
-#define __NR_signalfd            (__NR_SYSCALL_BASE+349)
942
-#define __NR_timerfd_create        (__NR_SYSCALL_BASE+350)
943
-#define __NR_eventfd            (__NR_SYSCALL_BASE+351)
944
-#define __NR_fallocate            (__NR_SYSCALL_BASE+352)
945
-#define __NR_timerfd_settime        (__NR_SYSCALL_BASE+353)
946
-#define __NR_timerfd_gettime        (__NR_SYSCALL_BASE+354)
947
-#define __NR_signalfd4            (__NR_SYSCALL_BASE+355)
948
-#define __NR_eventfd2            (__NR_SYSCALL_BASE+356)
949
-#define __NR_epoll_create1        (__NR_SYSCALL_BASE+357)
950
-#define __NR_dup3            (__NR_SYSCALL_BASE+358)
951
-#define __NR_pipe2            (__NR_SYSCALL_BASE+359)
952
-#define __NR_inotify_init1        (__NR_SYSCALL_BASE+360)
953
-#define __NR_preadv            (__NR_SYSCALL_BASE+361)
954
-#define __NR_pwritev            (__NR_SYSCALL_BASE+362)
955
-#define __NR_rt_tgsigqueueinfo        (__NR_SYSCALL_BASE+363)
956
-#define __NR_perf_event_open        (__NR_SYSCALL_BASE+364)
957
-#define __NR_recvmmsg            (__NR_SYSCALL_BASE+365)
958
-#define __NR_accept4            (__NR_SYSCALL_BASE+366)
959
-#define __NR_fanotify_init        (__NR_SYSCALL_BASE+367)
960
-#define __NR_fanotify_mark        (__NR_SYSCALL_BASE+368)
961
-#define __NR_prlimit64            (__NR_SYSCALL_BASE+369)
962
-#define __NR_name_to_handle_at        (__NR_SYSCALL_BASE+370)
963
-#define __NR_open_by_handle_at        (__NR_SYSCALL_BASE+371)
964
-#define __NR_clock_adjtime        (__NR_SYSCALL_BASE+372)
965
-#define __NR_syncfs            (__NR_SYSCALL_BASE+373)
966
-#define __NR_sendmmsg            (__NR_SYSCALL_BASE+374)
967
-#define __NR_setns            (__NR_SYSCALL_BASE+375)
968
-#define __NR_process_vm_readv        (__NR_SYSCALL_BASE+376)
969
-#define __NR_process_vm_writev        (__NR_SYSCALL_BASE+377)
970
-#define __NR_kcmp            (__NR_SYSCALL_BASE+378)
971
-#define __NR_finit_module        (__NR_SYSCALL_BASE+379)
972
-#define __NR_sched_setattr        (__NR_SYSCALL_BASE+380)
973
-#define __NR_sched_getattr        (__NR_SYSCALL_BASE+381)
974
-#define __NR_renameat2            (__NR_SYSCALL_BASE+382)
975
-#define __NR_seccomp            (__NR_SYSCALL_BASE+383)
976
-#define __NR_getrandom            (__NR_SYSCALL_BASE+384)
977
-#define __NR_memfd_create        (__NR_SYSCALL_BASE+385)
978
-#define __NR_bpf            (__NR_SYSCALL_BASE+386)
979
-#define __NR_execveat            (__NR_SYSCALL_BASE+387)
980
-#define __NR_userfaultfd        (__NR_SYSCALL_BASE+388)
981
-#define __NR_membarrier            (__NR_SYSCALL_BASE+389)
982
-#define __NR_mlock2            (__NR_SYSCALL_BASE+390)
983
-#define __NR_copy_file_range        (__NR_SYSCALL_BASE+391)
984
-#define __NR_preadv2            (__NR_SYSCALL_BASE+392)
985
-#define __NR_pwritev2            (__NR_SYSCALL_BASE+393)
986
987
/*
988
* The following SWIs are ARM private.
989
@@ -XXX,XX +XXX,XX @@
990
#define __ARM_NR_usr32            (__ARM_NR_BASE+4)
991
#define __ARM_NR_set_tls        (__ARM_NR_BASE+5)
992
993
-/*
994
- * The following syscalls are obsolete and no longer available for EABI.
995
- */
996
-#if defined(__ARM_EABI__)
997
-#undef __NR_time
998
-#undef __NR_umount
999
-#undef __NR_stime
1000
-#undef __NR_alarm
1001
-#undef __NR_utime
1002
-#undef __NR_getrlimit
1003
-#undef __NR_select
1004
-#undef __NR_readdir
1005
-#undef __NR_mmap
1006
-#undef __NR_socketcall
1007
-#undef __NR_syscall
1008
-#undef __NR_ipc
1009
-#endif
1010
-
1011
#endif /* __ASM_ARM_UNISTD_H */
1012
diff --git a/linux-headers/asm-arm64/kvm.h b/linux-headers/asm-arm64/kvm.h
1013
index XXXXXXX..XXXXXXX 100644
1014
--- a/linux-headers/asm-arm64/kvm.h
1015
+++ b/linux-headers/asm-arm64/kvm.h
1016
@@ -XXX,XX +XXX,XX @@ struct kvm_arch_memory_slot {
1017
#define KVM_DEV_ARM_VGIC_GRP_CPU_REGS    2
1018
#define KVM_DEV_ARM_VGIC_CPUID_SHIFT    32
1019
#define KVM_DEV_ARM_VGIC_CPUID_MASK    (0xffULL << KVM_DEV_ARM_VGIC_CPUID_SHIFT)
1020
+#define KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT 32
1021
+#define KVM_DEV_ARM_VGIC_V3_MPIDR_MASK \
1022
+            (0xffffffffULL << KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT)
1023
#define KVM_DEV_ARM_VGIC_OFFSET_SHIFT    0
1024
#define KVM_DEV_ARM_VGIC_OFFSET_MASK    (0xffffffffULL << KVM_DEV_ARM_VGIC_OFFSET_SHIFT)
1025
+#define KVM_DEV_ARM_VGIC_SYSREG_INSTR_MASK (0xffff)
1026
#define KVM_DEV_ARM_VGIC_GRP_NR_IRQS    3
1027
#define KVM_DEV_ARM_VGIC_GRP_CTRL    4
1028
+#define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5
1029
+#define KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS 6
1030
+#define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO 7
1031
+#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT    10
1032
+#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \
1033
+            (0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT)
1034
+#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK    0x3ff
1035
+#define VGIC_LEVEL_INFO_LINE_LEVEL    0
1036
+
1037
#define KVM_DEV_ARM_VGIC_CTRL_INIT    0
1038
1039
/* Device Control API on vcpu fd */
1040
diff --git a/linux-headers/asm-powerpc/kvm.h b/linux-headers/asm-powerpc/kvm.h
1041
index XXXXXXX..XXXXXXX 100644
1042
--- a/linux-headers/asm-powerpc/kvm.h
1043
+++ b/linux-headers/asm-powerpc/kvm.h
1044
@@ -XXX,XX +XXX,XX @@ struct kvm_get_htab_header {
1045
    __u16    n_invalid;
1046
};
1047
1048
+/* For KVM_PPC_CONFIGURE_V3_MMU */
1049
+struct kvm_ppc_mmuv3_cfg {
1050
+    __u64    flags;
1051
+    __u64    process_table;    /* second doubleword of partition table entry */
1052
+};
1053
+
1054
+/* Flag values for KVM_PPC_CONFIGURE_V3_MMU */
1055
+#define KVM_PPC_MMUV3_RADIX    1    /* 1 = radix mode, 0 = HPT */
1056
+#define KVM_PPC_MMUV3_GTSE    2    /* global translation shootdown enb. */
1057
+
1058
+/* For KVM_PPC_GET_RMMU_INFO */
1059
+struct kvm_ppc_rmmu_info {
1060
+    struct kvm_ppc_radix_geom {
1061
+        __u8    page_shift;
1062
+        __u8    level_bits[4];
1063
+        __u8    pad[3];
1064
+    }    geometries[8];
1065
+    __u32    ap_encodings[8];
1066
+};
1067
+
1068
/* Per-vcpu XICS interrupt controller state */
1069
#define KVM_REG_PPC_ICP_STATE    (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x8c)
1070
1071
@@ -XXX,XX +XXX,XX @@ struct kvm_get_htab_header {
1072
#define KVM_REG_PPC_SPRG9    (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xba)
1073
#define KVM_REG_PPC_DBSR    (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xbb)
1074
1075
+/* POWER9 registers */
1076
+#define KVM_REG_PPC_TIDR    (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbc)
1077
+#define KVM_REG_PPC_PSSCR    (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbd)
1078
+
1079
/* Transactional Memory checkpointed state:
1080
* This is all GPRs, all VSX regs and a subset of SPRs
1081
*/
1082
@@ -XXX,XX +XXX,XX @@ struct kvm_get_htab_header {
1083
#define KVM_REG_PPC_TM_VSCR    (KVM_REG_PPC_TM | KVM_REG_SIZE_U32 | 0x67)
1084
#define KVM_REG_PPC_TM_DSCR    (KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x68)
1085
#define KVM_REG_PPC_TM_TAR    (KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x69)
1086
+#define KVM_REG_PPC_TM_XER    (KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x6a)
1087
1088
/* PPC64 eXternal Interrupt Controller Specification */
1089
#define KVM_DEV_XICS_GRP_SOURCES    1    /* 64-bit source attributes */
1090
@@ -XXX,XX +XXX,XX @@ struct kvm_get_htab_header {
1091
#define KVM_XICS_LEVEL_SENSITIVE    (1ULL << 40)
1092
#define KVM_XICS_MASKED        (1ULL << 41)
1093
#define KVM_XICS_PENDING        (1ULL << 42)
1094
+#define KVM_XICS_PRESENTED        (1ULL << 43)
1095
+#define KVM_XICS_QUEUED        (1ULL << 44)
1096
1097
#endif /* __LINUX_KVM_POWERPC_H */
1098
diff --git a/linux-headers/asm-powerpc/unistd.h b/linux-headers/asm-powerpc/unistd.h
1099
index XXXXXXX..XXXXXXX 100644
1100
--- a/linux-headers/asm-powerpc/unistd.h
1101
+++ b/linux-headers/asm-powerpc/unistd.h
1102
@@ -XXX,XX +XXX,XX @@
1103
#define __NR_copy_file_range    379
1104
#define __NR_preadv2        380
1105
#define __NR_pwritev2        381
1106
+#define __NR_kexec_file_load    382
1107
1108
#endif /* _ASM_POWERPC_UNISTD_H_ */
1109
diff --git a/linux-headers/asm-x86/kvm_para.h b/linux-headers/asm-x86/kvm_para.h
1110
index XXXXXXX..XXXXXXX 100644
1111
--- a/linux-headers/asm-x86/kvm_para.h
1112
+++ b/linux-headers/asm-x86/kvm_para.h
1113
@@ -XXX,XX +XXX,XX @@ struct kvm_steal_time {
1114
    __u64 steal;
1115
    __u32 version;
1116
    __u32 flags;
1117
-    __u32 pad[12];
1118
+    __u8 preempted;
1119
+    __u8 u8_pad[3];
1120
+    __u32 pad[11];
1121
+};
1122
+
1123
+#define KVM_CLOCK_PAIRING_WALLCLOCK 0
1124
+struct kvm_clock_pairing {
1125
+    __s64 sec;
1126
+    __s64 nsec;
1127
+    __u64 tsc;
1128
+    __u32 flags;
1129
+    __u32 pad[9];
1130
};
1131
1132
#define KVM_STEAL_ALIGNMENT_BITS 5
1133
diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
1134
index XXXXXXX..XXXXXXX 100644
1135
--- a/linux-headers/linux/kvm.h
1136
+++ b/linux-headers/linux/kvm.h
1137
@@ -XXX,XX +XXX,XX @@ struct kvm_hyperv_exit {
1138
struct kvm_run {
1139
    /* in */
1140
    __u8 request_interrupt_window;
1141
-    __u8 padding1[7];
1142
+    __u8 immediate_exit;
1143
+    __u8 padding1[6];
1144
1145
    /* out */
1146
    __u32 exit_reason;
1147
@@ -XXX,XX +XXX,XX @@ struct kvm_enable_cap {
1148
};
1149
1150
/* for KVM_PPC_GET_PVINFO */
1151
+
1152
+#define KVM_PPC_PVINFO_FLAGS_EV_IDLE (1<<0)
1153
+
1154
struct kvm_ppc_pvinfo {
1155
    /* out */
1156
    __u32 flags;
1157
@@ -XXX,XX +XXX,XX @@ struct kvm_ppc_smmu_info {
1158
    struct kvm_ppc_one_seg_page_size sps[KVM_PPC_PAGE_SIZES_MAX_SZ];
1159
};
1160
1161
-#define KVM_PPC_PVINFO_FLAGS_EV_IDLE (1<<0)
1162
+/* for KVM_PPC_RESIZE_HPT_{PREPARE,COMMIT} */
1163
+struct kvm_ppc_resize_hpt {
1164
+    __u64 flags;
1165
+    __u32 shift;
1166
+    __u32 pad;
1167
+};
1168
1169
#define KVMIO 0xAE
1170
1171
@@ -XXX,XX +XXX,XX @@ struct kvm_ppc_smmu_info {
1172
#define KVM_CAP_S390_USER_INSTR0 130
1173
#define KVM_CAP_MSI_DEVID 131
1174
#define KVM_CAP_PPC_HTM 132
1175
+#define KVM_CAP_SPAPR_RESIZE_HPT 133
1176
+#define KVM_CAP_PPC_MMU_RADIX 134
1177
+#define KVM_CAP_PPC_MMU_HASH_V3 135
1178
+#define KVM_CAP_IMMEDIATE_EXIT 136
1179
1180
#ifdef KVM_CAP_IRQ_ROUTING
1181
1182
@@ -XXX,XX +XXX,XX @@ struct kvm_s390_ucas_mapping {
1183
#define KVM_ARM_SET_DEVICE_ADDR     _IOW(KVMIO, 0xab, struct kvm_arm_device_addr)
1184
/* Available with KVM_CAP_PPC_RTAS */
1185
#define KVM_PPC_RTAS_DEFINE_TOKEN _IOW(KVMIO, 0xac, struct kvm_rtas_token_args)
1186
+/* Available with KVM_CAP_SPAPR_RESIZE_HPT */
1187
+#define KVM_PPC_RESIZE_HPT_PREPARE _IOR(KVMIO, 0xad, struct kvm_ppc_resize_hpt)
1188
+#define KVM_PPC_RESIZE_HPT_COMMIT _IOR(KVMIO, 0xae, struct kvm_ppc_resize_hpt)
1189
+/* Available with KVM_CAP_PPC_RADIX_MMU or KVM_CAP_PPC_HASH_MMU_V3 */
1190
+#define KVM_PPC_CONFIGURE_V3_MMU _IOW(KVMIO, 0xaf, struct kvm_ppc_mmuv3_cfg)
1191
+/* Available with KVM_CAP_PPC_RADIX_MMU */
1192
+#define KVM_PPC_GET_RMMU_INFO     _IOW(KVMIO, 0xb0, struct kvm_ppc_rmmu_info)
1193
1194
/* ioctl for vm fd */
1195
#define KVM_CREATE_DEVICE     _IOWR(KVMIO, 0xe0, struct kvm_create_device)
1196
diff --git a/linux-headers/linux/kvm_para.h b/linux-headers/linux/kvm_para.h
1197
index XXXXXXX..XXXXXXX 100644
1198
--- a/linux-headers/linux/kvm_para.h
1199
+++ b/linux-headers/linux/kvm_para.h
1200
@@ -XXX,XX +XXX,XX @@
1201
#define KVM_EFAULT        EFAULT
1202
#define KVM_E2BIG        E2BIG
1203
#define KVM_EPERM        EPERM
1204
+#define KVM_EOPNOTSUPP        95
1205
1206
#define KVM_HC_VAPIC_POLL_IRQ        1
1207
#define KVM_HC_MMU_OP            2
1208
@@ -XXX,XX +XXX,XX @@
1209
#define KVM_HC_MIPS_GET_CLOCK_FREQ    6
1210
#define KVM_HC_MIPS_EXIT_VM        7
1211
#define KVM_HC_MIPS_CONSOLE_OUTPUT    8
1212
+#define KVM_HC_CLOCK_PAIRING        9
1213
1214
/*
1215
* hypercalls use architecture specific
1216
diff --git a/linux-headers/linux/userfaultfd.h b/linux-headers/linux/userfaultfd.h
1217
index XXXXXXX..XXXXXXX 100644
1218
--- a/linux-headers/linux/userfaultfd.h
1219
+++ b/linux-headers/linux/userfaultfd.h
1220
@@ -XXX,XX +XXX,XX @@
1221
1222
#include <linux/types.h>
1223
1224
-#define UFFD_API ((__u64)0xAA)
1225
/*
1226
- * After implementing the respective features it will become:
1227
- * #define UFFD_API_FEATURES (UFFD_FEATURE_PAGEFAULT_FLAG_WP | \
1228
- *             UFFD_FEATURE_EVENT_FORK)
1229
+ * If the UFFDIO_API is upgraded someday, the UFFDIO_UNREGISTER and
1230
+ * UFFDIO_WAKE ioctls should be defined as _IOW and not as _IOR. In
1231
+ * userfaultfd.h we assumed the kernel was reading (instead _IOC_READ
1232
+ * means the userland is reading).
1233
*/
1234
-#define UFFD_API_FEATURES (0)
1235
+#define UFFD_API ((__u64)0xAA)
1236
+#define UFFD_API_FEATURES (UFFD_FEATURE_EVENT_FORK |        \
1237
+             UFFD_FEATURE_EVENT_REMAP |        \
1238
+             UFFD_FEATURE_EVENT_MADVDONTNEED |    \
1239
+             UFFD_FEATURE_MISSING_HUGETLBFS |    \
1240
+             UFFD_FEATURE_MISSING_SHMEM)
1241
#define UFFD_API_IOCTLS                \
1242
    ((__u64)1 << _UFFDIO_REGISTER |        \
1243
     (__u64)1 << _UFFDIO_UNREGISTER |    \
1244
@@ -XXX,XX +XXX,XX @@
1245
    ((__u64)1 << _UFFDIO_WAKE |        \
1246
     (__u64)1 << _UFFDIO_COPY |        \
1247
     (__u64)1 << _UFFDIO_ZEROPAGE)
1248
+#define UFFD_API_RANGE_IOCTLS_BASIC        \
1249
+    ((__u64)1 << _UFFDIO_WAKE |        \
1250
+     (__u64)1 << _UFFDIO_COPY)
1251
1252
/*
1253
* Valid ioctl command number range with this API is from 0x00 to
1254
@@ -XXX,XX +XXX,XX @@ struct uffd_msg {
1255
        } pagefault;
1256
1257
        struct {
1258
+            __u32    ufd;
1259
+        } fork;
1260
+
1261
+        struct {
1262
+            __u64    from;
1263
+            __u64    to;
1264
+            __u64    len;
1265
+        } remap;
1266
+
1267
+        struct {
1268
+            __u64    start;
1269
+            __u64    end;
1270
+        } madv_dn;
1271
+
1272
+        struct {
1273
            /* unused reserved fields */
1274
            __u64    reserved1;
1275
            __u64    reserved2;
1276
@@ -XXX,XX +XXX,XX @@ struct uffd_msg {
1277
* Start at 0x12 and not at 0 to be more strict against bugs.
1278
*/
1279
#define UFFD_EVENT_PAGEFAULT    0x12
1280
-#if 0 /* not available yet */
1281
#define UFFD_EVENT_FORK        0x13
1282
-#endif
1283
+#define UFFD_EVENT_REMAP    0x14
1284
+#define UFFD_EVENT_MADVDONTNEED    0x15
1285
1286
/* flags for UFFD_EVENT_PAGEFAULT */
1287
#define UFFD_PAGEFAULT_FLAG_WRITE    (1<<0)    /* If this was a write fault */
1288
@@ -XXX,XX +XXX,XX @@ struct uffdio_api {
1289
     * Note: UFFD_EVENT_PAGEFAULT and UFFD_PAGEFAULT_FLAG_WRITE
1290
     * are to be considered implicitly always enabled in all kernels as
1291
     * long as the uffdio_api.api requested matches UFFD_API.
1292
+     *
1293
+     * UFFD_FEATURE_MISSING_HUGETLBFS means an UFFDIO_REGISTER
1294
+     * with UFFDIO_REGISTER_MODE_MISSING mode will succeed on
1295
+     * hugetlbfs virtual memory ranges. Adding or not adding
1296
+     * UFFD_FEATURE_MISSING_HUGETLBFS to uffdio_api.features has
1297
+     * no real functional effect after UFFDIO_API returns, but
1298
+     * it's only useful for an initial feature set probe at
1299
+     * UFFDIO_API time. There are two ways to use it:
1300
+     *
1301
+     * 1) by adding UFFD_FEATURE_MISSING_HUGETLBFS to the
1302
+     * uffdio_api.features before calling UFFDIO_API, an error
1303
+     * will be returned by UFFDIO_API on a kernel without
1304
+     * hugetlbfs missing support
1305
+     *
1306
+     * 2) the UFFD_FEATURE_MISSING_HUGETLBFS can not be added in
1307
+     * uffdio_api.features and instead it will be set by the
1308
+     * kernel in the uffdio_api.features if the kernel supports
1309
+     * it, so userland can later check if the feature flag is
1310
+     * present in uffdio_api.features after UFFDIO_API
1311
+     * succeeded.
1312
+     *
1313
+     * UFFD_FEATURE_MISSING_SHMEM works the same as
1314
+     * UFFD_FEATURE_MISSING_HUGETLBFS, but it applies to shmem
1315
+     * (i.e. tmpfs and other shmem based APIs).
1316
     */
1317
-#if 0 /* not available yet */
1318
#define UFFD_FEATURE_PAGEFAULT_FLAG_WP        (1<<0)
1319
#define UFFD_FEATURE_EVENT_FORK            (1<<1)
1320
-#endif
1321
+#define UFFD_FEATURE_EVENT_REMAP        (1<<2)
1322
+#define UFFD_FEATURE_EVENT_MADVDONTNEED        (1<<3)
1323
+#define UFFD_FEATURE_MISSING_HUGETLBFS        (1<<4)
1324
+#define UFFD_FEATURE_MISSING_SHMEM        (1<<5)
1325
    __u64 features;
1326
1327
    __u64 ioctls;
1328
diff --git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h
1329
index XXXXXXX..XXXXXXX 100644
1330
--- a/linux-headers/linux/vfio.h
1331
+++ b/linux-headers/linux/vfio.h
1332
@@ -XXX,XX +XXX,XX @@ struct vfio_device_info {
1333
};
1334
#define VFIO_DEVICE_GET_INFO        _IO(VFIO_TYPE, VFIO_BASE + 7)
1335
1336
+/*
1337
+ * Vendor driver using Mediated device framework should provide device_api
1338
+ * attribute in supported type attribute groups. Device API string should be one
1339
+ * of the following corresponding to device flags in vfio_device_info structure.
1340
+ */
1341
+
1342
+#define VFIO_DEVICE_API_PCI_STRING        "vfio-pci"
1343
+#define VFIO_DEVICE_API_PLATFORM_STRING        "vfio-platform"
1344
+#define VFIO_DEVICE_API_AMBA_STRING        "vfio-amba"
1345
+
1346
/**
1347
* VFIO_DEVICE_GET_REGION_INFO - _IOWR(VFIO_TYPE, VFIO_BASE + 8,
1348
*                 struct vfio_region_info)
1349
--
305
--
1350
2.7.4
306
2.20.1
1351
307
1352
308
diff view generated by jsdifflib
New patch
1
From: Thomas Huth <thuth@redhat.com>
1
2
3
When compiling with -Werror=implicit-fallthrough, gcc complains about
4
missing fallthrough annotations in this file. Looking at the code,
5
the fallthrough is very likely intended here, so add some comments
6
to silence the compiler warnings.
7
8
Signed-off-by: Thomas Huth <thuth@redhat.com>
9
Message-id: 20201020105938.23209-1-thuth@redhat.com
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
hw/arm/highbank.c | 2 ++
14
1 file changed, 2 insertions(+)
15
16
diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/highbank.c
19
+++ b/hw/arm/highbank.c
20
@@ -XXX,XX +XXX,XX @@ static void hb_reset_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
21
address_space_stl_notdirty(&address_space_memory,
22
SMP_BOOT_REG + 0x30, 0,
23
MEMTXATTRS_UNSPECIFIED, NULL);
24
+ /* fallthrough */
25
case 3:
26
address_space_stl_notdirty(&address_space_memory,
27
SMP_BOOT_REG + 0x20, 0,
28
MEMTXATTRS_UNSPECIFIED, NULL);
29
+ /* fallthrough */
30
case 2:
31
address_space_stl_notdirty(&address_space_memory,
32
SMP_BOOT_REG + 0x10, 0,
33
--
34
2.20.1
35
36
diff view generated by jsdifflib
New patch
1
From: Pavel Dovgalyuk <pavel.dovgalyuk@ispras.ru>
1
2
3
This patch sets min_cpus field for xlnx-versal-virt platform,
4
because it always creates XLNX_VERSAL_NR_ACPUS cpus even with
5
-smp 1 command line option.
6
7
Signed-off-by: Pavel Dovgalyuk <pavel.dovgalyuk@ispras.ru>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
10
Message-id: 160343854912.8460.17915238517799132371.stgit@pasha-ThinkPad-X280
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
hw/arm/xlnx-versal-virt.c | 1 +
14
1 file changed, 1 insertion(+)
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 versal_virt_machine_class_init(ObjectClass *oc, void *data)
21
22
mc->desc = "Xilinx Versal Virtual development board";
23
mc->init = versal_virt_init;
24
+ mc->min_cpus = XLNX_VERSAL_NR_ACPUS;
25
mc->max_cpus = XLNX_VERSAL_NR_ACPUS;
26
mc->default_cpus = XLNX_VERSAL_NR_ACPUS;
27
mc->no_cdrom = true;
28
--
29
2.20.1
30
31
diff view generated by jsdifflib
1
Instead of qdev_set_parent_bus() silently doing the wrong
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
thing if it's handed a device that's already on a bus,
3
have it remove the device from the old bus and add it to
4
the new one. This is useful for the raspi2 sdcard.
5
2
3
This allows us to reuse npcm7xx_timer_pause for the watchdog timer.
4
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
8
Message-id: 1488293711-14195-2-git-send-email-peter.maydell@linaro.org
9
---
8
---
10
hw/core/qdev.c | 14 ++++++++++++++
9
hw/timer/npcm7xx_timer.c | 6 +++---
11
1 file changed, 14 insertions(+)
10
1 file changed, 3 insertions(+), 3 deletions(-)
12
11
13
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
12
diff --git a/hw/timer/npcm7xx_timer.c b/hw/timer/npcm7xx_timer.c
14
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/core/qdev.c
14
--- a/hw/timer/npcm7xx_timer.c
16
+++ b/hw/core/qdev.c
15
+++ b/hw/timer/npcm7xx_timer.c
17
@@ -XXX,XX +XXX,XX @@ static void bus_add_child(BusState *bus, DeviceState *child)
16
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_pause(NPCM7xxTimer *t)
18
17
timer_del(&t->qtimer);
19
void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
18
now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
20
{
19
t->remaining_ns = t->expires_ns - now;
21
+ bool replugging = dev->parent_bus != NULL;
20
- if (t->remaining_ns <= 0) {
22
+
21
- npcm7xx_timer_reached_zero(t);
23
+ if (replugging) {
22
- }
24
+ /* Keep a reference to the device while it's not plugged into
25
+ * any bus, to avoid it potentially evaporating when it is
26
+ * dereffed in bus_remove_child().
27
+ */
28
+ object_ref(OBJECT(dev));
29
+ bus_remove_child(dev->parent_bus, dev);
30
+ object_unref(OBJECT(dev->parent_bus));
31
+ }
32
dev->parent_bus = bus;
33
object_ref(OBJECT(bus));
34
bus_add_child(bus, dev);
35
+ if (replugging) {
36
+ object_unref(OBJECT(dev));
37
+ }
38
}
23
}
39
24
40
/* Create a new device. This only initializes the device state
25
/*
26
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_write_tcsr(NPCM7xxTimer *t, uint32_t new_tcsr)
27
} else {
28
t->tcsr &= ~NPCM7XX_TCSR_CACT;
29
npcm7xx_timer_pause(t);
30
+ if (t->remaining_ns <= 0) {
31
+ npcm7xx_timer_reached_zero(t);
32
+ }
33
}
34
}
35
}
41
--
36
--
42
2.7.4
37
2.20.1
43
38
44
39
diff view generated by jsdifflib
1
From: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
This actually implements pre_save and post_load methods for in-kernel
3
The watchdog is part of NPCM7XX's timer module. Its behavior is
4
vGICv3.
4
controlled by the WTCR register in the timer.
5
5
6
Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
6
When enabled, the watchdog issues an interrupt signal after a pre-set
7
amount of cycles, and issues a reset signal shortly after that.
8
9
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
10
Signed-off-by: Hao Wu <wuhaotsh@google.com>
11
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
[PMM: deleted blank line at end of npcm_watchdog_timer-test.c]
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
10
Message-id: 1487850673-26455-4-git-send-email-vijay.kilari@gmail.com
11
[PMM:
12
* use decimal, not 0bnnn
13
* fixed typo in names of ICC_APR0R_EL1 and ICC_AP1R_EL1
14
* completely rearranged the get and put functions to read and write
15
the state in a natural order, rather than mixing distributor and
16
redistributor state together]
17
Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
18
[Vijay:
19
* Update macro KVM_VGIC_ATTR
20
* Use 32 bit access for gicd and gicr
21
* GICD_IROUTER, GICD_TYPER, GICR_PROPBASER and GICR_PENDBASER reg
22
access are changed from 64-bit to 32-bit access
23
* Add ICC_SRE_EL1 save and restore
24
* Dropped translate_fn mechanism and coded functions to handle
25
save and restore of edge_trigger and priority
26
* Number of APnR register saved/restored based on number of
27
priority bits supported]
28
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
29
---
15
---
30
hw/intc/gicv3_internal.h | 1 +
16
include/hw/misc/npcm7xx_clk.h | 2 +
31
hw/intc/arm_gicv3_kvm.c | 573 +++++++++++++++++++++++++++++++++++++++++++++--
17
include/hw/timer/npcm7xx_timer.h | 48 +++-
32
2 files changed, 558 insertions(+), 16 deletions(-)
18
hw/arm/npcm7xx.c | 12 +
19
hw/misc/npcm7xx_clk.c | 28 ++
20
hw/timer/npcm7xx_timer.c | 266 ++++++++++++++----
21
tests/qtest/npcm7xx_watchdog_timer-test.c | 319 ++++++++++++++++++++++
22
MAINTAINERS | 1 +
23
tests/qtest/meson.build | 2 +-
24
8 files changed, 624 insertions(+), 54 deletions(-)
25
create mode 100644 tests/qtest/npcm7xx_watchdog_timer-test.c
33
26
34
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
27
diff --git a/include/hw/misc/npcm7xx_clk.h b/include/hw/misc/npcm7xx_clk.h
35
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
36
--- a/hw/intc/gicv3_internal.h
29
--- a/include/hw/misc/npcm7xx_clk.h
37
+++ b/hw/intc/gicv3_internal.h
30
+++ b/include/hw/misc/npcm7xx_clk.h
38
@@ -XXX,XX +XXX,XX @@
31
@@ -XXX,XX +XXX,XX @@
39
#define ICC_CTLR_EL1_EOIMODE (1U << 1)
32
*/
40
#define ICC_CTLR_EL1_PMHE (1U << 6)
33
#define NPCM7XX_CLK_NR_REGS (0x70 / sizeof(uint32_t))
41
#define ICC_CTLR_EL1_PRIBITS_SHIFT 8
34
42
+#define ICC_CTLR_EL1_PRIBITS_MASK (7U << ICC_CTLR_EL1_PRIBITS_SHIFT)
35
+#define NPCM7XX_WATCHDOG_RESET_GPIO_IN "npcm7xx-clk-watchdog-reset-gpio-in"
43
#define ICC_CTLR_EL1_IDBITS_SHIFT 11
36
+
44
#define ICC_CTLR_EL1_SEIS (1U << 14)
37
typedef struct NPCM7xxCLKState {
45
#define ICC_CTLR_EL1_A3V (1U << 15)
38
SysBusDevice parent;
46
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
39
40
diff --git a/include/hw/timer/npcm7xx_timer.h b/include/hw/timer/npcm7xx_timer.h
47
index XXXXXXX..XXXXXXX 100644
41
index XXXXXXX..XXXXXXX 100644
48
--- a/hw/intc/arm_gicv3_kvm.c
42
--- a/include/hw/timer/npcm7xx_timer.h
49
+++ b/hw/intc/arm_gicv3_kvm.c
43
+++ b/include/hw/timer/npcm7xx_timer.h
50
@@ -XXX,XX +XXX,XX @@
44
@@ -XXX,XX +XXX,XX @@
51
#include "qapi/error.h"
45
*/
52
#include "hw/intc/arm_gicv3_common.h"
46
#define NPCM7XX_TIMER_NR_REGS (0x54 / sizeof(uint32_t))
53
#include "hw/sysbus.h"
47
54
+#include "qemu/error-report.h"
48
+/* The basic watchdog timer period is 2^14 clock cycles. */
55
#include "sysemu/kvm.h"
49
+#define NPCM7XX_WATCHDOG_BASETIME_SHIFT 14
56
#include "kvm_arm.h"
50
+
57
+#include "gicv3_internal.h"
51
+#define NPCM7XX_WATCHDOG_RESET_GPIO_OUT "npcm7xx-clk-watchdog-reset-gpio-out"
58
#include "vgic_common.h"
52
+
59
#include "migration/migration.h"
53
typedef struct NPCM7xxTimerCtrlState NPCM7xxTimerCtrlState;
60
54
55
/**
56
- * struct NPCM7xxTimer - Individual timer state.
57
- * @irq: GIC interrupt line to fire on expiration (if enabled).
58
+ * struct NPCM7xxBaseTimer - Basic functionality that both regular timer and
59
+ * watchdog timer use.
60
* @qtimer: QEMU timer that notifies us on expiration.
61
* @expires_ns: Absolute virtual expiration time.
62
* @remaining_ns: Remaining time until expiration if timer is paused.
63
+ */
64
+typedef struct NPCM7xxBaseTimer {
65
+ QEMUTimer qtimer;
66
+ int64_t expires_ns;
67
+ int64_t remaining_ns;
68
+} NPCM7xxBaseTimer;
69
+
70
+/**
71
+ * struct NPCM7xxTimer - Individual timer state.
72
+ * @ctrl: The timer module that owns this timer.
73
+ * @irq: GIC interrupt line to fire on expiration (if enabled).
74
+ * @base_timer: The basic timer functionality for this timer.
75
* @tcsr: The Timer Control and Status Register.
76
* @ticr: The Timer Initial Count Register.
77
*/
78
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxTimer {
79
NPCM7xxTimerCtrlState *ctrl;
80
81
qemu_irq irq;
82
- QEMUTimer qtimer;
83
- int64_t expires_ns;
84
- int64_t remaining_ns;
85
+ NPCM7xxBaseTimer base_timer;
86
87
uint32_t tcsr;
88
uint32_t ticr;
89
} NPCM7xxTimer;
90
91
+/**
92
+ * struct NPCM7xxWatchdogTimer - The watchdog timer state.
93
+ * @ctrl: The timer module that owns this timer.
94
+ * @irq: GIC interrupt line to fire on expiration (if enabled).
95
+ * @reset_signal: The GPIO used to send a reset signal.
96
+ * @base_timer: The basic timer functionality for this timer.
97
+ * @wtcr: The Watchdog Timer Control Register.
98
+ */
99
+typedef struct NPCM7xxWatchdogTimer {
100
+ NPCM7xxTimerCtrlState *ctrl;
101
+
102
+ qemu_irq irq;
103
+ qemu_irq reset_signal;
104
+ NPCM7xxBaseTimer base_timer;
105
+
106
+ uint32_t wtcr;
107
+} NPCM7xxWatchdogTimer;
108
+
109
/**
110
* struct NPCM7xxTimerCtrlState - Timer Module device state.
111
* @parent: System bus device.
112
* @iomem: Memory region through which registers are accessed.
113
+ * @index: The index of this timer module.
114
* @tisr: The Timer Interrupt Status Register.
115
- * @wtcr: The Watchdog Timer Control Register.
116
* @timer: The five individual timers managed by this module.
117
+ * @watchdog_timer: The watchdog timer managed by this module.
118
*/
119
struct NPCM7xxTimerCtrlState {
120
SysBusDevice parent;
121
@@ -XXX,XX +XXX,XX @@ struct NPCM7xxTimerCtrlState {
122
MemoryRegion iomem;
123
124
uint32_t tisr;
125
- uint32_t wtcr;
126
127
NPCM7xxTimer timer[NPCM7XX_TIMERS_PER_CTRL];
128
+ NPCM7xxWatchdogTimer watchdog_timer;
129
};
130
131
#define TYPE_NPCM7XX_TIMER "npcm7xx-timer"
132
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
133
index XXXXXXX..XXXXXXX 100644
134
--- a/hw/arm/npcm7xx.c
135
+++ b/hw/arm/npcm7xx.c
136
@@ -XXX,XX +XXX,XX @@ enum NPCM7xxInterrupt {
137
NPCM7XX_TIMER12_IRQ,
138
NPCM7XX_TIMER13_IRQ,
139
NPCM7XX_TIMER14_IRQ,
140
+ NPCM7XX_WDG0_IRQ = 47, /* Timer Module 0 Watchdog */
141
+ NPCM7XX_WDG1_IRQ, /* Timer Module 1 Watchdog */
142
+ NPCM7XX_WDG2_IRQ, /* Timer Module 2 Watchdog */
143
};
144
145
/* Total number of GIC interrupts, including internal Cortex-A9 interrupts. */
146
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
147
qemu_irq irq = npcm7xx_irq(s, first_irq + j);
148
sysbus_connect_irq(sbd, j, irq);
149
}
150
+
151
+ /* IRQ for watchdogs */
152
+ sysbus_connect_irq(sbd, NPCM7XX_TIMERS_PER_CTRL,
153
+ npcm7xx_irq(s, NPCM7XX_WDG0_IRQ + i));
154
+ /* GPIO that connects clk module with watchdog */
155
+ qdev_connect_gpio_out_named(DEVICE(&s->tim[i]),
156
+ NPCM7XX_WATCHDOG_RESET_GPIO_OUT, 0,
157
+ qdev_get_gpio_in_named(DEVICE(&s->clk),
158
+ NPCM7XX_WATCHDOG_RESET_GPIO_IN, i));
159
}
160
161
/* UART0..3 (16550 compatible) */
162
diff --git a/hw/misc/npcm7xx_clk.c b/hw/misc/npcm7xx_clk.c
163
index XXXXXXX..XXXXXXX 100644
164
--- a/hw/misc/npcm7xx_clk.c
165
+++ b/hw/misc/npcm7xx_clk.c
61
@@ -XXX,XX +XXX,XX @@
166
@@ -XXX,XX +XXX,XX @@
62
#define KVM_ARM_GICV3_GET_CLASS(obj) \
167
#include "qemu/osdep.h"
63
OBJECT_GET_CLASS(KVMARMGICv3Class, (obj), TYPE_KVM_ARM_GICV3)
168
64
169
#include "hw/misc/npcm7xx_clk.h"
65
+#define KVM_DEV_ARM_VGIC_SYSREG(op0, op1, crn, crm, op2) \
170
+#include "hw/timer/npcm7xx_timer.h"
66
+ (ARM64_SYS_REG_SHIFT_MASK(op0, OP0) | \
171
#include "migration/vmstate.h"
67
+ ARM64_SYS_REG_SHIFT_MASK(op1, OP1) | \
172
#include "qemu/error-report.h"
68
+ ARM64_SYS_REG_SHIFT_MASK(crn, CRN) | \
173
#include "qemu/log.h"
69
+ ARM64_SYS_REG_SHIFT_MASK(crm, CRM) | \
174
@@ -XXX,XX +XXX,XX @@
70
+ ARM64_SYS_REG_SHIFT_MASK(op2, OP2))
175
#include "qemu/timer.h"
71
+
176
#include "qemu/units.h"
72
+#define ICC_PMR_EL1 \
177
#include "trace.h"
73
+ KVM_DEV_ARM_VGIC_SYSREG(3, 0, 4, 6, 0)
178
+#include "sysemu/watchdog.h"
74
+#define ICC_BPR0_EL1 \
179
75
+ KVM_DEV_ARM_VGIC_SYSREG(3, 0, 12, 8, 3)
180
#define PLLCON_LOKI BIT(31)
76
+#define ICC_AP0R_EL1(n) \
181
#define PLLCON_LOKS BIT(30)
77
+ KVM_DEV_ARM_VGIC_SYSREG(3, 0, 12, 8, 4 | n)
182
@@ -XXX,XX +XXX,XX @@ static const uint32_t cold_reset_values[NPCM7XX_CLK_NR_REGS] = {
78
+#define ICC_AP1R_EL1(n) \
183
[NPCM7XX_CLK_AHBCKFI] = 0x000000c8,
79
+ KVM_DEV_ARM_VGIC_SYSREG(3, 0, 12, 9, n)
184
};
80
+#define ICC_BPR1_EL1 \
185
81
+ KVM_DEV_ARM_VGIC_SYSREG(3, 0, 12, 12, 3)
186
+/* Register Field Definitions */
82
+#define ICC_CTLR_EL1 \
187
+#define NPCM7XX_CLK_WDRCR_CA9C BIT(0) /* Cortex A9 Cores */
83
+ KVM_DEV_ARM_VGIC_SYSREG(3, 0, 12, 12, 4)
188
+
84
+#define ICC_SRE_EL1 \
189
+/* The number of watchdogs that can trigger a reset. */
85
+ KVM_DEV_ARM_VGIC_SYSREG(3, 0, 12, 12, 5)
190
+#define NPCM7XX_NR_WATCHDOGS (3)
86
+#define ICC_IGRPEN0_EL1 \
191
+
87
+ KVM_DEV_ARM_VGIC_SYSREG(3, 0, 12, 12, 6)
192
static uint64_t npcm7xx_clk_read(void *opaque, hwaddr offset, unsigned size)
88
+#define ICC_IGRPEN1_EL1 \
193
{
89
+ KVM_DEV_ARM_VGIC_SYSREG(3, 0, 12, 12, 7)
194
uint32_t reg = offset / sizeof(uint32_t);
90
+
195
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_write(void *opaque, hwaddr offset,
91
typedef struct KVMARMGICv3Class {
196
s->regs[reg] = value;
92
ARMGICv3CommonClass parent_class;
93
DeviceRealize parent_realize;
94
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gicv3_set_irq(void *opaque, int irq, int level)
95
kvm_arm_gic_set_irq(s->num_irq, irq, level);
96
}
197
}
97
198
98
+#define KVM_VGIC_ATTR(reg, typer) \
199
+/* Perform reset action triggered by a watchdog */
99
+ ((typer & KVM_DEV_ARM_VGIC_V3_MPIDR_MASK) | (reg))
200
+static void npcm7xx_clk_perform_watchdog_reset(void *opaque, int n,
100
+
201
+ int level)
101
+static inline void kvm_gicd_access(GICv3State *s, int offset,
202
+{
102
+ uint32_t *val, bool write)
203
+ NPCM7xxCLKState *clk = NPCM7XX_CLK(opaque);
103
+{
204
+ uint32_t rcr;
104
+ kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_DIST_REGS,
205
+
105
+ KVM_VGIC_ATTR(offset, 0),
206
+ g_assert(n >= 0 && n <= NPCM7XX_NR_WATCHDOGS);
106
+ val, write);
207
+ rcr = clk->regs[NPCM7XX_CLK_WD0RCR + n];
107
+}
208
+ if (rcr & NPCM7XX_CLK_WDRCR_CA9C) {
108
+
209
+ watchdog_perform_action();
109
+static inline void kvm_gicr_access(GICv3State *s, int offset, int cpu,
210
+ } else {
110
+ uint32_t *val, bool write)
211
+ qemu_log_mask(LOG_UNIMP,
111
+{
212
+ "%s: only CPU reset is implemented. (requested 0x%" PRIx32")\n",
112
+ kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_REDIST_REGS,
213
+ __func__, rcr);
113
+ KVM_VGIC_ATTR(offset, s->cpu[cpu].gicr_typer),
214
+ }
114
+ val, write);
215
+}
115
+}
216
+
116
+
217
static const struct MemoryRegionOps npcm7xx_clk_ops = {
117
+static inline void kvm_gicc_access(GICv3State *s, uint64_t reg, int cpu,
218
.read = npcm7xx_clk_read,
118
+ uint64_t *val, bool write)
219
.write = npcm7xx_clk_write,
119
+{
220
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_init(Object *obj)
120
+ kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS,
221
memory_region_init_io(&s->iomem, obj, &npcm7xx_clk_ops, s,
121
+ KVM_VGIC_ATTR(reg, s->cpu[cpu].gicr_typer),
222
TYPE_NPCM7XX_CLK, 4 * KiB);
122
+ val, write);
223
sysbus_init_mmio(&s->parent, &s->iomem);
123
+}
224
+ qdev_init_gpio_in_named(DEVICE(s), npcm7xx_clk_perform_watchdog_reset,
124
+
225
+ NPCM7XX_WATCHDOG_RESET_GPIO_IN, NPCM7XX_NR_WATCHDOGS);
125
+static inline void kvm_gic_line_level_access(GICv3State *s, int irq, int cpu,
226
}
126
+ uint32_t *val, bool write)
227
127
+{
228
static const VMStateDescription vmstate_npcm7xx_clk = {
128
+ kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO,
229
diff --git a/hw/timer/npcm7xx_timer.c b/hw/timer/npcm7xx_timer.c
129
+ KVM_VGIC_ATTR(irq, s->cpu[cpu].gicr_typer) |
230
index XXXXXXX..XXXXXXX 100644
130
+ (VGIC_LEVEL_INFO_LINE_LEVEL <<
231
--- a/hw/timer/npcm7xx_timer.c
131
+ KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT),
232
+++ b/hw/timer/npcm7xx_timer.c
132
+ val, write);
233
@@ -XXX,XX +XXX,XX @@
133
+}
234
#include "qemu/osdep.h"
134
+
235
135
+/* Loop through each distributor IRQ related register; since bits
236
#include "hw/irq.h"
136
+ * corresponding to SPIs and PPIs are RAZ/WI when affinity routing
237
+#include "hw/qdev-properties.h"
137
+ * is enabled, we skip those.
238
#include "hw/misc/npcm7xx_clk.h"
239
#include "hw/timer/npcm7xx_timer.h"
240
#include "migration/vmstate.h"
241
@@ -XXX,XX +XXX,XX @@ enum NPCM7xxTimerRegisters {
242
#define NPCM7XX_TCSR_PRESCALE_START 0
243
#define NPCM7XX_TCSR_PRESCALE_LEN 8
244
245
+#define NPCM7XX_WTCR_WTCLK(rv) extract32(rv, 10, 2)
246
+#define NPCM7XX_WTCR_FREEZE_EN BIT(9)
247
+#define NPCM7XX_WTCR_WTE BIT(7)
248
+#define NPCM7XX_WTCR_WTIE BIT(6)
249
+#define NPCM7XX_WTCR_WTIS(rv) extract32(rv, 4, 2)
250
+#define NPCM7XX_WTCR_WTIF BIT(3)
251
+#define NPCM7XX_WTCR_WTRF BIT(2)
252
+#define NPCM7XX_WTCR_WTRE BIT(1)
253
+#define NPCM7XX_WTCR_WTR BIT(0)
254
+
255
+/*
256
+ * The number of clock cycles between interrupt and reset in watchdog, used
257
+ * by the software to handle the interrupt before system is reset.
138
+ */
258
+ */
139
+#define for_each_dist_irq_reg(_irq, _max, _field_width) \
259
+#define NPCM7XX_WATCHDOG_INTERRUPT_TO_RESET_CYCLES 1024
140
+ for (_irq = GIC_INTERNAL; _irq < _max; _irq += (32 / _field_width))
260
+
141
+
261
+/* Start or resume the timer. */
142
+static void kvm_dist_get_priority(GICv3State *s, uint32_t offset, uint8_t *bmp)
262
+static void npcm7xx_timer_start(NPCM7xxBaseTimer *t)
143
+{
263
+{
144
+ uint32_t reg, *field;
264
+ int64_t now;
145
+ int irq;
265
+
146
+
266
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
147
+ field = (uint32_t *)bmp;
267
+ t->expires_ns = now + t->remaining_ns;
148
+ for_each_dist_irq_reg(irq, s->num_irq, 8) {
268
+ timer_mod(&t->qtimer, t->expires_ns);
149
+ kvm_gicd_access(s, offset, &reg, false);
269
+}
150
+ *field = reg;
270
+
151
+ offset += 4;
271
+/* Stop counting. Record the time remaining so we can continue later. */
152
+ field++;
272
+static void npcm7xx_timer_pause(NPCM7xxBaseTimer *t)
273
+{
274
+ int64_t now;
275
+
276
+ timer_del(&t->qtimer);
277
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
278
+ t->remaining_ns = t->expires_ns - now;
279
+}
280
+
281
+/* Delete the timer and reset it to default state. */
282
+static void npcm7xx_timer_clear(NPCM7xxBaseTimer *t)
283
+{
284
+ timer_del(&t->qtimer);
285
+ t->expires_ns = 0;
286
+ t->remaining_ns = 0;
287
+}
288
+
289
/*
290
* Returns the index of timer in the tc->timer array. This can be used to
291
* locate the registers that belong to this timer.
292
@@ -XXX,XX +XXX,XX @@ static uint32_t npcm7xx_timer_ns_to_count(NPCM7xxTimer *t, int64_t ns)
293
return count;
294
}
295
296
+static uint32_t npcm7xx_watchdog_timer_prescaler(const NPCM7xxWatchdogTimer *t)
297
+{
298
+ switch (NPCM7XX_WTCR_WTCLK(t->wtcr)) {
299
+ case 0:
300
+ return 1;
301
+ case 1:
302
+ return 256;
303
+ case 2:
304
+ return 2048;
305
+ case 3:
306
+ return 65536;
307
+ default:
308
+ g_assert_not_reached();
153
+ }
309
+ }
154
+}
310
+}
155
+
311
+
156
+static void kvm_dist_put_priority(GICv3State *s, uint32_t offset, uint8_t *bmp)
312
+static void npcm7xx_watchdog_timer_reset_cycles(NPCM7xxWatchdogTimer *t,
157
+{
313
+ int64_t cycles)
158
+ uint32_t reg, *field;
314
+{
159
+ int irq;
315
+ uint32_t prescaler = npcm7xx_watchdog_timer_prescaler(t);
160
+
316
+ int64_t ns = (NANOSECONDS_PER_SECOND / NPCM7XX_TIMER_REF_HZ) * cycles;
161
+ field = (uint32_t *)bmp;
317
+
162
+ for_each_dist_irq_reg(irq, s->num_irq, 8) {
318
+ /*
163
+ reg = *field;
319
+ * The reset function always clears the current timer. The caller of the
164
+ kvm_gicd_access(s, offset, &reg, true);
320
+ * this needs to decide whether to start the watchdog timer based on
165
+ offset += 4;
321
+ * specific flag in WTCR.
166
+ field++;
322
+ */
323
+ npcm7xx_timer_clear(&t->base_timer);
324
+
325
+ ns *= prescaler;
326
+ t->base_timer.remaining_ns = ns;
327
+}
328
+
329
+static void npcm7xx_watchdog_timer_reset(NPCM7xxWatchdogTimer *t)
330
+{
331
+ int64_t cycles = 1;
332
+ uint32_t s = NPCM7XX_WTCR_WTIS(t->wtcr);
333
+
334
+ g_assert(s <= 3);
335
+
336
+ cycles <<= NPCM7XX_WATCHDOG_BASETIME_SHIFT;
337
+ cycles <<= 2 * s;
338
+
339
+ npcm7xx_watchdog_timer_reset_cycles(t, cycles);
340
+}
341
+
342
/*
343
* Raise the interrupt line if there's a pending interrupt and interrupts are
344
* enabled for this timer. If not, lower it.
345
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_check_interrupt(NPCM7xxTimer *t)
346
trace_npcm7xx_timer_irq(DEVICE(tc)->canonical_path, index, pending);
347
}
348
349
-/* Start or resume the timer. */
350
-static void npcm7xx_timer_start(NPCM7xxTimer *t)
351
-{
352
- int64_t now;
353
-
354
- now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
355
- t->expires_ns = now + t->remaining_ns;
356
- timer_mod(&t->qtimer, t->expires_ns);
357
-}
358
-
359
/*
360
* Called when the counter reaches zero. Sets the interrupt flag, and either
361
* restarts or disables the timer.
362
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_reached_zero(NPCM7xxTimer *t)
363
tc->tisr |= BIT(index);
364
365
if (t->tcsr & NPCM7XX_TCSR_PERIODIC) {
366
- t->remaining_ns = npcm7xx_timer_count_to_ns(t, t->ticr);
367
+ t->base_timer.remaining_ns = npcm7xx_timer_count_to_ns(t, t->ticr);
368
if (t->tcsr & NPCM7XX_TCSR_CEN) {
369
- npcm7xx_timer_start(t);
370
+ npcm7xx_timer_start(&t->base_timer);
371
}
372
} else {
373
t->tcsr &= ~(NPCM7XX_TCSR_CEN | NPCM7XX_TCSR_CACT);
374
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_reached_zero(NPCM7xxTimer *t)
375
npcm7xx_timer_check_interrupt(t);
376
}
377
378
-/* Stop counting. Record the time remaining so we can continue later. */
379
-static void npcm7xx_timer_pause(NPCM7xxTimer *t)
380
-{
381
- int64_t now;
382
-
383
- timer_del(&t->qtimer);
384
- now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
385
- t->remaining_ns = t->expires_ns - now;
386
-}
387
388
/*
389
* Restart the timer from its initial value. If the timer was enabled and stays
390
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_pause(NPCM7xxTimer *t)
391
*/
392
static void npcm7xx_timer_restart(NPCM7xxTimer *t, uint32_t old_tcsr)
393
{
394
- t->remaining_ns = npcm7xx_timer_count_to_ns(t, t->ticr);
395
+ t->base_timer.remaining_ns = npcm7xx_timer_count_to_ns(t, t->ticr);
396
397
if (old_tcsr & t->tcsr & NPCM7XX_TCSR_CEN) {
398
- npcm7xx_timer_start(t);
399
+ npcm7xx_timer_start(&t->base_timer);
400
}
401
}
402
403
@@ -XXX,XX +XXX,XX @@ static uint32_t npcm7xx_timer_read_tdr(NPCM7xxTimer *t)
404
if (t->tcsr & NPCM7XX_TCSR_CEN) {
405
int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
406
407
- return npcm7xx_timer_ns_to_count(t, t->expires_ns - now);
408
+ return npcm7xx_timer_ns_to_count(t, t->base_timer.expires_ns - now);
409
}
410
411
- return npcm7xx_timer_ns_to_count(t, t->remaining_ns);
412
+ return npcm7xx_timer_ns_to_count(t, t->base_timer.remaining_ns);
413
}
414
415
static void npcm7xx_timer_write_tcsr(NPCM7xxTimer *t, uint32_t new_tcsr)
416
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_write_tcsr(NPCM7xxTimer *t, uint32_t new_tcsr)
417
418
if (npcm7xx_tcsr_prescaler(old_tcsr) != npcm7xx_tcsr_prescaler(new_tcsr)) {
419
/* Recalculate time remaining based on the current TDR value. */
420
- t->remaining_ns = npcm7xx_timer_count_to_ns(t, tdr);
421
+ t->base_timer.remaining_ns = npcm7xx_timer_count_to_ns(t, tdr);
422
if (old_tcsr & t->tcsr & NPCM7XX_TCSR_CEN) {
423
- npcm7xx_timer_start(t);
424
+ npcm7xx_timer_start(&t->base_timer);
425
}
426
}
427
428
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_write_tcsr(NPCM7xxTimer *t, uint32_t new_tcsr)
429
if ((old_tcsr ^ new_tcsr) & NPCM7XX_TCSR_CEN) {
430
if (new_tcsr & NPCM7XX_TCSR_CEN) {
431
t->tcsr |= NPCM7XX_TCSR_CACT;
432
- npcm7xx_timer_start(t);
433
+ npcm7xx_timer_start(&t->base_timer);
434
} else {
435
t->tcsr &= ~NPCM7XX_TCSR_CACT;
436
- npcm7xx_timer_pause(t);
437
- if (t->remaining_ns <= 0) {
438
+ npcm7xx_timer_pause(&t->base_timer);
439
+ if (t->base_timer.remaining_ns <= 0) {
440
npcm7xx_timer_reached_zero(t);
441
}
442
}
443
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_write_tisr(NPCM7xxTimerCtrlState *s, uint32_t value)
444
if (value & (1U << i)) {
445
npcm7xx_timer_check_interrupt(&s->timer[i]);
446
}
447
+
448
}
449
}
450
451
+static void npcm7xx_timer_write_wtcr(NPCM7xxWatchdogTimer *t, uint32_t new_wtcr)
452
+{
453
+ uint32_t old_wtcr = t->wtcr;
454
+
455
+ /*
456
+ * WTIF and WTRF are cleared by writing 1. Writing 0 makes these bits
457
+ * unchanged.
458
+ */
459
+ if (new_wtcr & NPCM7XX_WTCR_WTIF) {
460
+ new_wtcr &= ~NPCM7XX_WTCR_WTIF;
461
+ } else if (old_wtcr & NPCM7XX_WTCR_WTIF) {
462
+ new_wtcr |= NPCM7XX_WTCR_WTIF;
167
+ }
463
+ }
168
+}
464
+ if (new_wtcr & NPCM7XX_WTCR_WTRF) {
169
+
465
+ new_wtcr &= ~NPCM7XX_WTCR_WTRF;
170
+static void kvm_dist_get_edge_trigger(GICv3State *s, uint32_t offset,
466
+ } else if (old_wtcr & NPCM7XX_WTCR_WTRF) {
171
+ uint32_t *bmp)
467
+ new_wtcr |= NPCM7XX_WTCR_WTRF;
172
+{
468
+ }
173
+ uint32_t reg;
469
+
174
+ int irq;
470
+ t->wtcr = new_wtcr;
175
+
471
+
176
+ for_each_dist_irq_reg(irq, s->num_irq, 2) {
472
+ if (new_wtcr & NPCM7XX_WTCR_WTR) {
177
+ kvm_gicd_access(s, offset, &reg, false);
473
+ t->wtcr &= ~NPCM7XX_WTCR_WTR;
178
+ reg = half_unshuffle32(reg >> 1);
474
+ npcm7xx_watchdog_timer_reset(t);
179
+ if (irq % 32 != 0) {
475
+ if (new_wtcr & NPCM7XX_WTCR_WTE) {
180
+ reg = (reg << 16);
476
+ npcm7xx_timer_start(&t->base_timer);
181
+ }
477
+ }
182
+ *gic_bmp_ptr32(bmp, irq) |= reg;
478
+ } else if ((old_wtcr ^ new_wtcr) & NPCM7XX_WTCR_WTE) {
183
+ offset += 4;
479
+ if (new_wtcr & NPCM7XX_WTCR_WTE) {
184
+ }
480
+ npcm7xx_timer_start(&t->base_timer);
185
+}
186
+
187
+static void kvm_dist_put_edge_trigger(GICv3State *s, uint32_t offset,
188
+ uint32_t *bmp)
189
+{
190
+ uint32_t reg;
191
+ int irq;
192
+
193
+ for_each_dist_irq_reg(irq, s->num_irq, 2) {
194
+ reg = *gic_bmp_ptr32(bmp, irq);
195
+ if (irq % 32 != 0) {
196
+ reg = (reg & 0xffff0000) >> 16;
197
+ } else {
481
+ } else {
198
+ reg = reg & 0xffff;
482
+ npcm7xx_timer_pause(&t->base_timer);
199
+ }
200
+ reg = half_shuffle32(reg) << 1;
201
+ kvm_gicd_access(s, offset, &reg, true);
202
+ offset += 4;
203
+ }
204
+}
205
+
206
+static void kvm_gic_get_line_level_bmp(GICv3State *s, uint32_t *bmp)
207
+{
208
+ uint32_t reg;
209
+ int irq;
210
+
211
+ for_each_dist_irq_reg(irq, s->num_irq, 1) {
212
+ kvm_gic_line_level_access(s, irq, 0, &reg, false);
213
+ *gic_bmp_ptr32(bmp, irq) = reg;
214
+ }
215
+}
216
+
217
+static void kvm_gic_put_line_level_bmp(GICv3State *s, uint32_t *bmp)
218
+{
219
+ uint32_t reg;
220
+ int irq;
221
+
222
+ for_each_dist_irq_reg(irq, s->num_irq, 1) {
223
+ reg = *gic_bmp_ptr32(bmp, irq);
224
+ kvm_gic_line_level_access(s, irq, 0, &reg, true);
225
+ }
226
+}
227
+
228
+/* Read a bitmap register group from the kernel VGIC. */
229
+static void kvm_dist_getbmp(GICv3State *s, uint32_t offset, uint32_t *bmp)
230
+{
231
+ uint32_t reg;
232
+ int irq;
233
+
234
+ for_each_dist_irq_reg(irq, s->num_irq, 1) {
235
+ kvm_gicd_access(s, offset, &reg, false);
236
+ *gic_bmp_ptr32(bmp, irq) = reg;
237
+ offset += 4;
238
+ }
239
+}
240
+
241
+static void kvm_dist_putbmp(GICv3State *s, uint32_t offset,
242
+ uint32_t clroffset, uint32_t *bmp)
243
+{
244
+ uint32_t reg;
245
+ int irq;
246
+
247
+ for_each_dist_irq_reg(irq, s->num_irq, 1) {
248
+ /* If this bitmap is a set/clear register pair, first write to the
249
+ * clear-reg to clear all bits before using the set-reg to write
250
+ * the 1 bits.
251
+ */
252
+ if (clroffset != 0) {
253
+ reg = 0;
254
+ kvm_gicd_access(s, clroffset, &reg, true);
255
+ }
256
+ reg = *gic_bmp_ptr32(bmp, irq);
257
+ kvm_gicd_access(s, offset, &reg, true);
258
+ offset += 4;
259
+ }
260
+}
261
+
262
+static void kvm_arm_gicv3_check(GICv3State *s)
263
+{
264
+ uint32_t reg;
265
+ uint32_t num_irq;
266
+
267
+ /* Sanity checking s->num_irq */
268
+ kvm_gicd_access(s, GICD_TYPER, &reg, false);
269
+ num_irq = ((reg & 0x1f) + 1) * 32;
270
+
271
+ if (num_irq < s->num_irq) {
272
+ error_report("Model requests %u IRQs, but kernel supports max %u",
273
+ s->num_irq, num_irq);
274
+ abort();
275
+ }
276
+}
277
+
278
static void kvm_arm_gicv3_put(GICv3State *s)
279
{
280
- /* TODO */
281
- DPRINTF("Cannot put kernel gic state, no kernel interface\n");
282
+ uint32_t regl, regh, reg;
283
+ uint64_t reg64, redist_typer;
284
+ int ncpu, i;
285
+
286
+ kvm_arm_gicv3_check(s);
287
+
288
+ kvm_gicr_access(s, GICR_TYPER, 0, &regl, false);
289
+ kvm_gicr_access(s, GICR_TYPER + 4, 0, &regh, false);
290
+ redist_typer = ((uint64_t)regh << 32) | regl;
291
+
292
+ reg = s->gicd_ctlr;
293
+ kvm_gicd_access(s, GICD_CTLR, &reg, true);
294
+
295
+ if (redist_typer & GICR_TYPER_PLPIS) {
296
+ /* Set base addresses before LPIs are enabled by GICR_CTLR write */
297
+ for (ncpu = 0; ncpu < s->num_cpu; ncpu++) {
298
+ GICv3CPUState *c = &s->cpu[ncpu];
299
+
300
+ reg64 = c->gicr_propbaser;
301
+ regl = (uint32_t)reg64;
302
+ kvm_gicr_access(s, GICR_PROPBASER, ncpu, &regl, true);
303
+ regh = (uint32_t)(reg64 >> 32);
304
+ kvm_gicr_access(s, GICR_PROPBASER + 4, ncpu, &regh, true);
305
+
306
+ reg64 = c->gicr_pendbaser;
307
+ if (!c->gicr_ctlr & GICR_CTLR_ENABLE_LPIS) {
308
+ /* Setting PTZ is advised if LPIs are disabled, to reduce
309
+ * GIC initialization time.
310
+ */
311
+ reg64 |= GICR_PENDBASER_PTZ;
312
+ }
313
+ regl = (uint32_t)reg64;
314
+ kvm_gicr_access(s, GICR_PENDBASER, ncpu, &regl, true);
315
+ regh = (uint32_t)(reg64 >> 32);
316
+ kvm_gicr_access(s, GICR_PENDBASER + 4, ncpu, &regh, true);
317
+ }
483
+ }
318
+ }
484
+ }
319
+
485
+
320
+ /* Redistributor state (one per CPU) */
486
+}
321
+
487
+
322
+ for (ncpu = 0; ncpu < s->num_cpu; ncpu++) {
488
static hwaddr npcm7xx_tcsr_index(hwaddr reg)
323
+ GICv3CPUState *c = &s->cpu[ncpu];
489
{
324
+
490
switch (reg) {
325
+ reg = c->gicr_ctlr;
491
@@ -XXX,XX +XXX,XX @@ static uint64_t npcm7xx_timer_read(void *opaque, hwaddr offset, unsigned size)
326
+ kvm_gicr_access(s, GICR_CTLR, ncpu, &reg, true);
492
break;
327
+
493
328
+ reg = c->gicr_statusr[GICV3_NS];
494
case NPCM7XX_TIMER_WTCR:
329
+ kvm_gicr_access(s, GICR_STATUSR, ncpu, &reg, true);
495
- value = s->wtcr;
330
+
496
+ value = s->watchdog_timer.wtcr;
331
+ reg = c->gicr_waker;
497
break;
332
+ kvm_gicr_access(s, GICR_WAKER, ncpu, &reg, true);
498
333
+
499
default:
334
+ reg = c->gicr_igroupr0;
500
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_write(void *opaque, hwaddr offset,
335
+ kvm_gicr_access(s, GICR_IGROUPR0, ncpu, &reg, true);
501
return;
336
+
502
337
+ reg = ~0;
503
case NPCM7XX_TIMER_WTCR:
338
+ kvm_gicr_access(s, GICR_ICENABLER0, ncpu, &reg, true);
504
- qemu_log_mask(LOG_UNIMP, "%s: WTCR write not implemented: 0x%08x\n",
339
+ reg = c->gicr_ienabler0;
505
- __func__, value);
340
+ kvm_gicr_access(s, GICR_ISENABLER0, ncpu, &reg, true);
506
+ npcm7xx_timer_write_wtcr(&s->watchdog_timer, value);
341
+
507
return;
342
+ /* Restore config before pending so we treat level/edge correctly */
508
}
343
+ reg = half_shuffle32(c->edge_trigger >> 16) << 1;
509
344
+ kvm_gicr_access(s, GICR_ICFGR1, ncpu, &reg, true);
510
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_enter_reset(Object *obj, ResetType type)
345
+
511
for (i = 0; i < NPCM7XX_TIMERS_PER_CTRL; i++) {
346
+ reg = c->level;
512
NPCM7xxTimer *t = &s->timer[i];
347
+ kvm_gic_line_level_access(s, 0, ncpu, &reg, true);
513
348
+
514
- timer_del(&t->qtimer);
349
+ reg = ~0;
515
- t->expires_ns = 0;
350
+ kvm_gicr_access(s, GICR_ICPENDR0, ncpu, &reg, true);
516
- t->remaining_ns = 0;
351
+ reg = c->gicr_ipendr0;
517
+ npcm7xx_timer_clear(&t->base_timer);
352
+ kvm_gicr_access(s, GICR_ISPENDR0, ncpu, &reg, true);
518
t->tcsr = 0x00000005;
353
+
519
t->ticr = 0x00000000;
354
+ reg = ~0;
520
}
355
+ kvm_gicr_access(s, GICR_ICACTIVER0, ncpu, &reg, true);
521
356
+ reg = c->gicr_iactiver0;
522
s->tisr = 0x00000000;
357
+ kvm_gicr_access(s, GICR_ISACTIVER0, ncpu, &reg, true);
523
- s->wtcr = 0x00000400;
358
+
524
+ /*
359
+ for (i = 0; i < GIC_INTERNAL; i += 4) {
525
+ * Set WTCLK to 1(default) and reset all flags except WTRF.
360
+ reg = c->gicr_ipriorityr[i] |
526
+ * WTRF is not reset during a core domain reset.
361
+ (c->gicr_ipriorityr[i + 1] << 8) |
362
+ (c->gicr_ipriorityr[i + 2] << 16) |
363
+ (c->gicr_ipriorityr[i + 3] << 24);
364
+ kvm_gicr_access(s, GICR_IPRIORITYR + i, ncpu, &reg, true);
365
+ }
366
+ }
367
+
368
+ /* Distributor state (shared between all CPUs */
369
+ reg = s->gicd_statusr[GICV3_NS];
370
+ kvm_gicd_access(s, GICD_STATUSR, &reg, true);
371
+
372
+ /* s->enable bitmap -> GICD_ISENABLERn */
373
+ kvm_dist_putbmp(s, GICD_ISENABLER, GICD_ICENABLER, s->enabled);
374
+
375
+ /* s->group bitmap -> GICD_IGROUPRn */
376
+ kvm_dist_putbmp(s, GICD_IGROUPR, 0, s->group);
377
+
378
+ /* Restore targets before pending to ensure the pending state is set on
379
+ * the appropriate CPU interfaces in the kernel
380
+ */
527
+ */
381
+
528
+ s->watchdog_timer.wtcr = 0x00000400 | (s->watchdog_timer.wtcr &
382
+ /* s->gicd_irouter[irq] -> GICD_IROUTERn
529
+ NPCM7XX_WTCR_WTRF);
383
+ * We can't use kvm_dist_put() here because the registers are 64-bit
530
+}
384
+ */
531
+
385
+ for (i = GIC_INTERNAL; i < s->num_irq; i++) {
532
+static void npcm7xx_watchdog_timer_expired(void *opaque)
386
+ uint32_t offset;
533
+{
387
+
534
+ NPCM7xxWatchdogTimer *t = opaque;
388
+ offset = GICD_IROUTER + (sizeof(uint32_t) * i);
535
+
389
+ reg = (uint32_t)s->gicd_irouter[i];
536
+ if (t->wtcr & NPCM7XX_WTCR_WTE) {
390
+ kvm_gicd_access(s, offset, &reg, true);
537
+ if (t->wtcr & NPCM7XX_WTCR_WTIF) {
391
+
538
+ if (t->wtcr & NPCM7XX_WTCR_WTRE) {
392
+ offset = GICD_IROUTER + (sizeof(uint32_t) * i) + 4;
539
+ t->wtcr |= NPCM7XX_WTCR_WTRF;
393
+ reg = (uint32_t)(s->gicd_irouter[i] >> 32);
540
+ /* send reset signal to CLK module*/
394
+ kvm_gicd_access(s, offset, &reg, true);
541
+ qemu_irq_raise(t->reset_signal);
395
+ }
542
+ }
396
+
543
+ } else {
397
+ /* s->trigger bitmap -> GICD_ICFGRn
544
+ t->wtcr |= NPCM7XX_WTCR_WTIF;
398
+ * (restore configuration registers before pending IRQs so we treat
545
+ if (t->wtcr & NPCM7XX_WTCR_WTIE) {
399
+ * level/edge correctly)
546
+ /* send interrupt */
400
+ */
547
+ qemu_irq_raise(t->irq);
401
+ kvm_dist_put_edge_trigger(s, GICD_ICFGR, s->edge_trigger);
548
+ }
402
+
549
+ npcm7xx_watchdog_timer_reset_cycles(t,
403
+ /* s->level bitmap -> line_level */
550
+ NPCM7XX_WATCHDOG_INTERRUPT_TO_RESET_CYCLES);
404
+ kvm_gic_put_line_level_bmp(s, s->level);
551
+ npcm7xx_timer_start(&t->base_timer);
405
+
406
+ /* s->pending bitmap -> GICD_ISPENDRn */
407
+ kvm_dist_putbmp(s, GICD_ISPENDR, GICD_ICPENDR, s->pending);
408
+
409
+ /* s->active bitmap -> GICD_ISACTIVERn */
410
+ kvm_dist_putbmp(s, GICD_ISACTIVER, GICD_ICACTIVER, s->active);
411
+
412
+ /* s->gicd_ipriority[] -> GICD_IPRIORITYRn */
413
+ kvm_dist_put_priority(s, GICD_IPRIORITYR, s->gicd_ipriority);
414
+
415
+ /* CPU Interface state (one per CPU) */
416
+
417
+ for (ncpu = 0; ncpu < s->num_cpu; ncpu++) {
418
+ GICv3CPUState *c = &s->cpu[ncpu];
419
+ int num_pri_bits;
420
+
421
+ kvm_gicc_access(s, ICC_SRE_EL1, ncpu, &c->icc_sre_el1, true);
422
+ kvm_gicc_access(s, ICC_CTLR_EL1, ncpu,
423
+ &c->icc_ctlr_el1[GICV3_NS], true);
424
+ kvm_gicc_access(s, ICC_IGRPEN0_EL1, ncpu,
425
+ &c->icc_igrpen[GICV3_G0], true);
426
+ kvm_gicc_access(s, ICC_IGRPEN1_EL1, ncpu,
427
+ &c->icc_igrpen[GICV3_G1NS], true);
428
+ kvm_gicc_access(s, ICC_PMR_EL1, ncpu, &c->icc_pmr_el1, true);
429
+ kvm_gicc_access(s, ICC_BPR0_EL1, ncpu, &c->icc_bpr[GICV3_G0], true);
430
+ kvm_gicc_access(s, ICC_BPR1_EL1, ncpu, &c->icc_bpr[GICV3_G1NS], true);
431
+
432
+ num_pri_bits = ((c->icc_ctlr_el1[GICV3_NS] &
433
+ ICC_CTLR_EL1_PRIBITS_MASK) >>
434
+ ICC_CTLR_EL1_PRIBITS_SHIFT) + 1;
435
+
436
+ switch (num_pri_bits) {
437
+ case 7:
438
+ reg64 = c->icc_apr[GICV3_G0][3];
439
+ kvm_gicc_access(s, ICC_AP0R_EL1(3), ncpu, &reg64, true);
440
+ reg64 = c->icc_apr[GICV3_G0][2];
441
+ kvm_gicc_access(s, ICC_AP0R_EL1(2), ncpu, &reg64, true);
442
+ case 6:
443
+ reg64 = c->icc_apr[GICV3_G0][1];
444
+ kvm_gicc_access(s, ICC_AP0R_EL1(1), ncpu, &reg64, true);
445
+ default:
446
+ reg64 = c->icc_apr[GICV3_G0][0];
447
+ kvm_gicc_access(s, ICC_AP0R_EL1(0), ncpu, &reg64, true);
448
+ }
449
+
450
+ switch (num_pri_bits) {
451
+ case 7:
452
+ reg64 = c->icc_apr[GICV3_G1NS][3];
453
+ kvm_gicc_access(s, ICC_AP1R_EL1(3), ncpu, &reg64, true);
454
+ reg64 = c->icc_apr[GICV3_G1NS][2];
455
+ kvm_gicc_access(s, ICC_AP1R_EL1(2), ncpu, &reg64, true);
456
+ case 6:
457
+ reg64 = c->icc_apr[GICV3_G1NS][1];
458
+ kvm_gicc_access(s, ICC_AP1R_EL1(1), ncpu, &reg64, true);
459
+ default:
460
+ reg64 = c->icc_apr[GICV3_G1NS][0];
461
+ kvm_gicc_access(s, ICC_AP1R_EL1(0), ncpu, &reg64, true);
462
+ }
552
+ }
463
+ }
553
+ }
464
}
554
}
465
555
466
static void kvm_arm_gicv3_get(GICv3State *s)
556
static void npcm7xx_timer_hold_reset(Object *obj)
467
{
557
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_hold_reset(Object *obj)
468
- /* TODO */
558
for (i = 0; i < NPCM7XX_TIMERS_PER_CTRL; i++) {
469
- DPRINTF("Cannot get kernel gic state, no kernel interface\n");
559
qemu_irq_lower(s->timer[i].irq);
470
+ uint32_t regl, regh, reg;
560
}
471
+ uint64_t reg64, redist_typer;
561
+ qemu_irq_lower(s->watchdog_timer.irq);
472
+ int ncpu, i;
562
}
473
+
563
474
+ kvm_arm_gicv3_check(s);
564
static void npcm7xx_timer_realize(DeviceState *dev, Error **errp)
475
+
565
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_realize(DeviceState *dev, Error **errp)
476
+ kvm_gicr_access(s, GICR_TYPER, 0, &regl, false);
566
NPCM7xxTimerCtrlState *s = NPCM7XX_TIMER(dev);
477
+ kvm_gicr_access(s, GICR_TYPER + 4, 0, &regh, false);
567
SysBusDevice *sbd = &s->parent;
478
+ redist_typer = ((uint64_t)regh << 32) | regl;
568
int i;
479
+
569
+ NPCM7xxWatchdogTimer *w;
480
+ kvm_gicd_access(s, GICD_CTLR, &reg, false);
570
481
+ s->gicd_ctlr = reg;
571
for (i = 0; i < NPCM7XX_TIMERS_PER_CTRL; i++) {
482
+
572
NPCM7xxTimer *t = &s->timer[i];
483
+ /* Redistributor state (one per CPU) */
573
t->ctrl = s;
484
+
574
- timer_init_ns(&t->qtimer, QEMU_CLOCK_VIRTUAL, npcm7xx_timer_expired, t);
485
+ for (ncpu = 0; ncpu < s->num_cpu; ncpu++) {
575
+ timer_init_ns(&t->base_timer.qtimer, QEMU_CLOCK_VIRTUAL,
486
+ GICv3CPUState *c = &s->cpu[ncpu];
576
+ npcm7xx_timer_expired, t);
487
+
577
sysbus_init_irq(sbd, &t->irq);
488
+ kvm_gicr_access(s, GICR_CTLR, ncpu, &reg, false);
578
}
489
+ c->gicr_ctlr = reg;
579
490
+
580
+ w = &s->watchdog_timer;
491
+ kvm_gicr_access(s, GICR_STATUSR, ncpu, &reg, false);
581
+ w->ctrl = s;
492
+ c->gicr_statusr[GICV3_NS] = reg;
582
+ timer_init_ns(&w->base_timer.qtimer, QEMU_CLOCK_VIRTUAL,
493
+
583
+ npcm7xx_watchdog_timer_expired, w);
494
+ kvm_gicr_access(s, GICR_WAKER, ncpu, &reg, false);
584
+ sysbus_init_irq(sbd, &w->irq);
495
+ c->gicr_waker = reg;
585
+
496
+
586
memory_region_init_io(&s->iomem, OBJECT(s), &npcm7xx_timer_ops, s,
497
+ kvm_gicr_access(s, GICR_IGROUPR0, ncpu, &reg, false);
587
TYPE_NPCM7XX_TIMER, 4 * KiB);
498
+ c->gicr_igroupr0 = reg;
588
sysbus_init_mmio(sbd, &s->iomem);
499
+ kvm_gicr_access(s, GICR_ISENABLER0, ncpu, &reg, false);
589
+ qdev_init_gpio_out_named(dev, &w->reset_signal,
500
+ c->gicr_ienabler0 = reg;
590
+ NPCM7XX_WATCHDOG_RESET_GPIO_OUT, 1);
501
+ kvm_gicr_access(s, GICR_ICFGR1, ncpu, &reg, false);
591
}
502
+ c->edge_trigger = half_unshuffle32(reg >> 1) << 16;
592
503
+ kvm_gic_line_level_access(s, 0, ncpu, &reg, false);
593
-static const VMStateDescription vmstate_npcm7xx_timer = {
504
+ c->level = reg;
594
- .name = "npcm7xx-timer",
505
+ kvm_gicr_access(s, GICR_ISPENDR0, ncpu, &reg, false);
595
+static const VMStateDescription vmstate_npcm7xx_base_timer = {
506
+ c->gicr_ipendr0 = reg;
596
+ .name = "npcm7xx-base-timer",
507
+ kvm_gicr_access(s, GICR_ISACTIVER0, ncpu, &reg, false);
597
.version_id = 0,
508
+ c->gicr_iactiver0 = reg;
598
.minimum_version_id = 0,
509
+
599
.fields = (VMStateField[]) {
510
+ for (i = 0; i < GIC_INTERNAL; i += 4) {
600
- VMSTATE_TIMER(qtimer, NPCM7xxTimer),
511
+ kvm_gicr_access(s, GICR_IPRIORITYR + i, ncpu, &reg, false);
601
- VMSTATE_INT64(expires_ns, NPCM7xxTimer),
512
+ c->gicr_ipriorityr[i] = extract32(reg, 0, 8);
602
- VMSTATE_INT64(remaining_ns, NPCM7xxTimer),
513
+ c->gicr_ipriorityr[i + 1] = extract32(reg, 8, 8);
603
+ VMSTATE_TIMER(qtimer, NPCM7xxBaseTimer),
514
+ c->gicr_ipriorityr[i + 2] = extract32(reg, 16, 8);
604
+ VMSTATE_INT64(expires_ns, NPCM7xxBaseTimer),
515
+ c->gicr_ipriorityr[i + 3] = extract32(reg, 24, 8);
605
+ VMSTATE_INT64(remaining_ns, NPCM7xxBaseTimer),
606
+ VMSTATE_END_OF_LIST(),
607
+ },
608
+};
609
+
610
+static const VMStateDescription vmstate_npcm7xx_timer = {
611
+ .name = "npcm7xx-timer",
612
+ .version_id = 1,
613
+ .minimum_version_id = 1,
614
+ .fields = (VMStateField[]) {
615
+ VMSTATE_STRUCT(base_timer, NPCM7xxTimer,
616
+ 0, vmstate_npcm7xx_base_timer,
617
+ NPCM7xxBaseTimer),
618
VMSTATE_UINT32(tcsr, NPCM7xxTimer),
619
VMSTATE_UINT32(ticr, NPCM7xxTimer),
620
VMSTATE_END_OF_LIST(),
621
},
622
};
623
624
-static const VMStateDescription vmstate_npcm7xx_timer_ctrl = {
625
- .name = "npcm7xx-timer-ctrl",
626
+static const VMStateDescription vmstate_npcm7xx_watchdog_timer = {
627
+ .name = "npcm7xx-watchdog-timer",
628
.version_id = 0,
629
.minimum_version_id = 0,
630
+ .fields = (VMStateField[]) {
631
+ VMSTATE_STRUCT(base_timer, NPCM7xxWatchdogTimer,
632
+ 0, vmstate_npcm7xx_base_timer,
633
+ NPCM7xxBaseTimer),
634
+ VMSTATE_UINT32(wtcr, NPCM7xxWatchdogTimer),
635
+ VMSTATE_END_OF_LIST(),
636
+ },
637
+};
638
+
639
+static const VMStateDescription vmstate_npcm7xx_timer_ctrl = {
640
+ .name = "npcm7xx-timer-ctrl",
641
+ .version_id = 1,
642
+ .minimum_version_id = 1,
643
.fields = (VMStateField[]) {
644
VMSTATE_UINT32(tisr, NPCM7xxTimerCtrlState),
645
- VMSTATE_UINT32(wtcr, NPCM7xxTimerCtrlState),
646
VMSTATE_STRUCT_ARRAY(timer, NPCM7xxTimerCtrlState,
647
NPCM7XX_TIMERS_PER_CTRL, 0, vmstate_npcm7xx_timer,
648
NPCM7xxTimer),
649
+ VMSTATE_STRUCT(watchdog_timer, NPCM7xxTimerCtrlState,
650
+ 0, vmstate_npcm7xx_watchdog_timer,
651
+ NPCM7xxWatchdogTimer),
652
VMSTATE_END_OF_LIST(),
653
},
654
};
655
diff --git a/tests/qtest/npcm7xx_watchdog_timer-test.c b/tests/qtest/npcm7xx_watchdog_timer-test.c
656
new file mode 100644
657
index XXXXXXX..XXXXXXX
658
--- /dev/null
659
+++ b/tests/qtest/npcm7xx_watchdog_timer-test.c
660
@@ -XXX,XX +XXX,XX @@
661
+/*
662
+ * QTests for Nuvoton NPCM7xx Timer Watchdog Modules.
663
+ *
664
+ * Copyright 2020 Google LLC
665
+ *
666
+ * This program is free software; you can redistribute it and/or modify it
667
+ * under the terms of the GNU General Public License as published by the
668
+ * Free Software Foundation; either version 2 of the License, or
669
+ * (at your option) any later version.
670
+ *
671
+ * This program is distributed in the hope that it will be useful, but WITHOUT
672
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
673
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
674
+ * for more details.
675
+ */
676
+
677
+#include "qemu/osdep.h"
678
+#include "qemu/timer.h"
679
+
680
+#include "libqos/libqtest.h"
681
+#include "qapi/qmp/qdict.h"
682
+
683
+#define WTCR_OFFSET 0x1c
684
+#define REF_HZ (25000000)
685
+
686
+/* WTCR bit fields */
687
+#define WTCLK(rv) ((rv) << 10)
688
+#define WTE BIT(7)
689
+#define WTIE BIT(6)
690
+#define WTIS(rv) ((rv) << 4)
691
+#define WTIF BIT(3)
692
+#define WTRF BIT(2)
693
+#define WTRE BIT(1)
694
+#define WTR BIT(0)
695
+
696
+typedef struct Watchdog {
697
+ int irq;
698
+ uint64_t base_addr;
699
+} Watchdog;
700
+
701
+static const Watchdog watchdog_list[] = {
702
+ {
703
+ .irq = 47,
704
+ .base_addr = 0xf0008000
705
+ },
706
+ {
707
+ .irq = 48,
708
+ .base_addr = 0xf0009000
709
+ },
710
+ {
711
+ .irq = 49,
712
+ .base_addr = 0xf000a000
713
+ }
714
+};
715
+
716
+static int watchdog_index(const Watchdog *wd)
717
+{
718
+ ptrdiff_t diff = wd - watchdog_list;
719
+
720
+ g_assert(diff >= 0 && diff < ARRAY_SIZE(watchdog_list));
721
+
722
+ return diff;
723
+}
724
+
725
+static uint32_t watchdog_read_wtcr(QTestState *qts, const Watchdog *wd)
726
+{
727
+ return qtest_readl(qts, wd->base_addr + WTCR_OFFSET);
728
+}
729
+
730
+static void watchdog_write_wtcr(QTestState *qts, const Watchdog *wd,
731
+ uint32_t value)
732
+{
733
+ qtest_writel(qts, wd->base_addr + WTCR_OFFSET, value);
734
+}
735
+
736
+static uint32_t watchdog_prescaler(QTestState *qts, const Watchdog *wd)
737
+{
738
+ switch (extract32(watchdog_read_wtcr(qts, wd), 10, 2)) {
739
+ case 0:
740
+ return 1;
741
+ case 1:
742
+ return 256;
743
+ case 2:
744
+ return 2048;
745
+ case 3:
746
+ return 65536;
747
+ default:
748
+ g_assert_not_reached();
749
+ }
750
+}
751
+
752
+static QDict *get_watchdog_action(QTestState *qts)
753
+{
754
+ QDict *ev = qtest_qmp_eventwait_ref(qts, "WATCHDOG");
755
+ QDict *data;
756
+
757
+ data = qdict_get_qdict(ev, "data");
758
+ qobject_ref(data);
759
+ qobject_unref(ev);
760
+ return data;
761
+}
762
+
763
+#define RESET_CYCLES 1024
764
+static uint32_t watchdog_interrupt_cycles(QTestState *qts, const Watchdog *wd)
765
+{
766
+ uint32_t wtis = extract32(watchdog_read_wtcr(qts, wd), 4, 2);
767
+ return 1 << (14 + 2 * wtis);
768
+}
769
+
770
+static int64_t watchdog_calculate_steps(uint32_t count, uint32_t prescale)
771
+{
772
+ return (NANOSECONDS_PER_SECOND / REF_HZ) * count * prescale;
773
+}
774
+
775
+static int64_t watchdog_interrupt_steps(QTestState *qts, const Watchdog *wd)
776
+{
777
+ return watchdog_calculate_steps(watchdog_interrupt_cycles(qts, wd),
778
+ watchdog_prescaler(qts, wd));
779
+}
780
+
781
+/* Check wtcr can be reset to default value */
782
+static void test_init(gconstpointer watchdog)
783
+{
784
+ const Watchdog *wd = watchdog;
785
+ QTestState *qts = qtest_init("-machine quanta-gsj");
786
+
787
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
788
+
789
+ watchdog_write_wtcr(qts, wd, WTCLK(1) | WTRF | WTIF | WTR);
790
+ g_assert_cmphex(watchdog_read_wtcr(qts, wd), ==, WTCLK(1));
791
+
792
+ qtest_quit(qts);
793
+}
794
+
795
+/* Check a watchdog can generate interrupt and reset actions */
796
+static void test_reset_action(gconstpointer watchdog)
797
+{
798
+ const Watchdog *wd = watchdog;
799
+ QTestState *qts = qtest_init("-machine quanta-gsj");
800
+ QDict *ad;
801
+
802
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
803
+
804
+ watchdog_write_wtcr(qts, wd,
805
+ WTCLK(0) | WTE | WTRF | WTRE | WTIF | WTIE | WTR);
806
+ g_assert_cmphex(watchdog_read_wtcr(qts, wd), ==,
807
+ WTCLK(0) | WTE | WTRE | WTIE);
808
+
809
+ /* Check a watchdog can generate an interrupt */
810
+ qtest_clock_step(qts, watchdog_interrupt_steps(qts, wd));
811
+ g_assert_cmphex(watchdog_read_wtcr(qts, wd), ==,
812
+ WTCLK(0) | WTE | WTIF | WTIE | WTRE);
813
+ g_assert_true(qtest_get_irq(qts, wd->irq));
814
+
815
+ /* Check a watchdog can generate a reset signal */
816
+ qtest_clock_step(qts, watchdog_calculate_steps(RESET_CYCLES,
817
+ watchdog_prescaler(qts, wd)));
818
+ ad = get_watchdog_action(qts);
819
+ /* The signal is a reset signal */
820
+ g_assert_false(strcmp(qdict_get_str(ad, "action"), "reset"));
821
+ qobject_unref(ad);
822
+ qtest_qmp_eventwait(qts, "RESET");
823
+ /*
824
+ * Make sure WTCR is reset to default except for WTRF bit which shouldn't
825
+ * be reset.
826
+ */
827
+ g_assert_cmphex(watchdog_read_wtcr(qts, wd), ==, WTCLK(1) | WTRF);
828
+ qtest_quit(qts);
829
+}
830
+
831
+/* Check a watchdog works with all possible WTCLK prescalers and WTIS cycles */
832
+static void test_prescaler(gconstpointer watchdog)
833
+{
834
+ const Watchdog *wd = watchdog;
835
+
836
+ for (int wtclk = 0; wtclk < 4; ++wtclk) {
837
+ for (int wtis = 0; wtis < 4; ++wtis) {
838
+ QTestState *qts = qtest_init("-machine quanta-gsj");
839
+
840
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
841
+ watchdog_write_wtcr(qts, wd,
842
+ WTCLK(wtclk) | WTE | WTIF | WTIS(wtis) | WTIE | WTR);
843
+ /*
844
+ * The interrupt doesn't fire until watchdog_interrupt_steps()
845
+ * cycles passed
846
+ */
847
+ qtest_clock_step(qts, watchdog_interrupt_steps(qts, wd) - 1);
848
+ g_assert_false(watchdog_read_wtcr(qts, wd) & WTIF);
849
+ g_assert_false(qtest_get_irq(qts, wd->irq));
850
+ qtest_clock_step(qts, 1);
851
+ g_assert_true(watchdog_read_wtcr(qts, wd) & WTIF);
852
+ g_assert_true(qtest_get_irq(qts, wd->irq));
853
+
854
+ qtest_quit(qts);
516
+ }
855
+ }
517
+ }
856
+ }
518
+
857
+}
519
+ if (redist_typer & GICR_TYPER_PLPIS) {
858
+
520
+ for (ncpu = 0; ncpu < s->num_cpu; ncpu++) {
859
+/*
521
+ GICv3CPUState *c = &s->cpu[ncpu];
860
+ * Check a watchdog doesn't fire if corresponding flags (WTIE and WTRE) are not
522
+
861
+ * set.
523
+ kvm_gicr_access(s, GICR_PROPBASER, ncpu, &regl, false);
862
+ */
524
+ kvm_gicr_access(s, GICR_PROPBASER + 4, ncpu, &regh, false);
863
+static void test_enabling_flags(gconstpointer watchdog)
525
+ c->gicr_propbaser = ((uint64_t)regh << 32) | regl;
864
+{
526
+
865
+ const Watchdog *wd = watchdog;
527
+ kvm_gicr_access(s, GICR_PENDBASER, ncpu, &regl, false);
866
+ QTestState *qts;
528
+ kvm_gicr_access(s, GICR_PENDBASER + 4, ncpu, &regh, false);
867
+
529
+ c->gicr_pendbaser = ((uint64_t)regh << 32) | regl;
868
+ /* Neither WTIE or WTRE is set, no interrupt or reset should happen */
530
+ }
869
+ qts = qtest_init("-machine quanta-gsj");
870
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
871
+ watchdog_write_wtcr(qts, wd, WTCLK(0) | WTE | WTIF | WTRF | WTR);
872
+ qtest_clock_step(qts, watchdog_interrupt_steps(qts, wd));
873
+ g_assert_true(watchdog_read_wtcr(qts, wd) & WTIF);
874
+ g_assert_false(qtest_get_irq(qts, wd->irq));
875
+ qtest_clock_step(qts, watchdog_calculate_steps(RESET_CYCLES,
876
+ watchdog_prescaler(qts, wd)));
877
+ g_assert_true(watchdog_read_wtcr(qts, wd) & WTIF);
878
+ g_assert_false(watchdog_read_wtcr(qts, wd) & WTRF);
879
+ qtest_quit(qts);
880
+
881
+ /* Only WTIE is set, interrupt is triggered but reset should not happen */
882
+ qts = qtest_init("-machine quanta-gsj");
883
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
884
+ watchdog_write_wtcr(qts, wd, WTCLK(0) | WTE | WTIF | WTIE | WTRF | WTR);
885
+ qtest_clock_step(qts, watchdog_interrupt_steps(qts, wd));
886
+ g_assert_true(watchdog_read_wtcr(qts, wd) & WTIF);
887
+ g_assert_true(qtest_get_irq(qts, wd->irq));
888
+ qtest_clock_step(qts, watchdog_calculate_steps(RESET_CYCLES,
889
+ watchdog_prescaler(qts, wd)));
890
+ g_assert_true(watchdog_read_wtcr(qts, wd) & WTIF);
891
+ g_assert_false(watchdog_read_wtcr(qts, wd) & WTRF);
892
+ qtest_quit(qts);
893
+
894
+ /* Only WTRE is set, interrupt is triggered but reset should not happen */
895
+ qts = qtest_init("-machine quanta-gsj");
896
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
897
+ watchdog_write_wtcr(qts, wd, WTCLK(0) | WTE | WTIF | WTRE | WTRF | WTR);
898
+ qtest_clock_step(qts, watchdog_interrupt_steps(qts, wd));
899
+ g_assert_true(watchdog_read_wtcr(qts, wd) & WTIF);
900
+ g_assert_false(qtest_get_irq(qts, wd->irq));
901
+ qtest_clock_step(qts, watchdog_calculate_steps(RESET_CYCLES,
902
+ watchdog_prescaler(qts, wd)));
903
+ g_assert_false(strcmp(qdict_get_str(get_watchdog_action(qts), "action"),
904
+ "reset"));
905
+ qtest_qmp_eventwait(qts, "RESET");
906
+ qtest_quit(qts);
907
+
908
+ /*
909
+ * The case when both flags are set is already tested in
910
+ * test_reset_action().
911
+ */
912
+}
913
+
914
+/* Check a watchdog can pause and resume by setting WTE bits */
915
+static void test_pause(gconstpointer watchdog)
916
+{
917
+ const Watchdog *wd = watchdog;
918
+ QTestState *qts;
919
+ int64_t remaining_steps, steps;
920
+
921
+ qts = qtest_init("-machine quanta-gsj");
922
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
923
+ watchdog_write_wtcr(qts, wd, WTCLK(0) | WTE | WTIF | WTIE | WTRF | WTR);
924
+ remaining_steps = watchdog_interrupt_steps(qts, wd);
925
+ g_assert_cmphex(watchdog_read_wtcr(qts, wd), ==, WTCLK(0) | WTE | WTIE);
926
+
927
+ /* Run for half of the execution period. */
928
+ steps = remaining_steps / 2;
929
+ remaining_steps -= steps;
930
+ qtest_clock_step(qts, steps);
931
+
932
+ /* Pause the watchdog */
933
+ watchdog_write_wtcr(qts, wd, WTCLK(0) | WTIE);
934
+ g_assert_cmphex(watchdog_read_wtcr(qts, wd), ==, WTCLK(0) | WTIE);
935
+
936
+ /* Run for a long period of time, the watchdog shouldn't fire */
937
+ qtest_clock_step(qts, steps << 4);
938
+ g_assert_cmphex(watchdog_read_wtcr(qts, wd), ==, WTCLK(0) | WTIE);
939
+ g_assert_false(qtest_get_irq(qts, wd->irq));
940
+
941
+ /* Resume the watchdog */
942
+ watchdog_write_wtcr(qts, wd, WTCLK(0) | WTE | WTIE);
943
+ g_assert_cmphex(watchdog_read_wtcr(qts, wd), ==, WTCLK(0) | WTE | WTIE);
944
+
945
+ /* Run for the reset of the execution period, the watchdog should fire */
946
+ qtest_clock_step(qts, remaining_steps);
947
+ g_assert_cmphex(watchdog_read_wtcr(qts, wd), ==,
948
+ WTCLK(0) | WTE | WTIF | WTIE);
949
+ g_assert_true(qtest_get_irq(qts, wd->irq));
950
+
951
+ qtest_quit(qts);
952
+}
953
+
954
+static void watchdog_add_test(const char *name, const Watchdog* wd,
955
+ GTestDataFunc fn)
956
+{
957
+ g_autofree char *full_name = g_strdup_printf(
958
+ "npcm7xx_watchdog_timer[%d]/%s", watchdog_index(wd), name);
959
+ qtest_add_data_func(full_name, wd, fn);
960
+}
961
+#define add_test(name, td) watchdog_add_test(#name, td, test_##name)
962
+
963
+int main(int argc, char **argv)
964
+{
965
+ g_test_init(&argc, &argv, NULL);
966
+ g_test_set_nonfatal_assertions();
967
+
968
+ for (int i = 0; i < ARRAY_SIZE(watchdog_list); ++i) {
969
+ const Watchdog *wd = &watchdog_list[i];
970
+
971
+ add_test(init, wd);
972
+ add_test(reset_action, wd);
973
+ add_test(prescaler, wd);
974
+ add_test(enabling_flags, wd);
975
+ add_test(pause, wd);
531
+ }
976
+ }
532
+
977
+
533
+ /* Distributor state (shared between all CPUs */
978
+ return g_test_run();
534
+
979
+}
535
+ kvm_gicd_access(s, GICD_STATUSR, &reg, false);
980
diff --git a/MAINTAINERS b/MAINTAINERS
536
+ s->gicd_statusr[GICV3_NS] = reg;
981
index XXXXXXX..XXXXXXX 100644
537
+
982
--- a/MAINTAINERS
538
+ /* GICD_IGROUPRn -> s->group bitmap */
983
+++ b/MAINTAINERS
539
+ kvm_dist_getbmp(s, GICD_IGROUPR, s->group);
984
@@ -XXX,XX +XXX,XX @@ L: qemu-arm@nongnu.org
540
+
985
S: Supported
541
+ /* GICD_ISENABLERn -> s->enabled bitmap */
986
F: hw/*/npcm7xx*
542
+ kvm_dist_getbmp(s, GICD_ISENABLER, s->enabled);
987
F: include/hw/*/npcm7xx*
543
+
988
+F: tests/qtest/npcm7xx*
544
+ /* Line level of irq */
989
F: pc-bios/npcm7xx_bootrom.bin
545
+ kvm_gic_get_line_level_bmp(s, s->level);
990
F: roms/vbootrom
546
+ /* GICD_ISPENDRn -> s->pending bitmap */
991
547
+ kvm_dist_getbmp(s, GICD_ISPENDR, s->pending);
992
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
548
+
993
index XXXXXXX..XXXXXXX 100644
549
+ /* GICD_ISACTIVERn -> s->active bitmap */
994
--- a/tests/qtest/meson.build
550
+ kvm_dist_getbmp(s, GICD_ISACTIVER, s->active);
995
+++ b/tests/qtest/meson.build
551
+
996
@@ -XXX,XX +XXX,XX @@ qtests_sparc64 = \
552
+ /* GICD_ICFGRn -> s->trigger bitmap */
997
(config_all_devices.has_key('CONFIG_ISA_TESTDEV') ? ['endianness-test'] : []) + \
553
+ kvm_dist_get_edge_trigger(s, GICD_ICFGR, s->edge_trigger);
998
['prom-env-test', 'boot-serial-test']
554
+
999
555
+ /* GICD_IPRIORITYRn -> s->gicd_ipriority[] */
1000
-qtests_npcm7xx = ['npcm7xx_timer-test']
556
+ kvm_dist_get_priority(s, GICD_IPRIORITYR, s->gicd_ipriority);
1001
+qtests_npcm7xx = ['npcm7xx_timer-test', 'npcm7xx_watchdog_timer-test']
557
+
1002
qtests_arm = \
558
+ /* GICD_IROUTERn -> s->gicd_irouter[irq] */
1003
(config_all_devices.has_key('CONFIG_PFLASH_CFI02') ? ['pflash-cfi02-test'] : []) + \
559
+ for (i = GIC_INTERNAL; i < s->num_irq; i++) {
1004
(config_all_devices.has_key('CONFIG_NPCM7XX') ? qtests_npcm7xx : []) + \
560
+ uint32_t offset;
561
+
562
+ offset = GICD_IROUTER + (sizeof(uint32_t) * i);
563
+ kvm_gicd_access(s, offset, &regl, false);
564
+ offset = GICD_IROUTER + (sizeof(uint32_t) * i) + 4;
565
+ kvm_gicd_access(s, offset, &regh, false);
566
+ s->gicd_irouter[i] = ((uint64_t)regh << 32) | regl;
567
+ }
568
+
569
+ /*****************************************************************
570
+ * CPU Interface(s) State
571
+ */
572
+
573
+ for (ncpu = 0; ncpu < s->num_cpu; ncpu++) {
574
+ GICv3CPUState *c = &s->cpu[ncpu];
575
+ int num_pri_bits;
576
+
577
+ kvm_gicc_access(s, ICC_SRE_EL1, ncpu, &c->icc_sre_el1, false);
578
+ kvm_gicc_access(s, ICC_CTLR_EL1, ncpu,
579
+ &c->icc_ctlr_el1[GICV3_NS], false);
580
+ kvm_gicc_access(s, ICC_IGRPEN0_EL1, ncpu,
581
+ &c->icc_igrpen[GICV3_G0], false);
582
+ kvm_gicc_access(s, ICC_IGRPEN1_EL1, ncpu,
583
+ &c->icc_igrpen[GICV3_G1NS], false);
584
+ kvm_gicc_access(s, ICC_PMR_EL1, ncpu, &c->icc_pmr_el1, false);
585
+ kvm_gicc_access(s, ICC_BPR0_EL1, ncpu, &c->icc_bpr[GICV3_G0], false);
586
+ kvm_gicc_access(s, ICC_BPR1_EL1, ncpu, &c->icc_bpr[GICV3_G1NS], false);
587
+ num_pri_bits = ((c->icc_ctlr_el1[GICV3_NS] &
588
+ ICC_CTLR_EL1_PRIBITS_MASK) >>
589
+ ICC_CTLR_EL1_PRIBITS_SHIFT) + 1;
590
+
591
+ switch (num_pri_bits) {
592
+ case 7:
593
+ kvm_gicc_access(s, ICC_AP0R_EL1(3), ncpu, &reg64, false);
594
+ c->icc_apr[GICV3_G0][3] = reg64;
595
+ kvm_gicc_access(s, ICC_AP0R_EL1(2), ncpu, &reg64, false);
596
+ c->icc_apr[GICV3_G0][2] = reg64;
597
+ case 6:
598
+ kvm_gicc_access(s, ICC_AP0R_EL1(1), ncpu, &reg64, false);
599
+ c->icc_apr[GICV3_G0][1] = reg64;
600
+ default:
601
+ kvm_gicc_access(s, ICC_AP0R_EL1(0), ncpu, &reg64, false);
602
+ c->icc_apr[GICV3_G0][0] = reg64;
603
+ }
604
+
605
+ switch (num_pri_bits) {
606
+ case 7:
607
+ kvm_gicc_access(s, ICC_AP1R_EL1(3), ncpu, &reg64, false);
608
+ c->icc_apr[GICV3_G1NS][3] = reg64;
609
+ kvm_gicc_access(s, ICC_AP1R_EL1(2), ncpu, &reg64, false);
610
+ c->icc_apr[GICV3_G1NS][2] = reg64;
611
+ case 6:
612
+ kvm_gicc_access(s, ICC_AP1R_EL1(1), ncpu, &reg64, false);
613
+ c->icc_apr[GICV3_G1NS][1] = reg64;
614
+ default:
615
+ kvm_gicc_access(s, ICC_AP1R_EL1(0), ncpu, &reg64, false);
616
+ c->icc_apr[GICV3_G1NS][0] = reg64;
617
+ }
618
+ }
619
}
620
621
static void kvm_arm_gicv3_reset(DeviceState *dev)
622
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gicv3_reset(DeviceState *dev)
623
DPRINTF("Reset\n");
624
625
kgc->parent_reset(dev);
626
+
627
+ if (s->migration_blocker) {
628
+ DPRINTF("Cannot put kernel gic state, no kernel interface\n");
629
+ return;
630
+ }
631
+
632
kvm_arm_gicv3_put(s);
633
}
634
635
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
636
637
gicv3_init_irqs_and_mmio(s, kvm_arm_gicv3_set_irq, NULL);
638
639
- /* Block migration of a KVM GICv3 device: the API for saving and restoring
640
- * the state in the kernel is not yet finalised in the kernel or
641
- * implemented in QEMU.
642
- */
643
- error_setg(&s->migration_blocker, "vGICv3 migration is not implemented");
644
- migrate_add_blocker(s->migration_blocker, &local_err);
645
- if (local_err) {
646
- error_propagate(errp, local_err);
647
- error_free(s->migration_blocker);
648
- return;
649
- }
650
-
651
/* Try to create the device via the device control API */
652
s->dev_fd = kvm_create_device(kvm_state, KVM_DEV_TYPE_ARM_VGIC_V3, false);
653
if (s->dev_fd < 0) {
654
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
655
656
kvm_irqchip_commit_routes(kvm_state);
657
}
658
+
659
+ if (!kvm_device_check_attr(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_DIST_REGS,
660
+ GICD_CTLR)) {
661
+ error_setg(&s->migration_blocker, "This operating system kernel does "
662
+ "not support vGICv3 migration");
663
+ migrate_add_blocker(s->migration_blocker, &local_err);
664
+ if (local_err) {
665
+ error_propagate(errp, local_err);
666
+ error_free(s->migration_blocker);
667
+ return;
668
+ }
669
+ }
670
}
671
672
static void kvm_arm_gicv3_class_init(ObjectClass *klass, void *data)
673
--
1005
--
674
2.7.4
1006
2.20.1
675
1007
676
1008
diff view generated by jsdifflib
1
Move the NVICState struct definition into a header, so we can
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
embed it into other QOM objects like SoCs.
3
2
3
The RNG module returns a byte of randomness when the Data Valid bit is
4
set.
5
6
This implementation ignores the prescaler setting, and loads a new value
7
into RNGD every time RNGCS is read while the RNG is enabled and random
8
data is available.
9
10
A qtest featuring some simple randomness tests is included.
11
12
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Message-id: 1487604965-23220-3-git-send-email-peter.maydell@linaro.org
8
---
16
---
9
include/hw/arm/armv7m_nvic.h | 66 ++++++++++++++++++++++++++++++++++++++++++++
17
docs/system/arm/nuvoton.rst | 2 +-
10
hw/intc/armv7m_nvic.c | 49 +-------------------------------
18
include/hw/arm/npcm7xx.h | 2 +
11
2 files changed, 67 insertions(+), 48 deletions(-)
19
include/hw/misc/npcm7xx_rng.h | 34 ++++
12
create mode 100644 include/hw/arm/armv7m_nvic.h
20
hw/arm/npcm7xx.c | 7 +-
21
hw/misc/npcm7xx_rng.c | 180 +++++++++++++++++++++
22
tests/qtest/npcm7xx_rng-test.c | 278 +++++++++++++++++++++++++++++++++
23
hw/misc/meson.build | 1 +
24
hw/misc/trace-events | 4 +
25
tests/qtest/meson.build | 5 +-
26
9 files changed, 510 insertions(+), 3 deletions(-)
27
create mode 100644 include/hw/misc/npcm7xx_rng.h
28
create mode 100644 hw/misc/npcm7xx_rng.c
29
create mode 100644 tests/qtest/npcm7xx_rng-test.c
13
30
14
diff --git a/include/hw/arm/armv7m_nvic.h b/include/hw/arm/armv7m_nvic.h
31
diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
32
index XXXXXXX..XXXXXXX 100644
33
--- a/docs/system/arm/nuvoton.rst
34
+++ b/docs/system/arm/nuvoton.rst
35
@@ -XXX,XX +XXX,XX @@ Supported devices
36
* DDR4 memory controller (dummy interface indicating memory training is done)
37
* OTP controllers (no protection features)
38
* Flash Interface Unit (FIU; no protection features)
39
+ * Random Number Generator (RNG)
40
41
Missing devices
42
---------------
43
@@ -XXX,XX +XXX,XX @@ Missing devices
44
* Peripheral SPI controller (PSPI)
45
* Analog to Digital Converter (ADC)
46
* SD/MMC host
47
- * Random Number Generator (RNG)
48
* PECI interface
49
* Pulse Width Modulation (PWM)
50
* Tachometer
51
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
52
index XXXXXXX..XXXXXXX 100644
53
--- a/include/hw/arm/npcm7xx.h
54
+++ b/include/hw/arm/npcm7xx.h
55
@@ -XXX,XX +XXX,XX @@
56
#include "hw/mem/npcm7xx_mc.h"
57
#include "hw/misc/npcm7xx_clk.h"
58
#include "hw/misc/npcm7xx_gcr.h"
59
+#include "hw/misc/npcm7xx_rng.h"
60
#include "hw/nvram/npcm7xx_otp.h"
61
#include "hw/timer/npcm7xx_timer.h"
62
#include "hw/ssi/npcm7xx_fiu.h"
63
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
64
NPCM7xxOTPState key_storage;
65
NPCM7xxOTPState fuse_array;
66
NPCM7xxMCState mc;
67
+ NPCM7xxRNGState rng;
68
NPCM7xxFIUState fiu[2];
69
} NPCM7xxState;
70
71
diff --git a/include/hw/misc/npcm7xx_rng.h b/include/hw/misc/npcm7xx_rng.h
15
new file mode 100644
72
new file mode 100644
16
index XXXXXXX..XXXXXXX
73
index XXXXXXX..XXXXXXX
17
--- /dev/null
74
--- /dev/null
18
+++ b/include/hw/arm/armv7m_nvic.h
75
+++ b/include/hw/misc/npcm7xx_rng.h
19
@@ -XXX,XX +XXX,XX @@
76
@@ -XXX,XX +XXX,XX @@
20
+/*
77
+/*
21
+ * ARMv7M NVIC object
78
+ * Nuvoton NPCM7xx Random Number Generator.
22
+ *
79
+ *
23
+ * Copyright (c) 2017 Linaro Ltd
80
+ * Copyright 2020 Google LLC
24
+ * Written by Peter Maydell <peter.maydell@linaro.org>
81
+ *
25
+ *
82
+ * This program is free software; you can redistribute it and/or modify it
26
+ * This code is licensed under the GPL version 2 or later.
83
+ * under the terms of the GNU General Public License as published by the
27
+ */
84
+ * Free Software Foundation; either version 2 of the License, or
28
+
85
+ * (at your option) any later version.
29
+#ifndef HW_ARM_ARMV7M_NVIC_H
86
+ *
30
+#define HW_ARM_ARMV7M_NVIC_H
87
+ * This program is distributed in the hope that it will be useful, but WITHOUT
31
+
88
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
32
+#include "target/arm/cpu.h"
89
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
90
+ * for more details.
91
+ */
92
+#ifndef NPCM7XX_RNG_H
93
+#define NPCM7XX_RNG_H
94
+
33
+#include "hw/sysbus.h"
95
+#include "hw/sysbus.h"
34
+
96
+
35
+#define TYPE_NVIC "armv7m_nvic"
97
+typedef struct NPCM7xxRNGState {
36
+
98
+ SysBusDevice parent;
37
+#define NVIC(obj) \
99
+
38
+ OBJECT_CHECK(NVICState, (obj), TYPE_NVIC)
100
+ MemoryRegion iomem;
39
+
101
+
40
+/* Highest permitted number of exceptions (architectural limit) */
102
+ uint8_t rngcs;
41
+#define NVIC_MAX_VECTORS 512
103
+ uint8_t rngd;
42
+
104
+ uint8_t rngmode;
43
+typedef struct VecInfo {
105
+} NPCM7xxRNGState;
44
+ /* Exception priorities can range from -3 to 255; only the unmodifiable
106
+
45
+ * priority values for RESET, NMI and HardFault can be negative.
107
+#define TYPE_NPCM7XX_RNG "npcm7xx-rng"
46
+ */
108
+#define NPCM7XX_RNG(obj) OBJECT_CHECK(NPCM7xxRNGState, (obj), TYPE_NPCM7XX_RNG)
47
+ int16_t prio;
109
+
48
+ uint8_t enabled;
110
+#endif /* NPCM7XX_RNG_H */
49
+ uint8_t pending;
111
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
50
+ uint8_t active;
51
+ uint8_t level; /* exceptions <=15 never set level */
52
+} VecInfo;
53
+
54
+typedef struct NVICState {
55
+ /*< private >*/
56
+ SysBusDevice parent_obj;
57
+ /*< public >*/
58
+
59
+ ARMCPU *cpu;
60
+
61
+ VecInfo vectors[NVIC_MAX_VECTORS];
62
+ uint32_t prigroup;
63
+
64
+ /* vectpending and exception_prio are both cached state that can
65
+ * be recalculated from the vectors[] array and the prigroup field.
66
+ */
67
+ unsigned int vectpending; /* highest prio pending enabled exception */
68
+ int exception_prio; /* group prio of the highest prio active exception */
69
+
70
+ struct {
71
+ uint32_t control;
72
+ uint32_t reload;
73
+ int64_t tick;
74
+ QEMUTimer *timer;
75
+ } systick;
76
+
77
+ MemoryRegion sysregmem;
78
+ MemoryRegion container;
79
+
80
+ uint32_t num_irq;
81
+ qemu_irq excpout;
82
+ qemu_irq sysresetreq;
83
+} NVICState;
84
+
85
+#endif
86
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
87
index XXXXXXX..XXXXXXX 100644
112
index XXXXXXX..XXXXXXX 100644
88
--- a/hw/intc/armv7m_nvic.c
113
--- a/hw/arm/npcm7xx.c
89
+++ b/hw/intc/armv7m_nvic.c
114
+++ b/hw/arm/npcm7xx.c
90
@@ -XXX,XX +XXX,XX @@
115
@@ -XXX,XX +XXX,XX @@
91
#include "hw/sysbus.h"
116
#define NPCM7XX_GCR_BA (0xf0800000)
92
#include "qemu/timer.h"
117
#define NPCM7XX_CLK_BA (0xf0801000)
93
#include "hw/arm/arm.h"
118
#define NPCM7XX_MC_BA (0xf0824000)
94
+#include "hw/arm/armv7m_nvic.h"
119
+#define NPCM7XX_RNG_BA (0xf000b000)
95
#include "target/arm/cpu.h"
120
96
#include "exec/address-spaces.h"
121
/* Internal AHB SRAM */
97
#include "qemu/log.h"
122
#define NPCM7XX_RAM3_BA (0xc0008000)
123
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
124
object_initialize_child(obj, "otp2", &s->fuse_array,
125
TYPE_NPCM7XX_FUSE_ARRAY);
126
object_initialize_child(obj, "mc", &s->mc, TYPE_NPCM7XX_MC);
127
+ object_initialize_child(obj, "rng", &s->rng, TYPE_NPCM7XX_RNG);
128
129
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
130
object_initialize_child(obj, "tim[*]", &s->tim[i], TYPE_NPCM7XX_TIMER);
131
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
132
serial_hd(i), DEVICE_LITTLE_ENDIAN);
133
}
134
135
+ /* Random Number Generator. Cannot fail. */
136
+ sysbus_realize(SYS_BUS_DEVICE(&s->rng), &error_abort);
137
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->rng), 0, NPCM7XX_RNG_BA);
138
+
139
/*
140
* Flash Interface Unit (FIU). Can fail if incorrect number of chip selects
141
* specified, but this is a programming error.
142
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
143
create_unimplemented_device("npcm7xx.vdmx", 0xe0800000, 4 * KiB);
144
create_unimplemented_device("npcm7xx.pcierc", 0xe1000000, 64 * KiB);
145
create_unimplemented_device("npcm7xx.kcs", 0xf0007000, 4 * KiB);
146
- create_unimplemented_device("npcm7xx.rng", 0xf000b000, 4 * KiB);
147
create_unimplemented_device("npcm7xx.adc", 0xf000c000, 4 * KiB);
148
create_unimplemented_device("npcm7xx.gfxi", 0xf000e000, 4 * KiB);
149
create_unimplemented_device("npcm7xx.gpio[0]", 0xf0010000, 4 * KiB);
150
diff --git a/hw/misc/npcm7xx_rng.c b/hw/misc/npcm7xx_rng.c
151
new file mode 100644
152
index XXXXXXX..XXXXXXX
153
--- /dev/null
154
+++ b/hw/misc/npcm7xx_rng.c
98
@@ -XXX,XX +XXX,XX @@
155
@@ -XXX,XX +XXX,XX @@
99
* "exception" more or less interchangeably.
156
+/*
100
*/
157
+ * Nuvoton NPCM7xx Random Number Generator.
101
#define NVIC_FIRST_IRQ 16
158
+ *
102
-#define NVIC_MAX_VECTORS 512
159
+ * Copyright 2020 Google LLC
103
#define NVIC_MAX_IRQ (NVIC_MAX_VECTORS - NVIC_FIRST_IRQ)
160
+ *
104
161
+ * This program is free software; you can redistribute it and/or modify it
105
/* Effective running priority of the CPU when no exception is active
162
+ * under the terms of the GNU General Public License as published by the
163
+ * Free Software Foundation; either version 2 of the License, or
164
+ * (at your option) any later version.
165
+ *
166
+ * This program is distributed in the hope that it will be useful, but WITHOUT
167
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
168
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
169
+ * for more details.
170
+ */
171
+
172
+#include "qemu/osdep.h"
173
+
174
+#include "hw/misc/npcm7xx_rng.h"
175
+#include "migration/vmstate.h"
176
+#include "qemu/bitops.h"
177
+#include "qemu/guest-random.h"
178
+#include "qemu/log.h"
179
+#include "qemu/module.h"
180
+#include "qemu/units.h"
181
+
182
+#include "trace.h"
183
+
184
+#define NPCM7XX_RNG_REGS_SIZE (4 * KiB)
185
+
186
+#define NPCM7XX_RNGCS (0x00)
187
+#define NPCM7XX_RNGCS_CLKP(rv) extract32(rv, 2, 4)
188
+#define NPCM7XX_RNGCS_DVALID BIT(1)
189
+#define NPCM7XX_RNGCS_RNGE BIT(0)
190
+
191
+#define NPCM7XX_RNGD (0x04)
192
+#define NPCM7XX_RNGMODE (0x08)
193
+#define NPCM7XX_RNGMODE_NORMAL (0x02)
194
+
195
+static bool npcm7xx_rng_is_enabled(NPCM7xxRNGState *s)
196
+{
197
+ return (s->rngcs & NPCM7XX_RNGCS_RNGE) &&
198
+ (s->rngmode == NPCM7XX_RNGMODE_NORMAL);
199
+}
200
+
201
+static uint64_t npcm7xx_rng_read(void *opaque, hwaddr offset, unsigned size)
202
+{
203
+ NPCM7xxRNGState *s = opaque;
204
+ uint64_t value = 0;
205
+
206
+ switch (offset) {
207
+ case NPCM7XX_RNGCS:
208
+ /*
209
+ * If the RNG is enabled, but we don't have any valid random data, try
210
+ * obtaining some and update the DVALID bit accordingly.
211
+ */
212
+ if (!npcm7xx_rng_is_enabled(s)) {
213
+ s->rngcs &= ~NPCM7XX_RNGCS_DVALID;
214
+ } else if (!(s->rngcs & NPCM7XX_RNGCS_DVALID)) {
215
+ uint8_t byte = 0;
216
+
217
+ if (qemu_guest_getrandom(&byte, sizeof(byte), NULL) == 0) {
218
+ s->rngd = byte;
219
+ s->rngcs |= NPCM7XX_RNGCS_DVALID;
220
+ }
221
+ }
222
+ value = s->rngcs;
223
+ break;
224
+ case NPCM7XX_RNGD:
225
+ if (npcm7xx_rng_is_enabled(s) && s->rngcs & NPCM7XX_RNGCS_DVALID) {
226
+ s->rngcs &= ~NPCM7XX_RNGCS_DVALID;
227
+ value = s->rngd;
228
+ s->rngd = 0;
229
+ }
230
+ break;
231
+ case NPCM7XX_RNGMODE:
232
+ value = s->rngmode;
233
+ break;
234
+
235
+ default:
236
+ qemu_log_mask(LOG_GUEST_ERROR,
237
+ "%s: read from invalid offset 0x%" HWADDR_PRIx "\n",
238
+ DEVICE(s)->canonical_path, offset);
239
+ break;
240
+ }
241
+
242
+ trace_npcm7xx_rng_read(offset, value, size);
243
+
244
+ return value;
245
+}
246
+
247
+static void npcm7xx_rng_write(void *opaque, hwaddr offset, uint64_t value,
248
+ unsigned size)
249
+{
250
+ NPCM7xxRNGState *s = opaque;
251
+
252
+ trace_npcm7xx_rng_write(offset, value, size);
253
+
254
+ switch (offset) {
255
+ case NPCM7XX_RNGCS:
256
+ s->rngcs &= NPCM7XX_RNGCS_DVALID;
257
+ s->rngcs |= value & ~NPCM7XX_RNGCS_DVALID;
258
+ break;
259
+ case NPCM7XX_RNGD:
260
+ qemu_log_mask(LOG_GUEST_ERROR,
261
+ "%s: write to read-only register @ 0x%" HWADDR_PRIx "\n",
262
+ DEVICE(s)->canonical_path, offset);
263
+ break;
264
+ case NPCM7XX_RNGMODE:
265
+ s->rngmode = value;
266
+ break;
267
+ default:
268
+ qemu_log_mask(LOG_GUEST_ERROR,
269
+ "%s: write to invalid offset 0x%" HWADDR_PRIx "\n",
270
+ DEVICE(s)->canonical_path, offset);
271
+ break;
272
+ }
273
+}
274
+
275
+static const MemoryRegionOps npcm7xx_rng_ops = {
276
+ .read = npcm7xx_rng_read,
277
+ .write = npcm7xx_rng_write,
278
+ .endianness = DEVICE_LITTLE_ENDIAN,
279
+ .valid = {
280
+ .min_access_size = 1,
281
+ .max_access_size = 4,
282
+ .unaligned = false,
283
+ },
284
+};
285
+
286
+static void npcm7xx_rng_enter_reset(Object *obj, ResetType type)
287
+{
288
+ NPCM7xxRNGState *s = NPCM7XX_RNG(obj);
289
+
290
+ s->rngcs = 0;
291
+ s->rngd = 0;
292
+ s->rngmode = 0;
293
+}
294
+
295
+static void npcm7xx_rng_init(Object *obj)
296
+{
297
+ NPCM7xxRNGState *s = NPCM7XX_RNG(obj);
298
+
299
+ memory_region_init_io(&s->iomem, obj, &npcm7xx_rng_ops, s, "regs",
300
+ NPCM7XX_RNG_REGS_SIZE);
301
+ sysbus_init_mmio(&s->parent, &s->iomem);
302
+}
303
+
304
+static const VMStateDescription vmstate_npcm7xx_rng = {
305
+ .name = "npcm7xx-rng",
306
+ .version_id = 0,
307
+ .minimum_version_id = 0,
308
+ .fields = (VMStateField[]) {
309
+ VMSTATE_UINT8(rngcs, NPCM7xxRNGState),
310
+ VMSTATE_UINT8(rngd, NPCM7xxRNGState),
311
+ VMSTATE_UINT8(rngmode, NPCM7xxRNGState),
312
+ VMSTATE_END_OF_LIST(),
313
+ },
314
+};
315
+
316
+static void npcm7xx_rng_class_init(ObjectClass *klass, void *data)
317
+{
318
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
319
+ DeviceClass *dc = DEVICE_CLASS(klass);
320
+
321
+ dc->desc = "NPCM7xx Random Number Generator";
322
+ dc->vmsd = &vmstate_npcm7xx_rng;
323
+ rc->phases.enter = npcm7xx_rng_enter_reset;
324
+}
325
+
326
+static const TypeInfo npcm7xx_rng_types[] = {
327
+ {
328
+ .name = TYPE_NPCM7XX_RNG,
329
+ .parent = TYPE_SYS_BUS_DEVICE,
330
+ .instance_size = sizeof(NPCM7xxRNGState),
331
+ .class_init = npcm7xx_rng_class_init,
332
+ .instance_init = npcm7xx_rng_init,
333
+ },
334
+};
335
+DEFINE_TYPES(npcm7xx_rng_types);
336
diff --git a/tests/qtest/npcm7xx_rng-test.c b/tests/qtest/npcm7xx_rng-test.c
337
new file mode 100644
338
index XXXXXXX..XXXXXXX
339
--- /dev/null
340
+++ b/tests/qtest/npcm7xx_rng-test.c
106
@@ -XXX,XX +XXX,XX @@
341
@@ -XXX,XX +XXX,XX @@
107
*/
342
+/*
108
#define NVIC_NOEXC_PRIO 0x100
343
+ * QTest testcase for the Nuvoton NPCM7xx Random Number Generator
109
344
+ *
110
-typedef struct VecInfo {
345
+ * Copyright 2020 Google LLC
111
- /* Exception priorities can range from -3 to 255; only the unmodifiable
346
+ *
112
- * priority values for RESET, NMI and HardFault can be negative.
347
+ * This program is free software; you can redistribute it and/or modify it
113
- */
348
+ * under the terms of the GNU General Public License as published by the
114
- int16_t prio;
349
+ * Free Software Foundation; either version 2 of the License, or
115
- uint8_t enabled;
350
+ * (at your option) any later version.
116
- uint8_t pending;
351
+ *
117
- uint8_t active;
352
+ * This program is distributed in the hope that it will be useful, but WITHOUT
118
- uint8_t level; /* exceptions <=15 never set level */
353
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
119
-} VecInfo;
354
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
120
-
355
+ * for more details.
121
-typedef struct NVICState {
356
+ */
122
- /*< private >*/
357
+
123
- SysBusDevice parent_obj;
358
+#include "qemu/osdep.h"
124
- /*< public >*/
359
+
125
-
360
+#include <math.h>
126
- ARMCPU *cpu;
361
+
127
-
362
+#include "libqtest-single.h"
128
- VecInfo vectors[NVIC_MAX_VECTORS];
363
+#include "qemu/bitops.h"
129
- uint32_t prigroup;
364
+
130
-
365
+#define RNG_BASE_ADDR 0xf000b000
131
- /* vectpending and exception_prio are both cached state that can
366
+
132
- * be recalculated from the vectors[] array and the prigroup field.
367
+/* Control and Status Register */
133
- */
368
+#define RNGCS 0x00
134
- unsigned int vectpending; /* highest prio pending enabled exception */
369
+# define DVALID BIT(1) /* Data Valid */
135
- int exception_prio; /* group prio of the highest prio active exception */
370
+# define RNGE BIT(0) /* RNG Enable */
136
-
371
+/* Data Register */
137
- struct {
372
+#define RNGD 0x04
138
- uint32_t control;
373
+/* Mode Register */
139
- uint32_t reload;
374
+#define RNGMODE 0x08
140
- int64_t tick;
375
+# define ROSEL_NORMAL (2) /* RNG only works in this mode */
141
- QEMUTimer *timer;
376
+
142
- } systick;
377
+/* Number of bits to collect for randomness tests. */
143
-
378
+#define TEST_INPUT_BITS (128)
144
- MemoryRegion sysregmem;
379
+
145
- MemoryRegion container;
380
+static void rng_writeb(unsigned int offset, uint8_t value)
146
-
381
+{
147
- uint32_t num_irq;
382
+ writeb(RNG_BASE_ADDR + offset, value);
148
- qemu_irq excpout;
383
+}
149
- qemu_irq sysresetreq;
384
+
150
-} NVICState;
385
+static uint8_t rng_readb(unsigned int offset)
151
-
386
+{
152
-#define TYPE_NVIC "armv7m_nvic"
387
+ return readb(RNG_BASE_ADDR + offset);
153
-
388
+}
154
-#define NVIC(obj) \
389
+
155
- OBJECT_CHECK(NVICState, (obj), TYPE_NVIC)
390
+/* Disable RNG and set normal ring oscillator mode. */
156
-
391
+static void rng_reset(void)
157
static const uint8_t nvic_id[] = {
392
+{
158
0x00, 0xb0, 0x1b, 0x00, 0x0d, 0xe0, 0x05, 0xb1
393
+ rng_writeb(RNGCS, 0);
159
};
394
+ rng_writeb(RNGMODE, ROSEL_NORMAL);
395
+}
396
+
397
+/* Reset RNG and then enable it. */
398
+static void rng_reset_enable(void)
399
+{
400
+ rng_reset();
401
+ rng_writeb(RNGCS, RNGE);
402
+}
403
+
404
+/* Wait until Data Valid bit is set. */
405
+static bool rng_wait_ready(void)
406
+{
407
+ /* qemu_guest_getrandom may fail. Assume it won't fail 10 times in a row. */
408
+ int retries = 10;
409
+
410
+ while (retries-- > 0) {
411
+ if (rng_readb(RNGCS) & DVALID) {
412
+ return true;
413
+ }
414
+ }
415
+
416
+ return false;
417
+}
418
+
419
+/*
420
+ * Perform a frequency (monobit) test, as defined by NIST SP 800-22, on the
421
+ * sequence in buf and return the P-value. This represents the probability of a
422
+ * truly random sequence having the same proportion of zeros and ones as the
423
+ * sequence in buf.
424
+ *
425
+ * An RNG which always returns 0x00 or 0xff, or has some bits stuck at 0 or 1,
426
+ * will fail this test. However, an RNG which always returns 0x55, 0xf0 or some
427
+ * other value with an equal number of zeroes and ones will pass.
428
+ */
429
+static double calc_monobit_p(const uint8_t *buf, unsigned int len)
430
+{
431
+ unsigned int i;
432
+ double s_obs;
433
+ int sn = 0;
434
+
435
+ for (i = 0; i < len; i++) {
436
+ /*
437
+ * Each 1 counts as 1, each 0 counts as -1.
438
+ * s = cp - (8 - cp) = 2 * cp - 8
439
+ */
440
+ sn += 2 * ctpop8(buf[i]) - 8;
441
+ }
442
+
443
+ s_obs = abs(sn) / sqrt(len * BITS_PER_BYTE);
444
+
445
+ return erfc(s_obs / sqrt(2));
446
+}
447
+
448
+/*
449
+ * Perform a runs test, as defined by NIST SP 800-22, and return the P-value.
450
+ * This represents the probability of a truly random sequence having the same
451
+ * number of runs (i.e. uninterrupted sequences of identical bits) as the
452
+ * sequence in buf.
453
+ */
454
+static double calc_runs_p(const unsigned long *buf, unsigned int nr_bits)
455
+{
456
+ unsigned int j;
457
+ unsigned int k;
458
+ int nr_ones = 0;
459
+ int vn_obs = 0;
460
+ double pi;
461
+
462
+ g_assert(nr_bits % BITS_PER_LONG == 0);
463
+
464
+ for (j = 0; j < nr_bits / BITS_PER_LONG; j++) {
465
+ nr_ones += __builtin_popcountl(buf[j]);
466
+ }
467
+ pi = (double)nr_ones / nr_bits;
468
+
469
+ for (k = 0; k < nr_bits - 1; k++) {
470
+ vn_obs += !(test_bit(k, buf) ^ test_bit(k + 1, buf));
471
+ }
472
+ vn_obs += 1;
473
+
474
+ return erfc(fabs(vn_obs - 2 * nr_bits * pi * (1.0 - pi))
475
+ / (2 * sqrt(2 * nr_bits) * pi * (1.0 - pi)));
476
+}
477
+
478
+/*
479
+ * Verifies that DVALID is clear, and RNGD reads zero, when RNGE is cleared,
480
+ * and DVALID eventually becomes set when RNGE is set.
481
+ */
482
+static void test_enable_disable(void)
483
+{
484
+ /* Disable: DVALID should not be set, and RNGD should read zero */
485
+ rng_reset();
486
+ g_assert_cmphex(rng_readb(RNGCS), ==, 0);
487
+ g_assert_cmphex(rng_readb(RNGD), ==, 0);
488
+
489
+ /* Enable: DVALID should be set, but we can't make assumptions about RNGD */
490
+ rng_writeb(RNGCS, RNGE);
491
+ g_assert_true(rng_wait_ready());
492
+ g_assert_cmphex(rng_readb(RNGCS), ==, DVALID | RNGE);
493
+
494
+ /* Disable: DVALID should not be set, and RNGD should read zero */
495
+ rng_writeb(RNGCS, 0);
496
+ g_assert_cmphex(rng_readb(RNGCS), ==, 0);
497
+ g_assert_cmphex(rng_readb(RNGD), ==, 0);
498
+}
499
+
500
+/*
501
+ * Verifies that the RNG only produces data when RNGMODE is set to 'normal'
502
+ * ring oscillator mode.
503
+ */
504
+static void test_rosel(void)
505
+{
506
+ rng_reset_enable();
507
+ g_assert_true(rng_wait_ready());
508
+ rng_writeb(RNGMODE, 0);
509
+ g_assert_false(rng_wait_ready());
510
+ rng_writeb(RNGMODE, ROSEL_NORMAL);
511
+ g_assert_true(rng_wait_ready());
512
+ rng_writeb(RNGMODE, 0);
513
+ g_assert_false(rng_wait_ready());
514
+}
515
+
516
+/*
517
+ * Verifies that a continuous sequence of bits collected after enabling the RNG
518
+ * satisfies a monobit test.
519
+ */
520
+static void test_continuous_monobit(void)
521
+{
522
+ uint8_t buf[TEST_INPUT_BITS / BITS_PER_BYTE];
523
+ unsigned int i;
524
+
525
+ rng_reset_enable();
526
+ for (i = 0; i < sizeof(buf); i++) {
527
+ g_assert_true(rng_wait_ready());
528
+ buf[i] = rng_readb(RNGD);
529
+ }
530
+
531
+ g_assert_cmpfloat(calc_monobit_p(buf, sizeof(buf)), >, 0.01);
532
+}
533
+
534
+/*
535
+ * Verifies that a continuous sequence of bits collected after enabling the RNG
536
+ * satisfies a runs test.
537
+ */
538
+static void test_continuous_runs(void)
539
+{
540
+ union {
541
+ unsigned long l[TEST_INPUT_BITS / BITS_PER_LONG];
542
+ uint8_t c[TEST_INPUT_BITS / BITS_PER_BYTE];
543
+ } buf;
544
+ unsigned int i;
545
+
546
+ rng_reset_enable();
547
+ for (i = 0; i < sizeof(buf); i++) {
548
+ g_assert_true(rng_wait_ready());
549
+ buf.c[i] = rng_readb(RNGD);
550
+ }
551
+
552
+ g_assert_cmpfloat(calc_runs_p(buf.l, sizeof(buf) * BITS_PER_BYTE), >, 0.01);
553
+}
554
+
555
+/*
556
+ * Verifies that the first data byte collected after enabling the RNG satisfies
557
+ * a monobit test.
558
+ */
559
+static void test_first_byte_monobit(void)
560
+{
561
+ /* Enable, collect one byte, disable. Repeat until we have 100 bits. */
562
+ uint8_t buf[TEST_INPUT_BITS / BITS_PER_BYTE];
563
+ unsigned int i;
564
+
565
+ rng_reset();
566
+ for (i = 0; i < sizeof(buf); i++) {
567
+ rng_writeb(RNGCS, RNGE);
568
+ g_assert_true(rng_wait_ready());
569
+ buf[i] = rng_readb(RNGD);
570
+ rng_writeb(RNGCS, 0);
571
+ }
572
+
573
+ g_assert_cmpfloat(calc_monobit_p(buf, sizeof(buf)), >, 0.01);
574
+}
575
+
576
+/*
577
+ * Verifies that the first data byte collected after enabling the RNG satisfies
578
+ * a runs test.
579
+ */
580
+static void test_first_byte_runs(void)
581
+{
582
+ /* Enable, collect one byte, disable. Repeat until we have 100 bits. */
583
+ union {
584
+ unsigned long l[TEST_INPUT_BITS / BITS_PER_LONG];
585
+ uint8_t c[TEST_INPUT_BITS / BITS_PER_BYTE];
586
+ } buf;
587
+ unsigned int i;
588
+
589
+ rng_reset();
590
+ for (i = 0; i < sizeof(buf); i++) {
591
+ rng_writeb(RNGCS, RNGE);
592
+ g_assert_true(rng_wait_ready());
593
+ buf.c[i] = rng_readb(RNGD);
594
+ rng_writeb(RNGCS, 0);
595
+ }
596
+
597
+ g_assert_cmpfloat(calc_runs_p(buf.l, sizeof(buf) * BITS_PER_BYTE), >, 0.01);
598
+}
599
+
600
+int main(int argc, char **argv)
601
+{
602
+ int ret;
603
+
604
+ g_test_init(&argc, &argv, NULL);
605
+ g_test_set_nonfatal_assertions();
606
+
607
+ qtest_add_func("npcm7xx_rng/enable_disable", test_enable_disable);
608
+ qtest_add_func("npcm7xx_rng/rosel", test_rosel);
609
+ qtest_add_func("npcm7xx_rng/continuous/monobit", test_continuous_monobit);
610
+ qtest_add_func("npcm7xx_rng/continuous/runs", test_continuous_runs);
611
+ qtest_add_func("npcm7xx_rng/first_byte/monobit", test_first_byte_monobit);
612
+ qtest_add_func("npcm7xx_rng/first_byte/runs", test_first_byte_runs);
613
+
614
+ qtest_start("-machine npcm750-evb");
615
+ ret = g_test_run();
616
+ qtest_end();
617
+
618
+ return ret;
619
+}
620
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
621
index XXXXXXX..XXXXXXX 100644
622
--- a/hw/misc/meson.build
623
+++ b/hw/misc/meson.build
624
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_MAINSTONE', if_true: files('mst_fpga.c'))
625
softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files(
626
'npcm7xx_clk.c',
627
'npcm7xx_gcr.c',
628
+ 'npcm7xx_rng.c',
629
))
630
softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files(
631
'omap_clk.c',
632
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
633
index XXXXXXX..XXXXXXX 100644
634
--- a/hw/misc/trace-events
635
+++ b/hw/misc/trace-events
636
@@ -XXX,XX +XXX,XX @@ npcm7xx_clk_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " valu
637
npcm7xx_gcr_read(uint64_t offset, uint32_t value) " offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
638
npcm7xx_gcr_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
639
640
+# npcm7xx_rng.c
641
+npcm7xx_rng_read(uint64_t offset, uint64_t value, unsigned size) "offset: 0x%04" PRIx64 " value: 0x%02" PRIx64 " size: %u"
642
+npcm7xx_rng_write(uint64_t offset, uint64_t value, unsigned size) "offset: 0x%04" PRIx64 " value: 0x%02" PRIx64 " size: %u"
643
+
644
# stm32f4xx_syscfg.c
645
stm32f4xx_syscfg_set_irq(int gpio, int line, int level) "Interupt: GPIO: %d, Line: %d; Level: %d"
646
stm32f4xx_pulse_exti(int irq) "Pulse EXTI: %d"
647
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
648
index XXXXXXX..XXXXXXX 100644
649
--- a/tests/qtest/meson.build
650
+++ b/tests/qtest/meson.build
651
@@ -XXX,XX +XXX,XX @@ qtests_sparc64 = \
652
(config_all_devices.has_key('CONFIG_ISA_TESTDEV') ? ['endianness-test'] : []) + \
653
['prom-env-test', 'boot-serial-test']
654
655
-qtests_npcm7xx = ['npcm7xx_timer-test', 'npcm7xx_watchdog_timer-test']
656
+qtests_npcm7xx = \
657
+ ['npcm7xx_rng-test',
658
+ 'npcm7xx_timer-test',
659
+ 'npcm7xx_watchdog_timer-test']
660
qtests_arm = \
661
(config_all_devices.has_key('CONFIG_PFLASH_CFI02') ? ['pflash-cfi02-test'] : []) + \
662
(config_all_devices.has_key('CONFIG_NPCM7XX') ? qtests_npcm7xx : []) + \
160
--
663
--
161
2.7.4
664
2.20.1
162
665
163
666
diff view generated by jsdifflib
New patch
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
2
3
The NPCM730 and NPCM750 chips have a single USB host port shared between
4
a USB 2.0 EHCI host controller and a USB 1.1 OHCI host controller. This
5
adds support for both of them.
6
7
Testing notes:
8
* With -device usb-kbd, qemu will automatically insert a full-speed
9
hub, and the keyboard becomes controlled by the OHCI controller.
10
* With -device usb-kbd,bus=usb-bus.0,port=1, the keyboard is directly
11
attached to the port without any hubs, and the device becomes
12
controlled by the EHCI controller since it's high speed capable.
13
* With -device usb-kbd,bus=usb-bus.0,port=1,usb_version=1, the
14
keyboard is directly attached to the port, but it only advertises
15
itself as full-speed capable, so it becomes controlled by the OHCI
16
controller.
17
18
In all cases, the keyboard device enumerates correctly.
19
20
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
21
Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
22
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
---
25
docs/system/arm/nuvoton.rst | 2 +-
26
hw/usb/hcd-ehci.h | 1 +
27
include/hw/arm/npcm7xx.h | 4 ++++
28
hw/arm/npcm7xx.c | 27 +++++++++++++++++++++++++--
29
hw/usb/hcd-ehci-sysbus.c | 19 +++++++++++++++++++
30
5 files changed, 50 insertions(+), 3 deletions(-)
31
32
diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
33
index XXXXXXX..XXXXXXX 100644
34
--- a/docs/system/arm/nuvoton.rst
35
+++ b/docs/system/arm/nuvoton.rst
36
@@ -XXX,XX +XXX,XX @@ Supported devices
37
* OTP controllers (no protection features)
38
* Flash Interface Unit (FIU; no protection features)
39
* Random Number Generator (RNG)
40
+ * USB host (USBH)
41
42
Missing devices
43
---------------
44
@@ -XXX,XX +XXX,XX @@ Missing devices
45
* eSPI slave interface
46
47
* Ethernet controllers (GMAC and EMC)
48
- * USB host (USBH)
49
* USB device (USBD)
50
* SMBus controller (SMBF)
51
* Peripheral SPI controller (PSPI)
52
diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h
53
index XXXXXXX..XXXXXXX 100644
54
--- a/hw/usb/hcd-ehci.h
55
+++ b/hw/usb/hcd-ehci.h
56
@@ -XXX,XX +XXX,XX @@ struct EHCIPCIState {
57
#define TYPE_PLATFORM_EHCI "platform-ehci-usb"
58
#define TYPE_EXYNOS4210_EHCI "exynos4210-ehci-usb"
59
#define TYPE_AW_H3_EHCI "aw-h3-ehci-usb"
60
+#define TYPE_NPCM7XX_EHCI "npcm7xx-ehci-usb"
61
#define TYPE_TEGRA2_EHCI "tegra2-ehci-usb"
62
#define TYPE_PPC4xx_EHCI "ppc4xx-ehci-usb"
63
#define TYPE_FUSBH200_EHCI "fusbh200-ehci-usb"
64
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
65
index XXXXXXX..XXXXXXX 100644
66
--- a/include/hw/arm/npcm7xx.h
67
+++ b/include/hw/arm/npcm7xx.h
68
@@ -XXX,XX +XXX,XX @@
69
#include "hw/nvram/npcm7xx_otp.h"
70
#include "hw/timer/npcm7xx_timer.h"
71
#include "hw/ssi/npcm7xx_fiu.h"
72
+#include "hw/usb/hcd-ehci.h"
73
+#include "hw/usb/hcd-ohci.h"
74
#include "target/arm/cpu.h"
75
76
#define NPCM7XX_MAX_NUM_CPUS (2)
77
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
78
NPCM7xxOTPState fuse_array;
79
NPCM7xxMCState mc;
80
NPCM7xxRNGState rng;
81
+ EHCISysBusState ehci;
82
+ OHCISysBusState ohci;
83
NPCM7xxFIUState fiu[2];
84
} NPCM7xxState;
85
86
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
87
index XXXXXXX..XXXXXXX 100644
88
--- a/hw/arm/npcm7xx.c
89
+++ b/hw/arm/npcm7xx.c
90
@@ -XXX,XX +XXX,XX @@
91
#define NPCM7XX_MC_BA (0xf0824000)
92
#define NPCM7XX_RNG_BA (0xf000b000)
93
94
+/* USB Host modules */
95
+#define NPCM7XX_EHCI_BA (0xf0806000)
96
+#define NPCM7XX_OHCI_BA (0xf0807000)
97
+
98
/* Internal AHB SRAM */
99
#define NPCM7XX_RAM3_BA (0xc0008000)
100
#define NPCM7XX_RAM3_SZ (4 * KiB)
101
@@ -XXX,XX +XXX,XX @@ enum NPCM7xxInterrupt {
102
NPCM7XX_WDG0_IRQ = 47, /* Timer Module 0 Watchdog */
103
NPCM7XX_WDG1_IRQ, /* Timer Module 1 Watchdog */
104
NPCM7XX_WDG2_IRQ, /* Timer Module 2 Watchdog */
105
+ NPCM7XX_EHCI_IRQ = 61,
106
+ NPCM7XX_OHCI_IRQ = 62,
107
};
108
109
/* Total number of GIC interrupts, including internal Cortex-A9 interrupts. */
110
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
111
object_initialize_child(obj, "tim[*]", &s->tim[i], TYPE_NPCM7XX_TIMER);
112
}
113
114
+ object_initialize_child(obj, "ehci", &s->ehci, TYPE_NPCM7XX_EHCI);
115
+ object_initialize_child(obj, "ohci", &s->ohci, TYPE_SYSBUS_OHCI);
116
+
117
QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_fiu) != ARRAY_SIZE(s->fiu));
118
for (i = 0; i < ARRAY_SIZE(s->fiu); i++) {
119
object_initialize_child(obj, npcm7xx_fiu[i].name, &s->fiu[i],
120
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
121
sysbus_realize(SYS_BUS_DEVICE(&s->rng), &error_abort);
122
sysbus_mmio_map(SYS_BUS_DEVICE(&s->rng), 0, NPCM7XX_RNG_BA);
123
124
+ /* USB Host */
125
+ object_property_set_bool(OBJECT(&s->ehci), "companion-enable", true,
126
+ &error_abort);
127
+ sysbus_realize(SYS_BUS_DEVICE(&s->ehci), &error_abort);
128
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->ehci), 0, NPCM7XX_EHCI_BA);
129
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->ehci), 0,
130
+ npcm7xx_irq(s, NPCM7XX_EHCI_IRQ));
131
+
132
+ object_property_set_str(OBJECT(&s->ohci), "masterbus", "usb-bus.0",
133
+ &error_abort);
134
+ object_property_set_uint(OBJECT(&s->ohci), "num-ports", 1, &error_abort);
135
+ sysbus_realize(SYS_BUS_DEVICE(&s->ohci), &error_abort);
136
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->ohci), 0, NPCM7XX_OHCI_BA);
137
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->ohci), 0,
138
+ npcm7xx_irq(s, NPCM7XX_OHCI_IRQ));
139
+
140
/*
141
* Flash Interface Unit (FIU). Can fail if incorrect number of chip selects
142
* specified, but this is a programming error.
143
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
144
create_unimplemented_device("npcm7xx.mcphy", 0xf05f0000, 64 * KiB);
145
create_unimplemented_device("npcm7xx.gmac1", 0xf0802000, 8 * KiB);
146
create_unimplemented_device("npcm7xx.gmac2", 0xf0804000, 8 * KiB);
147
- create_unimplemented_device("npcm7xx.ehci", 0xf0806000, 4 * KiB);
148
- create_unimplemented_device("npcm7xx.ohci", 0xf0807000, 4 * KiB);
149
create_unimplemented_device("npcm7xx.vcd", 0xf0810000, 64 * KiB);
150
create_unimplemented_device("npcm7xx.ece", 0xf0820000, 8 * KiB);
151
create_unimplemented_device("npcm7xx.vdma", 0xf0822000, 8 * KiB);
152
diff --git a/hw/usb/hcd-ehci-sysbus.c b/hw/usb/hcd-ehci-sysbus.c
153
index XXXXXXX..XXXXXXX 100644
154
--- a/hw/usb/hcd-ehci-sysbus.c
155
+++ b/hw/usb/hcd-ehci-sysbus.c
156
@@ -XXX,XX +XXX,XX @@ static const TypeInfo ehci_aw_h3_type_info = {
157
.class_init = ehci_aw_h3_class_init,
158
};
159
160
+static void ehci_npcm7xx_class_init(ObjectClass *oc, void *data)
161
+{
162
+ SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
163
+ DeviceClass *dc = DEVICE_CLASS(oc);
164
+
165
+ sec->capsbase = 0x0;
166
+ sec->opregbase = 0x10;
167
+ sec->portscbase = 0x44;
168
+ sec->portnr = 1;
169
+ set_bit(DEVICE_CATEGORY_USB, dc->categories);
170
+}
171
+
172
+static const TypeInfo ehci_npcm7xx_type_info = {
173
+ .name = TYPE_NPCM7XX_EHCI,
174
+ .parent = TYPE_SYS_BUS_EHCI,
175
+ .class_init = ehci_npcm7xx_class_init,
176
+};
177
+
178
static void ehci_tegra2_class_init(ObjectClass *oc, void *data)
179
{
180
SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
181
@@ -XXX,XX +XXX,XX @@ static void ehci_sysbus_register_types(void)
182
type_register_static(&ehci_platform_type_info);
183
type_register_static(&ehci_exynos4210_type_info);
184
type_register_static(&ehci_aw_h3_type_info);
185
+ type_register_static(&ehci_npcm7xx_type_info);
186
type_register_static(&ehci_tegra2_type_info);
187
type_register_static(&ehci_ppc4xx_type_info);
188
type_register_static(&ehci_fusbh200_type_info);
189
--
190
2.20.1
191
192
diff view generated by jsdifflib
1
The SysTick timer isn't really part of the NVIC proper;
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
we just modelled it that way back when we couldn't
3
easily have devices that only occupied a small chunk
4
of a memory region. Split it out into its own device.
5
2
3
The NPCM7xx chips have multiple GPIO controllers that are mostly
4
identical except for some minor differences like the reset values of
5
some registers. Each controller controls up to 32 pins.
6
7
Each individual pin is modeled as a pair of unnamed GPIOs -- one for
8
emitting the actual pin state, and one for driving the pin externally.
9
Like the nRF51 GPIO controller, a gpio level may be negative, which
10
means the pin is not driven, or floating.
11
12
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
13
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 1487604965-23220-10-git-send-email-peter.maydell@linaro.org
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
---
16
---
10
hw/timer/Makefile.objs | 1 +
17
docs/system/arm/nuvoton.rst | 2 +-
11
include/hw/arm/armv7m_nvic.h | 10 +-
18
include/hw/arm/npcm7xx.h | 2 +
12
include/hw/timer/armv7m_systick.h | 34 ++++++
19
include/hw/gpio/npcm7xx_gpio.h | 55 +++++
13
hw/intc/armv7m_nvic.c | 160 ++++++-------------------
20
hw/arm/npcm7xx.c | 80 ++++++
14
hw/timer/armv7m_systick.c | 240 ++++++++++++++++++++++++++++++++++++++
21
hw/gpio/npcm7xx_gpio.c | 424 ++++++++++++++++++++++++++++++++
15
hw/timer/trace-events | 6 +
22
tests/qtest/npcm7xx_gpio-test.c | 385 +++++++++++++++++++++++++++++
16
6 files changed, 318 insertions(+), 133 deletions(-)
23
hw/gpio/meson.build | 1 +
17
create mode 100644 include/hw/timer/armv7m_systick.h
24
hw/gpio/trace-events | 7 +
18
create mode 100644 hw/timer/armv7m_systick.c
25
tests/qtest/meson.build | 3 +-
26
9 files changed, 957 insertions(+), 2 deletions(-)
27
create mode 100644 include/hw/gpio/npcm7xx_gpio.h
28
create mode 100644 hw/gpio/npcm7xx_gpio.c
29
create mode 100644 tests/qtest/npcm7xx_gpio-test.c
19
30
20
diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs
31
diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
21
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/timer/Makefile.objs
33
--- a/docs/system/arm/nuvoton.rst
23
+++ b/hw/timer/Makefile.objs
34
+++ b/docs/system/arm/nuvoton.rst
35
@@ -XXX,XX +XXX,XX @@ Supported devices
36
* Flash Interface Unit (FIU; no protection features)
37
* Random Number Generator (RNG)
38
* USB host (USBH)
39
+ * GPIO controller
40
41
Missing devices
42
---------------
43
44
- * GPIO controller
45
* LPC/eSPI host-to-BMC interface, including
46
47
* Keyboard and mouse controller interface (KBCI)
48
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
49
index XXXXXXX..XXXXXXX 100644
50
--- a/include/hw/arm/npcm7xx.h
51
+++ b/include/hw/arm/npcm7xx.h
24
@@ -XXX,XX +XXX,XX @@
52
@@ -XXX,XX +XXX,XX @@
25
common-obj-$(CONFIG_ARM_TIMER) += arm_timer.o
53
26
common-obj-$(CONFIG_ARM_MPTIMER) += arm_mptimer.o
54
#include "hw/boards.h"
27
+common-obj-$(CONFIG_ARM_V7M) += armv7m_systick.o
55
#include "hw/cpu/a9mpcore.h"
28
common-obj-$(CONFIG_A9_GTIMER) += a9gtimer.o
56
+#include "hw/gpio/npcm7xx_gpio.h"
29
common-obj-$(CONFIG_CADENCE) += cadence_ttc.o
57
#include "hw/mem/npcm7xx_mc.h"
30
common-obj-$(CONFIG_DS1338) += ds1338.o
58
#include "hw/misc/npcm7xx_clk.h"
31
diff --git a/include/hw/arm/armv7m_nvic.h b/include/hw/arm/armv7m_nvic.h
59
#include "hw/misc/npcm7xx_gcr.h"
32
index XXXXXXX..XXXXXXX 100644
60
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
33
--- a/include/hw/arm/armv7m_nvic.h
61
NPCM7xxOTPState fuse_array;
34
+++ b/include/hw/arm/armv7m_nvic.h
62
NPCM7xxMCState mc;
35
@@ -XXX,XX +XXX,XX @@
63
NPCM7xxRNGState rng;
36
64
+ NPCM7xxGPIOState gpio[8];
37
#include "target/arm/cpu.h"
65
EHCISysBusState ehci;
38
#include "hw/sysbus.h"
66
OHCISysBusState ohci;
39
+#include "hw/timer/armv7m_systick.h"
67
NPCM7xxFIUState fiu[2];
40
68
diff --git a/include/hw/gpio/npcm7xx_gpio.h b/include/hw/gpio/npcm7xx_gpio.h
41
#define TYPE_NVIC "armv7m_nvic"
42
43
@@ -XXX,XX +XXX,XX @@ typedef struct NVICState {
44
unsigned int vectpending; /* highest prio pending enabled exception */
45
int exception_prio; /* group prio of the highest prio active exception */
46
47
- struct {
48
- uint32_t control;
49
- uint32_t reload;
50
- int64_t tick;
51
- QEMUTimer *timer;
52
- } systick;
53
-
54
MemoryRegion sysregmem;
55
MemoryRegion container;
56
57
uint32_t num_irq;
58
qemu_irq excpout;
59
qemu_irq sysresetreq;
60
+
61
+ SysTickState systick;
62
} NVICState;
63
64
#endif
65
diff --git a/include/hw/timer/armv7m_systick.h b/include/hw/timer/armv7m_systick.h
66
new file mode 100644
69
new file mode 100644
67
index XXXXXXX..XXXXXXX
70
index XXXXXXX..XXXXXXX
68
--- /dev/null
71
--- /dev/null
69
+++ b/include/hw/timer/armv7m_systick.h
72
+++ b/include/hw/gpio/npcm7xx_gpio.h
70
@@ -XXX,XX +XXX,XX @@
73
@@ -XXX,XX +XXX,XX @@
71
+/*
74
+/*
72
+ * ARMv7M SysTick timer
75
+ * Nuvoton NPCM7xx General Purpose Input / Output (GPIO)
73
+ *
76
+ *
74
+ * Copyright (c) 2006-2007 CodeSourcery.
77
+ * Copyright 2020 Google LLC
75
+ * Written by Paul Brook
76
+ * Copyright (c) 2017 Linaro Ltd
77
+ * Written by Peter Maydell
78
+ *
78
+ *
79
+ * This code is licensed under the GPL (version 2 or later).
79
+ * This program is free software; you can redistribute it and/or
80
+ * modify it under the terms of the GNU General Public License
81
+ * version 2 as published by the Free Software Foundation.
82
+ *
83
+ * This program is distributed in the hope that it will be useful,
84
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
85
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
86
+ * GNU General Public License for more details.
80
+ */
87
+ */
81
+
88
+#ifndef NPCM7XX_GPIO_H
82
+#ifndef HW_TIMER_ARMV7M_SYSTICK_H
89
+#define NPCM7XX_GPIO_H
83
+#define HW_TIMER_ARMV7M_SYSTICK_H
90
+
84
+
91
+#include "exec/memory.h"
85
+#include "hw/sysbus.h"
92
+#include "hw/sysbus.h"
86
+
93
+
87
+#define TYPE_SYSTICK "armv7m_systick"
94
+/* Number of pins managed by each controller. */
88
+
95
+#define NPCM7XX_GPIO_NR_PINS (32)
89
+#define SYSTICK(obj) OBJECT_CHECK(SysTickState, (obj), TYPE_SYSTICK)
96
+
90
+
97
+/*
91
+typedef struct SysTickState {
98
+ * Number of registers in our device state structure. Don't change this without
92
+ /*< private >*/
99
+ * incrementing the version_id in the vmstate.
93
+ SysBusDevice parent_obj;
100
+ */
94
+ /*< public >*/
101
+#define NPCM7XX_GPIO_NR_REGS (0x80 / sizeof(uint32_t))
95
+
102
+
96
+ uint32_t control;
103
+typedef struct NPCM7xxGPIOState {
97
+ uint32_t reload;
104
+ SysBusDevice parent;
98
+ int64_t tick;
105
+
99
+ QEMUTimer *timer;
106
+ /* Properties to be defined by the SoC */
100
+ MemoryRegion iomem;
107
+ uint32_t reset_pu;
108
+ uint32_t reset_pd;
109
+ uint32_t reset_osrc;
110
+ uint32_t reset_odsc;
111
+
112
+ MemoryRegion mmio;
113
+
101
+ qemu_irq irq;
114
+ qemu_irq irq;
102
+} SysTickState;
115
+ qemu_irq output[NPCM7XX_GPIO_NR_PINS];
103
+
116
+
104
+#endif
117
+ uint32_t pin_level;
105
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
118
+ uint32_t ext_level;
119
+ uint32_t ext_driven;
120
+
121
+ uint32_t regs[NPCM7XX_GPIO_NR_REGS];
122
+} NPCM7xxGPIOState;
123
+
124
+#define TYPE_NPCM7XX_GPIO "npcm7xx-gpio"
125
+#define NPCM7XX_GPIO(obj) \
126
+ OBJECT_CHECK(NPCM7xxGPIOState, (obj), TYPE_NPCM7XX_GPIO)
127
+
128
+#endif /* NPCM7XX_GPIO_H */
129
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
106
index XXXXXXX..XXXXXXX 100644
130
index XXXXXXX..XXXXXXX 100644
107
--- a/hw/intc/armv7m_nvic.c
131
--- a/hw/arm/npcm7xx.c
108
+++ b/hw/intc/armv7m_nvic.c
132
+++ b/hw/arm/npcm7xx.c
109
@@ -XXX,XX +XXX,XX @@ static const uint8_t nvic_id[] = {
133
@@ -XXX,XX +XXX,XX @@ enum NPCM7xxInterrupt {
110
0x00, 0xb0, 0x1b, 0x00, 0x0d, 0xe0, 0x05, 0xb1
134
NPCM7XX_WDG2_IRQ, /* Timer Module 2 Watchdog */
135
NPCM7XX_EHCI_IRQ = 61,
136
NPCM7XX_OHCI_IRQ = 62,
137
+ NPCM7XX_GPIO0_IRQ = 116,
138
+ NPCM7XX_GPIO1_IRQ,
139
+ NPCM7XX_GPIO2_IRQ,
140
+ NPCM7XX_GPIO3_IRQ,
141
+ NPCM7XX_GPIO4_IRQ,
142
+ NPCM7XX_GPIO5_IRQ,
143
+ NPCM7XX_GPIO6_IRQ,
144
+ NPCM7XX_GPIO7_IRQ,
111
};
145
};
112
146
113
-/* qemu timers run at 1GHz. We want something closer to 1MHz. */
147
/* Total number of GIC interrupts, including internal Cortex-A9 interrupts. */
114
-#define SYSTICK_SCALE 1000ULL
148
@@ -XXX,XX +XXX,XX @@ static const hwaddr npcm7xx_fiu3_flash_addr[] = {
115
-
149
0xb8000000, /* CS3 */
116
-#define SYSTICK_ENABLE (1 << 0)
150
};
117
-#define SYSTICK_TICKINT (1 << 1)
151
118
-#define SYSTICK_CLKSOURCE (1 << 2)
152
+static const struct {
119
-#define SYSTICK_COUNTFLAG (1 << 16)
153
+ hwaddr regs_addr;
120
-
154
+ uint32_t unconnected_pins;
121
-int system_clock_scale;
155
+ uint32_t reset_pu;
122
-
156
+ uint32_t reset_pd;
123
-/* Conversion factor from qemu timer to SysTick frequencies. */
157
+ uint32_t reset_osrc;
124
-static inline int64_t systick_scale(NVICState *s)
158
+ uint32_t reset_odsc;
125
-{
159
+} npcm7xx_gpio[] = {
126
- if (s->systick.control & SYSTICK_CLKSOURCE)
160
+ {
127
- return system_clock_scale;
161
+ .regs_addr = 0xf0010000,
128
- else
162
+ .reset_pu = 0xff03ffff,
129
- return 1000;
163
+ .reset_pd = 0x00fc0000,
130
-}
164
+ }, {
131
-
165
+ .regs_addr = 0xf0011000,
132
-static void systick_reload(NVICState *s, int reset)
166
+ .unconnected_pins = 0x0000001e,
133
-{
167
+ .reset_pu = 0xfefffe07,
134
- /* The Cortex-M3 Devices Generic User Guide says that "When the
168
+ .reset_pd = 0x010001e0,
135
- * ENABLE bit is set to 1, the counter loads the RELOAD value from the
169
+ }, {
136
- * SYST RVR register and then counts down". So, we need to check the
170
+ .regs_addr = 0xf0012000,
137
- * ENABLE bit before reloading the value.
171
+ .reset_pu = 0x780fffff,
138
- */
172
+ .reset_pd = 0x07f00000,
139
- if ((s->systick.control & SYSTICK_ENABLE) == 0) {
173
+ .reset_odsc = 0x00700000,
140
- return;
174
+ }, {
141
- }
175
+ .regs_addr = 0xf0013000,
142
-
176
+ .reset_pu = 0x00fc0000,
143
- if (reset)
177
+ .reset_pd = 0xff000000,
144
- s->systick.tick = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
178
+ }, {
145
- s->systick.tick += (s->systick.reload + 1) * systick_scale(s);
179
+ .regs_addr = 0xf0014000,
146
- timer_mod(s->systick.timer, s->systick.tick);
180
+ .reset_pu = 0xffffffff,
147
-}
181
+ }, {
148
-
182
+ .regs_addr = 0xf0015000,
149
-static void systick_timer_tick(void * opaque)
183
+ .reset_pu = 0xbf83f801,
150
-{
184
+ .reset_pd = 0x007c0000,
151
- NVICState *s = (NVICState *)opaque;
185
+ .reset_osrc = 0x000000f1,
152
- s->systick.control |= SYSTICK_COUNTFLAG;
186
+ .reset_odsc = 0x3f9f80f1,
153
- if (s->systick.control & SYSTICK_TICKINT) {
187
+ }, {
154
- /* Trigger the interrupt. */
188
+ .regs_addr = 0xf0016000,
155
- armv7m_nvic_set_pending(s, ARMV7M_EXCP_SYSTICK);
189
+ .reset_pu = 0xfc00f801,
156
- }
190
+ .reset_pd = 0x000007fe,
157
- if (s->systick.reload == 0) {
191
+ .reset_odsc = 0x00000800,
158
- s->systick.control &= ~SYSTICK_ENABLE;
192
+ }, {
159
- } else {
193
+ .regs_addr = 0xf0017000,
160
- systick_reload(s, 0);
194
+ .unconnected_pins = 0xffffff00,
161
- }
195
+ .reset_pu = 0x0000007f,
162
-}
196
+ .reset_osrc = 0x0000007f,
163
-
197
+ .reset_odsc = 0x0000007f,
164
-static void systick_reset(NVICState *s)
198
+ },
165
-{
199
+};
166
- s->systick.control = 0;
200
+
167
- s->systick.reload = 0;
201
static const struct {
168
- s->systick.tick = 0;
202
const char *name;
169
- timer_del(s->systick.timer);
203
hwaddr regs_addr;
170
-}
204
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
171
-
205
object_initialize_child(obj, "tim[*]", &s->tim[i], TYPE_NPCM7XX_TIMER);
172
static int nvic_pending_prio(NVICState *s)
173
{
174
/* return the priority of the current pending interrupt,
175
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset)
176
switch (offset) {
177
case 4: /* Interrupt Control Type. */
178
return ((s->num_irq - NVIC_FIRST_IRQ) / 32) - 1;
179
- case 0x10: /* SysTick Control and Status. */
180
- val = s->systick.control;
181
- s->systick.control &= ~SYSTICK_COUNTFLAG;
182
- return val;
183
- case 0x14: /* SysTick Reload Value. */
184
- return s->systick.reload;
185
- case 0x18: /* SysTick Current Value. */
186
- {
187
- int64_t t;
188
- if ((s->systick.control & SYSTICK_ENABLE) == 0)
189
- return 0;
190
- t = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
191
- if (t >= s->systick.tick)
192
- return 0;
193
- val = ((s->systick.tick - (t + 1)) / systick_scale(s)) + 1;
194
- /* The interrupt in triggered when the timer reaches zero.
195
- However the counter is not reloaded until the next clock
196
- tick. This is a hack to return zero during the first tick. */
197
- if (val > s->systick.reload)
198
- val = 0;
199
- return val;
200
- }
201
- case 0x1c: /* SysTick Calibration Value. */
202
- return 10000;
203
case 0xd00: /* CPUID Base. */
204
return cpu->midr;
205
case 0xd04: /* Interrupt Control State. */
206
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset)
207
static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value)
208
{
209
ARMCPU *cpu = s->cpu;
210
- uint32_t oldval;
211
+
212
switch (offset) {
213
- case 0x10: /* SysTick Control and Status. */
214
- oldval = s->systick.control;
215
- s->systick.control &= 0xfffffff8;
216
- s->systick.control |= value & 7;
217
- if ((oldval ^ value) & SYSTICK_ENABLE) {
218
- int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
219
- if (value & SYSTICK_ENABLE) {
220
- if (s->systick.tick) {
221
- s->systick.tick += now;
222
- timer_mod(s->systick.timer, s->systick.tick);
223
- } else {
224
- systick_reload(s, 1);
225
- }
226
- } else {
227
- timer_del(s->systick.timer);
228
- s->systick.tick -= now;
229
- if (s->systick.tick < 0)
230
- s->systick.tick = 0;
231
- }
232
- } else if ((oldval ^ value) & SYSTICK_CLKSOURCE) {
233
- /* This is a hack. Force the timer to be reloaded
234
- when the reference clock is changed. */
235
- systick_reload(s, 1);
236
- }
237
- break;
238
- case 0x14: /* SysTick Reload Value. */
239
- s->systick.reload = value;
240
- break;
241
- case 0x18: /* SysTick Current Value. Writes reload the timer. */
242
- systick_reload(s, 1);
243
- s->systick.control &= ~SYSTICK_COUNTFLAG;
244
- break;
245
case 0xd04: /* Interrupt Control State. */
246
if (value & (1 << 31)) {
247
armv7m_nvic_set_pending(s, ARMV7M_EXCP_NMI);
248
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_VecInfo = {
249
250
static const VMStateDescription vmstate_nvic = {
251
.name = "armv7m_nvic",
252
- .version_id = 3,
253
- .minimum_version_id = 3,
254
+ .version_id = 4,
255
+ .minimum_version_id = 4,
256
.post_load = &nvic_post_load,
257
.fields = (VMStateField[]) {
258
VMSTATE_STRUCT_ARRAY(vectors, NVICState, NVIC_MAX_VECTORS, 1,
259
vmstate_VecInfo, VecInfo),
260
- VMSTATE_UINT32(systick.control, NVICState),
261
- VMSTATE_UINT32(systick.reload, NVICState),
262
- VMSTATE_INT64(systick.tick, NVICState),
263
- VMSTATE_TIMER_PTR(systick.timer, NVICState),
264
VMSTATE_UINT32(prigroup, NVICState),
265
VMSTATE_END_OF_LIST()
266
}
206
}
267
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_reset(DeviceState *dev)
207
268
208
+ for (i = 0; i < ARRAY_SIZE(s->gpio); i++) {
269
s->exception_prio = NVIC_NOEXC_PRIO;
209
+ object_initialize_child(obj, "gpio[*]", &s->gpio[i], TYPE_NPCM7XX_GPIO);
270
s->vectpending = 0;
271
+}
272
273
- systick_reset(s);
274
+static void nvic_systick_trigger(void *opaque, int n, int level)
275
+{
276
+ NVICState *s = opaque;
277
+
278
+ if (level) {
279
+ /* SysTick just asked us to pend its exception.
280
+ * (This is different from an external interrupt line's
281
+ * behaviour.)
282
+ */
283
+ armv7m_nvic_set_pending(s, ARMV7M_EXCP_SYSTICK);
284
+ }
210
+ }
285
}
211
+
286
212
object_initialize_child(obj, "ehci", &s->ehci, TYPE_NPCM7XX_EHCI);
287
static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
213
object_initialize_child(obj, "ohci", &s->ohci, TYPE_SYSBUS_OHCI);
288
{
214
289
NVICState *s = NVIC(dev);
215
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
290
+ SysBusDevice *systick_sbd;
216
sysbus_realize(SYS_BUS_DEVICE(&s->rng), &error_abort);
291
+ Error *err = NULL;
217
sysbus_mmio_map(SYS_BUS_DEVICE(&s->rng), 0, NPCM7XX_RNG_BA);
292
218
293
s->cpu = ARM_CPU(qemu_get_cpu(0));
219
+ /* GPIO modules. Cannot fail. */
294
assert(s->cpu);
220
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_gpio) != ARRAY_SIZE(s->gpio));
295
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
221
+ for (i = 0; i < ARRAY_SIZE(s->gpio); i++) {
296
/* include space for internal exception vectors */
222
+ Object *obj = OBJECT(&s->gpio[i]);
297
s->num_irq += NVIC_FIRST_IRQ;
223
+
298
224
+ object_property_set_uint(obj, "reset-pullup",
299
+ object_property_set_bool(OBJECT(&s->systick), true, "realized", &err);
225
+ npcm7xx_gpio[i].reset_pu, &error_abort);
300
+ if (err != NULL) {
226
+ object_property_set_uint(obj, "reset-pulldown",
301
+ error_propagate(errp, err);
227
+ npcm7xx_gpio[i].reset_pd, &error_abort);
302
+ return;
228
+ object_property_set_uint(obj, "reset-osrc",
229
+ npcm7xx_gpio[i].reset_osrc, &error_abort);
230
+ object_property_set_uint(obj, "reset-odsc",
231
+ npcm7xx_gpio[i].reset_odsc, &error_abort);
232
+ sysbus_realize(SYS_BUS_DEVICE(obj), &error_abort);
233
+ sysbus_mmio_map(SYS_BUS_DEVICE(obj), 0, npcm7xx_gpio[i].regs_addr);
234
+ sysbus_connect_irq(SYS_BUS_DEVICE(obj), 0,
235
+ npcm7xx_irq(s, NPCM7XX_GPIO0_IRQ + i));
303
+ }
236
+ }
304
+ systick_sbd = SYS_BUS_DEVICE(&s->systick);
237
+
305
+ sysbus_connect_irq(systick_sbd, 0,
238
/* USB Host */
306
+ qdev_get_gpio_in_named(dev, "systick-trigger", 0));
239
object_property_set_bool(OBJECT(&s->ehci), "companion-enable", true,
307
+
240
&error_abort);
308
/* The NVIC and System Control Space (SCS) starts at 0xe000e000
241
diff --git a/hw/gpio/npcm7xx_gpio.c b/hw/gpio/npcm7xx_gpio.c
309
* and looks like this:
310
* 0x004 - ICTR
311
- * 0x010 - 0x1c - systick
312
+ * 0x010 - 0xff - systick
313
* 0x100..0x7ec - NVIC
314
* 0x7f0..0xcff - Reserved
315
* 0xd00..0xd3c - SCS registers
316
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
317
memory_region_init_io(&s->sysregmem, OBJECT(s), &nvic_sysreg_ops, s,
318
"nvic_sysregs", 0x1000);
319
memory_region_add_subregion(&s->container, 0, &s->sysregmem);
320
+ memory_region_add_subregion_overlap(&s->container, 0x10,
321
+ sysbus_mmio_get_region(systick_sbd, 0),
322
+ 1);
323
324
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->container);
325
-
326
- s->systick.timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, systick_timer_tick, s);
327
}
328
329
static void armv7m_nvic_instance_init(Object *obj)
330
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_instance_init(Object *obj)
331
NVICState *nvic = NVIC(obj);
332
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
333
334
+ object_initialize(&nvic->systick, sizeof(nvic->systick), TYPE_SYSTICK);
335
+ qdev_set_parent_bus(DEVICE(&nvic->systick), sysbus_get_default());
336
+
337
sysbus_init_irq(sbd, &nvic->excpout);
338
qdev_init_gpio_out_named(dev, &nvic->sysresetreq, "SYSRESETREQ", 1);
339
+ qdev_init_gpio_in_named(dev, nvic_systick_trigger, "systick-trigger", 1);
340
}
341
342
static void armv7m_nvic_class_init(ObjectClass *klass, void *data)
343
diff --git a/hw/timer/armv7m_systick.c b/hw/timer/armv7m_systick.c
344
new file mode 100644
242
new file mode 100644
345
index XXXXXXX..XXXXXXX
243
index XXXXXXX..XXXXXXX
346
--- /dev/null
244
--- /dev/null
347
+++ b/hw/timer/armv7m_systick.c
245
+++ b/hw/gpio/npcm7xx_gpio.c
348
@@ -XXX,XX +XXX,XX @@
246
@@ -XXX,XX +XXX,XX @@
349
+/*
247
+/*
350
+ * ARMv7M SysTick timer
248
+ * Nuvoton NPCM7xx General Purpose Input / Output (GPIO)
351
+ *
249
+ *
352
+ * Copyright (c) 2006-2007 CodeSourcery.
250
+ * Copyright 2020 Google LLC
353
+ * Written by Paul Brook
354
+ * Copyright (c) 2017 Linaro Ltd
355
+ * Written by Peter Maydell
356
+ *
251
+ *
357
+ * This code is licensed under the GPL (version 2 or later).
252
+ * This program is free software; you can redistribute it and/or
253
+ * modify it under the terms of the GNU General Public License
254
+ * version 2 as published by the Free Software Foundation.
255
+ *
256
+ * This program is distributed in the hope that it will be useful,
257
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
258
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
259
+ * GNU General Public License for more details.
358
+ */
260
+ */
359
+
261
+
360
+#include "qemu/osdep.h"
262
+#include "qemu/osdep.h"
361
+#include "hw/timer/armv7m_systick.h"
263
+
362
+#include "qemu-common.h"
264
+#include "hw/gpio/npcm7xx_gpio.h"
363
+#include "hw/sysbus.h"
265
+#include "hw/irq.h"
364
+#include "qemu/timer.h"
266
+#include "hw/qdev-properties.h"
267
+#include "migration/vmstate.h"
268
+#include "qapi/error.h"
365
+#include "qemu/log.h"
269
+#include "qemu/log.h"
270
+#include "qemu/module.h"
271
+#include "qemu/units.h"
366
+#include "trace.h"
272
+#include "trace.h"
367
+
273
+
368
+/* qemu timers run at 1GHz. We want something closer to 1MHz. */
274
+/* 32-bit register indices. */
369
+#define SYSTICK_SCALE 1000ULL
275
+enum NPCM7xxGPIORegister {
370
+
276
+ NPCM7XX_GPIO_TLOCK1,
371
+#define SYSTICK_ENABLE (1 << 0)
277
+ NPCM7XX_GPIO_DIN,
372
+#define SYSTICK_TICKINT (1 << 1)
278
+ NPCM7XX_GPIO_POL,
373
+#define SYSTICK_CLKSOURCE (1 << 2)
279
+ NPCM7XX_GPIO_DOUT,
374
+#define SYSTICK_COUNTFLAG (1 << 16)
280
+ NPCM7XX_GPIO_OE,
375
+
281
+ NPCM7XX_GPIO_OTYP,
376
+int system_clock_scale;
282
+ NPCM7XX_GPIO_MP,
377
+
283
+ NPCM7XX_GPIO_PU,
378
+/* Conversion factor from qemu timer to SysTick frequencies. */
284
+ NPCM7XX_GPIO_PD,
379
+static inline int64_t systick_scale(SysTickState *s)
285
+ NPCM7XX_GPIO_DBNC,
380
+{
286
+ NPCM7XX_GPIO_EVTYP,
381
+ if (s->control & SYSTICK_CLKSOURCE) {
287
+ NPCM7XX_GPIO_EVBE,
382
+ return system_clock_scale;
288
+ NPCM7XX_GPIO_OBL0,
383
+ } else {
289
+ NPCM7XX_GPIO_OBL1,
384
+ return 1000;
290
+ NPCM7XX_GPIO_OBL2,
291
+ NPCM7XX_GPIO_OBL3,
292
+ NPCM7XX_GPIO_EVEN,
293
+ NPCM7XX_GPIO_EVENS,
294
+ NPCM7XX_GPIO_EVENC,
295
+ NPCM7XX_GPIO_EVST,
296
+ NPCM7XX_GPIO_SPLCK,
297
+ NPCM7XX_GPIO_MPLCK,
298
+ NPCM7XX_GPIO_IEM,
299
+ NPCM7XX_GPIO_OSRC,
300
+ NPCM7XX_GPIO_ODSC,
301
+ NPCM7XX_GPIO_DOS = 0x68 / sizeof(uint32_t),
302
+ NPCM7XX_GPIO_DOC,
303
+ NPCM7XX_GPIO_OES,
304
+ NPCM7XX_GPIO_OEC,
305
+ NPCM7XX_GPIO_TLOCK2 = 0x7c / sizeof(uint32_t),
306
+ NPCM7XX_GPIO_REGS_END,
307
+};
308
+
309
+#define NPCM7XX_GPIO_REGS_SIZE (4 * KiB)
310
+
311
+#define NPCM7XX_GPIO_LOCK_MAGIC1 (0xc0defa73)
312
+#define NPCM7XX_GPIO_LOCK_MAGIC2 (0xc0de1248)
313
+
314
+static void npcm7xx_gpio_update_events(NPCM7xxGPIOState *s, uint32_t din_diff)
315
+{
316
+ uint32_t din_new = s->regs[NPCM7XX_GPIO_DIN];
317
+
318
+ /* Trigger on high level */
319
+ s->regs[NPCM7XX_GPIO_EVST] |= din_new & ~s->regs[NPCM7XX_GPIO_EVTYP];
320
+ /* Trigger on both edges */
321
+ s->regs[NPCM7XX_GPIO_EVST] |= (din_diff & s->regs[NPCM7XX_GPIO_EVTYP]
322
+ & s->regs[NPCM7XX_GPIO_EVBE]);
323
+ /* Trigger on rising edge */
324
+ s->regs[NPCM7XX_GPIO_EVST] |= (din_diff & din_new
325
+ & s->regs[NPCM7XX_GPIO_EVTYP]);
326
+
327
+ trace_npcm7xx_gpio_update_events(DEVICE(s)->canonical_path,
328
+ s->regs[NPCM7XX_GPIO_EVST],
329
+ s->regs[NPCM7XX_GPIO_EVEN]);
330
+ qemu_set_irq(s->irq, !!(s->regs[NPCM7XX_GPIO_EVST]
331
+ & s->regs[NPCM7XX_GPIO_EVEN]));
332
+}
333
+
334
+static void npcm7xx_gpio_update_pins(NPCM7xxGPIOState *s, uint32_t diff)
335
+{
336
+ uint32_t drive_en;
337
+ uint32_t drive_lvl;
338
+ uint32_t not_driven;
339
+ uint32_t undefined;
340
+ uint32_t pin_diff;
341
+ uint32_t din_old;
342
+
343
+ /* Calculate level of each pin driven by GPIO controller. */
344
+ drive_lvl = s->regs[NPCM7XX_GPIO_DOUT] ^ s->regs[NPCM7XX_GPIO_POL];
345
+ /* If OTYP=1, only drive low (open drain) */
346
+ drive_en = s->regs[NPCM7XX_GPIO_OE] & ~(s->regs[NPCM7XX_GPIO_OTYP]
347
+ & drive_lvl);
348
+ /*
349
+ * If a pin is driven to opposite levels by the GPIO controller and the
350
+ * external driver, the result is undefined.
351
+ */
352
+ undefined = drive_en & s->ext_driven & (drive_lvl ^ s->ext_level);
353
+ if (undefined) {
354
+ qemu_log_mask(LOG_GUEST_ERROR,
355
+ "%s: pins have multiple drivers: 0x%" PRIx32 "\n",
356
+ DEVICE(s)->canonical_path, undefined);
385
+ }
357
+ }
386
+}
358
+
387
+
359
+ not_driven = ~(drive_en | s->ext_driven);
388
+static void systick_reload(SysTickState *s, int reset)
360
+ pin_diff = s->pin_level;
389
+{
361
+
390
+ /* The Cortex-M3 Devices Generic User Guide says that "When the
362
+ /* Set pins to externally driven level. */
391
+ * ENABLE bit is set to 1, the counter loads the RELOAD value from the
363
+ s->pin_level = s->ext_level & s->ext_driven;
392
+ * SYST RVR register and then counts down". So, we need to check the
364
+ /* Set internally driven pins, ignoring any conflicts. */
393
+ * ENABLE bit before reloading the value.
365
+ s->pin_level |= drive_lvl & drive_en;
394
+ */
366
+ /* Pull up undriven pins with internal pull-up enabled. */
395
+ trace_systick_reload();
367
+ s->pin_level |= not_driven & s->regs[NPCM7XX_GPIO_PU];
396
+
368
+ /* Pins not driven, pulled up or pulled down are undefined */
397
+ if ((s->control & SYSTICK_ENABLE) == 0) {
369
+ undefined |= not_driven & ~(s->regs[NPCM7XX_GPIO_PU]
370
+ | s->regs[NPCM7XX_GPIO_PD]);
371
+
372
+ /* If any pins changed state, update the outgoing GPIOs. */
373
+ pin_diff ^= s->pin_level;
374
+ pin_diff |= undefined & diff;
375
+ if (pin_diff) {
376
+ int i;
377
+
378
+ for (i = 0; i < NPCM7XX_GPIO_NR_PINS; i++) {
379
+ uint32_t mask = BIT(i);
380
+ if (pin_diff & mask) {
381
+ int level = (undefined & mask) ? -1 : !!(s->pin_level & mask);
382
+ trace_npcm7xx_gpio_set_output(DEVICE(s)->canonical_path,
383
+ i, level);
384
+ qemu_set_irq(s->output[i], level);
385
+ }
386
+ }
387
+ }
388
+
389
+ /* Calculate new value of DIN after masking and polarity setting. */
390
+ din_old = s->regs[NPCM7XX_GPIO_DIN];
391
+ s->regs[NPCM7XX_GPIO_DIN] = ((s->pin_level & s->regs[NPCM7XX_GPIO_IEM])
392
+ ^ s->regs[NPCM7XX_GPIO_POL]);
393
+
394
+ /* See if any new events triggered because of all this. */
395
+ npcm7xx_gpio_update_events(s, din_old ^ s->regs[NPCM7XX_GPIO_DIN]);
396
+}
397
+
398
+static bool npcm7xx_gpio_is_locked(NPCM7xxGPIOState *s)
399
+{
400
+ return s->regs[NPCM7XX_GPIO_TLOCK1] == 1;
401
+}
402
+
403
+static uint64_t npcm7xx_gpio_regs_read(void *opaque, hwaddr addr,
404
+ unsigned int size)
405
+{
406
+ hwaddr reg = addr / sizeof(uint32_t);
407
+ NPCM7xxGPIOState *s = opaque;
408
+ uint64_t value = 0;
409
+
410
+ switch (reg) {
411
+ case NPCM7XX_GPIO_TLOCK1 ... NPCM7XX_GPIO_EVEN:
412
+ case NPCM7XX_GPIO_EVST ... NPCM7XX_GPIO_ODSC:
413
+ value = s->regs[reg];
414
+ break;
415
+
416
+ case NPCM7XX_GPIO_EVENS ... NPCM7XX_GPIO_EVENC:
417
+ case NPCM7XX_GPIO_DOS ... NPCM7XX_GPIO_TLOCK2:
418
+ qemu_log_mask(LOG_GUEST_ERROR,
419
+ "%s: read from write-only register 0x%" HWADDR_PRIx "\n",
420
+ DEVICE(s)->canonical_path, addr);
421
+ break;
422
+
423
+ default:
424
+ qemu_log_mask(LOG_GUEST_ERROR,
425
+ "%s: read from invalid offset 0x%" HWADDR_PRIx "\n",
426
+ DEVICE(s)->canonical_path, addr);
427
+ break;
428
+ }
429
+
430
+ trace_npcm7xx_gpio_read(DEVICE(s)->canonical_path, addr, value);
431
+
432
+ return value;
433
+}
434
+
435
+static void npcm7xx_gpio_regs_write(void *opaque, hwaddr addr, uint64_t v,
436
+ unsigned int size)
437
+{
438
+ hwaddr reg = addr / sizeof(uint32_t);
439
+ NPCM7xxGPIOState *s = opaque;
440
+ uint32_t value = v;
441
+ uint32_t diff;
442
+
443
+ trace_npcm7xx_gpio_write(DEVICE(s)->canonical_path, addr, v);
444
+
445
+ if (npcm7xx_gpio_is_locked(s)) {
446
+ switch (reg) {
447
+ case NPCM7XX_GPIO_TLOCK1:
448
+ if (s->regs[NPCM7XX_GPIO_TLOCK2] == NPCM7XX_GPIO_LOCK_MAGIC2 &&
449
+ value == NPCM7XX_GPIO_LOCK_MAGIC1) {
450
+ s->regs[NPCM7XX_GPIO_TLOCK1] = 0;
451
+ s->regs[NPCM7XX_GPIO_TLOCK2] = 0;
452
+ }
453
+ break;
454
+
455
+ case NPCM7XX_GPIO_TLOCK2:
456
+ s->regs[reg] = value;
457
+ break;
458
+
459
+ default:
460
+ qemu_log_mask(LOG_GUEST_ERROR,
461
+ "%s: write to locked register @ 0x%" HWADDR_PRIx "\n",
462
+ DEVICE(s)->canonical_path, addr);
463
+ break;
464
+ }
465
+
398
+ return;
466
+ return;
399
+ }
467
+ }
400
+
468
+
401
+ if (reset) {
469
+ diff = s->regs[reg] ^ value;
402
+ s->tick = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
470
+
403
+ }
471
+ switch (reg) {
404
+ s->tick += (s->reload + 1) * systick_scale(s);
472
+ case NPCM7XX_GPIO_TLOCK1:
405
+ timer_mod(s->timer, s->tick);
473
+ case NPCM7XX_GPIO_TLOCK2:
406
+}
474
+ s->regs[NPCM7XX_GPIO_TLOCK1] = 1;
407
+
475
+ s->regs[NPCM7XX_GPIO_TLOCK2] = 0;
408
+static void systick_timer_tick(void *opaque)
476
+ break;
409
+{
477
+
410
+ SysTickState *s = (SysTickState *)opaque;
478
+ case NPCM7XX_GPIO_DIN:
411
+
412
+ trace_systick_timer_tick();
413
+
414
+ s->control |= SYSTICK_COUNTFLAG;
415
+ if (s->control & SYSTICK_TICKINT) {
416
+ /* Tell the NVIC to pend the SysTick exception */
417
+ qemu_irq_pulse(s->irq);
418
+ }
419
+ if (s->reload == 0) {
420
+ s->control &= ~SYSTICK_ENABLE;
421
+ } else {
422
+ systick_reload(s, 0);
423
+ }
424
+}
425
+
426
+static uint64_t systick_read(void *opaque, hwaddr addr, unsigned size)
427
+{
428
+ SysTickState *s = opaque;
429
+ uint32_t val;
430
+
431
+ switch (addr) {
432
+ case 0x0: /* SysTick Control and Status. */
433
+ val = s->control;
434
+ s->control &= ~SYSTICK_COUNTFLAG;
435
+ break;
436
+ case 0x4: /* SysTick Reload Value. */
437
+ val = s->reload;
438
+ break;
439
+ case 0x8: /* SysTick Current Value. */
440
+ {
441
+ int64_t t;
442
+
443
+ if ((s->control & SYSTICK_ENABLE) == 0) {
444
+ val = 0;
445
+ break;
446
+ }
447
+ t = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
448
+ if (t >= s->tick) {
449
+ val = 0;
450
+ break;
451
+ }
452
+ val = ((s->tick - (t + 1)) / systick_scale(s)) + 1;
453
+ /* The interrupt in triggered when the timer reaches zero.
454
+ However the counter is not reloaded until the next clock
455
+ tick. This is a hack to return zero during the first tick. */
456
+ if (val > s->reload) {
457
+ val = 0;
458
+ }
459
+ break;
460
+ }
461
+ case 0xc: /* SysTick Calibration Value. */
462
+ val = 10000;
463
+ break;
464
+ default:
465
+ val = 0;
466
+ qemu_log_mask(LOG_GUEST_ERROR,
479
+ qemu_log_mask(LOG_GUEST_ERROR,
467
+ "SysTick: Bad read offset 0x%" HWADDR_PRIx "\n", addr);
480
+ "%s: write to read-only register @ 0x%" HWADDR_PRIx "\n",
468
+ break;
481
+ DEVICE(s)->canonical_path, addr);
469
+ }
482
+ break;
470
+
483
+
471
+ trace_systick_read(addr, val, size);
484
+ case NPCM7XX_GPIO_POL:
472
+ return val;
485
+ case NPCM7XX_GPIO_DOUT:
473
+}
486
+ case NPCM7XX_GPIO_OE:
474
+
487
+ case NPCM7XX_GPIO_OTYP:
475
+static void systick_write(void *opaque, hwaddr addr,
488
+ case NPCM7XX_GPIO_PU:
476
+ uint64_t value, unsigned size)
489
+ case NPCM7XX_GPIO_PD:
477
+{
490
+ case NPCM7XX_GPIO_IEM:
478
+ SysTickState *s = opaque;
491
+ s->regs[reg] = value;
479
+
492
+ npcm7xx_gpio_update_pins(s, diff);
480
+ trace_systick_write(addr, value, size);
493
+ break;
481
+
494
+
482
+ switch (addr) {
495
+ case NPCM7XX_GPIO_DOS:
483
+ case 0x0: /* SysTick Control and Status. */
496
+ s->regs[NPCM7XX_GPIO_DOUT] |= value;
484
+ {
497
+ npcm7xx_gpio_update_pins(s, value);
485
+ uint32_t oldval = s->control;
498
+ break;
486
+
499
+ case NPCM7XX_GPIO_DOC:
487
+ s->control &= 0xfffffff8;
500
+ s->regs[NPCM7XX_GPIO_DOUT] &= ~value;
488
+ s->control |= value & 7;
501
+ npcm7xx_gpio_update_pins(s, value);
489
+ if ((oldval ^ value) & SYSTICK_ENABLE) {
502
+ break;
490
+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
503
+ case NPCM7XX_GPIO_OES:
491
+ if (value & SYSTICK_ENABLE) {
504
+ s->regs[NPCM7XX_GPIO_OE] |= value;
492
+ if (s->tick) {
505
+ npcm7xx_gpio_update_pins(s, value);
493
+ s->tick += now;
506
+ break;
494
+ timer_mod(s->timer, s->tick);
507
+ case NPCM7XX_GPIO_OEC:
495
+ } else {
508
+ s->regs[NPCM7XX_GPIO_OE] &= ~value;
496
+ systick_reload(s, 1);
509
+ npcm7xx_gpio_update_pins(s, value);
497
+ }
510
+ break;
498
+ } else {
511
+
499
+ timer_del(s->timer);
512
+ case NPCM7XX_GPIO_EVTYP:
500
+ s->tick -= now;
513
+ case NPCM7XX_GPIO_EVBE:
501
+ if (s->tick < 0) {
514
+ case NPCM7XX_GPIO_EVEN:
502
+ s->tick = 0;
515
+ s->regs[reg] = value;
503
+ }
516
+ npcm7xx_gpio_update_events(s, 0);
504
+ }
517
+ break;
505
+ } else if ((oldval ^ value) & SYSTICK_CLKSOURCE) {
518
+
506
+ /* This is a hack. Force the timer to be reloaded
519
+ case NPCM7XX_GPIO_EVENS:
507
+ when the reference clock is changed. */
520
+ s->regs[NPCM7XX_GPIO_EVEN] |= value;
508
+ systick_reload(s, 1);
521
+ npcm7xx_gpio_update_events(s, 0);
509
+ }
522
+ break;
510
+ break;
523
+ case NPCM7XX_GPIO_EVENC:
511
+ }
524
+ s->regs[NPCM7XX_GPIO_EVEN] &= ~value;
512
+ case 0x4: /* SysTick Reload Value. */
525
+ npcm7xx_gpio_update_events(s, 0);
513
+ s->reload = value;
526
+ break;
514
+ break;
527
+
515
+ case 0x8: /* SysTick Current Value. Writes reload the timer. */
528
+ case NPCM7XX_GPIO_EVST:
516
+ systick_reload(s, 1);
529
+ s->regs[reg] &= ~value;
517
+ s->control &= ~SYSTICK_COUNTFLAG;
530
+ npcm7xx_gpio_update_events(s, 0);
518
+ break;
531
+ break;
532
+
533
+ case NPCM7XX_GPIO_MP:
534
+ case NPCM7XX_GPIO_DBNC:
535
+ case NPCM7XX_GPIO_OSRC:
536
+ case NPCM7XX_GPIO_ODSC:
537
+ /* Nothing to do; just store the value. */
538
+ s->regs[reg] = value;
539
+ break;
540
+
541
+ case NPCM7XX_GPIO_OBL0:
542
+ case NPCM7XX_GPIO_OBL1:
543
+ case NPCM7XX_GPIO_OBL2:
544
+ case NPCM7XX_GPIO_OBL3:
545
+ s->regs[reg] = value;
546
+ qemu_log_mask(LOG_UNIMP, "%s: Blinking is not implemented\n",
547
+ __func__);
548
+ break;
549
+
550
+ case NPCM7XX_GPIO_SPLCK:
551
+ case NPCM7XX_GPIO_MPLCK:
552
+ qemu_log_mask(LOG_UNIMP, "%s: Per-pin lock is not implemented\n",
553
+ __func__);
554
+ break;
555
+
519
+ default:
556
+ default:
520
+ qemu_log_mask(LOG_GUEST_ERROR,
557
+ qemu_log_mask(LOG_GUEST_ERROR,
521
+ "SysTick: Bad write offset 0x%" HWADDR_PRIx "\n", addr);
558
+ "%s: write to invalid offset 0x%" HWADDR_PRIx "\n",
559
+ DEVICE(s)->canonical_path, addr);
560
+ break;
522
+ }
561
+ }
523
+}
562
+}
524
+
563
+
525
+static const MemoryRegionOps systick_ops = {
564
+static const MemoryRegionOps npcm7xx_gpio_regs_ops = {
526
+ .read = systick_read,
565
+ .read = npcm7xx_gpio_regs_read,
527
+ .write = systick_write,
566
+ .write = npcm7xx_gpio_regs_write,
528
+ .endianness = DEVICE_NATIVE_ENDIAN,
567
+ .endianness = DEVICE_NATIVE_ENDIAN,
529
+ .valid.min_access_size = 4,
568
+ .valid = {
530
+ .valid.max_access_size = 4,
569
+ .min_access_size = 4,
570
+ .max_access_size = 4,
571
+ .unaligned = false,
572
+ },
531
+};
573
+};
532
+
574
+
533
+static void systick_reset(DeviceState *dev)
575
+static void npcm7xx_gpio_set_input(void *opaque, int line, int level)
534
+{
576
+{
535
+ SysTickState *s = SYSTICK(dev);
577
+ NPCM7xxGPIOState *s = opaque;
536
+
578
+
537
+ s->control = 0;
579
+ trace_npcm7xx_gpio_set_input(DEVICE(s)->canonical_path, line, level);
538
+ s->reload = 0;
580
+
539
+ s->tick = 0;
581
+ g_assert(line >= 0 && line < NPCM7XX_GPIO_NR_PINS);
540
+ timer_del(s->timer);
582
+
541
+}
583
+ s->ext_driven = deposit32(s->ext_driven, line, 1, level >= 0);
542
+
584
+ s->ext_level = deposit32(s->ext_level, line, 1, level > 0);
543
+static void systick_instance_init(Object *obj)
585
+
544
+{
586
+ npcm7xx_gpio_update_pins(s, BIT(line));
545
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
587
+}
546
+ SysTickState *s = SYSTICK(obj);
588
+
547
+
589
+static void npcm7xx_gpio_enter_reset(Object *obj, ResetType type)
548
+ memory_region_init_io(&s->iomem, obj, &systick_ops, s, "systick", 0xe0);
590
+{
549
+ sysbus_init_mmio(sbd, &s->iomem);
591
+ NPCM7xxGPIOState *s = NPCM7XX_GPIO(obj);
550
+ sysbus_init_irq(sbd, &s->irq);
592
+
551
+ s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, systick_timer_tick, s);
593
+ memset(s->regs, 0, sizeof(s->regs));
552
+}
594
+
553
+
595
+ s->regs[NPCM7XX_GPIO_PU] = s->reset_pu;
554
+static const VMStateDescription vmstate_systick = {
596
+ s->regs[NPCM7XX_GPIO_PD] = s->reset_pd;
555
+ .name = "armv7m_systick",
597
+ s->regs[NPCM7XX_GPIO_OSRC] = s->reset_osrc;
556
+ .version_id = 1,
598
+ s->regs[NPCM7XX_GPIO_ODSC] = s->reset_odsc;
557
+ .minimum_version_id = 1,
599
+}
600
+
601
+static void npcm7xx_gpio_hold_reset(Object *obj)
602
+{
603
+ NPCM7xxGPIOState *s = NPCM7XX_GPIO(obj);
604
+
605
+ npcm7xx_gpio_update_pins(s, -1);
606
+}
607
+
608
+static void npcm7xx_gpio_init(Object *obj)
609
+{
610
+ NPCM7xxGPIOState *s = NPCM7XX_GPIO(obj);
611
+ DeviceState *dev = DEVICE(obj);
612
+
613
+ memory_region_init_io(&s->mmio, obj, &npcm7xx_gpio_regs_ops, s,
614
+ "regs", NPCM7XX_GPIO_REGS_SIZE);
615
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
616
+ sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
617
+
618
+ qdev_init_gpio_in(dev, npcm7xx_gpio_set_input, NPCM7XX_GPIO_NR_PINS);
619
+ qdev_init_gpio_out(dev, s->output, NPCM7XX_GPIO_NR_PINS);
620
+}
621
+
622
+static const VMStateDescription vmstate_npcm7xx_gpio = {
623
+ .name = "npcm7xx-gpio",
624
+ .version_id = 0,
625
+ .minimum_version_id = 0,
558
+ .fields = (VMStateField[]) {
626
+ .fields = (VMStateField[]) {
559
+ VMSTATE_UINT32(control, SysTickState),
627
+ VMSTATE_UINT32(pin_level, NPCM7xxGPIOState),
560
+ VMSTATE_UINT32(reload, SysTickState),
628
+ VMSTATE_UINT32(ext_level, NPCM7xxGPIOState),
561
+ VMSTATE_INT64(tick, SysTickState),
629
+ VMSTATE_UINT32(ext_driven, NPCM7xxGPIOState),
562
+ VMSTATE_TIMER_PTR(timer, SysTickState),
630
+ VMSTATE_UINT32_ARRAY(regs, NPCM7xxGPIOState, NPCM7XX_GPIO_NR_REGS),
563
+ VMSTATE_END_OF_LIST()
631
+ VMSTATE_END_OF_LIST(),
632
+ },
633
+};
634
+
635
+static Property npcm7xx_gpio_properties[] = {
636
+ /* Bit n set => pin n has pullup enabled by default. */
637
+ DEFINE_PROP_UINT32("reset-pullup", NPCM7xxGPIOState, reset_pu, 0),
638
+ /* Bit n set => pin n has pulldown enabled by default. */
639
+ DEFINE_PROP_UINT32("reset-pulldown", NPCM7xxGPIOState, reset_pd, 0),
640
+ /* Bit n set => pin n has high slew rate by default. */
641
+ DEFINE_PROP_UINT32("reset-osrc", NPCM7xxGPIOState, reset_osrc, 0),
642
+ /* Bit n set => pin n has high drive strength by default. */
643
+ DEFINE_PROP_UINT32("reset-odsc", NPCM7xxGPIOState, reset_odsc, 0),
644
+ DEFINE_PROP_END_OF_LIST(),
645
+};
646
+
647
+static void npcm7xx_gpio_class_init(ObjectClass *klass, void *data)
648
+{
649
+ ResettableClass *reset = RESETTABLE_CLASS(klass);
650
+ DeviceClass *dc = DEVICE_CLASS(klass);
651
+
652
+ QEMU_BUILD_BUG_ON(NPCM7XX_GPIO_REGS_END > NPCM7XX_GPIO_NR_REGS);
653
+
654
+ dc->desc = "NPCM7xx GPIO Controller";
655
+ dc->vmsd = &vmstate_npcm7xx_gpio;
656
+ reset->phases.enter = npcm7xx_gpio_enter_reset;
657
+ reset->phases.hold = npcm7xx_gpio_hold_reset;
658
+ device_class_set_props(dc, npcm7xx_gpio_properties);
659
+}
660
+
661
+static const TypeInfo npcm7xx_gpio_types[] = {
662
+ {
663
+ .name = TYPE_NPCM7XX_GPIO,
664
+ .parent = TYPE_SYS_BUS_DEVICE,
665
+ .instance_size = sizeof(NPCM7xxGPIOState),
666
+ .class_init = npcm7xx_gpio_class_init,
667
+ .instance_init = npcm7xx_gpio_init,
668
+ },
669
+};
670
+DEFINE_TYPES(npcm7xx_gpio_types);
671
diff --git a/tests/qtest/npcm7xx_gpio-test.c b/tests/qtest/npcm7xx_gpio-test.c
672
new file mode 100644
673
index XXXXXXX..XXXXXXX
674
--- /dev/null
675
+++ b/tests/qtest/npcm7xx_gpio-test.c
676
@@ -XXX,XX +XXX,XX @@
677
+/*
678
+ * QTest testcase for the Nuvoton NPCM7xx GPIO modules.
679
+ *
680
+ * Copyright 2020 Google LLC
681
+ *
682
+ * This program is free software; you can redistribute it and/or modify it
683
+ * under the terms of the GNU General Public License as published by the
684
+ * Free Software Foundation; either version 2 of the License, or
685
+ * (at your option) any later version.
686
+ *
687
+ * This program is distributed in the hope that it will be useful, but WITHOUT
688
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
689
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
690
+ * for more details.
691
+ */
692
+
693
+#include "qemu/osdep.h"
694
+#include "libqtest-single.h"
695
+
696
+#define NR_GPIO_DEVICES (8)
697
+#define GPIO(x) (0xf0010000 + (x) * 0x1000)
698
+#define GPIO_IRQ(x) (116 + (x))
699
+
700
+/* GPIO registers */
701
+#define GP_N_TLOCK1 0x00
702
+#define GP_N_DIN 0x04 /* Data IN */
703
+#define GP_N_POL 0x08 /* Polarity */
704
+#define GP_N_DOUT 0x0c /* Data OUT */
705
+#define GP_N_OE 0x10 /* Output Enable */
706
+#define GP_N_OTYP 0x14
707
+#define GP_N_MP 0x18
708
+#define GP_N_PU 0x1c /* Pull-up */
709
+#define GP_N_PD 0x20 /* Pull-down */
710
+#define GP_N_DBNC 0x24 /* Debounce */
711
+#define GP_N_EVTYP 0x28 /* Event Type */
712
+#define GP_N_EVBE 0x2c /* Event Both Edge */
713
+#define GP_N_OBL0 0x30
714
+#define GP_N_OBL1 0x34
715
+#define GP_N_OBL2 0x38
716
+#define GP_N_OBL3 0x3c
717
+#define GP_N_EVEN 0x40 /* Event Enable */
718
+#define GP_N_EVENS 0x44 /* Event Set (enable) */
719
+#define GP_N_EVENC 0x48 /* Event Clear (disable) */
720
+#define GP_N_EVST 0x4c /* Event Status */
721
+#define GP_N_SPLCK 0x50
722
+#define GP_N_MPLCK 0x54
723
+#define GP_N_IEM 0x58 /* Input Enable */
724
+#define GP_N_OSRC 0x5c
725
+#define GP_N_ODSC 0x60
726
+#define GP_N_DOS 0x68 /* Data OUT Set */
727
+#define GP_N_DOC 0x6c /* Data OUT Clear */
728
+#define GP_N_OES 0x70 /* Output Enable Set */
729
+#define GP_N_OEC 0x74 /* Output Enable Clear */
730
+#define GP_N_TLOCK2 0x7c
731
+
732
+static void gpio_unlock(int n)
733
+{
734
+ if (readl(GPIO(n) + GP_N_TLOCK1) != 0) {
735
+ writel(GPIO(n) + GP_N_TLOCK2, 0xc0de1248);
736
+ writel(GPIO(n) + GP_N_TLOCK1, 0xc0defa73);
564
+ }
737
+ }
565
+};
738
+}
566
+
739
+
567
+static void systick_class_init(ObjectClass *klass, void *data)
740
+/* Restore the GPIO controller to a sensible default state. */
568
+{
741
+static void gpio_reset(int n)
569
+ DeviceClass *dc = DEVICE_CLASS(klass);
742
+{
570
+
743
+ gpio_unlock(0);
571
+ dc->vmsd = &vmstate_systick;
744
+
572
+ dc->reset = systick_reset;
745
+ writel(GPIO(n) + GP_N_EVEN, 0x00000000);
573
+}
746
+ writel(GPIO(n) + GP_N_EVST, 0xffffffff);
574
+
747
+ writel(GPIO(n) + GP_N_POL, 0x00000000);
575
+static const TypeInfo armv7m_systick_info = {
748
+ writel(GPIO(n) + GP_N_DOUT, 0x00000000);
576
+ .name = TYPE_SYSTICK,
749
+ writel(GPIO(n) + GP_N_OE, 0x00000000);
577
+ .parent = TYPE_SYS_BUS_DEVICE,
750
+ writel(GPIO(n) + GP_N_OTYP, 0x00000000);
578
+ .instance_init = systick_instance_init,
751
+ writel(GPIO(n) + GP_N_PU, 0xffffffff);
579
+ .instance_size = sizeof(SysTickState),
752
+ writel(GPIO(n) + GP_N_PD, 0x00000000);
580
+ .class_init = systick_class_init,
753
+ writel(GPIO(n) + GP_N_IEM, 0xffffffff);
581
+};
754
+}
582
+
755
+
583
+static void armv7m_systick_register_types(void)
756
+static void test_dout_to_din(void)
584
+{
757
+{
585
+ type_register_static(&armv7m_systick_info);
758
+ gpio_reset(0);
586
+}
759
+
587
+
760
+ /* When output is enabled, DOUT should be reflected on DIN. */
588
+type_init(armv7m_systick_register_types)
761
+ writel(GPIO(0) + GP_N_OE, 0xffffffff);
589
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
762
+ /* PU and PD shouldn't have any impact on DIN. */
763
+ writel(GPIO(0) + GP_N_PU, 0xffff0000);
764
+ writel(GPIO(0) + GP_N_PD, 0x0000ffff);
765
+ writel(GPIO(0) + GP_N_DOUT, 0x12345678);
766
+ g_assert_cmphex(readl(GPIO(0) + GP_N_DOUT), ==, 0x12345678);
767
+ g_assert_cmphex(readl(GPIO(0) + GP_N_DIN), ==, 0x12345678);
768
+}
769
+
770
+static void test_pullup_pulldown(void)
771
+{
772
+ gpio_reset(0);
773
+
774
+ /*
775
+ * When output is disabled, and PD is the inverse of PU, PU should be
776
+ * reflected on DIN. If PD is not the inverse of PU, the state of DIN is
777
+ * undefined, so we don't test that.
778
+ */
779
+ writel(GPIO(0) + GP_N_OE, 0x00000000);
780
+ /* DOUT shouldn't have any impact on DIN. */
781
+ writel(GPIO(0) + GP_N_DOUT, 0xffff0000);
782
+ writel(GPIO(0) + GP_N_PU, 0x23456789);
783
+ writel(GPIO(0) + GP_N_PD, ~0x23456789U);
784
+ g_assert_cmphex(readl(GPIO(0) + GP_N_PU), ==, 0x23456789);
785
+ g_assert_cmphex(readl(GPIO(0) + GP_N_PD), ==, ~0x23456789U);
786
+ g_assert_cmphex(readl(GPIO(0) + GP_N_DIN), ==, 0x23456789);
787
+}
788
+
789
+static void test_output_enable(void)
790
+{
791
+ gpio_reset(0);
792
+
793
+ /*
794
+ * With all pins weakly pulled down, and DOUT all-ones, OE should be
795
+ * reflected on DIN.
796
+ */
797
+ writel(GPIO(0) + GP_N_DOUT, 0xffffffff);
798
+ writel(GPIO(0) + GP_N_PU, 0x00000000);
799
+ writel(GPIO(0) + GP_N_PD, 0xffffffff);
800
+ writel(GPIO(0) + GP_N_OE, 0x3456789a);
801
+ g_assert_cmphex(readl(GPIO(0) + GP_N_OE), ==, 0x3456789a);
802
+ g_assert_cmphex(readl(GPIO(0) + GP_N_DIN), ==, 0x3456789a);
803
+
804
+ writel(GPIO(0) + GP_N_OEC, 0x00030002);
805
+ g_assert_cmphex(readl(GPIO(0) + GP_N_OE), ==, 0x34547898);
806
+ g_assert_cmphex(readl(GPIO(0) + GP_N_DIN), ==, 0x34547898);
807
+
808
+ writel(GPIO(0) + GP_N_OES, 0x0000f001);
809
+ g_assert_cmphex(readl(GPIO(0) + GP_N_OE), ==, 0x3454f899);
810
+ g_assert_cmphex(readl(GPIO(0) + GP_N_DIN), ==, 0x3454f899);
811
+}
812
+
813
+static void test_open_drain(void)
814
+{
815
+ gpio_reset(0);
816
+
817
+ /*
818
+ * Upper half of DOUT drives a 1 only if the corresponding bit in OTYP is
819
+ * not set. If OTYP is set, DIN is determined by PU/PD. Lower half of
820
+ * DOUT always drives a 0 regardless of OTYP; PU/PD have no effect. When
821
+ * OE is 0, output is determined by PU/PD; OTYP has no effect.
822
+ */
823
+ writel(GPIO(0) + GP_N_OTYP, 0x456789ab);
824
+ writel(GPIO(0) + GP_N_OE, 0xf0f0f0f0);
825
+ writel(GPIO(0) + GP_N_DOUT, 0xffff0000);
826
+ writel(GPIO(0) + GP_N_PU, 0xff00ff00);
827
+ writel(GPIO(0) + GP_N_PD, 0x00ff00ff);
828
+ g_assert_cmphex(readl(GPIO(0) + GP_N_OTYP), ==, 0x456789ab);
829
+ g_assert_cmphex(readl(GPIO(0) + GP_N_DIN), ==, 0xff900f00);
830
+}
831
+
832
+static void test_polarity(void)
833
+{
834
+ gpio_reset(0);
835
+
836
+ /*
837
+ * In push-pull mode, DIN should reflect DOUT because the signal is
838
+ * inverted in both directions.
839
+ */
840
+ writel(GPIO(0) + GP_N_OTYP, 0x00000000);
841
+ writel(GPIO(0) + GP_N_OE, 0xffffffff);
842
+ writel(GPIO(0) + GP_N_DOUT, 0x56789abc);
843
+ writel(GPIO(0) + GP_N_POL, 0x6789abcd);
844
+ g_assert_cmphex(readl(GPIO(0) + GP_N_POL), ==, 0x6789abcd);
845
+ g_assert_cmphex(readl(GPIO(0) + GP_N_DIN), ==, 0x56789abc);
846
+
847
+ /*
848
+ * When turning off the drivers, DIN should reflect the inverse of the
849
+ * pulled-up lines.
850
+ */
851
+ writel(GPIO(0) + GP_N_OE, 0x00000000);
852
+ writel(GPIO(0) + GP_N_POL, 0xffffffff);
853
+ writel(GPIO(0) + GP_N_PU, 0x789abcde);
854
+ writel(GPIO(0) + GP_N_PD, ~0x789abcdeU);
855
+ g_assert_cmphex(readl(GPIO(0) + GP_N_DIN), ==, ~0x789abcdeU);
856
+
857
+ /*
858
+ * In open-drain mode, DOUT=1 will appear to drive the pin high (since DIN
859
+ * is inverted), while DOUT=0 will leave the pin floating.
860
+ */
861
+ writel(GPIO(0) + GP_N_OTYP, 0xffffffff);
862
+ writel(GPIO(0) + GP_N_OE, 0xffffffff);
863
+ writel(GPIO(0) + GP_N_PU, 0xffff0000);
864
+ writel(GPIO(0) + GP_N_PD, 0x0000ffff);
865
+ writel(GPIO(0) + GP_N_DOUT, 0xff00ff00);
866
+ g_assert_cmphex(readl(GPIO(0) + GP_N_DIN), ==, 0xff00ffff);
867
+}
868
+
869
+static void test_input_mask(void)
870
+{
871
+ gpio_reset(0);
872
+
873
+ /* IEM=0 forces the input to zero before polarity inversion. */
874
+ writel(GPIO(0) + GP_N_OE, 0xffffffff);
875
+ writel(GPIO(0) + GP_N_DOUT, 0xff00ff00);
876
+ writel(GPIO(0) + GP_N_POL, 0xffff0000);
877
+ writel(GPIO(0) + GP_N_IEM, 0x87654321);
878
+ g_assert_cmphex(readl(GPIO(0) + GP_N_DIN), ==, 0xff9a4300);
879
+}
880
+
881
+static void test_temp_lock(void)
882
+{
883
+ gpio_reset(0);
884
+
885
+ writel(GPIO(0) + GP_N_DOUT, 0x98765432);
886
+
887
+ /* Make sure we're unlocked initially. */
888
+ g_assert_cmphex(readl(GPIO(0) + GP_N_TLOCK1), ==, 0);
889
+ /* Writing any value to TLOCK1 will lock. */
890
+ writel(GPIO(0) + GP_N_TLOCK1, 0);
891
+ g_assert_cmphex(readl(GPIO(0) + GP_N_TLOCK1), ==, 1);
892
+ writel(GPIO(0) + GP_N_DOUT, 0xa9876543);
893
+ g_assert_cmphex(readl(GPIO(0) + GP_N_DOUT), ==, 0x98765432);
894
+ /* Now, try to unlock. */
895
+ gpio_unlock(0);
896
+ g_assert_cmphex(readl(GPIO(0) + GP_N_TLOCK1), ==, 0);
897
+ writel(GPIO(0) + GP_N_DOUT, 0xa9876543);
898
+ g_assert_cmphex(readl(GPIO(0) + GP_N_DOUT), ==, 0xa9876543);
899
+
900
+ /* Try it again, but write TLOCK2 to lock. */
901
+ writel(GPIO(0) + GP_N_TLOCK2, 0);
902
+ g_assert_cmphex(readl(GPIO(0) + GP_N_TLOCK1), ==, 1);
903
+ writel(GPIO(0) + GP_N_DOUT, 0x98765432);
904
+ g_assert_cmphex(readl(GPIO(0) + GP_N_DOUT), ==, 0xa9876543);
905
+ /* Now, try to unlock. */
906
+ gpio_unlock(0);
907
+ g_assert_cmphex(readl(GPIO(0) + GP_N_TLOCK1), ==, 0);
908
+ writel(GPIO(0) + GP_N_DOUT, 0x98765432);
909
+ g_assert_cmphex(readl(GPIO(0) + GP_N_DOUT), ==, 0x98765432);
910
+}
911
+
912
+static void test_events_level(void)
913
+{
914
+ gpio_reset(0);
915
+
916
+ writel(GPIO(0) + GP_N_EVTYP, 0x00000000);
917
+ writel(GPIO(0) + GP_N_DOUT, 0xba987654);
918
+ writel(GPIO(0) + GP_N_OE, 0xffffffff);
919
+ writel(GPIO(0) + GP_N_EVST, 0xffffffff);
920
+
921
+ g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0xba987654);
922
+ g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
923
+ writel(GPIO(0) + GP_N_DOUT, 0x00000000);
924
+ g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0xba987654);
925
+ g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
926
+ writel(GPIO(0) + GP_N_EVST, 0x00007654);
927
+ g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0xba980000);
928
+ g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
929
+ writel(GPIO(0) + GP_N_EVST, 0xba980000);
930
+ g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x00000000);
931
+ g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
932
+}
933
+
934
+static void test_events_rising_edge(void)
935
+{
936
+ gpio_reset(0);
937
+
938
+ writel(GPIO(0) + GP_N_EVTYP, 0xffffffff);
939
+ writel(GPIO(0) + GP_N_EVBE, 0x00000000);
940
+ writel(GPIO(0) + GP_N_DOUT, 0xffff0000);
941
+ writel(GPIO(0) + GP_N_OE, 0xffffffff);
942
+ writel(GPIO(0) + GP_N_EVST, 0xffffffff);
943
+
944
+ g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x00000000);
945
+ g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
946
+ writel(GPIO(0) + GP_N_DOUT, 0xff00ff00);
947
+ g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x0000ff00);
948
+ g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
949
+ writel(GPIO(0) + GP_N_DOUT, 0x00ff0000);
950
+ g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x00ffff00);
951
+ g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
952
+ writel(GPIO(0) + GP_N_EVST, 0x0000f000);
953
+ g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x00ff0f00);
954
+ g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
955
+ writel(GPIO(0) + GP_N_EVST, 0x00ff0f00);
956
+ g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x00000000);
957
+ g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
958
+}
959
+
960
+static void test_events_both_edges(void)
961
+{
962
+ gpio_reset(0);
963
+
964
+ writel(GPIO(0) + GP_N_EVTYP, 0xffffffff);
965
+ writel(GPIO(0) + GP_N_EVBE, 0xffffffff);
966
+ writel(GPIO(0) + GP_N_DOUT, 0xffff0000);
967
+ writel(GPIO(0) + GP_N_OE, 0xffffffff);
968
+ writel(GPIO(0) + GP_N_EVST, 0xffffffff);
969
+
970
+ g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x00000000);
971
+ g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
972
+ writel(GPIO(0) + GP_N_DOUT, 0xff00ff00);
973
+ g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x00ffff00);
974
+ g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
975
+ writel(GPIO(0) + GP_N_DOUT, 0xef00ff08);
976
+ g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x10ffff08);
977
+ g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
978
+ writel(GPIO(0) + GP_N_EVST, 0x0000f000);
979
+ g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x10ff0f08);
980
+ g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
981
+ writel(GPIO(0) + GP_N_EVST, 0x10ff0f08);
982
+ g_assert_cmphex(readl(GPIO(0) + GP_N_EVST), ==, 0x00000000);
983
+ g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(0)));
984
+}
985
+
986
+static void test_gpion_irq(gconstpointer test_data)
987
+{
988
+ intptr_t n = (intptr_t)test_data;
989
+
990
+ gpio_reset(n);
991
+
992
+ writel(GPIO(n) + GP_N_EVTYP, 0x00000000);
993
+ writel(GPIO(n) + GP_N_DOUT, 0x00000000);
994
+ writel(GPIO(n) + GP_N_OE, 0xffffffff);
995
+ writel(GPIO(n) + GP_N_EVST, 0xffffffff);
996
+ writel(GPIO(n) + GP_N_EVEN, 0x00000000);
997
+
998
+ /* Trigger an event; interrupts are masked. */
999
+ g_assert_cmphex(readl(GPIO(n) + GP_N_EVST), ==, 0x00000000);
1000
+ g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(n)));
1001
+ writel(GPIO(n) + GP_N_DOS, 0x00008000);
1002
+ g_assert_cmphex(readl(GPIO(n) + GP_N_EVST), ==, 0x00008000);
1003
+ g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(n)));
1004
+
1005
+ /* Unmask all event interrupts; verify that the interrupt fired. */
1006
+ writel(GPIO(n) + GP_N_EVEN, 0xffffffff);
1007
+ g_assert_true(qtest_get_irq(global_qtest, GPIO_IRQ(n)));
1008
+
1009
+ /* Clear the current bit, set a new bit, irq stays asserted. */
1010
+ writel(GPIO(n) + GP_N_DOC, 0x00008000);
1011
+ g_assert_true(qtest_get_irq(global_qtest, GPIO_IRQ(n)));
1012
+ writel(GPIO(n) + GP_N_DOS, 0x00000200);
1013
+ g_assert_true(qtest_get_irq(global_qtest, GPIO_IRQ(n)));
1014
+ writel(GPIO(n) + GP_N_EVST, 0x00008000);
1015
+ g_assert_true(qtest_get_irq(global_qtest, GPIO_IRQ(n)));
1016
+
1017
+ /* Mask/unmask the event that's currently active. */
1018
+ writel(GPIO(n) + GP_N_EVENC, 0x00000200);
1019
+ g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(n)));
1020
+ writel(GPIO(n) + GP_N_EVENS, 0x00000200);
1021
+ g_assert_true(qtest_get_irq(global_qtest, GPIO_IRQ(n)));
1022
+
1023
+ /* Clear the input and the status bit, irq is deasserted. */
1024
+ writel(GPIO(n) + GP_N_DOC, 0x00000200);
1025
+ g_assert_true(qtest_get_irq(global_qtest, GPIO_IRQ(n)));
1026
+ writel(GPIO(n) + GP_N_EVST, 0x00000200);
1027
+ g_assert_false(qtest_get_irq(global_qtest, GPIO_IRQ(n)));
1028
+}
1029
+
1030
+int main(int argc, char **argv)
1031
+{
1032
+ int ret;
1033
+ int i;
1034
+
1035
+ g_test_init(&argc, &argv, NULL);
1036
+ g_test_set_nonfatal_assertions();
1037
+
1038
+ qtest_add_func("/npcm7xx_gpio/dout_to_din", test_dout_to_din);
1039
+ qtest_add_func("/npcm7xx_gpio/pullup_pulldown", test_pullup_pulldown);
1040
+ qtest_add_func("/npcm7xx_gpio/output_enable", test_output_enable);
1041
+ qtest_add_func("/npcm7xx_gpio/open_drain", test_open_drain);
1042
+ qtest_add_func("/npcm7xx_gpio/polarity", test_polarity);
1043
+ qtest_add_func("/npcm7xx_gpio/input_mask", test_input_mask);
1044
+ qtest_add_func("/npcm7xx_gpio/temp_lock", test_temp_lock);
1045
+ qtest_add_func("/npcm7xx_gpio/events/level", test_events_level);
1046
+ qtest_add_func("/npcm7xx_gpio/events/rising_edge", test_events_rising_edge);
1047
+ qtest_add_func("/npcm7xx_gpio/events/both_edges", test_events_both_edges);
1048
+
1049
+ for (i = 0; i < NR_GPIO_DEVICES; i++) {
1050
+ g_autofree char *test_name =
1051
+ g_strdup_printf("/npcm7xx_gpio/gpio[%d]/irq", i);
1052
+ qtest_add_data_func(test_name, (void *)(intptr_t)i, test_gpion_irq);
1053
+ }
1054
+
1055
+ qtest_start("-machine npcm750-evb");
1056
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/a9mpcore/gic");
1057
+ ret = g_test_run();
1058
+ qtest_end();
1059
+
1060
+ return ret;
1061
+}
1062
diff --git a/hw/gpio/meson.build b/hw/gpio/meson.build
590
index XXXXXXX..XXXXXXX 100644
1063
index XXXXXXX..XXXXXXX 100644
591
--- a/hw/timer/trace-events
1064
--- a/hw/gpio/meson.build
592
+++ b/hw/timer/trace-events
1065
+++ b/hw/gpio/meson.build
593
@@ -XXX,XX +XXX,XX @@ aspeed_timer_ctrl_pulse_enable(uint8_t i, bool enable) "Timer %" PRIu8 ": %d"
1066
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_PUV3', if_true: files('puv3_gpio.c'))
594
aspeed_timer_set_ctrl2(uint32_t value) "Value: 0x%" PRIx32
1067
softmmu_ss.add(when: 'CONFIG_ZAURUS', if_true: files('zaurus.c'))
595
aspeed_timer_set_value(int timer, int reg, uint32_t value) "Timer %d register %d: 0x%" PRIx32
1068
596
aspeed_timer_read(uint64_t offset, unsigned size, uint64_t value) "From 0x%" PRIx64 ": of size %u: 0x%" PRIx64
1069
softmmu_ss.add(when: 'CONFIG_IMX', if_true: files('imx_gpio.c'))
597
+
1070
+softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_gpio.c'))
598
+# hw/timer/armv7m_systick.c
1071
softmmu_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_gpio.c'))
599
+systick_reload(void) "systick reload"
1072
softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_gpio.c'))
600
+systick_timer_tick(void) "systick reload"
1073
softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_gpio.c'))
601
+systick_read(uint64_t addr, uint32_t value, unsigned size) "systick read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
1074
diff --git a/hw/gpio/trace-events b/hw/gpio/trace-events
602
+systick_write(uint64_t addr, uint32_t value, unsigned size) "systick write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
1075
index XXXXXXX..XXXXXXX 100644
1076
--- a/hw/gpio/trace-events
1077
+++ b/hw/gpio/trace-events
1078
@@ -XXX,XX +XXX,XX @@
1079
# See docs/devel/tracing.txt for syntax documentation.
1080
1081
+# npcm7xx_gpio.c
1082
+npcm7xx_gpio_read(const char *id, uint64_t offset, uint64_t value) " %s offset: 0x%04" PRIx64 " value 0x%08" PRIx64
1083
+npcm7xx_gpio_write(const char *id, uint64_t offset, uint64_t value) "%s offset: 0x%04" PRIx64 " value 0x%08" PRIx64
1084
+npcm7xx_gpio_set_input(const char *id, int32_t line, int32_t level) "%s line: %" PRIi32 " level: %" PRIi32
1085
+npcm7xx_gpio_set_output(const char *id, int32_t line, int32_t level) "%s line: %" PRIi32 " level: %" PRIi32
1086
+npcm7xx_gpio_update_events(const char *id, uint32_t evst, uint32_t even) "%s evst: 0x%08" PRIx32 " even: 0x%08" PRIx32
1087
+
1088
# nrf51_gpio.c
1089
nrf51_gpio_read(uint64_t offset, uint64_t r) "offset 0x%" PRIx64 " value 0x%" PRIx64
1090
nrf51_gpio_write(uint64_t offset, uint64_t value) "offset 0x%" PRIx64 " value 0x%" PRIx64
1091
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
1092
index XXXXXXX..XXXXXXX 100644
1093
--- a/tests/qtest/meson.build
1094
+++ b/tests/qtest/meson.build
1095
@@ -XXX,XX +XXX,XX @@ qtests_sparc64 = \
1096
['prom-env-test', 'boot-serial-test']
1097
1098
qtests_npcm7xx = \
1099
- ['npcm7xx_rng-test',
1100
+ ['npcm7xx_gpio-test',
1101
+ 'npcm7xx_rng-test',
1102
'npcm7xx_timer-test',
1103
'npcm7xx_watchdog_timer-test']
1104
qtests_arm = \
603
--
1105
--
604
2.7.4
1106
2.20.1
605
1107
606
1108
diff view generated by jsdifflib
New patch
1
From: Zenghui Yu <yuzenghui@huawei.com>
1
2
3
Ensure the vSMMUv3 will be restored before all PCIe devices so that DMA
4
translation can work properly during migration.
5
6
Signed-off-by: Zenghui Yu <yuzenghui@huawei.com>
7
Message-id: 20201019091508.197-1-yuzenghui@huawei.com
8
Acked-by: Eric Auger <eric.auger@redhat.com>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
hw/arm/smmuv3.c | 1 +
12
1 file changed, 1 insertion(+)
13
14
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/smmuv3.c
17
+++ b/hw/arm/smmuv3.c
18
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_smmuv3 = {
19
.name = "smmuv3",
20
.version_id = 1,
21
.minimum_version_id = 1,
22
+ .priority = MIG_PRI_IOMMU,
23
.fields = (VMStateField[]) {
24
VMSTATE_UINT32(features, SMMUv3State),
25
VMSTATE_UINT8(sid_size, SMMUv3State),
26
--
27
2.20.1
28
29
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
2
3
No code out of bcm2836.c uses (or requires) the BCM283XInfo
4
declarations. Move it locally to the C source file.
5
6
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
7
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20201024170127.3592182-2-f4bug@amsat.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
include/hw/arm/bcm2836.h | 8 --------
12
hw/arm/bcm2836.c | 14 ++++++++++++++
13
2 files changed, 14 insertions(+), 8 deletions(-)
14
15
diff --git a/include/hw/arm/bcm2836.h b/include/hw/arm/bcm2836.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/arm/bcm2836.h
18
+++ b/include/hw/arm/bcm2836.h
19
@@ -XXX,XX +XXX,XX @@ struct BCM283XState {
20
BCM2835PeripheralState peripherals;
21
};
22
23
-typedef struct BCM283XInfo BCM283XInfo;
24
-
25
-struct BCM283XClass {
26
- DeviceClass parent_class;
27
- const BCM283XInfo *info;
28
-};
29
-
30
-
31
#endif /* BCM2836_H */
32
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/hw/arm/bcm2836.c
35
+++ b/hw/arm/bcm2836.c
36
@@ -XXX,XX +XXX,XX @@
37
#include "hw/arm/raspi_platform.h"
38
#include "hw/sysbus.h"
39
40
+typedef struct BCM283XInfo BCM283XInfo;
41
+
42
+typedef struct BCM283XClass {
43
+ /*< private >*/
44
+ DeviceClass parent_class;
45
+ /*< public >*/
46
+ const BCM283XInfo *info;
47
+} BCM283XClass;
48
+
49
struct BCM283XInfo {
50
const char *name;
51
const char *cpu_type;
52
@@ -XXX,XX +XXX,XX @@ struct BCM283XInfo {
53
int clusterid;
54
};
55
56
+#define BCM283X_CLASS(klass) \
57
+ OBJECT_CLASS_CHECK(BCM283XClass, (klass), TYPE_BCM283X)
58
+#define BCM283X_GET_CLASS(obj) \
59
+ OBJECT_GET_CLASS(BCM283XClass, (obj), TYPE_BCM283X)
60
+
61
static const BCM283XInfo bcm283x_socs[] = {
62
{
63
.name = TYPE_BCM2836,
64
--
65
2.20.1
66
67
diff view generated by jsdifflib
New patch
1
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
3
Remove usage of TypeInfo::class_data. Instead fill the fields in
4
the corresponding class_init().
5
6
So far all children use the same values for almost all fields,
7
but we are going to add the BCM2711/BCM2838 SoC for the raspi4
8
machine which use different fields.
9
10
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
11
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Message-id: 20201024170127.3592182-3-f4bug@amsat.org
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
hw/arm/bcm2836.c | 108 ++++++++++++++++++++++-------------------------
16
1 file changed, 51 insertions(+), 57 deletions(-)
17
18
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/arm/bcm2836.c
21
+++ b/hw/arm/bcm2836.c
22
@@ -XXX,XX +XXX,XX @@
23
#include "hw/arm/raspi_platform.h"
24
#include "hw/sysbus.h"
25
26
-typedef struct BCM283XInfo BCM283XInfo;
27
-
28
typedef struct BCM283XClass {
29
/*< private >*/
30
DeviceClass parent_class;
31
/*< public >*/
32
- const BCM283XInfo *info;
33
-} BCM283XClass;
34
-
35
-struct BCM283XInfo {
36
const char *name;
37
const char *cpu_type;
38
hwaddr peri_base; /* Peripheral base address seen by the CPU */
39
hwaddr ctrl_base; /* Interrupt controller and mailboxes etc. */
40
int clusterid;
41
-};
42
+} BCM283XClass;
43
44
#define BCM283X_CLASS(klass) \
45
OBJECT_CLASS_CHECK(BCM283XClass, (klass), TYPE_BCM283X)
46
#define BCM283X_GET_CLASS(obj) \
47
OBJECT_GET_CLASS(BCM283XClass, (obj), TYPE_BCM283X)
48
49
-static const BCM283XInfo bcm283x_socs[] = {
50
- {
51
- .name = TYPE_BCM2836,
52
- .cpu_type = ARM_CPU_TYPE_NAME("cortex-a7"),
53
- .peri_base = 0x3f000000,
54
- .ctrl_base = 0x40000000,
55
- .clusterid = 0xf,
56
- },
57
-#ifdef TARGET_AARCH64
58
- {
59
- .name = TYPE_BCM2837,
60
- .cpu_type = ARM_CPU_TYPE_NAME("cortex-a53"),
61
- .peri_base = 0x3f000000,
62
- .ctrl_base = 0x40000000,
63
- .clusterid = 0x0,
64
- },
65
-#endif
66
-};
67
-
68
static void bcm2836_init(Object *obj)
69
{
70
BCM283XState *s = BCM283X(obj);
71
BCM283XClass *bc = BCM283X_GET_CLASS(obj);
72
- const BCM283XInfo *info = bc->info;
73
int n;
74
75
for (n = 0; n < BCM283X_NCPUS; n++) {
76
object_initialize_child(obj, "cpu[*]", &s->cpu[n].core,
77
- info->cpu_type);
78
+ bc->cpu_type);
79
}
80
81
object_initialize_child(obj, "control", &s->control, TYPE_BCM2836_CONTROL);
82
@@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
83
{
84
BCM283XState *s = BCM283X(dev);
85
BCM283XClass *bc = BCM283X_GET_CLASS(dev);
86
- const BCM283XInfo *info = bc->info;
87
Object *obj;
88
int n;
89
90
@@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
91
"sd-bus");
92
93
sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->peripherals), 0,
94
- info->peri_base, 1);
95
+ bc->peri_base, 1);
96
97
/* bcm2836 interrupt controller (and mailboxes, etc.) */
98
if (!sysbus_realize(SYS_BUS_DEVICE(&s->control), errp)) {
99
return;
100
}
101
102
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->control), 0, info->ctrl_base);
103
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->control), 0, bc->ctrl_base);
104
105
sysbus_connect_irq(SYS_BUS_DEVICE(&s->peripherals), 0,
106
qdev_get_gpio_in_named(DEVICE(&s->control), "gpu-irq", 0));
107
@@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
108
109
for (n = 0; n < BCM283X_NCPUS; n++) {
110
/* TODO: this should be converted to a property of ARM_CPU */
111
- s->cpu[n].core.mp_affinity = (info->clusterid << 8) | n;
112
+ s->cpu[n].core.mp_affinity = (bc->clusterid << 8) | n;
113
114
/* set periphbase/CBAR value for CPU-local registers */
115
if (!object_property_set_int(OBJECT(&s->cpu[n].core), "reset-cbar",
116
- info->peri_base, errp)) {
117
+ bc->peri_base, errp)) {
118
return;
119
}
120
121
@@ -XXX,XX +XXX,XX @@ static Property bcm2836_props[] = {
122
static void bcm283x_class_init(ObjectClass *oc, void *data)
123
{
124
DeviceClass *dc = DEVICE_CLASS(oc);
125
- BCM283XClass *bc = BCM283X_CLASS(oc);
126
127
- bc->info = data;
128
- dc->realize = bcm2836_realize;
129
- device_class_set_props(dc, bcm2836_props);
130
/* Reason: Must be wired up in code (see raspi_init() function) */
131
dc->user_creatable = false;
132
}
133
134
-static const TypeInfo bcm283x_type_info = {
135
- .name = TYPE_BCM283X,
136
- .parent = TYPE_DEVICE,
137
- .instance_size = sizeof(BCM283XState),
138
- .instance_init = bcm2836_init,
139
- .class_size = sizeof(BCM283XClass),
140
- .abstract = true,
141
+static void bcm2836_class_init(ObjectClass *oc, void *data)
142
+{
143
+ DeviceClass *dc = DEVICE_CLASS(oc);
144
+ BCM283XClass *bc = BCM283X_CLASS(oc);
145
+
146
+ bc->cpu_type = ARM_CPU_TYPE_NAME("cortex-a7");
147
+ bc->peri_base = 0x3f000000;
148
+ bc->ctrl_base = 0x40000000;
149
+ bc->clusterid = 0xf;
150
+ dc->realize = bcm2836_realize;
151
+ device_class_set_props(dc, bcm2836_props);
152
};
153
154
-static void bcm2836_register_types(void)
155
+#ifdef TARGET_AARCH64
156
+static void bcm2837_class_init(ObjectClass *oc, void *data)
157
{
158
- int i;
159
+ DeviceClass *dc = DEVICE_CLASS(oc);
160
+ BCM283XClass *bc = BCM283X_CLASS(oc);
161
162
- type_register_static(&bcm283x_type_info);
163
- for (i = 0; i < ARRAY_SIZE(bcm283x_socs); i++) {
164
- TypeInfo ti = {
165
- .name = bcm283x_socs[i].name,
166
- .parent = TYPE_BCM283X,
167
- .class_init = bcm283x_class_init,
168
- .class_data = (void *) &bcm283x_socs[i],
169
- };
170
- type_register(&ti);
171
+ bc->cpu_type = ARM_CPU_TYPE_NAME("cortex-a53");
172
+ bc->peri_base = 0x3f000000;
173
+ bc->ctrl_base = 0x40000000;
174
+ bc->clusterid = 0x0;
175
+ dc->realize = bcm2836_realize;
176
+ device_class_set_props(dc, bcm2836_props);
177
+};
178
+#endif
179
+
180
+static const TypeInfo bcm283x_types[] = {
181
+ {
182
+ .name = TYPE_BCM2836,
183
+ .parent = TYPE_BCM283X,
184
+ .class_init = bcm2836_class_init,
185
+#ifdef TARGET_AARCH64
186
+ }, {
187
+ .name = TYPE_BCM2837,
188
+ .parent = TYPE_BCM283X,
189
+ .class_init = bcm2837_class_init,
190
+#endif
191
+ }, {
192
+ .name = TYPE_BCM283X,
193
+ .parent = TYPE_DEVICE,
194
+ .instance_size = sizeof(BCM283XState),
195
+ .instance_init = bcm2836_init,
196
+ .class_size = sizeof(BCM283XClass),
197
+ .class_init = bcm283x_class_init,
198
+ .abstract = true,
199
}
200
-}
201
+};
202
203
-type_init(bcm2836_register_types)
204
+DEFINE_TYPES(bcm283x_types)
205
--
206
2.20.1
207
208
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
2
3
The BCM2835 has only one core. Introduce the core_count field to
4
be able to use values different than BCM283X_NCPUS (4).
5
6
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
7
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20201024170127.3592182-4-f4bug@amsat.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
hw/arm/bcm2836.c | 5 ++++-
12
1 file changed, 4 insertions(+), 1 deletion(-)
13
14
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/bcm2836.c
17
+++ b/hw/arm/bcm2836.c
18
@@ -XXX,XX +XXX,XX @@ typedef struct BCM283XClass {
19
/*< public >*/
20
const char *name;
21
const char *cpu_type;
22
+ unsigned core_count;
23
hwaddr peri_base; /* Peripheral base address seen by the CPU */
24
hwaddr ctrl_base; /* Interrupt controller and mailboxes etc. */
25
int clusterid;
26
@@ -XXX,XX +XXX,XX @@ static void bcm2836_init(Object *obj)
27
BCM283XClass *bc = BCM283X_GET_CLASS(obj);
28
int n;
29
30
- for (n = 0; n < BCM283X_NCPUS; n++) {
31
+ for (n = 0; n < bc->core_count; n++) {
32
object_initialize_child(obj, "cpu[*]", &s->cpu[n].core,
33
bc->cpu_type);
34
}
35
@@ -XXX,XX +XXX,XX @@ static void bcm2836_class_init(ObjectClass *oc, void *data)
36
BCM283XClass *bc = BCM283X_CLASS(oc);
37
38
bc->cpu_type = ARM_CPU_TYPE_NAME("cortex-a7");
39
+ bc->core_count = BCM283X_NCPUS;
40
bc->peri_base = 0x3f000000;
41
bc->ctrl_base = 0x40000000;
42
bc->clusterid = 0xf;
43
@@ -XXX,XX +XXX,XX @@ static void bcm2837_class_init(ObjectClass *oc, void *data)
44
BCM283XClass *bc = BCM283X_CLASS(oc);
45
46
bc->cpu_type = ARM_CPU_TYPE_NAME("cortex-a53");
47
+ bc->core_count = BCM283X_NCPUS;
48
bc->peri_base = 0x3f000000;
49
bc->ctrl_base = 0x40000000;
50
bc->clusterid = 0x0;
51
--
52
2.20.1
53
54
diff view generated by jsdifflib
1
Make the ARMv7M object take a memory region link which it uses
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
to wire up the bitband rather than having them always put
3
themselves in the system address space.
4
2
3
It makes no sense to set enabled-cpus=0 on single core SoCs.
4
5
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
6
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20201024170127.3592182-5-f4bug@amsat.org
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Message-id: 1487604965-23220-6-git-send-email-peter.maydell@linaro.org
8
---
9
---
9
include/hw/arm/armv7m.h | 10 ++++++++++
10
hw/arm/bcm2836.c | 15 +++++++--------
10
hw/arm/armv7m.c | 23 ++++++++++++++++++++++-
11
1 file changed, 7 insertions(+), 8 deletions(-)
11
2 files changed, 32 insertions(+), 1 deletion(-)
12
12
13
diff --git a/include/hw/arm/armv7m.h b/include/hw/arm/armv7m.h
13
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
14
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/arm/armv7m.h
15
--- a/hw/arm/bcm2836.c
16
+++ b/include/hw/arm/armv7m.h
16
+++ b/hw/arm/bcm2836.c
17
@@ -XXX,XX +XXX,XX @@ typedef struct {
17
@@ -XXX,XX +XXX,XX @@ typedef struct BCM283XClass {
18
* + Named GPIO output SYSRESETREQ: signalled for guest AIRCR.SYSRESETREQ
18
#define BCM283X_GET_CLASS(obj) \
19
* + Property "cpu-model": CPU model to instantiate
19
OBJECT_GET_CLASS(BCM283XClass, (obj), TYPE_BCM283X)
20
* + Property "num-irq": number of external IRQ lines
20
21
+ * + Property "memory": MemoryRegion defining the physical address space
21
+static Property bcm2836_enabled_cores_property =
22
+ * that CPU accesses see. (The NVIC, bitbanding and other CPU-internal
22
+ DEFINE_PROP_UINT32("enabled-cpus", BCM283XState, enabled_cpus, 0);
23
+ * devices will be automatically layered on top of this view.)
24
*/
25
typedef struct ARMv7MState {
26
/*< private >*/
27
@@ -XXX,XX +XXX,XX @@ typedef struct ARMv7MState {
28
BitBandState bitband[ARMV7M_NUM_BITBANDS];
29
ARMCPU *cpu;
30
31
+ /* MemoryRegion we pass to the CPU, with our devices layered on
32
+ * top of the ones the board provides in board_memory.
33
+ */
34
+ MemoryRegion container;
35
+
23
+
36
/* Properties */
24
static void bcm2836_init(Object *obj)
37
char *cpu_model;
25
{
38
+ /* MemoryRegion the board provides to us (with its devices, RAM, etc) */
26
BCM283XState *s = BCM283X(obj);
39
+ MemoryRegion *board_memory;
27
@@ -XXX,XX +XXX,XX @@ static void bcm2836_init(Object *obj)
40
} ARMv7MState;
28
object_initialize_child(obj, "cpu[*]", &s->cpu[n].core,
41
29
bc->cpu_type);
42
#endif
30
}
43
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
31
+ if (bc->core_count > 1) {
44
index XXXXXXX..XXXXXXX 100644
32
+ qdev_property_add_static(DEVICE(obj), &bcm2836_enabled_cores_property);
45
--- a/hw/arm/armv7m.c
33
+ qdev_prop_set_uint32(DEVICE(obj), "enabled-cpus", bc->core_count);
46
+++ b/hw/arm/armv7m.c
47
@@ -XXX,XX +XXX,XX @@
48
#include "elf.h"
49
#include "sysemu/qtest.h"
50
#include "qemu/error-report.h"
51
+#include "exec/address-spaces.h"
52
53
/* Bitbanded IO. Each word corresponds to a single bit. */
54
55
@@ -XXX,XX +XXX,XX @@ static void armv7m_instance_init(Object *obj)
56
57
/* Can't init the cpu here, we don't yet know which model to use */
58
59
+ object_property_add_link(obj, "memory",
60
+ TYPE_MEMORY_REGION,
61
+ (Object **)&s->board_memory,
62
+ qdev_prop_allow_set_link_before_realize,
63
+ OBJ_PROP_LINK_UNREF_ON_RELEASE,
64
+ &error_abort);
65
+ memory_region_init(&s->container, obj, "armv7m-container", UINT64_MAX);
66
+
67
object_initialize(&s->nvic, sizeof(s->nvic), "armv7m_nvic");
68
qdev_set_parent_bus(DEVICE(&s->nvic), sysbus_get_default());
69
object_property_add_alias(obj, "num-irq",
70
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
71
const char *typename;
72
CPUClass *cc;
73
74
+ if (!s->board_memory) {
75
+ error_setg(errp, "memory property was not set");
76
+ return;
77
+ }
34
+ }
78
+
35
79
+ memory_region_add_subregion_overlap(&s->container, 0, s->board_memory, -1);
36
object_initialize_child(obj, "control", &s->control, TYPE_BCM2836_CONTROL);
80
+
37
81
cpustr = g_strsplit(s->cpu_model, ",", 2);
38
@@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
82
83
oc = cpu_class_by_name(TYPE_ARM_CPU, cpustr[0]);
84
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
85
return;
86
}
87
88
+ object_property_set_link(OBJECT(s->cpu), OBJECT(&s->container), "memory",
89
+ &error_abort);
90
object_property_set_bool(OBJECT(s->cpu), true, "realized", &err);
91
if (err != NULL) {
92
error_propagate(errp, err);
93
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
94
return;
95
}
96
97
- sysbus_mmio_map(sbd, 0, bitband_output_addr[i]);
98
+ memory_region_add_subregion(&s->container, bitband_output_addr[i],
99
+ sysbus_mmio_get_region(sbd, 0));
100
}
39
}
101
}
40
}
102
41
103
@@ -XXX,XX +XXX,XX @@ DeviceState *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq,
42
-static Property bcm2836_props[] = {
104
armv7m = qdev_create(NULL, "armv7m");
43
- DEFINE_PROP_UINT32("enabled-cpus", BCM283XState, enabled_cpus,
105
qdev_prop_set_uint32(armv7m, "num-irq", num_irq);
44
- BCM283X_NCPUS),
106
qdev_prop_set_string(armv7m, "cpu-model", cpu_model);
45
- DEFINE_PROP_END_OF_LIST()
107
+ object_property_set_link(OBJECT(armv7m), OBJECT(get_system_memory()),
46
-};
108
+ "memory", &error_abort);
47
-
109
/* This will exit with an error if the user passed us a bad cpu_model */
48
static void bcm283x_class_init(ObjectClass *oc, void *data)
110
qdev_init_nofail(armv7m);
49
{
50
DeviceClass *dc = DEVICE_CLASS(oc);
51
@@ -XXX,XX +XXX,XX @@ static void bcm2836_class_init(ObjectClass *oc, void *data)
52
bc->ctrl_base = 0x40000000;
53
bc->clusterid = 0xf;
54
dc->realize = bcm2836_realize;
55
- device_class_set_props(dc, bcm2836_props);
56
};
57
58
#ifdef TARGET_AARCH64
59
@@ -XXX,XX +XXX,XX @@ static void bcm2837_class_init(ObjectClass *oc, void *data)
60
bc->ctrl_base = 0x40000000;
61
bc->clusterid = 0x0;
62
dc->realize = bcm2836_realize;
63
- device_class_set_props(dc, bcm2836_props);
64
};
65
#endif
111
66
112
--
67
--
113
2.7.4
68
2.20.1
114
69
115
70
diff view generated by jsdifflib
1
Switch the stm32f205 SoC to create the armv7m object directly
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
rather than via the armv7m_init() wrapper. This fits better
3
with the SoC model's very QOMified design.
4
2
5
In particular this means we can push loading the guest image
3
The realize() function is clearly composed of two parts,
6
out to the top level board code where it belongs, rather
4
each described by a comment:
7
than the SoC object having a QOM property for the filename
8
to load.
9
5
6
void realize()
7
{
8
/* common peripherals from bcm2835 */
9
...
10
/* bcm2836 interrupt controller (and mailboxes, etc.) */
11
...
12
}
13
14
Split the two part, so we can reuse the common part with other
15
SoCs from this family.
16
17
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
18
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
19
Message-id: 20201024170127.3592182-6-f4bug@amsat.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
13
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
14
Message-id: 1487604965-23220-11-git-send-email-peter.maydell@linaro.org
15
---
21
---
16
include/hw/arm/stm32f205_soc.h | 4 +++-
22
hw/arm/bcm2836.c | 22 ++++++++++++++++++----
17
hw/arm/netduino2.c | 7 ++++---
23
1 file changed, 18 insertions(+), 4 deletions(-)
18
hw/arm/stm32f205_soc.c | 16 +++++++++++++---
19
3 files changed, 20 insertions(+), 7 deletions(-)
20
24
21
diff --git a/include/hw/arm/stm32f205_soc.h b/include/hw/arm/stm32f205_soc.h
25
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
22
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
23
--- a/include/hw/arm/stm32f205_soc.h
27
--- a/hw/arm/bcm2836.c
24
+++ b/include/hw/arm/stm32f205_soc.h
28
+++ b/hw/arm/bcm2836.c
25
@@ -XXX,XX +XXX,XX @@
29
@@ -XXX,XX +XXX,XX @@ static void bcm2836_init(Object *obj)
26
#include "hw/adc/stm32f2xx_adc.h"
30
qdev_prop_set_uint32(DEVICE(obj), "enabled-cpus", bc->core_count);
27
#include "hw/or-irq.h"
31
}
28
#include "hw/ssi/stm32f2xx_spi.h"
32
29
+#include "hw/arm/armv7m.h"
33
- object_initialize_child(obj, "control", &s->control, TYPE_BCM2836_CONTROL);
30
34
+ if (bc->ctrl_base) {
31
#define TYPE_STM32F205_SOC "stm32f205-soc"
35
+ object_initialize_child(obj, "control", &s->control,
32
#define STM32F205_SOC(obj) \
36
+ TYPE_BCM2836_CONTROL);
33
@@ -XXX,XX +XXX,XX @@ typedef struct STM32F205State {
37
+ }
34
SysBusDevice parent_obj;
38
35
/*< public >*/
39
object_initialize_child(obj, "peripherals", &s->peripherals,
36
40
TYPE_BCM2835_PERIPHERALS);
37
- char *kernel_filename;
41
@@ -XXX,XX +XXX,XX @@ static void bcm2836_init(Object *obj)
38
char *cpu_model;
42
"vcram-size");
39
43
}
40
+ ARMv7MState armv7m;
44
45
-static void bcm2836_realize(DeviceState *dev, Error **errp)
46
+static bool bcm283x_common_realize(DeviceState *dev, Error **errp)
47
{
48
BCM283XState *s = BCM283X(dev);
49
BCM283XClass *bc = BCM283X_GET_CLASS(dev);
50
Object *obj;
51
- int n;
52
53
/* common peripherals from bcm2835 */
54
55
@@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
56
object_property_add_const_link(OBJECT(&s->peripherals), "ram", obj);
57
58
if (!sysbus_realize(SYS_BUS_DEVICE(&s->peripherals), errp)) {
59
- return;
60
+ return false;
61
}
62
63
object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->peripherals),
64
@@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
65
66
sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->peripherals), 0,
67
bc->peri_base, 1);
68
+ return true;
69
+}
41
+
70
+
42
STM32F2XXSyscfgState syscfg;
71
+static void bcm2836_realize(DeviceState *dev, Error **errp)
43
STM32F2XXUsartState usart[STM_NUM_USARTS];
72
+{
44
STM32F2XXTimerState timer[STM_NUM_TIMERS];
73
+ BCM283XState *s = BCM283X(dev);
45
diff --git a/hw/arm/netduino2.c b/hw/arm/netduino2.c
74
+ BCM283XClass *bc = BCM283X_GET_CLASS(dev);
46
index XXXXXXX..XXXXXXX 100644
75
+ int n;
47
--- a/hw/arm/netduino2.c
48
+++ b/hw/arm/netduino2.c
49
@@ -XXX,XX +XXX,XX @@
50
#include "hw/boards.h"
51
#include "qemu/error-report.h"
52
#include "hw/arm/stm32f205_soc.h"
53
+#include "hw/arm/arm.h"
54
55
static void netduino2_init(MachineState *machine)
56
{
57
DeviceState *dev;
58
59
dev = qdev_create(NULL, TYPE_STM32F205_SOC);
60
- if (machine->kernel_filename) {
61
- qdev_prop_set_string(dev, "kernel-filename", machine->kernel_filename);
62
- }
63
qdev_prop_set_string(dev, "cpu-model", "cortex-m3");
64
object_property_set_bool(OBJECT(dev), true, "realized", &error_fatal);
65
+
76
+
66
+ armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
77
+ if (!bcm283x_common_realize(dev, errp)) {
67
+ FLASH_SIZE);
68
}
69
70
static void netduino2_machine_init(MachineClass *mc)
71
diff --git a/hw/arm/stm32f205_soc.c b/hw/arm/stm32f205_soc.c
72
index XXXXXXX..XXXXXXX 100644
73
--- a/hw/arm/stm32f205_soc.c
74
+++ b/hw/arm/stm32f205_soc.c
75
@@ -XXX,XX +XXX,XX @@ static void stm32f205_soc_initfn(Object *obj)
76
STM32F205State *s = STM32F205_SOC(obj);
77
int i;
78
79
+ object_initialize(&s->armv7m, sizeof(s->armv7m), TYPE_ARMV7M);
80
+ qdev_set_parent_bus(DEVICE(&s->armv7m), sysbus_get_default());
81
+
82
object_initialize(&s->syscfg, sizeof(s->syscfg), TYPE_STM32F2XX_SYSCFG);
83
qdev_set_parent_bus(DEVICE(&s->syscfg), sysbus_get_default());
84
85
@@ -XXX,XX +XXX,XX @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp)
86
vmstate_register_ram_global(sram);
87
memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, sram);
88
89
- nvic = armv7m_init(get_system_memory(), FLASH_SIZE, 96,
90
- s->kernel_filename, s->cpu_model);
91
+ nvic = DEVICE(&s->armv7m);
92
+ qdev_prop_set_uint32(nvic, "num-irq", 96);
93
+ qdev_prop_set_string(nvic, "cpu-model", s->cpu_model);
94
+ object_property_set_link(OBJECT(&s->armv7m), OBJECT(get_system_memory()),
95
+ "memory", &error_abort);
96
+ object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err);
97
+ if (err != NULL) {
98
+ error_propagate(errp, err);
99
+ return;
78
+ return;
100
+ }
79
+ }
101
80
102
/* System configuration controller */
81
/* bcm2836 interrupt controller (and mailboxes, etc.) */
103
dev = DEVICE(&s->syscfg);
82
if (!sysbus_realize(SYS_BUS_DEVICE(&s->control), errp)) {
104
@@ -XXX,XX +XXX,XX @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp)
105
}
106
107
static Property stm32f205_soc_properties[] = {
108
- DEFINE_PROP_STRING("kernel-filename", STM32F205State, kernel_filename),
109
DEFINE_PROP_STRING("cpu-model", STM32F205State, cpu_model),
110
DEFINE_PROP_END_OF_LIST(),
111
};
112
--
83
--
113
2.7.4
84
2.20.1
114
85
115
86
diff view generated by jsdifflib
1
Instead of the bitband device doing a cpu_physical_memory_read/write,
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
make it take a MemoryRegion which specifies where it should be
3
accessing, and use address_space_read/write to access the
4
corresponding AddressSpace.
5
2
6
Since this entails pretty much a rewrite, convert away from
3
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
7
old_mmio in the process.
4
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Message-id: 20201024170127.3592182-7-f4bug@amsat.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
8
include/hw/arm/bcm2836.h | 1 +
9
hw/arm/bcm2836.c | 34 ++++++++++++++++++++++++++++++++++
10
hw/arm/raspi.c | 2 ++
11
3 files changed, 37 insertions(+)
8
12
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
diff --git a/include/hw/arm/bcm2836.h b/include/hw/arm/bcm2836.h
10
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
11
Message-id: 1487604965-23220-8-git-send-email-peter.maydell@linaro.org
12
---
13
include/hw/arm/armv7m.h | 2 +
14
hw/arm/armv7m.c | 166 +++++++++++++++++++++++-------------------------
15
2 files changed, 81 insertions(+), 87 deletions(-)
16
17
diff --git a/include/hw/arm/armv7m.h b/include/hw/arm/armv7m.h
18
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/arm/armv7m.h
15
--- a/include/hw/arm/bcm2836.h
20
+++ b/include/hw/arm/armv7m.h
16
+++ b/include/hw/arm/bcm2836.h
21
@@ -XXX,XX +XXX,XX @@ typedef struct {
17
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_TYPE(BCM283XState, BCM283XClass, BCM283X)
22
SysBusDevice parent_obj;
18
* them, code using these devices should always handle them via the
23
/*< public >*/
19
* BCM283x base class, so they have no BCM2836(obj) etc macros.
24
20
*/
25
+ AddressSpace *source_as;
21
+#define TYPE_BCM2835 "bcm2835"
26
MemoryRegion iomem;
22
#define TYPE_BCM2836 "bcm2836"
27
uint32_t base;
23
#define TYPE_BCM2837 "bcm2837"
28
+ MemoryRegion *source_memory;
24
29
} BitBandState;
25
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
30
31
#define TYPE_ARMV7M "armv7m"
32
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
33
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
34
--- a/hw/arm/armv7m.c
27
--- a/hw/arm/bcm2836.c
35
+++ b/hw/arm/armv7m.c
28
+++ b/hw/arm/bcm2836.c
36
@@ -XXX,XX +XXX,XX @@
29
@@ -XXX,XX +XXX,XX @@ static bool bcm283x_common_realize(DeviceState *dev, Error **errp)
37
/* Bitbanded IO. Each word corresponds to a single bit. */
30
return true;
38
39
/* Get the byte address of the real memory for a bitband access. */
40
-static inline uint32_t bitband_addr(void * opaque, uint32_t addr)
41
+static inline hwaddr bitband_addr(BitBandState *s, hwaddr offset)
42
{
43
- uint32_t res;
44
-
45
- res = *(uint32_t *)opaque;
46
- res |= (addr & 0x1ffffff) >> 5;
47
- return res;
48
-
49
-}
50
-
51
-static uint32_t bitband_readb(void *opaque, hwaddr offset)
52
-{
53
- uint8_t v;
54
- cpu_physical_memory_read(bitband_addr(opaque, offset), &v, 1);
55
- return (v & (1 << ((offset >> 2) & 7))) != 0;
56
-}
57
-
58
-static void bitband_writeb(void *opaque, hwaddr offset,
59
- uint32_t value)
60
-{
61
- uint32_t addr;
62
- uint8_t mask;
63
- uint8_t v;
64
- addr = bitband_addr(opaque, offset);
65
- mask = (1 << ((offset >> 2) & 7));
66
- cpu_physical_memory_read(addr, &v, 1);
67
- if (value & 1)
68
- v |= mask;
69
- else
70
- v &= ~mask;
71
- cpu_physical_memory_write(addr, &v, 1);
72
-}
73
-
74
-static uint32_t bitband_readw(void *opaque, hwaddr offset)
75
-{
76
- uint32_t addr;
77
- uint16_t mask;
78
- uint16_t v;
79
- addr = bitband_addr(opaque, offset) & ~1;
80
- mask = (1 << ((offset >> 2) & 15));
81
- mask = tswap16(mask);
82
- cpu_physical_memory_read(addr, &v, 2);
83
- return (v & mask) != 0;
84
-}
85
-
86
-static void bitband_writew(void *opaque, hwaddr offset,
87
- uint32_t value)
88
-{
89
- uint32_t addr;
90
- uint16_t mask;
91
- uint16_t v;
92
- addr = bitband_addr(opaque, offset) & ~1;
93
- mask = (1 << ((offset >> 2) & 15));
94
- mask = tswap16(mask);
95
- cpu_physical_memory_read(addr, &v, 2);
96
- if (value & 1)
97
- v |= mask;
98
- else
99
- v &= ~mask;
100
- cpu_physical_memory_write(addr, &v, 2);
101
+ return s->base | (offset & 0x1ffffff) >> 5;
102
}
31
}
103
32
104
-static uint32_t bitband_readl(void *opaque, hwaddr offset)
33
+static void bcm2835_realize(DeviceState *dev, Error **errp)
105
+static MemTxResult bitband_read(void *opaque, hwaddr offset,
34
+{
106
+ uint64_t *data, unsigned size, MemTxAttrs attrs)
35
+ BCM283XState *s = BCM283X(dev);
107
{
108
- uint32_t addr;
109
- uint32_t mask;
110
- uint32_t v;
111
- addr = bitband_addr(opaque, offset) & ~3;
112
- mask = (1 << ((offset >> 2) & 31));
113
- mask = tswap32(mask);
114
- cpu_physical_memory_read(addr, &v, 4);
115
- return (v & mask) != 0;
116
+ BitBandState *s = opaque;
117
+ uint8_t buf[4];
118
+ MemTxResult res;
119
+ int bitpos, bit;
120
+ hwaddr addr;
121
+
36
+
122
+ assert(size <= 4);
37
+ if (!bcm283x_common_realize(dev, errp)) {
123
+
124
+ /* Find address in underlying memory and round down to multiple of size */
125
+ addr = bitband_addr(s, offset) & (-size);
126
+ res = address_space_read(s->source_as, addr, attrs, buf, size);
127
+ if (res) {
128
+ return res;
129
+ }
130
+ /* Bit position in the N bytes read... */
131
+ bitpos = (offset >> 2) & ((size * 8) - 1);
132
+ /* ...converted to byte in buffer and bit in byte */
133
+ bit = (buf[bitpos >> 3] >> (bitpos & 7)) & 1;
134
+ *data = bit;
135
+ return MEMTX_OK;
136
}
137
138
-static void bitband_writel(void *opaque, hwaddr offset,
139
- uint32_t value)
140
+static MemTxResult bitband_write(void *opaque, hwaddr offset, uint64_t value,
141
+ unsigned size, MemTxAttrs attrs)
142
{
143
- uint32_t addr;
144
- uint32_t mask;
145
- uint32_t v;
146
- addr = bitband_addr(opaque, offset) & ~3;
147
- mask = (1 << ((offset >> 2) & 31));
148
- mask = tswap32(mask);
149
- cpu_physical_memory_read(addr, &v, 4);
150
- if (value & 1)
151
- v |= mask;
152
- else
153
- v &= ~mask;
154
- cpu_physical_memory_write(addr, &v, 4);
155
+ BitBandState *s = opaque;
156
+ uint8_t buf[4];
157
+ MemTxResult res;
158
+ int bitpos, bit;
159
+ hwaddr addr;
160
+
161
+ assert(size <= 4);
162
+
163
+ /* Find address in underlying memory and round down to multiple of size */
164
+ addr = bitband_addr(s, offset) & (-size);
165
+ res = address_space_read(s->source_as, addr, attrs, buf, size);
166
+ if (res) {
167
+ return res;
168
+ }
169
+ /* Bit position in the N bytes read... */
170
+ bitpos = (offset >> 2) & ((size * 8) - 1);
171
+ /* ...converted to byte in buffer and bit in byte */
172
+ bit = 1 << (bitpos & 7);
173
+ if (value & 1) {
174
+ buf[bitpos >> 3] |= bit;
175
+ } else {
176
+ buf[bitpos >> 3] &= ~bit;
177
+ }
178
+ return address_space_write(s->source_as, addr, attrs, buf, size);
179
}
180
181
static const MemoryRegionOps bitband_ops = {
182
- .old_mmio = {
183
- .read = { bitband_readb, bitband_readw, bitband_readl, },
184
- .write = { bitband_writeb, bitband_writew, bitband_writel, },
185
- },
186
+ .read_with_attrs = bitband_read,
187
+ .write_with_attrs = bitband_write,
188
.endianness = DEVICE_NATIVE_ENDIAN,
189
+ .impl.min_access_size = 1,
190
+ .impl.max_access_size = 4,
191
+ .valid.min_access_size = 1,
192
+ .valid.max_access_size = 4,
193
};
194
195
static void bitband_init(Object *obj)
196
@@ -XXX,XX +XXX,XX @@ static void bitband_init(Object *obj)
197
BitBandState *s = BITBAND(obj);
198
SysBusDevice *dev = SYS_BUS_DEVICE(obj);
199
200
- memory_region_init_io(&s->iomem, obj, &bitband_ops, &s->base,
201
+ object_property_add_link(obj, "source-memory",
202
+ TYPE_MEMORY_REGION,
203
+ (Object **)&s->source_memory,
204
+ qdev_prop_allow_set_link_before_realize,
205
+ OBJ_PROP_LINK_UNREF_ON_RELEASE,
206
+ &error_abort);
207
+ memory_region_init_io(&s->iomem, obj, &bitband_ops, s,
208
"bitband", 0x02000000);
209
sysbus_init_mmio(dev, &s->iomem);
210
}
211
212
+static void bitband_realize(DeviceState *dev, Error **errp)
213
+{
214
+ BitBandState *s = BITBAND(dev);
215
+
216
+ if (!s->source_memory) {
217
+ error_setg(errp, "source-memory property not set");
218
+ return;
38
+ return;
219
+ }
39
+ }
220
+
40
+
221
+ s->source_as = address_space_init_shareable(s->source_memory,
41
+ if (!qdev_realize(DEVICE(&s->cpu[0].core), NULL, errp)) {
222
+ "bitband-source");
42
+ return;
43
+ }
44
+
45
+ /* Connect irq/fiq outputs from the interrupt controller. */
46
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->peripherals), 0,
47
+ qdev_get_gpio_in(DEVICE(&s->cpu[0].core), ARM_CPU_IRQ));
48
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->peripherals), 1,
49
+ qdev_get_gpio_in(DEVICE(&s->cpu[0].core), ARM_CPU_FIQ));
223
+}
50
+}
224
+
51
+
225
/* Board init. */
52
static void bcm2836_realize(DeviceState *dev, Error **errp)
226
227
static const hwaddr bitband_input_addr[ARMV7M_NUM_BITBANDS] = {
228
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
229
error_propagate(errp, err);
230
return;
231
}
232
+ object_property_set_link(obj, OBJECT(s->board_memory),
233
+ "source-memory", &error_abort);
234
object_property_set_bool(obj, true, "realized", &err);
235
if (err != NULL) {
236
error_propagate(errp, err);
237
@@ -XXX,XX +XXX,XX @@ static void bitband_class_init(ObjectClass *klass, void *data)
238
{
53
{
239
DeviceClass *dc = DEVICE_CLASS(klass);
54
BCM283XState *s = BCM283X(dev);
240
55
@@ -XXX,XX +XXX,XX @@ static void bcm283x_class_init(ObjectClass *oc, void *data)
241
+ dc->realize = bitband_realize;
56
dc->user_creatable = false;
242
dc->props = bitband_properties;
243
}
57
}
244
58
59
+static void bcm2835_class_init(ObjectClass *oc, void *data)
60
+{
61
+ DeviceClass *dc = DEVICE_CLASS(oc);
62
+ BCM283XClass *bc = BCM283X_CLASS(oc);
63
+
64
+ bc->cpu_type = ARM_CPU_TYPE_NAME("arm1176");
65
+ bc->core_count = 1;
66
+ bc->peri_base = 0x20000000;
67
+ dc->realize = bcm2835_realize;
68
+};
69
+
70
static void bcm2836_class_init(ObjectClass *oc, void *data)
71
{
72
DeviceClass *dc = DEVICE_CLASS(oc);
73
@@ -XXX,XX +XXX,XX @@ static void bcm2837_class_init(ObjectClass *oc, void *data)
74
75
static const TypeInfo bcm283x_types[] = {
76
{
77
+ .name = TYPE_BCM2835,
78
+ .parent = TYPE_BCM283X,
79
+ .class_init = bcm2835_class_init,
80
+ }, {
81
.name = TYPE_BCM2836,
82
.parent = TYPE_BCM283X,
83
.class_init = bcm2836_class_init,
84
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
85
index XXXXXXX..XXXXXXX 100644
86
--- a/hw/arm/raspi.c
87
+++ b/hw/arm/raspi.c
88
@@ -XXX,XX +XXX,XX @@ FIELD(REV_CODE, MEMORY_SIZE, 20, 3);
89
FIELD(REV_CODE, STYLE, 23, 1);
90
91
typedef enum RaspiProcessorId {
92
+ PROCESSOR_ID_BCM2835 = 0,
93
PROCESSOR_ID_BCM2836 = 1,
94
PROCESSOR_ID_BCM2837 = 2,
95
} RaspiProcessorId;
96
@@ -XXX,XX +XXX,XX @@ static const struct {
97
const char *type;
98
int cores_count;
99
} soc_property[] = {
100
+ [PROCESSOR_ID_BCM2835] = {TYPE_BCM2835, 1},
101
[PROCESSOR_ID_BCM2836] = {TYPE_BCM2836, BCM283X_NCPUS},
102
[PROCESSOR_ID_BCM2837] = {TYPE_BCM2837, BCM283X_NCPUS},
103
};
245
--
104
--
246
2.7.4
105
2.20.1
247
106
248
107
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
2
3
The Pi A is almost the first machine released.
4
It uses a BCM2835 SoC which includes a ARMv6Z core.
5
6
Example booting the machine using content from [*]
7
(we use the device tree from the B model):
8
9
$ qemu-system-arm -M raspi1ap -serial stdio \
10
-kernel raspberrypi/firmware/boot/kernel.img \
11
-dtb raspberrypi/firmware/boot/bcm2708-rpi-b-plus.dtb \
12
-append 'earlycon=pl011,0x20201000 console=ttyAMA0'
13
[ 0.000000] Booting Linux on physical CPU 0x0
14
[ 0.000000] Linux version 4.19.118+ (dom@buildbot) (gcc version 4.9.3 (crosstool-NG crosstool-ng-1.22.0-88-g8460611)) #1311 Mon Apr 27 14:16:15 BST 2020
15
[ 0.000000] CPU: ARMv6-compatible processor [410fb767] revision 7 (ARMv7), cr=00c5387d
16
[ 0.000000] CPU: VIPT aliasing data cache, unknown instruction cache
17
[ 0.000000] OF: fdt: Machine model: Raspberry Pi Model B+
18
...
19
20
[*] http://archive.raspberrypi.org/debian/pool/main/r/raspberrypi-firmware/raspberrypi-kernel_1.20200512-2_armhf.deb
21
22
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
23
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
24
Message-id: 20201024170127.3592182-8-f4bug@amsat.org
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
---
27
hw/arm/raspi.c | 13 +++++++++++++
28
1 file changed, 13 insertions(+)
29
30
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/arm/raspi.c
33
+++ b/hw/arm/raspi.c
34
@@ -XXX,XX +XXX,XX @@ static void raspi_machine_class_common_init(MachineClass *mc,
35
mc->default_ram_id = "ram";
36
};
37
38
+static void raspi1ap_machine_class_init(ObjectClass *oc, void *data)
39
+{
40
+ MachineClass *mc = MACHINE_CLASS(oc);
41
+ RaspiMachineClass *rmc = RASPI_MACHINE_CLASS(oc);
42
+
43
+ rmc->board_rev = 0x900021; /* Revision 1.1 */
44
+ raspi_machine_class_common_init(mc, rmc->board_rev);
45
+};
46
+
47
static void raspi2b_machine_class_init(ObjectClass *oc, void *data)
48
{
49
MachineClass *mc = MACHINE_CLASS(oc);
50
@@ -XXX,XX +XXX,XX @@ static void raspi3b_machine_class_init(ObjectClass *oc, void *data)
51
52
static const TypeInfo raspi_machine_types[] = {
53
{
54
+ .name = MACHINE_TYPE_NAME("raspi1ap"),
55
+ .parent = TYPE_RASPI_MACHINE,
56
+ .class_init = raspi1ap_machine_class_init,
57
+ }, {
58
.name = MACHINE_TYPE_NAME("raspi2b"),
59
.parent = TYPE_RASPI_MACHINE,
60
.class_init = raspi2b_machine_class_init,
61
--
62
2.20.1
63
64
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
2
3
Similarly to the Pi A, the Pi Zero uses a BCM2835 SoC (ARMv6Z core).
4
5
The only difference between the revision 1.2 and 1.3 is the latter
6
exposes a CSI camera connector. As we do not implement the Unicam
7
peripheral, there is no point in exposing a camera connector :)
8
Therefore we choose to model the 1.2 revision.
9
10
Example booting the machine using content from [*]:
11
12
$ qemu-system-arm -M raspi0 -serial stdio \
13
-kernel raspberrypi/firmware/boot/kernel.img \
14
-dtb raspberrypi/firmware/boot/bcm2708-rpi-zero.dtb \
15
-append 'printk.time=0 earlycon=pl011,0x20201000 console=ttyAMA0'
16
[ 0.000000] Booting Linux on physical CPU 0x0
17
[ 0.000000] Linux version 4.19.118+ (dom@buildbot) (gcc version 4.9.3 (crosstool-NG crosstool-ng-1.22.0-88-g8460611)) #1311 Mon Apr 27 14:16:15 BST 2020
18
[ 0.000000] CPU: ARMv6-compatible processor [410fb767] revision 7 (ARMv7), cr=00c5387d
19
[ 0.000000] CPU: VIPT aliasing data cache, unknown instruction cache
20
[ 0.000000] OF: fdt: Machine model: Raspberry Pi Zero
21
...
22
23
[*] http://archive.raspberrypi.org/debian/pool/main/r/raspberrypi-firmware/raspberrypi-kernel_1.20200512-2_armhf.deb
24
25
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
26
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
27
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
28
Message-id: 20201024170127.3592182-9-f4bug@amsat.org
29
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
30
---
31
hw/arm/raspi.c | 13 +++++++++++++
32
1 file changed, 13 insertions(+)
33
34
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/hw/arm/raspi.c
37
+++ b/hw/arm/raspi.c
38
@@ -XXX,XX +XXX,XX @@ static void raspi_machine_class_common_init(MachineClass *mc,
39
mc->default_ram_id = "ram";
40
};
41
42
+static void raspi0_machine_class_init(ObjectClass *oc, void *data)
43
+{
44
+ MachineClass *mc = MACHINE_CLASS(oc);
45
+ RaspiMachineClass *rmc = RASPI_MACHINE_CLASS(oc);
46
+
47
+ rmc->board_rev = 0x920092; /* Revision 1.2 */
48
+ raspi_machine_class_common_init(mc, rmc->board_rev);
49
+};
50
+
51
static void raspi1ap_machine_class_init(ObjectClass *oc, void *data)
52
{
53
MachineClass *mc = MACHINE_CLASS(oc);
54
@@ -XXX,XX +XXX,XX @@ static void raspi3b_machine_class_init(ObjectClass *oc, void *data)
55
56
static const TypeInfo raspi_machine_types[] = {
57
{
58
+ .name = MACHINE_TYPE_NAME("raspi0"),
59
+ .parent = TYPE_RASPI_MACHINE,
60
+ .class_init = raspi0_machine_class_init,
61
+ }, {
62
.name = MACHINE_TYPE_NAME("raspi1ap"),
63
.parent = TYPE_RASPI_MACHINE,
64
.class_init = raspi1ap_machine_class_init,
65
--
66
2.20.1
67
68
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
2
3
The Pi 3A+ is a stripped down version of the 3B:
4
- 512 MiB of RAM instead of 1 GiB
5
- no on-board ethernet chipset
6
7
Add it as it is a closer match to what we model.
8
9
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
10
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Message-id: 20201024170127.3592182-10-f4bug@amsat.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
hw/arm/raspi.c | 13 +++++++++++++
15
1 file changed, 13 insertions(+)
16
17
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/raspi.c
20
+++ b/hw/arm/raspi.c
21
@@ -XXX,XX +XXX,XX @@ static void raspi2b_machine_class_init(ObjectClass *oc, void *data)
22
};
23
24
#ifdef TARGET_AARCH64
25
+static void raspi3ap_machine_class_init(ObjectClass *oc, void *data)
26
+{
27
+ MachineClass *mc = MACHINE_CLASS(oc);
28
+ RaspiMachineClass *rmc = RASPI_MACHINE_CLASS(oc);
29
+
30
+ rmc->board_rev = 0x9020e0; /* Revision 1.0 */
31
+ raspi_machine_class_common_init(mc, rmc->board_rev);
32
+};
33
+
34
static void raspi3b_machine_class_init(ObjectClass *oc, void *data)
35
{
36
MachineClass *mc = MACHINE_CLASS(oc);
37
@@ -XXX,XX +XXX,XX @@ static const TypeInfo raspi_machine_types[] = {
38
.parent = TYPE_RASPI_MACHINE,
39
.class_init = raspi2b_machine_class_init,
40
#ifdef TARGET_AARCH64
41
+ }, {
42
+ .name = MACHINE_TYPE_NAME("raspi3ap"),
43
+ .parent = TYPE_RASPI_MACHINE,
44
+ .class_init = raspi3ap_machine_class_init,
45
}, {
46
.name = MACHINE_TYPE_NAME("raspi3b"),
47
.parent = TYPE_RASPI_MACHINE,
48
--
49
2.20.1
50
51
diff view generated by jsdifflib
New patch
1
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
1
2
3
Use of 0x%d - make up our mind as 0x%x
4
5
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Acked-by: Eric Auger <eric.auger@redhat.com>
8
Message-id: 20201014193355.53074-1-dgilbert@redhat.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
hw/arm/trace-events | 2 +-
12
1 file changed, 1 insertion(+), 1 deletion(-)
13
14
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/trace-events
17
+++ b/hw/arm/trace-events
18
@@ -XXX,XX +XXX,XX @@ smmuv3_get_cd(uint64_t addr) "CD addr: 0x%"PRIx64
19
smmuv3_decode_cd(uint32_t oas) "oas=%d"
20
smmuv3_decode_cd_tt(int i, uint32_t tsz, uint64_t ttb, uint32_t granule_sz, bool had) "TT[%d]:tsz:%d ttb:0x%"PRIx64" granule_sz:%d had:%d"
21
smmuv3_cmdq_cfgi_ste(int streamid) "streamid =%d"
22
-smmuv3_cmdq_cfgi_ste_range(int start, int end) "start=0x%d - end=0x%d"
23
+smmuv3_cmdq_cfgi_ste_range(int start, int end) "start=0x%x - end=0x%x"
24
smmuv3_cmdq_cfgi_cd(uint32_t sid) "streamid = %d"
25
smmuv3_config_cache_hit(uint32_t sid, uint32_t hits, uint32_t misses, uint32_t perc) "Config cache HIT for sid %d (hits=%d, misses=%d, hit rate=%d)"
26
smmuv3_config_cache_miss(uint32_t sid, uint32_t hits, uint32_t misses, uint32_t perc) "Config cache MISS for sid %d (hits=%d, misses=%d, hit rate=%d)"
27
--
28
2.20.1
29
30
diff view generated by jsdifflib
New patch
1
From: Luc Michel <luc@lmichel.fr>
1
2
3
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
Reviewed-by: Damien Hedde <damien.hedde@greensocs.com>
5
Signed-off-by: Luc Michel <luc@lmichel.fr>
6
Tested-by: Guenter Roeck <linux@roeck-us.net>
7
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
include/hw/clock.h | 5 +++++
11
1 file changed, 5 insertions(+)
12
13
diff --git a/include/hw/clock.h b/include/hw/clock.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/clock.h
16
+++ b/include/hw/clock.h
17
@@ -XXX,XX +XXX,XX @@ extern const VMStateDescription vmstate_clock;
18
VMSTATE_CLOCK_V(field, state, 0)
19
#define VMSTATE_CLOCK_V(field, state, version) \
20
VMSTATE_STRUCT_POINTER_V(field, state, version, vmstate_clock, Clock)
21
+#define VMSTATE_ARRAY_CLOCK(field, state, num) \
22
+ VMSTATE_ARRAY_CLOCK_V(field, state, num, 0)
23
+#define VMSTATE_ARRAY_CLOCK_V(field, state, num, version) \
24
+ VMSTATE_ARRAY_OF_POINTER_TO_STRUCT(field, state, num, version, \
25
+ vmstate_clock, Clock)
26
27
/**
28
* clock_setup_canonical_path:
29
--
30
2.20.1
31
32
diff view generated by jsdifflib
New patch
1
From: Luc Michel <luc@lmichel.fr>
1
2
3
The nanosecond unit greatly limits the dynamic range we can display in
4
clock value traces, for values in the order of 1GHz and more. The
5
internal representation can go way beyond this value and it is quite
6
common for today's clocks to be within those ranges.
7
8
For example, a frequency between 500MHz+ and 1GHz will be displayed as
9
1ns. Beyond 1GHz, it will show up as 0ns.
10
11
Replace nanosecond periods traces with frequencies in the Hz unit
12
to have more dynamic range in the trace output.
13
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Reviewed-by: Damien Hedde <damien.hedde@greensocs.com>
16
Signed-off-by: Luc Michel <luc@lmichel.fr>
17
Tested-by: Guenter Roeck <linux@roeck-us.net>
18
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
---
21
hw/core/clock.c | 6 +++---
22
hw/core/trace-events | 4 ++--
23
2 files changed, 5 insertions(+), 5 deletions(-)
24
25
diff --git a/hw/core/clock.c b/hw/core/clock.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/core/clock.c
28
+++ b/hw/core/clock.c
29
@@ -XXX,XX +XXX,XX @@ bool clock_set(Clock *clk, uint64_t period)
30
if (clk->period == period) {
31
return false;
32
}
33
- trace_clock_set(CLOCK_PATH(clk), CLOCK_PERIOD_TO_NS(clk->period),
34
- CLOCK_PERIOD_TO_NS(period));
35
+ trace_clock_set(CLOCK_PATH(clk), CLOCK_PERIOD_TO_HZ(clk->period),
36
+ CLOCK_PERIOD_TO_HZ(period));
37
clk->period = period;
38
39
return true;
40
@@ -XXX,XX +XXX,XX @@ static void clock_propagate_period(Clock *clk, bool call_callbacks)
41
if (child->period != clk->period) {
42
child->period = clk->period;
43
trace_clock_update(CLOCK_PATH(child), CLOCK_PATH(clk),
44
- CLOCK_PERIOD_TO_NS(clk->period),
45
+ CLOCK_PERIOD_TO_HZ(clk->period),
46
call_callbacks);
47
if (call_callbacks && child->callback) {
48
child->callback(child->callback_opaque);
49
diff --git a/hw/core/trace-events b/hw/core/trace-events
50
index XXXXXXX..XXXXXXX 100644
51
--- a/hw/core/trace-events
52
+++ b/hw/core/trace-events
53
@@ -XXX,XX +XXX,XX @@ resettable_transitional_function(void *obj, const char *objtype) "obj=%p(%s)"
54
# clock.c
55
clock_set_source(const char *clk, const char *src) "'%s', src='%s'"
56
clock_disconnect(const char *clk) "'%s'"
57
-clock_set(const char *clk, uint64_t old, uint64_t new) "'%s', ns=%"PRIu64"->%"PRIu64
58
+clock_set(const char *clk, uint64_t old, uint64_t new) "'%s', %"PRIu64"Hz->%"PRIu64"Hz"
59
clock_propagate(const char *clk) "'%s'"
60
-clock_update(const char *clk, const char *src, uint64_t val, int cb) "'%s', src='%s', ns=%"PRIu64", cb=%d"
61
+clock_update(const char *clk, const char *src, uint64_t hz, int cb) "'%s', src='%s', val=%"PRIu64"Hz cb=%d"
62
--
63
2.20.1
64
65
diff view generated by jsdifflib
New patch
1
From: Luc Michel <luc@lmichel.fr>
1
2
3
The CPRMAN (clock controller) was mapped at the watchdog/power manager
4
address. It was also split into two unimplemented peripherals (CM and
5
A2W) but this is really the same one, as shown by this extract of the
6
Raspberry Pi 3 Linux device tree:
7
8
watchdog@7e100000 {
9
compatible = "brcm,bcm2835-pm\0brcm,bcm2835-pm-wdt";
10
[...]
11
reg = <0x7e100000 0x114 0x7e00a000 0x24>;
12
[...]
13
};
14
15
[...]
16
cprman@7e101000 {
17
compatible = "brcm,bcm2835-cprman";
18
[...]
19
reg = <0x7e101000 0x2000>;
20
[...]
21
};
22
23
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
24
Signed-off-by: Luc Michel <luc@lmichel.fr>
25
Tested-by: Guenter Roeck <linux@roeck-us.net>
26
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
28
---
29
include/hw/arm/bcm2835_peripherals.h | 2 +-
30
include/hw/arm/raspi_platform.h | 5 ++---
31
hw/arm/bcm2835_peripherals.c | 4 ++--
32
3 files changed, 5 insertions(+), 6 deletions(-)
33
34
diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h
35
index XXXXXXX..XXXXXXX 100644
36
--- a/include/hw/arm/bcm2835_peripherals.h
37
+++ b/include/hw/arm/bcm2835_peripherals.h
38
@@ -XXX,XX +XXX,XX @@ struct BCM2835PeripheralState {
39
BCM2835MphiState mphi;
40
UnimplementedDeviceState txp;
41
UnimplementedDeviceState armtmr;
42
+ UnimplementedDeviceState powermgt;
43
UnimplementedDeviceState cprman;
44
- UnimplementedDeviceState a2w;
45
PL011State uart0;
46
BCM2835AuxState aux;
47
BCM2835FBState fb;
48
diff --git a/include/hw/arm/raspi_platform.h b/include/hw/arm/raspi_platform.h
49
index XXXXXXX..XXXXXXX 100644
50
--- a/include/hw/arm/raspi_platform.h
51
+++ b/include/hw/arm/raspi_platform.h
52
@@ -XXX,XX +XXX,XX @@
53
#define ARMCTRL_TIMER0_1_OFFSET (ARM_OFFSET + 0x400) /* Timer 0 and 1 (SP804) */
54
#define ARMCTRL_0_SBM_OFFSET (ARM_OFFSET + 0x800) /* User 0 (ARM) Semaphores
55
* Doorbells & Mailboxes */
56
-#define CPRMAN_OFFSET 0x100000 /* Power Management, Watchdog */
57
-#define CM_OFFSET 0x101000 /* Clock Management */
58
-#define A2W_OFFSET 0x102000 /* Reset controller */
59
+#define PM_OFFSET 0x100000 /* Power Management */
60
+#define CPRMAN_OFFSET 0x101000 /* Clock Management */
61
#define AVS_OFFSET 0x103000 /* Audio Video Standard */
62
#define RNG_OFFSET 0x104000
63
#define GPIO_OFFSET 0x200000
64
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/hw/arm/bcm2835_peripherals.c
67
+++ b/hw/arm/bcm2835_peripherals.c
68
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
69
70
create_unimp(s, &s->txp, "bcm2835-txp", TXP_OFFSET, 0x1000);
71
create_unimp(s, &s->armtmr, "bcm2835-sp804", ARMCTRL_TIMER0_1_OFFSET, 0x40);
72
- create_unimp(s, &s->cprman, "bcm2835-cprman", CPRMAN_OFFSET, 0x1000);
73
- create_unimp(s, &s->a2w, "bcm2835-a2w", A2W_OFFSET, 0x1000);
74
+ create_unimp(s, &s->powermgt, "bcm2835-powermgt", PM_OFFSET, 0x114);
75
+ create_unimp(s, &s->cprman, "bcm2835-cprman", CPRMAN_OFFSET, 0x2000);
76
create_unimp(s, &s->i2s, "bcm2835-i2s", I2S_OFFSET, 0x100);
77
create_unimp(s, &s->smi, "bcm2835-smi", SMI_OFFSET, 0x100);
78
create_unimp(s, &s->spi[0], "bcm2835-spi0", SPI0_OFFSET, 0x20);
79
--
80
2.20.1
81
82
diff view generated by jsdifflib
1
From: Clement Deschamps <clement.deschamps@antfield.fr>
1
From: Luc Michel <luc@lmichel.fr>
2
2
3
This adds the bcm2835_sdhost and bcm2835_gpio to the BCM2835 platform.
3
The BCM2835 CPRMAN is the clock manager of the SoC. It is composed of a
4
4
main oscillator, and several sub-components (PLLs, multiplexers, ...) to
5
For supporting the SD controller selection (alternate function of GPIOs
5
generate the BCM2835 clock tree.
6
48-53), the bcm2835_gpio now exposes an sdbus.
6
7
It also has a link to both the sdbus of sdhci and sdhost controllers,
7
This commit adds a skeleton of the CPRMAN, with a dummy register
8
and the card is reparented from one bus to another when the alternate
8
read/write implementation. It embeds the main oscillator (xosc) from
9
function of GPIOs 48-53 is modified.
9
which all the clocks will be derived.
10
10
11
Signed-off-by: Clement Deschamps <clement.deschamps@antfield.fr>
11
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Luc Michel <luc@lmichel.fr>
14
Message-id: 1488293711-14195-5-git-send-email-peter.maydell@linaro.org
14
Tested-by: Guenter Roeck <linux@roeck-us.net>
15
Message-id: 20170224164021.9066-5-clement.deschamps@antfield.fr
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
16
---
19
include/hw/arm/bcm2835_peripherals.h | 4 ++++
17
include/hw/arm/bcm2835_peripherals.h | 3 +-
20
hw/arm/bcm2835_peripherals.c | 43 ++++++++++++++++++++++++++++++++++--
18
include/hw/misc/bcm2835_cprman.h | 37 +++++
21
2 files changed, 45 insertions(+), 2 deletions(-)
19
include/hw/misc/bcm2835_cprman_internals.h | 24 +++
20
hw/arm/bcm2835_peripherals.c | 11 +-
21
hw/misc/bcm2835_cprman.c | 163 +++++++++++++++++++++
22
hw/misc/meson.build | 1 +
23
hw/misc/trace-events | 5 +
24
7 files changed, 242 insertions(+), 2 deletions(-)
25
create mode 100644 include/hw/misc/bcm2835_cprman.h
26
create mode 100644 include/hw/misc/bcm2835_cprman_internals.h
27
create mode 100644 hw/misc/bcm2835_cprman.c
22
28
23
diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h
29
diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h
24
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/arm/bcm2835_peripherals.h
31
--- a/include/hw/arm/bcm2835_peripherals.h
26
+++ b/include/hw/arm/bcm2835_peripherals.h
32
+++ b/include/hw/arm/bcm2835_peripherals.h
27
@@ -XXX,XX +XXX,XX @@
33
@@ -XXX,XX +XXX,XX @@
28
#include "hw/misc/bcm2835_rng.h"
29
#include "hw/misc/bcm2835_mbox.h"
34
#include "hw/misc/bcm2835_mbox.h"
35
#include "hw/misc/bcm2835_mphi.h"
36
#include "hw/misc/bcm2835_thermal.h"
37
+#include "hw/misc/bcm2835_cprman.h"
30
#include "hw/sd/sdhci.h"
38
#include "hw/sd/sdhci.h"
31
+#include "hw/sd/bcm2835_sdhost.h"
39
#include "hw/sd/bcm2835_sdhost.h"
32
+#include "hw/gpio/bcm2835_gpio.h"
40
#include "hw/gpio/bcm2835_gpio.h"
33
41
@@ -XXX,XX +XXX,XX @@ struct BCM2835PeripheralState {
34
#define TYPE_BCM2835_PERIPHERALS "bcm2835-peripherals"
42
UnimplementedDeviceState txp;
35
#define BCM2835_PERIPHERALS(obj) \
43
UnimplementedDeviceState armtmr;
36
@@ -XXX,XX +XXX,XX @@ typedef struct BCM2835PeripheralState {
44
UnimplementedDeviceState powermgt;
37
BCM2835RngState rng;
45
- UnimplementedDeviceState cprman;
38
BCM2835MboxState mboxes;
46
+ BCM2835CprmanState cprman;
39
SDHCIState sdhci;
47
PL011State uart0;
40
+ BCM2835SDHostState sdhost;
48
BCM2835AuxState aux;
41
+ BCM2835GpioState gpio;
49
BCM2835FBState fb;
42
} BCM2835PeripheralState;
50
diff --git a/include/hw/misc/bcm2835_cprman.h b/include/hw/misc/bcm2835_cprman.h
43
51
new file mode 100644
44
#endif /* BCM2835_PERIPHERALS_H */
52
index XXXXXXX..XXXXXXX
53
--- /dev/null
54
+++ b/include/hw/misc/bcm2835_cprman.h
55
@@ -XXX,XX +XXX,XX @@
56
+/*
57
+ * BCM2835 CPRMAN clock manager
58
+ *
59
+ * Copyright (c) 2020 Luc Michel <luc@lmichel.fr>
60
+ *
61
+ * SPDX-License-Identifier: GPL-2.0-or-later
62
+ */
63
+
64
+#ifndef HW_MISC_CPRMAN_H
65
+#define HW_MISC_CPRMAN_H
66
+
67
+#include "hw/sysbus.h"
68
+#include "hw/qdev-clock.h"
69
+
70
+#define TYPE_BCM2835_CPRMAN "bcm2835-cprman"
71
+
72
+typedef struct BCM2835CprmanState BCM2835CprmanState;
73
+
74
+DECLARE_INSTANCE_CHECKER(BCM2835CprmanState, CPRMAN,
75
+ TYPE_BCM2835_CPRMAN)
76
+
77
+#define CPRMAN_NUM_REGS (0x2000 / sizeof(uint32_t))
78
+
79
+struct BCM2835CprmanState {
80
+ /*< private >*/
81
+ SysBusDevice parent_obj;
82
+
83
+ /*< public >*/
84
+ MemoryRegion iomem;
85
+
86
+ uint32_t regs[CPRMAN_NUM_REGS];
87
+ uint32_t xosc_freq;
88
+
89
+ Clock *xosc;
90
+};
91
+
92
+#endif
93
diff --git a/include/hw/misc/bcm2835_cprman_internals.h b/include/hw/misc/bcm2835_cprman_internals.h
94
new file mode 100644
95
index XXXXXXX..XXXXXXX
96
--- /dev/null
97
+++ b/include/hw/misc/bcm2835_cprman_internals.h
98
@@ -XXX,XX +XXX,XX @@
99
+/*
100
+ * BCM2835 CPRMAN clock manager
101
+ *
102
+ * Copyright (c) 2020 Luc Michel <luc@lmichel.fr>
103
+ *
104
+ * SPDX-License-Identifier: GPL-2.0-or-later
105
+ */
106
+
107
+#ifndef HW_MISC_CPRMAN_INTERNALS_H
108
+#define HW_MISC_CPRMAN_INTERNALS_H
109
+
110
+#include "hw/registerfields.h"
111
+#include "hw/misc/bcm2835_cprman.h"
112
+
113
+/* Register map */
114
+
115
+/*
116
+ * This field is common to all registers. Each register write value must match
117
+ * the CPRMAN_PASSWORD magic value in its 8 MSB.
118
+ */
119
+FIELD(CPRMAN, PASSWORD, 24, 8)
120
+#define CPRMAN_PASSWORD 0x5a
121
+
122
+#endif
45
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
123
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
46
index XXXXXXX..XXXXXXX 100644
124
index XXXXXXX..XXXXXXX 100644
47
--- a/hw/arm/bcm2835_peripherals.c
125
--- a/hw/arm/bcm2835_peripherals.c
48
+++ b/hw/arm/bcm2835_peripherals.c
126
+++ b/hw/arm/bcm2835_peripherals.c
49
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_init(Object *obj)
127
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_init(Object *obj)
50
object_property_add_child(obj, "sdhci", OBJECT(&s->sdhci), NULL);
128
/* DWC2 */
51
qdev_set_parent_bus(DEVICE(&s->sdhci), sysbus_get_default());
129
object_initialize_child(obj, "dwc2", &s->dwc2, TYPE_DWC2_USB);
52
130
53
+ /* SDHOST */
131
+ /* CPRMAN clock manager */
54
+ object_initialize(&s->sdhost, sizeof(s->sdhost), TYPE_BCM2835_SDHOST);
132
+ object_initialize_child(obj, "cprman", &s->cprman, TYPE_BCM2835_CPRMAN);
55
+ object_property_add_child(obj, "sdhost", OBJECT(&s->sdhost), NULL);
133
+
56
+ qdev_set_parent_bus(DEVICE(&s->sdhost), sysbus_get_default());
134
object_property_add_const_link(OBJECT(&s->dwc2), "dma-mr",
57
+
135
OBJECT(&s->gpu_bus_mr));
58
/* DMA Channels */
59
object_initialize(&s->dma, sizeof(s->dma), TYPE_BCM2835_DMA);
60
object_property_add_child(obj, "dma", OBJECT(&s->dma), NULL);
61
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_init(Object *obj)
62
63
object_property_add_const_link(OBJECT(&s->dma), "dma-mr",
64
OBJECT(&s->gpu_bus_mr), &error_abort);
65
+
66
+ /* GPIO */
67
+ object_initialize(&s->gpio, sizeof(s->gpio), TYPE_BCM2835_GPIO);
68
+ object_property_add_child(obj, "gpio", OBJECT(&s->gpio), NULL);
69
+ qdev_set_parent_bus(DEVICE(&s->gpio), sysbus_get_default());
70
+
71
+ object_property_add_const_link(OBJECT(&s->gpio), "sdbus-sdhci",
72
+ OBJECT(&s->sdhci.sdbus), &error_abort);
73
+ object_property_add_const_link(OBJECT(&s->gpio), "sdbus-sdhost",
74
+ OBJECT(&s->sdhost.sdbus), &error_abort);
75
}
136
}
76
77
static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
78
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
137
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
79
sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci), 0,
80
qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
81
INTERRUPT_ARASANSDIO));
82
- object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->sdhci), "sd-bus",
83
- &err);
84
+
85
+ /* SDHOST */
86
+ object_property_set_bool(OBJECT(&s->sdhost), true, "realized", &err);
87
if (err) {
88
error_propagate(errp, err);
89
return;
138
return;
90
}
139
}
91
140
92
+ memory_region_add_subregion(&s->peri_mr, MMCI0_OFFSET,
141
+ /* CPRMAN clock manager */
93
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->sdhost), 0));
142
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->cprman), errp)) {
94
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhost), 0,
95
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
96
+ INTERRUPT_SDIO));
97
+
98
/* DMA Channels */
99
object_property_set_bool(OBJECT(&s->dma), true, "realized", &err);
100
if (err) {
101
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
102
BCM2835_IC_GPU_IRQ,
103
INTERRUPT_DMA0 + n));
104
}
105
+
106
+ /* GPIO */
107
+ object_property_set_bool(OBJECT(&s->gpio), true, "realized", &err);
108
+ if (err) {
109
+ error_propagate(errp, err);
110
+ return;
143
+ return;
111
+ }
144
+ }
112
+
145
+ memory_region_add_subregion(&s->peri_mr, CPRMAN_OFFSET,
113
+ memory_region_add_subregion(&s->peri_mr, GPIO_OFFSET,
146
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->cprman), 0));
114
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->gpio), 0));
147
+
115
+
148
memory_region_add_subregion(&s->peri_mr, ARMCTRL_IC_OFFSET,
116
+ object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->gpio), "sd-bus",
149
sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->ic), 0));
117
+ &err);
150
sysbus_pass_irq(SYS_BUS_DEVICE(s), SYS_BUS_DEVICE(&s->ic));
118
+ if (err) {
151
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
119
+ error_propagate(errp, err);
152
create_unimp(s, &s->txp, "bcm2835-txp", TXP_OFFSET, 0x1000);
153
create_unimp(s, &s->armtmr, "bcm2835-sp804", ARMCTRL_TIMER0_1_OFFSET, 0x40);
154
create_unimp(s, &s->powermgt, "bcm2835-powermgt", PM_OFFSET, 0x114);
155
- create_unimp(s, &s->cprman, "bcm2835-cprman", CPRMAN_OFFSET, 0x2000);
156
create_unimp(s, &s->i2s, "bcm2835-i2s", I2S_OFFSET, 0x100);
157
create_unimp(s, &s->smi, "bcm2835-smi", SMI_OFFSET, 0x100);
158
create_unimp(s, &s->spi[0], "bcm2835-spi0", SPI0_OFFSET, 0x20);
159
diff --git a/hw/misc/bcm2835_cprman.c b/hw/misc/bcm2835_cprman.c
160
new file mode 100644
161
index XXXXXXX..XXXXXXX
162
--- /dev/null
163
+++ b/hw/misc/bcm2835_cprman.c
164
@@ -XXX,XX +XXX,XX @@
165
+/*
166
+ * BCM2835 CPRMAN clock manager
167
+ *
168
+ * Copyright (c) 2020 Luc Michel <luc@lmichel.fr>
169
+ *
170
+ * SPDX-License-Identifier: GPL-2.0-or-later
171
+ */
172
+
173
+/*
174
+ * This peripheral is roughly divided into 3 main parts:
175
+ * - the PLLs
176
+ * - the PLL channels
177
+ * - the clock muxes
178
+ *
179
+ * A main oscillator (xosc) feeds all the PLLs. Each PLLs has one or more
180
+ * channels. Those channel are then connected to the clock muxes. Each mux has
181
+ * multiples sources (usually the xosc, some of the PLL channels and some "test
182
+ * debug" clocks). A mux is configured to select a given source through its
183
+ * control register. Each mux has one output clock that also goes out of the
184
+ * CPRMAN. This output clock usually connects to another peripheral in the SoC
185
+ * (so a given mux is dedicated to a peripheral).
186
+ *
187
+ * At each level (PLL, channel and mux), the clock can be altered through
188
+ * dividers (and multipliers in case of the PLLs), and can be disabled (in this
189
+ * case, the next levels see no clock).
190
+ *
191
+ * This can be sum-up as follows (this is an example and not the actual BCM2835
192
+ * clock tree):
193
+ *
194
+ * /-->[PLL]-|->[PLL channel]--... [mux]--> to peripherals
195
+ * | |->[PLL channel] muxes takes [mux]
196
+ * | \->[PLL channel] inputs from [mux]
197
+ * | some channels [mux]
198
+ * [xosc]---|-->[PLL]-|->[PLL channel] and other srcs [mux]
199
+ * | \->[PLL channel] ...-->[mux]
200
+ * | [mux]
201
+ * \-->[PLL]--->[PLL channel] [mux]
202
+ *
203
+ * The page at https://elinux.org/The_Undocumented_Pi gives the actual clock
204
+ * tree configuration.
205
+ */
206
+
207
+#include "qemu/osdep.h"
208
+#include "qemu/log.h"
209
+#include "migration/vmstate.h"
210
+#include "hw/qdev-properties.h"
211
+#include "hw/misc/bcm2835_cprman.h"
212
+#include "hw/misc/bcm2835_cprman_internals.h"
213
+#include "trace.h"
214
+
215
+/* CPRMAN "top level" model */
216
+
217
+static uint64_t cprman_read(void *opaque, hwaddr offset,
218
+ unsigned size)
219
+{
220
+ BCM2835CprmanState *s = CPRMAN(opaque);
221
+ uint64_t r = 0;
222
+ size_t idx = offset / sizeof(uint32_t);
223
+
224
+ switch (idx) {
225
+ default:
226
+ r = s->regs[idx];
227
+ }
228
+
229
+ trace_bcm2835_cprman_read(offset, r);
230
+ return r;
231
+}
232
+
233
+static void cprman_write(void *opaque, hwaddr offset,
234
+ uint64_t value, unsigned size)
235
+{
236
+ BCM2835CprmanState *s = CPRMAN(opaque);
237
+ size_t idx = offset / sizeof(uint32_t);
238
+
239
+ if (FIELD_EX32(value, CPRMAN, PASSWORD) != CPRMAN_PASSWORD) {
240
+ trace_bcm2835_cprman_write_invalid_magic(offset, value);
120
+ return;
241
+ return;
121
+ }
242
+ }
122
}
243
+
123
244
+ value &= ~R_CPRMAN_PASSWORD_MASK;
124
static void bcm2835_peripherals_class_init(ObjectClass *oc, void *data)
245
+
246
+ trace_bcm2835_cprman_write(offset, value);
247
+ s->regs[idx] = value;
248
+
249
+}
250
+
251
+static const MemoryRegionOps cprman_ops = {
252
+ .read = cprman_read,
253
+ .write = cprman_write,
254
+ .endianness = DEVICE_LITTLE_ENDIAN,
255
+ .valid = {
256
+ /*
257
+ * Although this hasn't been checked against real hardware, nor the
258
+ * information can be found in a datasheet, it seems reasonable because
259
+ * of the "PASSWORD" magic value found in every registers.
260
+ */
261
+ .min_access_size = 4,
262
+ .max_access_size = 4,
263
+ .unaligned = false,
264
+ },
265
+ .impl = {
266
+ .max_access_size = 4,
267
+ },
268
+};
269
+
270
+static void cprman_reset(DeviceState *dev)
271
+{
272
+ BCM2835CprmanState *s = CPRMAN(dev);
273
+
274
+ memset(s->regs, 0, sizeof(s->regs));
275
+
276
+ clock_update_hz(s->xosc, s->xosc_freq);
277
+}
278
+
279
+static void cprman_init(Object *obj)
280
+{
281
+ BCM2835CprmanState *s = CPRMAN(obj);
282
+
283
+ s->xosc = clock_new(obj, "xosc");
284
+
285
+ memory_region_init_io(&s->iomem, obj, &cprman_ops,
286
+ s, "bcm2835-cprman", 0x2000);
287
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
288
+}
289
+
290
+static const VMStateDescription cprman_vmstate = {
291
+ .name = TYPE_BCM2835_CPRMAN,
292
+ .version_id = 1,
293
+ .minimum_version_id = 1,
294
+ .fields = (VMStateField[]) {
295
+ VMSTATE_UINT32_ARRAY(regs, BCM2835CprmanState, CPRMAN_NUM_REGS),
296
+ VMSTATE_END_OF_LIST()
297
+ }
298
+};
299
+
300
+static Property cprman_properties[] = {
301
+ DEFINE_PROP_UINT32("xosc-freq-hz", BCM2835CprmanState, xosc_freq, 19200000),
302
+ DEFINE_PROP_END_OF_LIST()
303
+};
304
+
305
+static void cprman_class_init(ObjectClass *klass, void *data)
306
+{
307
+ DeviceClass *dc = DEVICE_CLASS(klass);
308
+
309
+ dc->reset = cprman_reset;
310
+ dc->vmsd = &cprman_vmstate;
311
+ device_class_set_props(dc, cprman_properties);
312
+}
313
+
314
+static const TypeInfo cprman_info = {
315
+ .name = TYPE_BCM2835_CPRMAN,
316
+ .parent = TYPE_SYS_BUS_DEVICE,
317
+ .instance_size = sizeof(BCM2835CprmanState),
318
+ .class_init = cprman_class_init,
319
+ .instance_init = cprman_init,
320
+};
321
+
322
+static void cprman_register_types(void)
323
+{
324
+ type_register_static(&cprman_info);
325
+}
326
+
327
+type_init(cprman_register_types);
328
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
329
index XXXXXXX..XXXXXXX 100644
330
--- a/hw/misc/meson.build
331
+++ b/hw/misc/meson.build
332
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files(
333
'bcm2835_property.c',
334
'bcm2835_rng.c',
335
'bcm2835_thermal.c',
336
+ 'bcm2835_cprman.c',
337
))
338
softmmu_ss.add(when: 'CONFIG_SLAVIO', if_true: files('slavio_misc.c'))
339
softmmu_ss.add(when: 'CONFIG_ZYNQ', if_true: files('zynq_slcr.c', 'zynq-xadc.c'))
340
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
341
index XXXXXXX..XXXXXXX 100644
342
--- a/hw/misc/trace-events
343
+++ b/hw/misc/trace-events
344
@@ -XXX,XX +XXX,XX @@ grlib_apb_pnp_read(uint64_t addr, uint32_t value) "APB PnP read addr:0x%03"PRIx6
345
# pca9552.c
346
pca955x_gpio_status(const char *description, const char *buf) "%s GPIOs 0-15 [%s]"
347
pca955x_gpio_change(const char *description, unsigned id, unsigned prev_state, unsigned current_state) "%s GPIO id:%u status: %u -> %u"
348
+
349
+# bcm2835_cprman.c
350
+bcm2835_cprman_read(uint64_t offset, uint64_t value) "offset:0x%" PRIx64 " value:0x%" PRIx64
351
+bcm2835_cprman_write(uint64_t offset, uint64_t value) "offset:0x%" PRIx64 " value:0x%" PRIx64
352
+bcm2835_cprman_write_invalid_magic(uint64_t offset, uint64_t value) "offset:0x%" PRIx64 " value:0x%" PRIx64
125
--
353
--
126
2.7.4
354
2.20.1
127
355
128
356
diff view generated by jsdifflib
New patch
1
1
From: Luc Michel <luc@lmichel.fr>
2
3
There are 5 PLLs in the CPRMAN, namely PLL A, C, D, H and B. All of them
4
take the xosc clock as input and produce a new clock.
5
6
This commit adds a skeleton implementation for the PLLs as sub-devices
7
of the CPRMAN. The PLLs are instantiated and connected internally to the
8
main oscillator.
9
10
Each PLL has 6 registers : CM, A2W_CTRL, A2W_ANA[0,1,2,3], A2W_FRAC. A
11
write to any of them triggers a call to the (not yet implemented)
12
pll_update function.
13
14
If the main oscillator changes frequency, an update is also triggered.
15
16
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
18
Signed-off-by: Luc Michel <luc@lmichel.fr>
19
Tested-by: Guenter Roeck <linux@roeck-us.net>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
---
22
include/hw/misc/bcm2835_cprman.h | 29 +++++
23
include/hw/misc/bcm2835_cprman_internals.h | 144 +++++++++++++++++++++
24
hw/misc/bcm2835_cprman.c | 108 ++++++++++++++++
25
3 files changed, 281 insertions(+)
26
27
diff --git a/include/hw/misc/bcm2835_cprman.h b/include/hw/misc/bcm2835_cprman.h
28
index XXXXXXX..XXXXXXX 100644
29
--- a/include/hw/misc/bcm2835_cprman.h
30
+++ b/include/hw/misc/bcm2835_cprman.h
31
@@ -XXX,XX +XXX,XX @@ DECLARE_INSTANCE_CHECKER(BCM2835CprmanState, CPRMAN,
32
33
#define CPRMAN_NUM_REGS (0x2000 / sizeof(uint32_t))
34
35
+typedef enum CprmanPll {
36
+ CPRMAN_PLLA = 0,
37
+ CPRMAN_PLLC,
38
+ CPRMAN_PLLD,
39
+ CPRMAN_PLLH,
40
+ CPRMAN_PLLB,
41
+
42
+ CPRMAN_NUM_PLL
43
+} CprmanPll;
44
+
45
+typedef struct CprmanPllState {
46
+ /*< private >*/
47
+ DeviceState parent_obj;
48
+
49
+ /*< public >*/
50
+ CprmanPll id;
51
+
52
+ uint32_t *reg_cm;
53
+ uint32_t *reg_a2w_ctrl;
54
+ uint32_t *reg_a2w_ana; /* ANA[0] .. ANA[3] */
55
+ uint32_t prediv_mask; /* prediv bit in ana[1] */
56
+ uint32_t *reg_a2w_frac;
57
+
58
+ Clock *xosc_in;
59
+ Clock *out;
60
+} CprmanPllState;
61
+
62
struct BCM2835CprmanState {
63
/*< private >*/
64
SysBusDevice parent_obj;
65
@@ -XXX,XX +XXX,XX @@ struct BCM2835CprmanState {
66
/*< public >*/
67
MemoryRegion iomem;
68
69
+ CprmanPllState plls[CPRMAN_NUM_PLL];
70
+
71
uint32_t regs[CPRMAN_NUM_REGS];
72
uint32_t xosc_freq;
73
74
diff --git a/include/hw/misc/bcm2835_cprman_internals.h b/include/hw/misc/bcm2835_cprman_internals.h
75
index XXXXXXX..XXXXXXX 100644
76
--- a/include/hw/misc/bcm2835_cprman_internals.h
77
+++ b/include/hw/misc/bcm2835_cprman_internals.h
78
@@ -XXX,XX +XXX,XX @@
79
#include "hw/registerfields.h"
80
#include "hw/misc/bcm2835_cprman.h"
81
82
+#define TYPE_CPRMAN_PLL "bcm2835-cprman-pll"
83
+
84
+DECLARE_INSTANCE_CHECKER(CprmanPllState, CPRMAN_PLL,
85
+ TYPE_CPRMAN_PLL)
86
+
87
/* Register map */
88
89
+/* PLLs */
90
+REG32(CM_PLLA, 0x104)
91
+ FIELD(CM_PLLA, LOADDSI0, 0, 1)
92
+ FIELD(CM_PLLA, HOLDDSI0, 1, 1)
93
+ FIELD(CM_PLLA, LOADCCP2, 2, 1)
94
+ FIELD(CM_PLLA, HOLDCCP2, 3, 1)
95
+ FIELD(CM_PLLA, LOADCORE, 4, 1)
96
+ FIELD(CM_PLLA, HOLDCORE, 5, 1)
97
+ FIELD(CM_PLLA, LOADPER, 6, 1)
98
+ FIELD(CM_PLLA, HOLDPER, 7, 1)
99
+ FIELD(CM_PLLx, ANARST, 8, 1)
100
+REG32(CM_PLLC, 0x108)
101
+ FIELD(CM_PLLC, LOADCORE0, 0, 1)
102
+ FIELD(CM_PLLC, HOLDCORE0, 1, 1)
103
+ FIELD(CM_PLLC, LOADCORE1, 2, 1)
104
+ FIELD(CM_PLLC, HOLDCORE1, 3, 1)
105
+ FIELD(CM_PLLC, LOADCORE2, 4, 1)
106
+ FIELD(CM_PLLC, HOLDCORE2, 5, 1)
107
+ FIELD(CM_PLLC, LOADPER, 6, 1)
108
+ FIELD(CM_PLLC, HOLDPER, 7, 1)
109
+REG32(CM_PLLD, 0x10c)
110
+ FIELD(CM_PLLD, LOADDSI0, 0, 1)
111
+ FIELD(CM_PLLD, HOLDDSI0, 1, 1)
112
+ FIELD(CM_PLLD, LOADDSI1, 2, 1)
113
+ FIELD(CM_PLLD, HOLDDSI1, 3, 1)
114
+ FIELD(CM_PLLD, LOADCORE, 4, 1)
115
+ FIELD(CM_PLLD, HOLDCORE, 5, 1)
116
+ FIELD(CM_PLLD, LOADPER, 6, 1)
117
+ FIELD(CM_PLLD, HOLDPER, 7, 1)
118
+REG32(CM_PLLH, 0x110)
119
+ FIELD(CM_PLLH, LOADPIX, 0, 1)
120
+ FIELD(CM_PLLH, LOADAUX, 1, 1)
121
+ FIELD(CM_PLLH, LOADRCAL, 2, 1)
122
+REG32(CM_PLLB, 0x170)
123
+ FIELD(CM_PLLB, LOADARM, 0, 1)
124
+ FIELD(CM_PLLB, HOLDARM, 1, 1)
125
+
126
+REG32(A2W_PLLA_CTRL, 0x1100)
127
+ FIELD(A2W_PLLx_CTRL, NDIV, 0, 10)
128
+ FIELD(A2W_PLLx_CTRL, PDIV, 12, 3)
129
+ FIELD(A2W_PLLx_CTRL, PWRDN, 16, 1)
130
+ FIELD(A2W_PLLx_CTRL, PRST_DISABLE, 17, 1)
131
+REG32(A2W_PLLC_CTRL, 0x1120)
132
+REG32(A2W_PLLD_CTRL, 0x1140)
133
+REG32(A2W_PLLH_CTRL, 0x1160)
134
+REG32(A2W_PLLB_CTRL, 0x11e0)
135
+
136
+REG32(A2W_PLLA_ANA0, 0x1010)
137
+REG32(A2W_PLLA_ANA1, 0x1014)
138
+ FIELD(A2W_PLLx_ANA1, FB_PREDIV, 14, 1)
139
+REG32(A2W_PLLA_ANA2, 0x1018)
140
+REG32(A2W_PLLA_ANA3, 0x101c)
141
+
142
+REG32(A2W_PLLC_ANA0, 0x1030)
143
+REG32(A2W_PLLC_ANA1, 0x1034)
144
+REG32(A2W_PLLC_ANA2, 0x1038)
145
+REG32(A2W_PLLC_ANA3, 0x103c)
146
+
147
+REG32(A2W_PLLD_ANA0, 0x1050)
148
+REG32(A2W_PLLD_ANA1, 0x1054)
149
+REG32(A2W_PLLD_ANA2, 0x1058)
150
+REG32(A2W_PLLD_ANA3, 0x105c)
151
+
152
+REG32(A2W_PLLH_ANA0, 0x1070)
153
+REG32(A2W_PLLH_ANA1, 0x1074)
154
+ FIELD(A2W_PLLH_ANA1, FB_PREDIV, 11, 1)
155
+REG32(A2W_PLLH_ANA2, 0x1078)
156
+REG32(A2W_PLLH_ANA3, 0x107c)
157
+
158
+REG32(A2W_PLLB_ANA0, 0x10f0)
159
+REG32(A2W_PLLB_ANA1, 0x10f4)
160
+REG32(A2W_PLLB_ANA2, 0x10f8)
161
+REG32(A2W_PLLB_ANA3, 0x10fc)
162
+
163
+REG32(A2W_PLLA_FRAC, 0x1200)
164
+ FIELD(A2W_PLLx_FRAC, FRAC, 0, 20)
165
+REG32(A2W_PLLC_FRAC, 0x1220)
166
+REG32(A2W_PLLD_FRAC, 0x1240)
167
+REG32(A2W_PLLH_FRAC, 0x1260)
168
+REG32(A2W_PLLB_FRAC, 0x12e0)
169
+
170
/*
171
* This field is common to all registers. Each register write value must match
172
* the CPRMAN_PASSWORD magic value in its 8 MSB.
173
@@ -XXX,XX +XXX,XX @@
174
FIELD(CPRMAN, PASSWORD, 24, 8)
175
#define CPRMAN_PASSWORD 0x5a
176
177
+/* PLL init info */
178
+typedef struct PLLInitInfo {
179
+ const char *name;
180
+ size_t cm_offset;
181
+ size_t a2w_ctrl_offset;
182
+ size_t a2w_ana_offset;
183
+ uint32_t prediv_mask; /* Prediv bit in ana[1] */
184
+ size_t a2w_frac_offset;
185
+} PLLInitInfo;
186
+
187
+#define FILL_PLL_INIT_INFO(pll_) \
188
+ .cm_offset = R_CM_ ## pll_, \
189
+ .a2w_ctrl_offset = R_A2W_ ## pll_ ## _CTRL, \
190
+ .a2w_ana_offset = R_A2W_ ## pll_ ## _ANA0, \
191
+ .a2w_frac_offset = R_A2W_ ## pll_ ## _FRAC
192
+
193
+static const PLLInitInfo PLL_INIT_INFO[] = {
194
+ [CPRMAN_PLLA] = {
195
+ .name = "plla",
196
+ .prediv_mask = R_A2W_PLLx_ANA1_FB_PREDIV_MASK,
197
+ FILL_PLL_INIT_INFO(PLLA),
198
+ },
199
+ [CPRMAN_PLLC] = {
200
+ .name = "pllc",
201
+ .prediv_mask = R_A2W_PLLx_ANA1_FB_PREDIV_MASK,
202
+ FILL_PLL_INIT_INFO(PLLC),
203
+ },
204
+ [CPRMAN_PLLD] = {
205
+ .name = "plld",
206
+ .prediv_mask = R_A2W_PLLx_ANA1_FB_PREDIV_MASK,
207
+ FILL_PLL_INIT_INFO(PLLD),
208
+ },
209
+ [CPRMAN_PLLH] = {
210
+ .name = "pllh",
211
+ .prediv_mask = R_A2W_PLLH_ANA1_FB_PREDIV_MASK,
212
+ FILL_PLL_INIT_INFO(PLLH),
213
+ },
214
+ [CPRMAN_PLLB] = {
215
+ .name = "pllb",
216
+ .prediv_mask = R_A2W_PLLx_ANA1_FB_PREDIV_MASK,
217
+ FILL_PLL_INIT_INFO(PLLB),
218
+ },
219
+};
220
+
221
+#undef FILL_PLL_CHANNEL_INIT_INFO
222
+
223
+static inline void set_pll_init_info(BCM2835CprmanState *s,
224
+ CprmanPllState *pll,
225
+ CprmanPll id)
226
+{
227
+ pll->id = id;
228
+ pll->reg_cm = &s->regs[PLL_INIT_INFO[id].cm_offset];
229
+ pll->reg_a2w_ctrl = &s->regs[PLL_INIT_INFO[id].a2w_ctrl_offset];
230
+ pll->reg_a2w_ana = &s->regs[PLL_INIT_INFO[id].a2w_ana_offset];
231
+ pll->prediv_mask = PLL_INIT_INFO[id].prediv_mask;
232
+ pll->reg_a2w_frac = &s->regs[PLL_INIT_INFO[id].a2w_frac_offset];
233
+}
234
+
235
#endif
236
diff --git a/hw/misc/bcm2835_cprman.c b/hw/misc/bcm2835_cprman.c
237
index XXXXXXX..XXXXXXX 100644
238
--- a/hw/misc/bcm2835_cprman.c
239
+++ b/hw/misc/bcm2835_cprman.c
240
@@ -XXX,XX +XXX,XX @@
241
#include "hw/misc/bcm2835_cprman_internals.h"
242
#include "trace.h"
243
244
+/* PLL */
245
+
246
+static void pll_update(CprmanPllState *pll)
247
+{
248
+ clock_update(pll->out, 0);
249
+}
250
+
251
+static void pll_xosc_update(void *opaque)
252
+{
253
+ pll_update(CPRMAN_PLL(opaque));
254
+}
255
+
256
+static void pll_init(Object *obj)
257
+{
258
+ CprmanPllState *s = CPRMAN_PLL(obj);
259
+
260
+ s->xosc_in = qdev_init_clock_in(DEVICE(s), "xosc-in", pll_xosc_update, s);
261
+ s->out = qdev_init_clock_out(DEVICE(s), "out");
262
+}
263
+
264
+static const VMStateDescription pll_vmstate = {
265
+ .name = TYPE_CPRMAN_PLL,
266
+ .version_id = 1,
267
+ .minimum_version_id = 1,
268
+ .fields = (VMStateField[]) {
269
+ VMSTATE_CLOCK(xosc_in, CprmanPllState),
270
+ VMSTATE_END_OF_LIST()
271
+ }
272
+};
273
+
274
+static void pll_class_init(ObjectClass *klass, void *data)
275
+{
276
+ DeviceClass *dc = DEVICE_CLASS(klass);
277
+
278
+ dc->vmsd = &pll_vmstate;
279
+}
280
+
281
+static const TypeInfo cprman_pll_info = {
282
+ .name = TYPE_CPRMAN_PLL,
283
+ .parent = TYPE_DEVICE,
284
+ .instance_size = sizeof(CprmanPllState),
285
+ .class_init = pll_class_init,
286
+ .instance_init = pll_init,
287
+};
288
+
289
+
290
/* CPRMAN "top level" model */
291
292
static uint64_t cprman_read(void *opaque, hwaddr offset,
293
@@ -XXX,XX +XXX,XX @@ static uint64_t cprman_read(void *opaque, hwaddr offset,
294
return r;
295
}
296
297
+#define CASE_PLL_REGS(pll_) \
298
+ case R_CM_ ## pll_: \
299
+ case R_A2W_ ## pll_ ## _CTRL: \
300
+ case R_A2W_ ## pll_ ## _ANA0: \
301
+ case R_A2W_ ## pll_ ## _ANA1: \
302
+ case R_A2W_ ## pll_ ## _ANA2: \
303
+ case R_A2W_ ## pll_ ## _ANA3: \
304
+ case R_A2W_ ## pll_ ## _FRAC
305
+
306
static void cprman_write(void *opaque, hwaddr offset,
307
uint64_t value, unsigned size)
308
{
309
@@ -XXX,XX +XXX,XX @@ static void cprman_write(void *opaque, hwaddr offset,
310
trace_bcm2835_cprman_write(offset, value);
311
s->regs[idx] = value;
312
313
+ switch (idx) {
314
+ CASE_PLL_REGS(PLLA) :
315
+ pll_update(&s->plls[CPRMAN_PLLA]);
316
+ break;
317
+
318
+ CASE_PLL_REGS(PLLC) :
319
+ pll_update(&s->plls[CPRMAN_PLLC]);
320
+ break;
321
+
322
+ CASE_PLL_REGS(PLLD) :
323
+ pll_update(&s->plls[CPRMAN_PLLD]);
324
+ break;
325
+
326
+ CASE_PLL_REGS(PLLH) :
327
+ pll_update(&s->plls[CPRMAN_PLLH]);
328
+ break;
329
+
330
+ CASE_PLL_REGS(PLLB) :
331
+ pll_update(&s->plls[CPRMAN_PLLB]);
332
+ break;
333
+ }
334
}
335
336
+#undef CASE_PLL_REGS
337
+
338
static const MemoryRegionOps cprman_ops = {
339
.read = cprman_read,
340
.write = cprman_write,
341
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps cprman_ops = {
342
static void cprman_reset(DeviceState *dev)
343
{
344
BCM2835CprmanState *s = CPRMAN(dev);
345
+ size_t i;
346
347
memset(s->regs, 0, sizeof(s->regs));
348
349
+ for (i = 0; i < CPRMAN_NUM_PLL; i++) {
350
+ device_cold_reset(DEVICE(&s->plls[i]));
351
+ }
352
+
353
clock_update_hz(s->xosc, s->xosc_freq);
354
}
355
356
static void cprman_init(Object *obj)
357
{
358
BCM2835CprmanState *s = CPRMAN(obj);
359
+ size_t i;
360
+
361
+ for (i = 0; i < CPRMAN_NUM_PLL; i++) {
362
+ object_initialize_child(obj, PLL_INIT_INFO[i].name,
363
+ &s->plls[i], TYPE_CPRMAN_PLL);
364
+ set_pll_init_info(s, &s->plls[i], i);
365
+ }
366
367
s->xosc = clock_new(obj, "xosc");
368
369
@@ -XXX,XX +XXX,XX @@ static void cprman_init(Object *obj)
370
sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
371
}
372
373
+static void cprman_realize(DeviceState *dev, Error **errp)
374
+{
375
+ BCM2835CprmanState *s = CPRMAN(dev);
376
+ size_t i;
377
+
378
+ for (i = 0; i < CPRMAN_NUM_PLL; i++) {
379
+ CprmanPllState *pll = &s->plls[i];
380
+
381
+ clock_set_source(pll->xosc_in, s->xosc);
382
+
383
+ if (!qdev_realize(DEVICE(pll), NULL, errp)) {
384
+ return;
385
+ }
386
+ }
387
+}
388
+
389
static const VMStateDescription cprman_vmstate = {
390
.name = TYPE_BCM2835_CPRMAN,
391
.version_id = 1,
392
@@ -XXX,XX +XXX,XX @@ static void cprman_class_init(ObjectClass *klass, void *data)
393
{
394
DeviceClass *dc = DEVICE_CLASS(klass);
395
396
+ dc->realize = cprman_realize;
397
dc->reset = cprman_reset;
398
dc->vmsd = &cprman_vmstate;
399
device_class_set_props(dc, cprman_properties);
400
@@ -XXX,XX +XXX,XX @@ static const TypeInfo cprman_info = {
401
static void cprman_register_types(void)
402
{
403
type_register_static(&cprman_info);
404
+ type_register_static(&cprman_pll_info);
405
}
406
407
type_init(cprman_register_types);
408
--
409
2.20.1
410
411
diff view generated by jsdifflib
1
From: Clement Deschamps <clement.deschamps@antfield.fr>
1
From: Luc Michel <luc@lmichel.fr>
2
2
3
Provide a new function sdbus_reparent_card() in sd core for reparenting
3
The CPRMAN PLLs generate a clock based on a prescaler, a multiplier and
4
a card from a SDBus to another one.
4
a divider. The prescaler doubles the parent (xosc) frequency, then the
5
multiplier/divider are applied. The multiplier has an integer and a
6
fractional part.
5
7
6
This function is required by the raspi platform, where the two SD
8
This commit also implements the CPRMAN CM_LOCK register. This register
7
controllers can be dynamically switched.
9
reports which PLL is currently locked. We consider a PLL has being
10
locked as soon as it is enabled (on real hardware, there is a delay
11
after turning a PLL on, for it to stabilize).
8
12
9
Signed-off-by: Clement Deschamps <clement.deschamps@antfield.fr>
13
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Luc Michel <luc@lmichel.fr>
12
Message-id: 1488293711-14195-3-git-send-email-peter.maydell@linaro.org
16
Tested-by: Guenter Roeck <linux@roeck-us.net>
13
Message-id: 20170224164021.9066-3-clement.deschamps@antfield.fr
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
[PMM: added a doc comment to the header file; changed to
16
use new behaviour of qdev_set_parent_bus()]
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
18
---
19
include/hw/sd/sd.h | 11 +++++++++++
19
include/hw/misc/bcm2835_cprman_internals.h | 8 +++
20
hw/sd/core.c | 27 +++++++++++++++++++++++++++
20
hw/misc/bcm2835_cprman.c | 64 +++++++++++++++++++++-
21
2 files changed, 38 insertions(+)
21
2 files changed, 71 insertions(+), 1 deletion(-)
22
22
23
diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h
23
diff --git a/include/hw/misc/bcm2835_cprman_internals.h b/include/hw/misc/bcm2835_cprman_internals.h
24
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/sd/sd.h
25
--- a/include/hw/misc/bcm2835_cprman_internals.h
26
+++ b/include/hw/sd/sd.h
26
+++ b/include/hw/misc/bcm2835_cprman_internals.h
27
@@ -XXX,XX +XXX,XX @@ uint8_t sdbus_read_data(SDBus *sd);
27
@@ -XXX,XX +XXX,XX @@ REG32(A2W_PLLD_FRAC, 0x1240)
28
bool sdbus_data_ready(SDBus *sd);
28
REG32(A2W_PLLH_FRAC, 0x1260)
29
bool sdbus_get_inserted(SDBus *sd);
29
REG32(A2W_PLLB_FRAC, 0x12e0)
30
bool sdbus_get_readonly(SDBus *sd);
30
31
+/**
31
+/* misc registers */
32
+ * sdbus_reparent_card: Reparent an SD card from one controller to another
32
+REG32(CM_LOCK, 0x114)
33
+ * @from: controller bus to remove card from
33
+ FIELD(CM_LOCK, FLOCKH, 12, 1)
34
+ * @to: controller bus to move card to
34
+ FIELD(CM_LOCK, FLOCKD, 11, 1)
35
+ *
35
+ FIELD(CM_LOCK, FLOCKC, 10, 1)
36
+ * Reparent an SD card, effectively unplugging it from one controller
36
+ FIELD(CM_LOCK, FLOCKB, 9, 1)
37
+ * and inserting it into another. This is useful for SoCs like the
37
+ FIELD(CM_LOCK, FLOCKA, 8, 1)
38
+ * bcm2835 which have two SD controllers and connect a single SD card
38
+
39
+ * to them, selected by the guest reprogramming GPIO line routing.
39
/*
40
+ */
40
* This field is common to all registers. Each register write value must match
41
+void sdbus_reparent_card(SDBus *from, SDBus *to);
41
* the CPRMAN_PASSWORD magic value in its 8 MSB.
42
42
diff --git a/hw/misc/bcm2835_cprman.c b/hw/misc/bcm2835_cprman.c
43
/* Functions to be used by SD devices to report back to qdevified controllers */
44
void sdbus_set_inserted(SDBus *sd, bool inserted);
45
diff --git a/hw/sd/core.c b/hw/sd/core.c
46
index XXXXXXX..XXXXXXX 100644
43
index XXXXXXX..XXXXXXX 100644
47
--- a/hw/sd/core.c
44
--- a/hw/misc/bcm2835_cprman.c
48
+++ b/hw/sd/core.c
45
+++ b/hw/misc/bcm2835_cprman.c
49
@@ -XXX,XX +XXX,XX @@ void sdbus_set_readonly(SDBus *sdbus, bool readonly)
46
@@ -XXX,XX +XXX,XX @@
50
}
47
51
}
48
/* PLL */
52
49
53
+void sdbus_reparent_card(SDBus *from, SDBus *to)
50
+static bool pll_is_locked(const CprmanPllState *pll)
54
+{
51
+{
55
+ SDState *card = get_card(from);
52
+ return !FIELD_EX32(*pll->reg_a2w_ctrl, A2W_PLLx_CTRL, PWRDN)
56
+ SDCardClass *sc;
53
+ && !FIELD_EX32(*pll->reg_cm, CM_PLLx, ANARST);
57
+ bool readonly;
54
+}
58
+
55
+
59
+ /* We directly reparent the card object rather than implementing this
56
static void pll_update(CprmanPllState *pll)
60
+ * as a hotpluggable connection because we don't want to expose SD cards
57
{
61
+ * to users as being hotpluggable, and we can get away with it in this
58
- clock_update(pll->out, 0);
62
+ * limited use case. This could perhaps be implemented more cleanly in
59
+ uint64_t freq, ndiv, fdiv, pdiv;
63
+ * future by adding support to the hotplug infrastructure for "device
64
+ * can be hotplugged only via code, not by user".
65
+ */
66
+
60
+
67
+ if (!card) {
61
+ if (!pll_is_locked(pll)) {
62
+ clock_update(pll->out, 0);
68
+ return;
63
+ return;
69
+ }
64
+ }
70
+
65
+
71
+ sc = SD_CARD_GET_CLASS(card);
66
+ pdiv = FIELD_EX32(*pll->reg_a2w_ctrl, A2W_PLLx_CTRL, PDIV);
72
+ readonly = sc->get_readonly(card);
73
+
67
+
74
+ sdbus_set_inserted(from, false);
68
+ if (!pdiv) {
75
+ qdev_set_parent_bus(DEVICE(card), &to->qbus);
69
+ clock_update(pll->out, 0);
76
+ sdbus_set_inserted(to, true);
70
+ return;
77
+ sdbus_set_readonly(to, readonly);
71
+ }
72
+
73
+ ndiv = FIELD_EX32(*pll->reg_a2w_ctrl, A2W_PLLx_CTRL, NDIV);
74
+ fdiv = FIELD_EX32(*pll->reg_a2w_frac, A2W_PLLx_FRAC, FRAC);
75
+
76
+ if (pll->reg_a2w_ana[1] & pll->prediv_mask) {
77
+ /* The prescaler doubles the parent frequency */
78
+ ndiv *= 2;
79
+ fdiv *= 2;
80
+ }
81
+
82
+ /*
83
+ * We have a multiplier with an integer part (ndiv) and a fractional part
84
+ * (fdiv), and a divider (pdiv).
85
+ */
86
+ freq = clock_get_hz(pll->xosc_in) *
87
+ ((ndiv << R_A2W_PLLx_FRAC_FRAC_LENGTH) + fdiv);
88
+ freq /= pdiv;
89
+ freq >>= R_A2W_PLLx_FRAC_FRAC_LENGTH;
90
+
91
+ clock_update_hz(pll->out, freq);
92
}
93
94
static void pll_xosc_update(void *opaque)
95
@@ -XXX,XX +XXX,XX @@ static const TypeInfo cprman_pll_info = {
96
97
/* CPRMAN "top level" model */
98
99
+static uint32_t get_cm_lock(const BCM2835CprmanState *s)
100
+{
101
+ static const int CM_LOCK_MAPPING[CPRMAN_NUM_PLL] = {
102
+ [CPRMAN_PLLA] = R_CM_LOCK_FLOCKA_SHIFT,
103
+ [CPRMAN_PLLC] = R_CM_LOCK_FLOCKC_SHIFT,
104
+ [CPRMAN_PLLD] = R_CM_LOCK_FLOCKD_SHIFT,
105
+ [CPRMAN_PLLH] = R_CM_LOCK_FLOCKH_SHIFT,
106
+ [CPRMAN_PLLB] = R_CM_LOCK_FLOCKB_SHIFT,
107
+ };
108
+
109
+ uint32_t r = 0;
110
+ size_t i;
111
+
112
+ for (i = 0; i < CPRMAN_NUM_PLL; i++) {
113
+ r |= pll_is_locked(&s->plls[i]) << CM_LOCK_MAPPING[i];
114
+ }
115
+
116
+ return r;
78
+}
117
+}
79
+
118
+
80
static const TypeInfo sd_bus_info = {
119
static uint64_t cprman_read(void *opaque, hwaddr offset,
81
.name = TYPE_SD_BUS,
120
unsigned size)
82
.parent = TYPE_BUS,
121
{
122
@@ -XXX,XX +XXX,XX @@ static uint64_t cprman_read(void *opaque, hwaddr offset,
123
size_t idx = offset / sizeof(uint32_t);
124
125
switch (idx) {
126
+ case R_CM_LOCK:
127
+ r = get_cm_lock(s);
128
+ break;
129
+
130
default:
131
r = s->regs[idx];
132
}
83
--
133
--
84
2.7.4
134
2.20.1
85
135
86
136
diff view generated by jsdifflib
New patch
1
1
From: Luc Michel <luc@lmichel.fr>
2
3
PLLs are composed of multiple channels. Each channel outputs one clock
4
signal. They are modeled as one device taking the PLL generated clock as
5
input, and outputting a new clock.
6
7
A channel shares the CM register with its parent PLL, and has its own
8
A2W_CTRL register. A write to the CM register will trigger an update of
9
the PLL and all its channels, while a write to an A2W_CTRL channel
10
register will update the required channel only.
11
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Signed-off-by: Luc Michel <luc@lmichel.fr>
15
Tested-by: Guenter Roeck <linux@roeck-us.net>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
include/hw/misc/bcm2835_cprman.h | 44 ++++++
19
include/hw/misc/bcm2835_cprman_internals.h | 146 +++++++++++++++++++
20
hw/misc/bcm2835_cprman.c | 155 +++++++++++++++++++--
21
3 files changed, 337 insertions(+), 8 deletions(-)
22
23
diff --git a/include/hw/misc/bcm2835_cprman.h b/include/hw/misc/bcm2835_cprman.h
24
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/misc/bcm2835_cprman.h
26
+++ b/include/hw/misc/bcm2835_cprman.h
27
@@ -XXX,XX +XXX,XX @@ typedef enum CprmanPll {
28
CPRMAN_NUM_PLL
29
} CprmanPll;
30
31
+typedef enum CprmanPllChannel {
32
+ CPRMAN_PLLA_CHANNEL_DSI0 = 0,
33
+ CPRMAN_PLLA_CHANNEL_CORE,
34
+ CPRMAN_PLLA_CHANNEL_PER,
35
+ CPRMAN_PLLA_CHANNEL_CCP2,
36
+
37
+ CPRMAN_PLLC_CHANNEL_CORE2,
38
+ CPRMAN_PLLC_CHANNEL_CORE1,
39
+ CPRMAN_PLLC_CHANNEL_PER,
40
+ CPRMAN_PLLC_CHANNEL_CORE0,
41
+
42
+ CPRMAN_PLLD_CHANNEL_DSI0,
43
+ CPRMAN_PLLD_CHANNEL_CORE,
44
+ CPRMAN_PLLD_CHANNEL_PER,
45
+ CPRMAN_PLLD_CHANNEL_DSI1,
46
+
47
+ CPRMAN_PLLH_CHANNEL_AUX,
48
+ CPRMAN_PLLH_CHANNEL_RCAL,
49
+ CPRMAN_PLLH_CHANNEL_PIX,
50
+
51
+ CPRMAN_PLLB_CHANNEL_ARM,
52
+
53
+ CPRMAN_NUM_PLL_CHANNEL,
54
+} CprmanPllChannel;
55
+
56
typedef struct CprmanPllState {
57
/*< private >*/
58
DeviceState parent_obj;
59
@@ -XXX,XX +XXX,XX @@ typedef struct CprmanPllState {
60
Clock *out;
61
} CprmanPllState;
62
63
+typedef struct CprmanPllChannelState {
64
+ /*< private >*/
65
+ DeviceState parent_obj;
66
+
67
+ /*< public >*/
68
+ CprmanPllChannel id;
69
+ CprmanPll parent;
70
+
71
+ uint32_t *reg_cm;
72
+ uint32_t hold_mask;
73
+ uint32_t load_mask;
74
+ uint32_t *reg_a2w_ctrl;
75
+ int fixed_divider;
76
+
77
+ Clock *pll_in;
78
+ Clock *out;
79
+} CprmanPllChannelState;
80
+
81
struct BCM2835CprmanState {
82
/*< private >*/
83
SysBusDevice parent_obj;
84
@@ -XXX,XX +XXX,XX @@ struct BCM2835CprmanState {
85
MemoryRegion iomem;
86
87
CprmanPllState plls[CPRMAN_NUM_PLL];
88
+ CprmanPllChannelState channels[CPRMAN_NUM_PLL_CHANNEL];
89
90
uint32_t regs[CPRMAN_NUM_REGS];
91
uint32_t xosc_freq;
92
diff --git a/include/hw/misc/bcm2835_cprman_internals.h b/include/hw/misc/bcm2835_cprman_internals.h
93
index XXXXXXX..XXXXXXX 100644
94
--- a/include/hw/misc/bcm2835_cprman_internals.h
95
+++ b/include/hw/misc/bcm2835_cprman_internals.h
96
@@ -XXX,XX +XXX,XX @@
97
#include "hw/misc/bcm2835_cprman.h"
98
99
#define TYPE_CPRMAN_PLL "bcm2835-cprman-pll"
100
+#define TYPE_CPRMAN_PLL_CHANNEL "bcm2835-cprman-pll-channel"
101
102
DECLARE_INSTANCE_CHECKER(CprmanPllState, CPRMAN_PLL,
103
TYPE_CPRMAN_PLL)
104
+DECLARE_INSTANCE_CHECKER(CprmanPllChannelState, CPRMAN_PLL_CHANNEL,
105
+ TYPE_CPRMAN_PLL_CHANNEL)
106
107
/* Register map */
108
109
@@ -XXX,XX +XXX,XX @@ REG32(A2W_PLLD_FRAC, 0x1240)
110
REG32(A2W_PLLH_FRAC, 0x1260)
111
REG32(A2W_PLLB_FRAC, 0x12e0)
112
113
+/* PLL channels */
114
+REG32(A2W_PLLA_DSI0, 0x1300)
115
+ FIELD(A2W_PLLx_CHANNELy, DIV, 0, 8)
116
+ FIELD(A2W_PLLx_CHANNELy, DISABLE, 8, 1)
117
+REG32(A2W_PLLA_CORE, 0x1400)
118
+REG32(A2W_PLLA_PER, 0x1500)
119
+REG32(A2W_PLLA_CCP2, 0x1600)
120
+
121
+REG32(A2W_PLLC_CORE2, 0x1320)
122
+REG32(A2W_PLLC_CORE1, 0x1420)
123
+REG32(A2W_PLLC_PER, 0x1520)
124
+REG32(A2W_PLLC_CORE0, 0x1620)
125
+
126
+REG32(A2W_PLLD_DSI0, 0x1340)
127
+REG32(A2W_PLLD_CORE, 0x1440)
128
+REG32(A2W_PLLD_PER, 0x1540)
129
+REG32(A2W_PLLD_DSI1, 0x1640)
130
+
131
+REG32(A2W_PLLH_AUX, 0x1360)
132
+REG32(A2W_PLLH_RCAL, 0x1460)
133
+REG32(A2W_PLLH_PIX, 0x1560)
134
+REG32(A2W_PLLH_STS, 0x1660)
135
+
136
+REG32(A2W_PLLB_ARM, 0x13e0)
137
+
138
/* misc registers */
139
REG32(CM_LOCK, 0x114)
140
FIELD(CM_LOCK, FLOCKH, 12, 1)
141
@@ -XXX,XX +XXX,XX @@ static inline void set_pll_init_info(BCM2835CprmanState *s,
142
pll->reg_a2w_frac = &s->regs[PLL_INIT_INFO[id].a2w_frac_offset];
143
}
144
145
+
146
+/* PLL channel init info */
147
+typedef struct PLLChannelInitInfo {
148
+ const char *name;
149
+ CprmanPll parent;
150
+ size_t cm_offset;
151
+ uint32_t cm_hold_mask;
152
+ uint32_t cm_load_mask;
153
+ size_t a2w_ctrl_offset;
154
+ unsigned int fixed_divider;
155
+} PLLChannelInitInfo;
156
+
157
+#define FILL_PLL_CHANNEL_INIT_INFO_common(pll_, channel_) \
158
+ .parent = CPRMAN_ ## pll_, \
159
+ .cm_offset = R_CM_ ## pll_, \
160
+ .cm_load_mask = R_CM_ ## pll_ ## _ ## LOAD ## channel_ ## _MASK, \
161
+ .a2w_ctrl_offset = R_A2W_ ## pll_ ## _ ## channel_
162
+
163
+#define FILL_PLL_CHANNEL_INIT_INFO(pll_, channel_) \
164
+ FILL_PLL_CHANNEL_INIT_INFO_common(pll_, channel_), \
165
+ .cm_hold_mask = R_CM_ ## pll_ ## _ ## HOLD ## channel_ ## _MASK, \
166
+ .fixed_divider = 1
167
+
168
+#define FILL_PLL_CHANNEL_INIT_INFO_nohold(pll_, channel_) \
169
+ FILL_PLL_CHANNEL_INIT_INFO_common(pll_, channel_), \
170
+ .cm_hold_mask = 0
171
+
172
+static PLLChannelInitInfo PLL_CHANNEL_INIT_INFO[] = {
173
+ [CPRMAN_PLLA_CHANNEL_DSI0] = {
174
+ .name = "plla-dsi0",
175
+ FILL_PLL_CHANNEL_INIT_INFO(PLLA, DSI0),
176
+ },
177
+ [CPRMAN_PLLA_CHANNEL_CORE] = {
178
+ .name = "plla-core",
179
+ FILL_PLL_CHANNEL_INIT_INFO(PLLA, CORE),
180
+ },
181
+ [CPRMAN_PLLA_CHANNEL_PER] = {
182
+ .name = "plla-per",
183
+ FILL_PLL_CHANNEL_INIT_INFO(PLLA, PER),
184
+ },
185
+ [CPRMAN_PLLA_CHANNEL_CCP2] = {
186
+ .name = "plla-ccp2",
187
+ FILL_PLL_CHANNEL_INIT_INFO(PLLA, CCP2),
188
+ },
189
+
190
+ [CPRMAN_PLLC_CHANNEL_CORE2] = {
191
+ .name = "pllc-core2",
192
+ FILL_PLL_CHANNEL_INIT_INFO(PLLC, CORE2),
193
+ },
194
+ [CPRMAN_PLLC_CHANNEL_CORE1] = {
195
+ .name = "pllc-core1",
196
+ FILL_PLL_CHANNEL_INIT_INFO(PLLC, CORE1),
197
+ },
198
+ [CPRMAN_PLLC_CHANNEL_PER] = {
199
+ .name = "pllc-per",
200
+ FILL_PLL_CHANNEL_INIT_INFO(PLLC, PER),
201
+ },
202
+ [CPRMAN_PLLC_CHANNEL_CORE0] = {
203
+ .name = "pllc-core0",
204
+ FILL_PLL_CHANNEL_INIT_INFO(PLLC, CORE0),
205
+ },
206
+
207
+ [CPRMAN_PLLD_CHANNEL_DSI0] = {
208
+ .name = "plld-dsi0",
209
+ FILL_PLL_CHANNEL_INIT_INFO(PLLD, DSI0),
210
+ },
211
+ [CPRMAN_PLLD_CHANNEL_CORE] = {
212
+ .name = "plld-core",
213
+ FILL_PLL_CHANNEL_INIT_INFO(PLLD, CORE),
214
+ },
215
+ [CPRMAN_PLLD_CHANNEL_PER] = {
216
+ .name = "plld-per",
217
+ FILL_PLL_CHANNEL_INIT_INFO(PLLD, PER),
218
+ },
219
+ [CPRMAN_PLLD_CHANNEL_DSI1] = {
220
+ .name = "plld-dsi1",
221
+ FILL_PLL_CHANNEL_INIT_INFO(PLLD, DSI1),
222
+ },
223
+
224
+ [CPRMAN_PLLH_CHANNEL_AUX] = {
225
+ .name = "pllh-aux",
226
+ .fixed_divider = 1,
227
+ FILL_PLL_CHANNEL_INIT_INFO_nohold(PLLH, AUX),
228
+ },
229
+ [CPRMAN_PLLH_CHANNEL_RCAL] = {
230
+ .name = "pllh-rcal",
231
+ .fixed_divider = 10,
232
+ FILL_PLL_CHANNEL_INIT_INFO_nohold(PLLH, RCAL),
233
+ },
234
+ [CPRMAN_PLLH_CHANNEL_PIX] = {
235
+ .name = "pllh-pix",
236
+ .fixed_divider = 10,
237
+ FILL_PLL_CHANNEL_INIT_INFO_nohold(PLLH, PIX),
238
+ },
239
+
240
+ [CPRMAN_PLLB_CHANNEL_ARM] = {
241
+ .name = "pllb-arm",
242
+ FILL_PLL_CHANNEL_INIT_INFO(PLLB, ARM),
243
+ },
244
+};
245
+
246
+#undef FILL_PLL_CHANNEL_INIT_INFO_nohold
247
+#undef FILL_PLL_CHANNEL_INIT_INFO
248
+#undef FILL_PLL_CHANNEL_INIT_INFO_common
249
+
250
+static inline void set_pll_channel_init_info(BCM2835CprmanState *s,
251
+ CprmanPllChannelState *channel,
252
+ CprmanPllChannel id)
253
+{
254
+ channel->id = id;
255
+ channel->parent = PLL_CHANNEL_INIT_INFO[id].parent;
256
+ channel->reg_cm = &s->regs[PLL_CHANNEL_INIT_INFO[id].cm_offset];
257
+ channel->hold_mask = PLL_CHANNEL_INIT_INFO[id].cm_hold_mask;
258
+ channel->load_mask = PLL_CHANNEL_INIT_INFO[id].cm_load_mask;
259
+ channel->reg_a2w_ctrl = &s->regs[PLL_CHANNEL_INIT_INFO[id].a2w_ctrl_offset];
260
+ channel->fixed_divider = PLL_CHANNEL_INIT_INFO[id].fixed_divider;
261
+}
262
+
263
#endif
264
diff --git a/hw/misc/bcm2835_cprman.c b/hw/misc/bcm2835_cprman.c
265
index XXXXXXX..XXXXXXX 100644
266
--- a/hw/misc/bcm2835_cprman.c
267
+++ b/hw/misc/bcm2835_cprman.c
268
@@ -XXX,XX +XXX,XX @@ static const TypeInfo cprman_pll_info = {
269
};
270
271
272
+/* PLL channel */
273
+
274
+static void pll_channel_update(CprmanPllChannelState *channel)
275
+{
276
+ clock_update(channel->out, 0);
277
+}
278
+
279
+/* Update a PLL and all its channels */
280
+static void pll_update_all_channels(BCM2835CprmanState *s,
281
+ CprmanPllState *pll)
282
+{
283
+ size_t i;
284
+
285
+ pll_update(pll);
286
+
287
+ for (i = 0; i < CPRMAN_NUM_PLL_CHANNEL; i++) {
288
+ CprmanPllChannelState *channel = &s->channels[i];
289
+ if (channel->parent == pll->id) {
290
+ pll_channel_update(channel);
291
+ }
292
+ }
293
+}
294
+
295
+static void pll_channel_pll_in_update(void *opaque)
296
+{
297
+ pll_channel_update(CPRMAN_PLL_CHANNEL(opaque));
298
+}
299
+
300
+static void pll_channel_init(Object *obj)
301
+{
302
+ CprmanPllChannelState *s = CPRMAN_PLL_CHANNEL(obj);
303
+
304
+ s->pll_in = qdev_init_clock_in(DEVICE(s), "pll-in",
305
+ pll_channel_pll_in_update, s);
306
+ s->out = qdev_init_clock_out(DEVICE(s), "out");
307
+}
308
+
309
+static const VMStateDescription pll_channel_vmstate = {
310
+ .name = TYPE_CPRMAN_PLL_CHANNEL,
311
+ .version_id = 1,
312
+ .minimum_version_id = 1,
313
+ .fields = (VMStateField[]) {
314
+ VMSTATE_CLOCK(pll_in, CprmanPllChannelState),
315
+ VMSTATE_END_OF_LIST()
316
+ }
317
+};
318
+
319
+static void pll_channel_class_init(ObjectClass *klass, void *data)
320
+{
321
+ DeviceClass *dc = DEVICE_CLASS(klass);
322
+
323
+ dc->vmsd = &pll_channel_vmstate;
324
+}
325
+
326
+static const TypeInfo cprman_pll_channel_info = {
327
+ .name = TYPE_CPRMAN_PLL_CHANNEL,
328
+ .parent = TYPE_DEVICE,
329
+ .instance_size = sizeof(CprmanPllChannelState),
330
+ .class_init = pll_channel_class_init,
331
+ .instance_init = pll_channel_init,
332
+};
333
+
334
+
335
/* CPRMAN "top level" model */
336
337
static uint32_t get_cm_lock(const BCM2835CprmanState *s)
338
@@ -XXX,XX +XXX,XX @@ static uint64_t cprman_read(void *opaque, hwaddr offset,
339
return r;
340
}
341
342
-#define CASE_PLL_REGS(pll_) \
343
- case R_CM_ ## pll_: \
344
+static inline void update_pll_and_channels_from_cm(BCM2835CprmanState *s,
345
+ size_t idx)
346
+{
347
+ size_t i;
348
+
349
+ for (i = 0; i < CPRMAN_NUM_PLL; i++) {
350
+ if (PLL_INIT_INFO[i].cm_offset == idx) {
351
+ pll_update_all_channels(s, &s->plls[i]);
352
+ return;
353
+ }
354
+ }
355
+}
356
+
357
+static inline void update_channel_from_a2w(BCM2835CprmanState *s, size_t idx)
358
+{
359
+ size_t i;
360
+
361
+ for (i = 0; i < CPRMAN_NUM_PLL_CHANNEL; i++) {
362
+ if (PLL_CHANNEL_INIT_INFO[i].a2w_ctrl_offset == idx) {
363
+ pll_channel_update(&s->channels[i]);
364
+ return;
365
+ }
366
+ }
367
+}
368
+
369
+#define CASE_PLL_A2W_REGS(pll_) \
370
case R_A2W_ ## pll_ ## _CTRL: \
371
case R_A2W_ ## pll_ ## _ANA0: \
372
case R_A2W_ ## pll_ ## _ANA1: \
373
@@ -XXX,XX +XXX,XX @@ static void cprman_write(void *opaque, hwaddr offset,
374
s->regs[idx] = value;
375
376
switch (idx) {
377
- CASE_PLL_REGS(PLLA) :
378
+ case R_CM_PLLA ... R_CM_PLLH:
379
+ case R_CM_PLLB:
380
+ /*
381
+ * A given CM_PLLx register is shared by both the PLL and the channels
382
+ * of this PLL.
383
+ */
384
+ update_pll_and_channels_from_cm(s, idx);
385
+ break;
386
+
387
+ CASE_PLL_A2W_REGS(PLLA) :
388
pll_update(&s->plls[CPRMAN_PLLA]);
389
break;
390
391
- CASE_PLL_REGS(PLLC) :
392
+ CASE_PLL_A2W_REGS(PLLC) :
393
pll_update(&s->plls[CPRMAN_PLLC]);
394
break;
395
396
- CASE_PLL_REGS(PLLD) :
397
+ CASE_PLL_A2W_REGS(PLLD) :
398
pll_update(&s->plls[CPRMAN_PLLD]);
399
break;
400
401
- CASE_PLL_REGS(PLLH) :
402
+ CASE_PLL_A2W_REGS(PLLH) :
403
pll_update(&s->plls[CPRMAN_PLLH]);
404
break;
405
406
- CASE_PLL_REGS(PLLB) :
407
+ CASE_PLL_A2W_REGS(PLLB) :
408
pll_update(&s->plls[CPRMAN_PLLB]);
409
break;
410
+
411
+ case R_A2W_PLLA_DSI0:
412
+ case R_A2W_PLLA_CORE:
413
+ case R_A2W_PLLA_PER:
414
+ case R_A2W_PLLA_CCP2:
415
+ case R_A2W_PLLC_CORE2:
416
+ case R_A2W_PLLC_CORE1:
417
+ case R_A2W_PLLC_PER:
418
+ case R_A2W_PLLC_CORE0:
419
+ case R_A2W_PLLD_DSI0:
420
+ case R_A2W_PLLD_CORE:
421
+ case R_A2W_PLLD_PER:
422
+ case R_A2W_PLLD_DSI1:
423
+ case R_A2W_PLLH_AUX:
424
+ case R_A2W_PLLH_RCAL:
425
+ case R_A2W_PLLH_PIX:
426
+ case R_A2W_PLLB_ARM:
427
+ update_channel_from_a2w(s, idx);
428
+ break;
429
}
430
}
431
432
-#undef CASE_PLL_REGS
433
+#undef CASE_PLL_A2W_REGS
434
435
static const MemoryRegionOps cprman_ops = {
436
.read = cprman_read,
437
@@ -XXX,XX +XXX,XX @@ static void cprman_reset(DeviceState *dev)
438
device_cold_reset(DEVICE(&s->plls[i]));
439
}
440
441
+ for (i = 0; i < CPRMAN_NUM_PLL_CHANNEL; i++) {
442
+ device_cold_reset(DEVICE(&s->channels[i]));
443
+ }
444
+
445
clock_update_hz(s->xosc, s->xosc_freq);
446
}
447
448
@@ -XXX,XX +XXX,XX @@ static void cprman_init(Object *obj)
449
set_pll_init_info(s, &s->plls[i], i);
450
}
451
452
+ for (i = 0; i < CPRMAN_NUM_PLL_CHANNEL; i++) {
453
+ object_initialize_child(obj, PLL_CHANNEL_INIT_INFO[i].name,
454
+ &s->channels[i],
455
+ TYPE_CPRMAN_PLL_CHANNEL);
456
+ set_pll_channel_init_info(s, &s->channels[i], i);
457
+ }
458
+
459
s->xosc = clock_new(obj, "xosc");
460
461
memory_region_init_io(&s->iomem, obj, &cprman_ops,
462
@@ -XXX,XX +XXX,XX @@ static void cprman_realize(DeviceState *dev, Error **errp)
463
return;
464
}
465
}
466
+
467
+ for (i = 0; i < CPRMAN_NUM_PLL_CHANNEL; i++) {
468
+ CprmanPllChannelState *channel = &s->channels[i];
469
+ CprmanPll parent = PLL_CHANNEL_INIT_INFO[i].parent;
470
+ Clock *parent_clk = s->plls[parent].out;
471
+
472
+ clock_set_source(channel->pll_in, parent_clk);
473
+
474
+ if (!qdev_realize(DEVICE(channel), NULL, errp)) {
475
+ return;
476
+ }
477
+ }
478
}
479
480
static const VMStateDescription cprman_vmstate = {
481
@@ -XXX,XX +XXX,XX @@ static void cprman_register_types(void)
482
{
483
type_register_static(&cprman_info);
484
type_register_static(&cprman_pll_info);
485
+ type_register_static(&cprman_pll_channel_info);
486
}
487
488
type_init(cprman_register_types);
489
--
490
2.20.1
491
492
diff view generated by jsdifflib
1
Abstract the "load kernel" code out of armv7m_init() into its own
1
From: Luc Michel <luc@lmichel.fr>
2
function. This includes the registration of the CPU reset function,
3
to parallel how we handle this for A profile cores.
4
2
5
We make the function public so that boards which choose to
3
A PLL channel is able to further divide the generated PLL frequency.
6
directly instantiate an ARMv7M device object can call it.
4
The divider is given in the CTRL_A2W register. Some channels have an
5
additional fixed divider which is always applied to the signal.
7
6
7
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Signed-off-by: Luc Michel <luc@lmichel.fr>
10
Tested-by: Guenter Roeck <linux@roeck-us.net>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
11
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
12
Message-id: 1487604965-23220-2-git-send-email-peter.maydell@linaro.org
13
---
12
---
14
include/hw/arm/arm.h | 12 ++++++++++++
13
hw/misc/bcm2835_cprman.c | 33 ++++++++++++++++++++++++++++++++-
15
hw/arm/armv7m.c | 23 ++++++++++++++++++-----
14
1 file changed, 32 insertions(+), 1 deletion(-)
16
2 files changed, 30 insertions(+), 5 deletions(-)
17
15
18
diff --git a/include/hw/arm/arm.h b/include/hw/arm/arm.h
16
diff --git a/hw/misc/bcm2835_cprman.c b/hw/misc/bcm2835_cprman.c
19
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/arm/arm.h
18
--- a/hw/misc/bcm2835_cprman.c
21
+++ b/include/hw/arm/arm.h
19
+++ b/hw/misc/bcm2835_cprman.c
22
@@ -XXX,XX +XXX,XX @@ typedef enum {
20
@@ -XXX,XX +XXX,XX @@ static const TypeInfo cprman_pll_info = {
23
/* armv7m.c */
21
24
DeviceState *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq,
22
/* PLL channel */
25
const char *kernel_filename, const char *cpu_model);
23
26
+/**
24
+static bool pll_channel_is_enabled(CprmanPllChannelState *channel)
27
+ * armv7m_load_kernel:
25
+{
28
+ * @cpu: CPU
26
+ /*
29
+ * @kernel_filename: file to load
27
+ * XXX I'm not sure of the purpose of the LOAD field. The Linux driver does
30
+ * @mem_size: mem_size: maximum image size to load
28
+ * not set it when enabling the channel, but does clear it when disabling
31
+ *
29
+ * it.
32
+ * Load the guest image for an ARMv7M system. This must be called by
30
+ */
33
+ * any ARMv7M board, either directly or via armv7m_init(). (This is
31
+ return !FIELD_EX32(*channel->reg_a2w_ctrl, A2W_PLLx_CHANNELy, DISABLE)
34
+ * necessary to ensure that the CPU resets correctly on system reset,
32
+ && !(*channel->reg_cm & channel->hold_mask);
35
+ * as well as for kernel loading.)
36
+ */
37
+void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size);
38
39
/*
40
* struct used as a parameter of the arm_load_kernel machine init
41
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
42
index XXXXXXX..XXXXXXX 100644
43
--- a/hw/arm/armv7m.c
44
+++ b/hw/arm/armv7m.c
45
@@ -XXX,XX +XXX,XX @@ DeviceState *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq,
46
ARMCPU *cpu;
47
CPUARMState *env;
48
DeviceState *nvic;
49
- int image_size;
50
- uint64_t entry;
51
- uint64_t lowaddr;
52
- int big_endian;
53
54
if (cpu_model == NULL) {
55
    cpu_model = "cortex-m3";
56
@@ -XXX,XX +XXX,XX @@ DeviceState *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq,
57
qdev_init_nofail(nvic);
58
sysbus_connect_irq(SYS_BUS_DEVICE(nvic), 0,
59
qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ));
60
+ armv7m_load_kernel(cpu, kernel_filename, mem_size);
61
+ return nvic;
62
+}
33
+}
63
+
34
+
64
+void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size)
35
static void pll_channel_update(CprmanPllChannelState *channel)
65
+{
36
{
66
+ int image_size;
37
- clock_update(channel->out, 0);
67
+ uint64_t entry;
38
+ uint64_t freq, div;
68
+ uint64_t lowaddr;
39
+
69
+ int big_endian;
40
+ if (!pll_channel_is_enabled(channel)) {
70
41
+ clock_update(channel->out, 0);
71
#ifdef TARGET_WORDS_BIGENDIAN
42
+ return;
72
big_endian = 1;
43
+ }
73
@@ -XXX,XX +XXX,XX @@ DeviceState *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq,
44
+
74
}
45
+ div = FIELD_EX32(*channel->reg_a2w_ctrl, A2W_PLLx_CHANNELy, DIV);
75
}
46
+
76
47
+ if (!div) {
77
+ /* CPU objects (unlike devices) are not automatically reset on system
48
+ /*
78
+ * reset, so we must always register a handler to do so. Unlike
49
+ * It seems that when the divider value is 0, it is considered as
79
+ * A-profile CPUs, we don't need to do anything special in the
50
+ * being maximum by the hardware (see the Linux driver).
80
+ * handler to arrange that it starts correctly.
51
+ */
81
+ * This is arguably the wrong place to do this, but it matches the
52
+ div = R_A2W_PLLx_CHANNELy_DIV_MASK;
82
+ * way A-profile does it. Note that this means that every M profile
53
+ }
83
+ * board must call this function!
54
+
84
+ */
55
+ /* Some channels have an additional fixed divider */
85
qemu_register_reset(armv7m_reset, cpu);
56
+ freq = clock_get_hz(channel->pll_in) / (div * channel->fixed_divider);
86
- return nvic;
57
+
58
+ clock_update_hz(channel->out, freq);
87
}
59
}
88
60
89
static Property bitband_properties[] = {
61
/* Update a PLL and all its channels */
90
--
62
--
91
2.7.4
63
2.20.1
92
64
93
65
diff view generated by jsdifflib
1
From: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
1
From: Luc Michel <luc@lmichel.fr>
2
2
3
Reset CPU interface registers of GICv3 when CPU is reset.
3
The clock multiplexers are the last clock stage in the CPRMAN. Each mux
4
For this, ARMCPRegInfo struct is registered with one ICC
4
outputs one clock signal that goes out of the CPRMAN to the SoC
5
register whose resetfn is called when cpu is reset.
5
peripherals.
6
6
7
All the ICC registers are reset under one single register
7
Each mux has at most 10 sources. The sources 0 to 3 are common to all
8
reset function instead of calling resetfn for each ICC
8
muxes. They are:
9
register.
9
0. ground (no clock signal)
10
10
1. the main oscillator (xosc)
11
Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
11
2. "test debug 0" clock
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
3. "test debug 1" clock
13
Reviewed-by: Eric Auger <eric.auger@redhat.com>
13
14
Message-id: 1487850673-26455-6-git-send-email-vijay.kilari@gmail.com
14
Test debug 0 and 1 are actual clock muxes that can be used as sources to
15
other muxes (for debug purpose).
16
17
Sources 4 to 9 are mux specific and can be unpopulated (grounded). Those
18
sources are fed by the PLL channels outputs.
19
20
One corner case exists for DSI0E and DSI0P muxes. They have their source
21
number 4 connected to an intermediate multiplexer that can select
22
between PLLA-DSI0 and PLLD-DSI0 channel. This multiplexer is called
23
DSI0HSCK and is not a clock mux as such. It is really a simple mux from
24
the hardware point of view (see https://elinux.org/The_Undocumented_Pi).
25
This mux is not implemented in this commit.
26
27
Note that there is some muxes for which sources are unknown (because of
28
a lack of documentation). For those cases all the sources are connected
29
to ground in this implementation.
30
31
Each clock mux output is exported by the CPRMAN at the qdev level,
32
adding the suffix '-out' to the mux name to form the output clock name.
33
(E.g. the 'uart' mux sees its output exported as 'uart-out' at the
34
CPRMAN level.)
35
36
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
37
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
38
Signed-off-by: Luc Michel <luc@lmichel.fr>
39
Tested-by: Guenter Roeck <linux@roeck-us.net>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
40
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
41
---
17
hw/intc/arm_gicv3_kvm.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++
42
include/hw/misc/bcm2835_cprman.h | 85 +++++
18
1 file changed, 60 insertions(+)
43
include/hw/misc/bcm2835_cprman_internals.h | 422 +++++++++++++++++++++
19
44
hw/misc/bcm2835_cprman.c | 151 ++++++++
20
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
45
3 files changed, 658 insertions(+)
46
47
diff --git a/include/hw/misc/bcm2835_cprman.h b/include/hw/misc/bcm2835_cprman.h
21
index XXXXXXX..XXXXXXX 100644
48
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/intc/arm_gicv3_kvm.c
49
--- a/include/hw/misc/bcm2835_cprman.h
23
+++ b/hw/intc/arm_gicv3_kvm.c
50
+++ b/include/hw/misc/bcm2835_cprman.h
24
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gicv3_get(GICv3State *s)
51
@@ -XXX,XX +XXX,XX @@ typedef enum CprmanPllChannel {
52
CPRMAN_PLLB_CHANNEL_ARM,
53
54
CPRMAN_NUM_PLL_CHANNEL,
55
+
56
+ /* Special values used when connecting clock sources to clocks */
57
+ CPRMAN_CLOCK_SRC_NORMAL = -1,
58
+ CPRMAN_CLOCK_SRC_FORCE_GROUND = -2,
59
+ CPRMAN_CLOCK_SRC_DSI0HSCK = -3,
60
} CprmanPllChannel;
61
62
+typedef enum CprmanClockMux {
63
+ CPRMAN_CLOCK_GNRIC,
64
+ CPRMAN_CLOCK_VPU,
65
+ CPRMAN_CLOCK_SYS,
66
+ CPRMAN_CLOCK_PERIA,
67
+ CPRMAN_CLOCK_PERII,
68
+ CPRMAN_CLOCK_H264,
69
+ CPRMAN_CLOCK_ISP,
70
+ CPRMAN_CLOCK_V3D,
71
+ CPRMAN_CLOCK_CAM0,
72
+ CPRMAN_CLOCK_CAM1,
73
+ CPRMAN_CLOCK_CCP2,
74
+ CPRMAN_CLOCK_DSI0E,
75
+ CPRMAN_CLOCK_DSI0P,
76
+ CPRMAN_CLOCK_DPI,
77
+ CPRMAN_CLOCK_GP0,
78
+ CPRMAN_CLOCK_GP1,
79
+ CPRMAN_CLOCK_GP2,
80
+ CPRMAN_CLOCK_HSM,
81
+ CPRMAN_CLOCK_OTP,
82
+ CPRMAN_CLOCK_PCM,
83
+ CPRMAN_CLOCK_PWM,
84
+ CPRMAN_CLOCK_SLIM,
85
+ CPRMAN_CLOCK_SMI,
86
+ CPRMAN_CLOCK_TEC,
87
+ CPRMAN_CLOCK_TD0,
88
+ CPRMAN_CLOCK_TD1,
89
+ CPRMAN_CLOCK_TSENS,
90
+ CPRMAN_CLOCK_TIMER,
91
+ CPRMAN_CLOCK_UART,
92
+ CPRMAN_CLOCK_VEC,
93
+ CPRMAN_CLOCK_PULSE,
94
+ CPRMAN_CLOCK_SDC,
95
+ CPRMAN_CLOCK_ARM,
96
+ CPRMAN_CLOCK_AVEO,
97
+ CPRMAN_CLOCK_EMMC,
98
+ CPRMAN_CLOCK_EMMC2,
99
+
100
+ CPRMAN_NUM_CLOCK_MUX
101
+} CprmanClockMux;
102
+
103
+typedef enum CprmanClockMuxSource {
104
+ CPRMAN_CLOCK_SRC_GND = 0,
105
+ CPRMAN_CLOCK_SRC_XOSC,
106
+ CPRMAN_CLOCK_SRC_TD0,
107
+ CPRMAN_CLOCK_SRC_TD1,
108
+ CPRMAN_CLOCK_SRC_PLLA,
109
+ CPRMAN_CLOCK_SRC_PLLC,
110
+ CPRMAN_CLOCK_SRC_PLLD,
111
+ CPRMAN_CLOCK_SRC_PLLH,
112
+ CPRMAN_CLOCK_SRC_PLLC_CORE1,
113
+ CPRMAN_CLOCK_SRC_PLLC_CORE2,
114
+
115
+ CPRMAN_NUM_CLOCK_MUX_SRC
116
+} CprmanClockMuxSource;
117
+
118
typedef struct CprmanPllState {
119
/*< private >*/
120
DeviceState parent_obj;
121
@@ -XXX,XX +XXX,XX @@ typedef struct CprmanPllChannelState {
122
Clock *out;
123
} CprmanPllChannelState;
124
125
+typedef struct CprmanClockMuxState {
126
+ /*< private >*/
127
+ DeviceState parent_obj;
128
+
129
+ /*< public >*/
130
+ CprmanClockMux id;
131
+
132
+ uint32_t *reg_ctl;
133
+ uint32_t *reg_div;
134
+ int int_bits;
135
+ int frac_bits;
136
+
137
+ Clock *srcs[CPRMAN_NUM_CLOCK_MUX_SRC];
138
+ Clock *out;
139
+
140
+ /*
141
+ * Used by clock srcs update callback to retrieve both the clock and the
142
+ * source number.
143
+ */
144
+ struct CprmanClockMuxState *backref[CPRMAN_NUM_CLOCK_MUX_SRC];
145
+} CprmanClockMuxState;
146
+
147
struct BCM2835CprmanState {
148
/*< private >*/
149
SysBusDevice parent_obj;
150
@@ -XXX,XX +XXX,XX @@ struct BCM2835CprmanState {
151
152
CprmanPllState plls[CPRMAN_NUM_PLL];
153
CprmanPllChannelState channels[CPRMAN_NUM_PLL_CHANNEL];
154
+ CprmanClockMuxState clock_muxes[CPRMAN_NUM_CLOCK_MUX];
155
156
uint32_t regs[CPRMAN_NUM_REGS];
157
uint32_t xosc_freq;
158
159
Clock *xosc;
160
+ Clock *gnd;
161
};
162
163
#endif
164
diff --git a/include/hw/misc/bcm2835_cprman_internals.h b/include/hw/misc/bcm2835_cprman_internals.h
165
index XXXXXXX..XXXXXXX 100644
166
--- a/include/hw/misc/bcm2835_cprman_internals.h
167
+++ b/include/hw/misc/bcm2835_cprman_internals.h
168
@@ -XXX,XX +XXX,XX @@
169
170
#define TYPE_CPRMAN_PLL "bcm2835-cprman-pll"
171
#define TYPE_CPRMAN_PLL_CHANNEL "bcm2835-cprman-pll-channel"
172
+#define TYPE_CPRMAN_CLOCK_MUX "bcm2835-cprman-clock-mux"
173
174
DECLARE_INSTANCE_CHECKER(CprmanPllState, CPRMAN_PLL,
175
TYPE_CPRMAN_PLL)
176
DECLARE_INSTANCE_CHECKER(CprmanPllChannelState, CPRMAN_PLL_CHANNEL,
177
TYPE_CPRMAN_PLL_CHANNEL)
178
+DECLARE_INSTANCE_CHECKER(CprmanClockMuxState, CPRMAN_CLOCK_MUX,
179
+ TYPE_CPRMAN_CLOCK_MUX)
180
181
/* Register map */
182
183
@@ -XXX,XX +XXX,XX @@ REG32(A2W_PLLH_STS, 0x1660)
184
185
REG32(A2W_PLLB_ARM, 0x13e0)
186
187
+/* Clock muxes */
188
+REG32(CM_GNRICCTL, 0x000)
189
+ FIELD(CM_CLOCKx_CTL, SRC, 0, 4)
190
+ FIELD(CM_CLOCKx_CTL, ENABLE, 4, 1)
191
+ FIELD(CM_CLOCKx_CTL, KILL, 5, 1)
192
+ FIELD(CM_CLOCKx_CTL, GATE, 6, 1)
193
+ FIELD(CM_CLOCKx_CTL, BUSY, 7, 1)
194
+ FIELD(CM_CLOCKx_CTL, BUSYD, 8, 1)
195
+ FIELD(CM_CLOCKx_CTL, MASH, 9, 2)
196
+ FIELD(CM_CLOCKx_CTL, FLIP, 11, 1)
197
+REG32(CM_GNRICDIV, 0x004)
198
+ FIELD(CM_CLOCKx_DIV, FRAC, 0, 12)
199
+REG32(CM_VPUCTL, 0x008)
200
+REG32(CM_VPUDIV, 0x00c)
201
+REG32(CM_SYSCTL, 0x010)
202
+REG32(CM_SYSDIV, 0x014)
203
+REG32(CM_PERIACTL, 0x018)
204
+REG32(CM_PERIADIV, 0x01c)
205
+REG32(CM_PERIICTL, 0x020)
206
+REG32(CM_PERIIDIV, 0x024)
207
+REG32(CM_H264CTL, 0x028)
208
+REG32(CM_H264DIV, 0x02c)
209
+REG32(CM_ISPCTL, 0x030)
210
+REG32(CM_ISPDIV, 0x034)
211
+REG32(CM_V3DCTL, 0x038)
212
+REG32(CM_V3DDIV, 0x03c)
213
+REG32(CM_CAM0CTL, 0x040)
214
+REG32(CM_CAM0DIV, 0x044)
215
+REG32(CM_CAM1CTL, 0x048)
216
+REG32(CM_CAM1DIV, 0x04c)
217
+REG32(CM_CCP2CTL, 0x050)
218
+REG32(CM_CCP2DIV, 0x054)
219
+REG32(CM_DSI0ECTL, 0x058)
220
+REG32(CM_DSI0EDIV, 0x05c)
221
+REG32(CM_DSI0PCTL, 0x060)
222
+REG32(CM_DSI0PDIV, 0x064)
223
+REG32(CM_DPICTL, 0x068)
224
+REG32(CM_DPIDIV, 0x06c)
225
+REG32(CM_GP0CTL, 0x070)
226
+REG32(CM_GP0DIV, 0x074)
227
+REG32(CM_GP1CTL, 0x078)
228
+REG32(CM_GP1DIV, 0x07c)
229
+REG32(CM_GP2CTL, 0x080)
230
+REG32(CM_GP2DIV, 0x084)
231
+REG32(CM_HSMCTL, 0x088)
232
+REG32(CM_HSMDIV, 0x08c)
233
+REG32(CM_OTPCTL, 0x090)
234
+REG32(CM_OTPDIV, 0x094)
235
+REG32(CM_PCMCTL, 0x098)
236
+REG32(CM_PCMDIV, 0x09c)
237
+REG32(CM_PWMCTL, 0x0a0)
238
+REG32(CM_PWMDIV, 0x0a4)
239
+REG32(CM_SLIMCTL, 0x0a8)
240
+REG32(CM_SLIMDIV, 0x0ac)
241
+REG32(CM_SMICTL, 0x0b0)
242
+REG32(CM_SMIDIV, 0x0b4)
243
+REG32(CM_TCNTCTL, 0x0c0)
244
+REG32(CM_TCNTCNT, 0x0c4)
245
+REG32(CM_TECCTL, 0x0c8)
246
+REG32(CM_TECDIV, 0x0cc)
247
+REG32(CM_TD0CTL, 0x0d0)
248
+REG32(CM_TD0DIV, 0x0d4)
249
+REG32(CM_TD1CTL, 0x0d8)
250
+REG32(CM_TD1DIV, 0x0dc)
251
+REG32(CM_TSENSCTL, 0x0e0)
252
+REG32(CM_TSENSDIV, 0x0e4)
253
+REG32(CM_TIMERCTL, 0x0e8)
254
+REG32(CM_TIMERDIV, 0x0ec)
255
+REG32(CM_UARTCTL, 0x0f0)
256
+REG32(CM_UARTDIV, 0x0f4)
257
+REG32(CM_VECCTL, 0x0f8)
258
+REG32(CM_VECDIV, 0x0fc)
259
+REG32(CM_PULSECTL, 0x190)
260
+REG32(CM_PULSEDIV, 0x194)
261
+REG32(CM_SDCCTL, 0x1a8)
262
+REG32(CM_SDCDIV, 0x1ac)
263
+REG32(CM_ARMCTL, 0x1b0)
264
+REG32(CM_AVEOCTL, 0x1b8)
265
+REG32(CM_AVEODIV, 0x1bc)
266
+REG32(CM_EMMCCTL, 0x1c0)
267
+REG32(CM_EMMCDIV, 0x1c4)
268
+REG32(CM_EMMC2CTL, 0x1d0)
269
+REG32(CM_EMMC2DIV, 0x1d4)
270
+
271
/* misc registers */
272
REG32(CM_LOCK, 0x114)
273
FIELD(CM_LOCK, FLOCKH, 12, 1)
274
@@ -XXX,XX +XXX,XX @@ static inline void set_pll_channel_init_info(BCM2835CprmanState *s,
275
channel->fixed_divider = PLL_CHANNEL_INIT_INFO[id].fixed_divider;
276
}
277
278
+/* Clock mux init info */
279
+typedef struct ClockMuxInitInfo {
280
+ const char *name;
281
+ size_t cm_offset; /* cm_offset[0]->CM_CTL, cm_offset[1]->CM_DIV */
282
+ int int_bits;
283
+ int frac_bits;
284
+
285
+ CprmanPllChannel src_mapping[CPRMAN_NUM_CLOCK_MUX_SRC];
286
+} ClockMuxInitInfo;
287
+
288
+/*
289
+ * Each clock mux can have up to 10 sources. Sources 0 to 3 are always the
290
+ * same (ground, xosc, td0, td1). Sources 4 to 9 are mux specific, and are not
291
+ * always populated. The following macros catch all those cases.
292
+ */
293
+
294
+/* Unknown mapping. Connect everything to ground */
295
+#define SRC_MAPPING_INFO_unknown \
296
+ .src_mapping = { \
297
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, /* gnd */ \
298
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, /* xosc */ \
299
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, /* test debug 0 */ \
300
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, /* test debug 1 */ \
301
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll a */ \
302
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll c */ \
303
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll d */ \
304
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll h */ \
305
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll c, core1 */ \
306
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll c, core2 */ \
307
+ }
308
+
309
+/* Only the oscillator and the two test debug clocks */
310
+#define SRC_MAPPING_INFO_xosc \
311
+ .src_mapping = { \
312
+ CPRMAN_CLOCK_SRC_NORMAL, \
313
+ CPRMAN_CLOCK_SRC_NORMAL, \
314
+ CPRMAN_CLOCK_SRC_NORMAL, \
315
+ CPRMAN_CLOCK_SRC_NORMAL, \
316
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
317
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
318
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
319
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
320
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
321
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
322
+ }
323
+
324
+/* All the PLL "core" channels */
325
+#define SRC_MAPPING_INFO_core \
326
+ .src_mapping = { \
327
+ CPRMAN_CLOCK_SRC_NORMAL, \
328
+ CPRMAN_CLOCK_SRC_NORMAL, \
329
+ CPRMAN_CLOCK_SRC_NORMAL, \
330
+ CPRMAN_CLOCK_SRC_NORMAL, \
331
+ CPRMAN_PLLA_CHANNEL_CORE, \
332
+ CPRMAN_PLLC_CHANNEL_CORE0, \
333
+ CPRMAN_PLLD_CHANNEL_CORE, \
334
+ CPRMAN_PLLH_CHANNEL_AUX, \
335
+ CPRMAN_PLLC_CHANNEL_CORE1, \
336
+ CPRMAN_PLLC_CHANNEL_CORE2, \
337
+ }
338
+
339
+/* All the PLL "per" channels */
340
+#define SRC_MAPPING_INFO_periph \
341
+ .src_mapping = { \
342
+ CPRMAN_CLOCK_SRC_NORMAL, \
343
+ CPRMAN_CLOCK_SRC_NORMAL, \
344
+ CPRMAN_CLOCK_SRC_NORMAL, \
345
+ CPRMAN_CLOCK_SRC_NORMAL, \
346
+ CPRMAN_PLLA_CHANNEL_PER, \
347
+ CPRMAN_PLLC_CHANNEL_PER, \
348
+ CPRMAN_PLLD_CHANNEL_PER, \
349
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
350
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
351
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
352
+ }
353
+
354
+/*
355
+ * The DSI0 channels. This one got an intermediate mux between the PLL channels
356
+ * and the clock input.
357
+ */
358
+#define SRC_MAPPING_INFO_dsi0 \
359
+ .src_mapping = { \
360
+ CPRMAN_CLOCK_SRC_NORMAL, \
361
+ CPRMAN_CLOCK_SRC_NORMAL, \
362
+ CPRMAN_CLOCK_SRC_NORMAL, \
363
+ CPRMAN_CLOCK_SRC_NORMAL, \
364
+ CPRMAN_CLOCK_SRC_DSI0HSCK, \
365
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
366
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
367
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
368
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
369
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
370
+ }
371
+
372
+/* The DSI1 channel */
373
+#define SRC_MAPPING_INFO_dsi1 \
374
+ .src_mapping = { \
375
+ CPRMAN_CLOCK_SRC_NORMAL, \
376
+ CPRMAN_CLOCK_SRC_NORMAL, \
377
+ CPRMAN_CLOCK_SRC_NORMAL, \
378
+ CPRMAN_CLOCK_SRC_NORMAL, \
379
+ CPRMAN_PLLD_CHANNEL_DSI1, \
380
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
381
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
382
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
383
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
384
+ CPRMAN_CLOCK_SRC_FORCE_GROUND, \
385
+ }
386
+
387
+#define FILL_CLOCK_MUX_SRC_MAPPING_INIT_INFO(kind_) \
388
+ SRC_MAPPING_INFO_ ## kind_
389
+
390
+#define FILL_CLOCK_MUX_INIT_INFO(clock_, kind_) \
391
+ .cm_offset = R_CM_ ## clock_ ## CTL, \
392
+ FILL_CLOCK_MUX_SRC_MAPPING_INIT_INFO(kind_)
393
+
394
+static ClockMuxInitInfo CLOCK_MUX_INIT_INFO[] = {
395
+ [CPRMAN_CLOCK_GNRIC] = {
396
+ .name = "gnric",
397
+ FILL_CLOCK_MUX_INIT_INFO(GNRIC, unknown),
398
+ },
399
+ [CPRMAN_CLOCK_VPU] = {
400
+ .name = "vpu",
401
+ .int_bits = 12,
402
+ .frac_bits = 8,
403
+ FILL_CLOCK_MUX_INIT_INFO(VPU, core),
404
+ },
405
+ [CPRMAN_CLOCK_SYS] = {
406
+ .name = "sys",
407
+ FILL_CLOCK_MUX_INIT_INFO(SYS, unknown),
408
+ },
409
+ [CPRMAN_CLOCK_PERIA] = {
410
+ .name = "peria",
411
+ FILL_CLOCK_MUX_INIT_INFO(PERIA, unknown),
412
+ },
413
+ [CPRMAN_CLOCK_PERII] = {
414
+ .name = "perii",
415
+ FILL_CLOCK_MUX_INIT_INFO(PERII, unknown),
416
+ },
417
+ [CPRMAN_CLOCK_H264] = {
418
+ .name = "h264",
419
+ .int_bits = 4,
420
+ .frac_bits = 8,
421
+ FILL_CLOCK_MUX_INIT_INFO(H264, core),
422
+ },
423
+ [CPRMAN_CLOCK_ISP] = {
424
+ .name = "isp",
425
+ .int_bits = 4,
426
+ .frac_bits = 8,
427
+ FILL_CLOCK_MUX_INIT_INFO(ISP, core),
428
+ },
429
+ [CPRMAN_CLOCK_V3D] = {
430
+ .name = "v3d",
431
+ FILL_CLOCK_MUX_INIT_INFO(V3D, core),
432
+ },
433
+ [CPRMAN_CLOCK_CAM0] = {
434
+ .name = "cam0",
435
+ .int_bits = 4,
436
+ .frac_bits = 8,
437
+ FILL_CLOCK_MUX_INIT_INFO(CAM0, periph),
438
+ },
439
+ [CPRMAN_CLOCK_CAM1] = {
440
+ .name = "cam1",
441
+ .int_bits = 4,
442
+ .frac_bits = 8,
443
+ FILL_CLOCK_MUX_INIT_INFO(CAM1, periph),
444
+ },
445
+ [CPRMAN_CLOCK_CCP2] = {
446
+ .name = "ccp2",
447
+ FILL_CLOCK_MUX_INIT_INFO(CCP2, unknown),
448
+ },
449
+ [CPRMAN_CLOCK_DSI0E] = {
450
+ .name = "dsi0e",
451
+ .int_bits = 4,
452
+ .frac_bits = 8,
453
+ FILL_CLOCK_MUX_INIT_INFO(DSI0E, dsi0),
454
+ },
455
+ [CPRMAN_CLOCK_DSI0P] = {
456
+ .name = "dsi0p",
457
+ .int_bits = 0,
458
+ .frac_bits = 0,
459
+ FILL_CLOCK_MUX_INIT_INFO(DSI0P, dsi0),
460
+ },
461
+ [CPRMAN_CLOCK_DPI] = {
462
+ .name = "dpi",
463
+ .int_bits = 4,
464
+ .frac_bits = 8,
465
+ FILL_CLOCK_MUX_INIT_INFO(DPI, periph),
466
+ },
467
+ [CPRMAN_CLOCK_GP0] = {
468
+ .name = "gp0",
469
+ .int_bits = 12,
470
+ .frac_bits = 12,
471
+ FILL_CLOCK_MUX_INIT_INFO(GP0, periph),
472
+ },
473
+ [CPRMAN_CLOCK_GP1] = {
474
+ .name = "gp1",
475
+ .int_bits = 12,
476
+ .frac_bits = 12,
477
+ FILL_CLOCK_MUX_INIT_INFO(GP1, periph),
478
+ },
479
+ [CPRMAN_CLOCK_GP2] = {
480
+ .name = "gp2",
481
+ .int_bits = 12,
482
+ .frac_bits = 12,
483
+ FILL_CLOCK_MUX_INIT_INFO(GP2, periph),
484
+ },
485
+ [CPRMAN_CLOCK_HSM] = {
486
+ .name = "hsm",
487
+ .int_bits = 4,
488
+ .frac_bits = 8,
489
+ FILL_CLOCK_MUX_INIT_INFO(HSM, periph),
490
+ },
491
+ [CPRMAN_CLOCK_OTP] = {
492
+ .name = "otp",
493
+ .int_bits = 4,
494
+ .frac_bits = 0,
495
+ FILL_CLOCK_MUX_INIT_INFO(OTP, xosc),
496
+ },
497
+ [CPRMAN_CLOCK_PCM] = {
498
+ .name = "pcm",
499
+ .int_bits = 12,
500
+ .frac_bits = 12,
501
+ FILL_CLOCK_MUX_INIT_INFO(PCM, periph),
502
+ },
503
+ [CPRMAN_CLOCK_PWM] = {
504
+ .name = "pwm",
505
+ .int_bits = 12,
506
+ .frac_bits = 12,
507
+ FILL_CLOCK_MUX_INIT_INFO(PWM, periph),
508
+ },
509
+ [CPRMAN_CLOCK_SLIM] = {
510
+ .name = "slim",
511
+ .int_bits = 12,
512
+ .frac_bits = 12,
513
+ FILL_CLOCK_MUX_INIT_INFO(SLIM, periph),
514
+ },
515
+ [CPRMAN_CLOCK_SMI] = {
516
+ .name = "smi",
517
+ .int_bits = 4,
518
+ .frac_bits = 8,
519
+ FILL_CLOCK_MUX_INIT_INFO(SMI, periph),
520
+ },
521
+ [CPRMAN_CLOCK_TEC] = {
522
+ .name = "tec",
523
+ .int_bits = 6,
524
+ .frac_bits = 0,
525
+ FILL_CLOCK_MUX_INIT_INFO(TEC, xosc),
526
+ },
527
+ [CPRMAN_CLOCK_TD0] = {
528
+ .name = "td0",
529
+ FILL_CLOCK_MUX_INIT_INFO(TD0, unknown),
530
+ },
531
+ [CPRMAN_CLOCK_TD1] = {
532
+ .name = "td1",
533
+ FILL_CLOCK_MUX_INIT_INFO(TD1, unknown),
534
+ },
535
+ [CPRMAN_CLOCK_TSENS] = {
536
+ .name = "tsens",
537
+ .int_bits = 5,
538
+ .frac_bits = 0,
539
+ FILL_CLOCK_MUX_INIT_INFO(TSENS, xosc),
540
+ },
541
+ [CPRMAN_CLOCK_TIMER] = {
542
+ .name = "timer",
543
+ .int_bits = 6,
544
+ .frac_bits = 12,
545
+ FILL_CLOCK_MUX_INIT_INFO(TIMER, xosc),
546
+ },
547
+ [CPRMAN_CLOCK_UART] = {
548
+ .name = "uart",
549
+ .int_bits = 10,
550
+ .frac_bits = 12,
551
+ FILL_CLOCK_MUX_INIT_INFO(UART, periph),
552
+ },
553
+ [CPRMAN_CLOCK_VEC] = {
554
+ .name = "vec",
555
+ .int_bits = 4,
556
+ .frac_bits = 0,
557
+ FILL_CLOCK_MUX_INIT_INFO(VEC, periph),
558
+ },
559
+ [CPRMAN_CLOCK_PULSE] = {
560
+ .name = "pulse",
561
+ FILL_CLOCK_MUX_INIT_INFO(PULSE, xosc),
562
+ },
563
+ [CPRMAN_CLOCK_SDC] = {
564
+ .name = "sdram",
565
+ .int_bits = 6,
566
+ .frac_bits = 0,
567
+ FILL_CLOCK_MUX_INIT_INFO(SDC, core),
568
+ },
569
+ [CPRMAN_CLOCK_ARM] = {
570
+ .name = "arm",
571
+ FILL_CLOCK_MUX_INIT_INFO(ARM, unknown),
572
+ },
573
+ [CPRMAN_CLOCK_AVEO] = {
574
+ .name = "aveo",
575
+ .int_bits = 4,
576
+ .frac_bits = 0,
577
+ FILL_CLOCK_MUX_INIT_INFO(AVEO, periph),
578
+ },
579
+ [CPRMAN_CLOCK_EMMC] = {
580
+ .name = "emmc",
581
+ .int_bits = 4,
582
+ .frac_bits = 8,
583
+ FILL_CLOCK_MUX_INIT_INFO(EMMC, periph),
584
+ },
585
+ [CPRMAN_CLOCK_EMMC2] = {
586
+ .name = "emmc2",
587
+ .int_bits = 4,
588
+ .frac_bits = 8,
589
+ FILL_CLOCK_MUX_INIT_INFO(EMMC2, unknown),
590
+ },
591
+};
592
+
593
+#undef FILL_CLOCK_MUX_INIT_INFO
594
+#undef FILL_CLOCK_MUX_SRC_MAPPING_INIT_INFO
595
+#undef SRC_MAPPING_INFO_dsi1
596
+#undef SRC_MAPPING_INFO_dsi0
597
+#undef SRC_MAPPING_INFO_periph
598
+#undef SRC_MAPPING_INFO_core
599
+#undef SRC_MAPPING_INFO_xosc
600
+#undef SRC_MAPPING_INFO_unknown
601
+
602
+static inline void set_clock_mux_init_info(BCM2835CprmanState *s,
603
+ CprmanClockMuxState *mux,
604
+ CprmanClockMux id)
605
+{
606
+ mux->id = id;
607
+ mux->reg_ctl = &s->regs[CLOCK_MUX_INIT_INFO[id].cm_offset];
608
+ mux->reg_div = &s->regs[CLOCK_MUX_INIT_INFO[id].cm_offset + 1];
609
+ mux->int_bits = CLOCK_MUX_INIT_INFO[id].int_bits;
610
+ mux->frac_bits = CLOCK_MUX_INIT_INFO[id].frac_bits;
611
+}
612
+
613
#endif
614
diff --git a/hw/misc/bcm2835_cprman.c b/hw/misc/bcm2835_cprman.c
615
index XXXXXXX..XXXXXXX 100644
616
--- a/hw/misc/bcm2835_cprman.c
617
+++ b/hw/misc/bcm2835_cprman.c
618
@@ -XXX,XX +XXX,XX @@
619
*
620
* The page at https://elinux.org/The_Undocumented_Pi gives the actual clock
621
* tree configuration.
622
+ *
623
+ * The CPRMAN exposes clock outputs with the name of the clock mux suffixed
624
+ * with "-out" (e.g. "uart-out", "h264-out", ...).
625
*/
626
627
#include "qemu/osdep.h"
628
@@ -XXX,XX +XXX,XX @@ static const TypeInfo cprman_pll_channel_info = {
629
};
630
631
632
+/* clock mux */
633
+
634
+static void clock_mux_update(CprmanClockMuxState *mux)
635
+{
636
+ clock_update(mux->out, 0);
637
+}
638
+
639
+static void clock_mux_src_update(void *opaque)
640
+{
641
+ CprmanClockMuxState **backref = opaque;
642
+ CprmanClockMuxState *s = *backref;
643
+
644
+ clock_mux_update(s);
645
+}
646
+
647
+static void clock_mux_init(Object *obj)
648
+{
649
+ CprmanClockMuxState *s = CPRMAN_CLOCK_MUX(obj);
650
+ size_t i;
651
+
652
+ for (i = 0; i < CPRMAN_NUM_CLOCK_MUX_SRC; i++) {
653
+ char *name = g_strdup_printf("srcs[%zu]", i);
654
+ s->backref[i] = s;
655
+ s->srcs[i] = qdev_init_clock_in(DEVICE(s), name,
656
+ clock_mux_src_update,
657
+ &s->backref[i]);
658
+ g_free(name);
659
+ }
660
+
661
+ s->out = qdev_init_clock_out(DEVICE(s), "out");
662
+}
663
+
664
+static const VMStateDescription clock_mux_vmstate = {
665
+ .name = TYPE_CPRMAN_CLOCK_MUX,
666
+ .version_id = 1,
667
+ .minimum_version_id = 1,
668
+ .fields = (VMStateField[]) {
669
+ VMSTATE_ARRAY_CLOCK(srcs, CprmanClockMuxState,
670
+ CPRMAN_NUM_CLOCK_MUX_SRC),
671
+ VMSTATE_END_OF_LIST()
672
+ }
673
+};
674
+
675
+static void clock_mux_class_init(ObjectClass *klass, void *data)
676
+{
677
+ DeviceClass *dc = DEVICE_CLASS(klass);
678
+
679
+ dc->vmsd = &clock_mux_vmstate;
680
+}
681
+
682
+static const TypeInfo cprman_clock_mux_info = {
683
+ .name = TYPE_CPRMAN_CLOCK_MUX,
684
+ .parent = TYPE_DEVICE,
685
+ .instance_size = sizeof(CprmanClockMuxState),
686
+ .class_init = clock_mux_class_init,
687
+ .instance_init = clock_mux_init,
688
+};
689
+
690
+
691
/* CPRMAN "top level" model */
692
693
static uint32_t get_cm_lock(const BCM2835CprmanState *s)
694
@@ -XXX,XX +XXX,XX @@ static inline void update_channel_from_a2w(BCM2835CprmanState *s, size_t idx)
25
}
695
}
26
}
696
}
27
697
28
+static void arm_gicv3_icc_reset(CPUARMState *env, const ARMCPRegInfo *ri)
698
+static inline void update_mux_from_cm(BCM2835CprmanState *s, size_t idx)
29
+{
699
+{
30
+ ARMCPU *cpu;
700
+ size_t i;
31
+ GICv3State *s;
701
+
32
+ GICv3CPUState *c;
702
+ for (i = 0; i < CPRMAN_NUM_CLOCK_MUX; i++) {
33
+
703
+ if ((CLOCK_MUX_INIT_INFO[i].cm_offset == idx) ||
34
+ c = (GICv3CPUState *)env->gicv3state;
704
+ (CLOCK_MUX_INIT_INFO[i].cm_offset + 4 == idx)) {
35
+ s = c->gic;
705
+ /* matches CM_CTL or CM_DIV mux register */
36
+ cpu = ARM_CPU(c->cpu);
706
+ clock_mux_update(&s->clock_muxes[i]);
37
+
707
+ return;
38
+ /* Initialize to actual HW supported configuration */
708
+ }
39
+ kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS,
709
+ }
40
+ KVM_VGIC_ATTR(ICC_CTLR_EL1, cpu->mp_affinity),
41
+ &c->icc_ctlr_el1[GICV3_NS], false);
42
+
43
+ c->icc_ctlr_el1[GICV3_S] = c->icc_ctlr_el1[GICV3_NS];
44
+ c->icc_pmr_el1 = 0;
45
+ c->icc_bpr[GICV3_G0] = GIC_MIN_BPR;
46
+ c->icc_bpr[GICV3_G1] = GIC_MIN_BPR;
47
+ c->icc_bpr[GICV3_G1NS] = GIC_MIN_BPR;
48
+
49
+ c->icc_sre_el1 = 0x7;
50
+ memset(c->icc_apr, 0, sizeof(c->icc_apr));
51
+ memset(c->icc_igrpen, 0, sizeof(c->icc_igrpen));
52
+}
710
+}
53
+
711
+
54
static void kvm_arm_gicv3_reset(DeviceState *dev)
712
#define CASE_PLL_A2W_REGS(pll_) \
713
case R_A2W_ ## pll_ ## _CTRL: \
714
case R_A2W_ ## pll_ ## _ANA0: \
715
@@ -XXX,XX +XXX,XX @@ static void cprman_write(void *opaque, hwaddr offset,
716
case R_A2W_PLLB_ARM:
717
update_channel_from_a2w(s, idx);
718
break;
719
+
720
+ case R_CM_GNRICCTL ... R_CM_SMIDIV:
721
+ case R_CM_TCNTCNT ... R_CM_VECDIV:
722
+ case R_CM_PULSECTL ... R_CM_PULSEDIV:
723
+ case R_CM_SDCCTL ... R_CM_ARMCTL:
724
+ case R_CM_AVEOCTL ... R_CM_EMMCDIV:
725
+ case R_CM_EMMC2CTL ... R_CM_EMMC2DIV:
726
+ update_mux_from_cm(s, idx);
727
+ break;
728
}
729
}
730
731
@@ -XXX,XX +XXX,XX @@ static void cprman_reset(DeviceState *dev)
732
device_cold_reset(DEVICE(&s->channels[i]));
733
}
734
735
+ for (i = 0; i < CPRMAN_NUM_CLOCK_MUX; i++) {
736
+ device_cold_reset(DEVICE(&s->clock_muxes[i]));
737
+ }
738
+
739
clock_update_hz(s->xosc, s->xosc_freq);
740
}
741
742
@@ -XXX,XX +XXX,XX @@ static void cprman_init(Object *obj)
743
set_pll_channel_init_info(s, &s->channels[i], i);
744
}
745
746
+ for (i = 0; i < CPRMAN_NUM_CLOCK_MUX; i++) {
747
+ char *alias;
748
+
749
+ object_initialize_child(obj, CLOCK_MUX_INIT_INFO[i].name,
750
+ &s->clock_muxes[i],
751
+ TYPE_CPRMAN_CLOCK_MUX);
752
+ set_clock_mux_init_info(s, &s->clock_muxes[i], i);
753
+
754
+ /* Expose muxes output as CPRMAN outputs */
755
+ alias = g_strdup_printf("%s-out", CLOCK_MUX_INIT_INFO[i].name);
756
+ qdev_alias_clock(DEVICE(&s->clock_muxes[i]), "out", DEVICE(obj), alias);
757
+ g_free(alias);
758
+ }
759
+
760
s->xosc = clock_new(obj, "xosc");
761
+ s->gnd = clock_new(obj, "gnd");
762
+
763
+ clock_set(s->gnd, 0);
764
765
memory_region_init_io(&s->iomem, obj, &cprman_ops,
766
s, "bcm2835-cprman", 0x2000);
767
sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
768
}
769
770
+static void connect_mux_sources(BCM2835CprmanState *s,
771
+ CprmanClockMuxState *mux,
772
+ const CprmanPllChannel *clk_mapping)
773
+{
774
+ size_t i;
775
+ Clock *td0 = s->clock_muxes[CPRMAN_CLOCK_TD0].out;
776
+ Clock *td1 = s->clock_muxes[CPRMAN_CLOCK_TD1].out;
777
+
778
+ /* For sources from 0 to 3. Source 4 to 9 are mux specific */
779
+ Clock * const CLK_SRC_MAPPING[] = {
780
+ [CPRMAN_CLOCK_SRC_GND] = s->gnd,
781
+ [CPRMAN_CLOCK_SRC_XOSC] = s->xosc,
782
+ [CPRMAN_CLOCK_SRC_TD0] = td0,
783
+ [CPRMAN_CLOCK_SRC_TD1] = td1,
784
+ };
785
+
786
+ for (i = 0; i < CPRMAN_NUM_CLOCK_MUX_SRC; i++) {
787
+ CprmanPllChannel mapping = clk_mapping[i];
788
+ Clock *src;
789
+
790
+ if (mapping == CPRMAN_CLOCK_SRC_FORCE_GROUND) {
791
+ src = s->gnd;
792
+ } else if (mapping == CPRMAN_CLOCK_SRC_DSI0HSCK) {
793
+ src = s->gnd; /* TODO */
794
+ } else if (i < CPRMAN_CLOCK_SRC_PLLA) {
795
+ src = CLK_SRC_MAPPING[i];
796
+ } else {
797
+ src = s->channels[mapping].out;
798
+ }
799
+
800
+ clock_set_source(mux->srcs[i], src);
801
+ }
802
+}
803
+
804
static void cprman_realize(DeviceState *dev, Error **errp)
55
{
805
{
56
GICv3State *s = ARM_GICV3_COMMON(dev);
806
BCM2835CprmanState *s = CPRMAN(dev);
57
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gicv3_reset(DeviceState *dev)
807
@@ -XXX,XX +XXX,XX @@ static void cprman_realize(DeviceState *dev, Error **errp)
58
kvm_arm_gicv3_put(s);
808
return;
809
}
810
}
811
+
812
+ for (i = 0; i < CPRMAN_NUM_CLOCK_MUX; i++) {
813
+ CprmanClockMuxState *clock_mux = &s->clock_muxes[i];
814
+
815
+ connect_mux_sources(s, clock_mux, CLOCK_MUX_INIT_INFO[i].src_mapping);
816
+
817
+ if (!qdev_realize(DEVICE(clock_mux), NULL, errp)) {
818
+ return;
819
+ }
820
+ }
59
}
821
}
60
822
61
+/*
823
static const VMStateDescription cprman_vmstate = {
62
+ * CPU interface registers of GIC needs to be reset on CPU reset.
824
@@ -XXX,XX +XXX,XX @@ static void cprman_register_types(void)
63
+ * For the calling arm_gicv3_icc_reset() on CPU reset, we register
825
type_register_static(&cprman_info);
64
+ * below ARMCPRegInfo. As we reset the whole cpu interface under single
826
type_register_static(&cprman_pll_info);
65
+ * register reset, we define only one register of CPU interface instead
827
type_register_static(&cprman_pll_channel_info);
66
+ * of defining all the registers.
828
+ type_register_static(&cprman_clock_mux_info);
67
+ */
829
}
68
+static const ARMCPRegInfo gicv3_cpuif_reginfo[] = {
830
69
+ { .name = "ICC_CTLR_EL1", .state = ARM_CP_STATE_BOTH,
831
type_init(cprman_register_types);
70
+ .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 12, .opc2 = 4,
71
+ /*
72
+ * If ARM_CP_NOP is used, resetfn is not called,
73
+ * So ARM_CP_NO_RAW is appropriate type.
74
+ */
75
+ .type = ARM_CP_NO_RAW,
76
+ .access = PL1_RW,
77
+ .readfn = arm_cp_read_zero,
78
+ .writefn = arm_cp_write_ignore,
79
+ /*
80
+ * We hang the whole cpu interface reset routine off here
81
+ * rather than parcelling it out into one little function
82
+ * per register
83
+ */
84
+ .resetfn = arm_gicv3_icc_reset,
85
+ },
86
+ REGINFO_SENTINEL
87
+};
88
+
89
static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
90
{
91
GICv3State *s = KVM_ARM_GICV3(dev);
92
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
93
94
gicv3_init_irqs_and_mmio(s, kvm_arm_gicv3_set_irq, NULL);
95
96
+ for (i = 0; i < s->num_cpu; i++) {
97
+ ARMCPU *cpu = ARM_CPU(qemu_get_cpu(i));
98
+
99
+ define_arm_cp_regs(cpu, gicv3_cpuif_reginfo);
100
+ }
101
+
102
/* Try to create the device via the device control API */
103
s->dev_fd = kvm_create_device(kvm_state, KVM_DEV_TYPE_ARM_VGIC_V3, false);
104
if (s->dev_fd < 0) {
105
--
832
--
106
2.7.4
833
2.20.1
107
834
108
835
diff view generated by jsdifflib
1
Create a proper QOM object for the armv7m container, which
1
From: Luc Michel <luc@lmichel.fr>
2
holds the CPU, the NVIC and the bitband regions.
3
2
3
A clock mux can be configured to select one of its 10 sources through
4
the CM_CTL register. It also embeds yet another clock divider, composed
5
of an integer part and a fractional part. The number of bits of each
6
part is mux dependent.
7
8
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Signed-off-by: Luc Michel <luc@lmichel.fr>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Tested-by: Guenter Roeck <linux@roeck-us.net>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Message-id: 1487604965-23220-4-git-send-email-peter.maydell@linaro.org
7
---
13
---
8
include/hw/arm/armv7m.h | 51 ++++++++++++++++++
14
hw/misc/bcm2835_cprman.c | 53 +++++++++++++++++++++++++++++++++++++++-
9
hw/arm/armv7m.c | 139 +++++++++++++++++++++++++++++++++++++++++++-----
15
1 file changed, 52 insertions(+), 1 deletion(-)
10
2 files changed, 178 insertions(+), 12 deletions(-)
11
create mode 100644 include/hw/arm/armv7m.h
12
16
13
diff --git a/include/hw/arm/armv7m.h b/include/hw/arm/armv7m.h
17
diff --git a/hw/misc/bcm2835_cprman.c b/hw/misc/bcm2835_cprman.c
14
new file mode 100644
15
index XXXXXXX..XXXXXXX
16
--- /dev/null
17
+++ b/include/hw/arm/armv7m.h
18
@@ -XXX,XX +XXX,XX @@
19
+/*
20
+ * ARMv7M CPU object
21
+ *
22
+ * Copyright (c) 2017 Linaro Ltd
23
+ * Written by Peter Maydell <peter.maydell@linaro.org>
24
+ *
25
+ * This code is licensed under the GPL version 2 or later.
26
+ */
27
+
28
+#ifndef HW_ARM_ARMV7M_H
29
+#define HW_ARM_ARMV7M_H
30
+
31
+#include "hw/sysbus.h"
32
+#include "hw/arm/armv7m_nvic.h"
33
+
34
+#define TYPE_BITBAND "ARM,bitband-memory"
35
+#define BITBAND(obj) OBJECT_CHECK(BitBandState, (obj), TYPE_BITBAND)
36
+
37
+typedef struct {
38
+ /*< private >*/
39
+ SysBusDevice parent_obj;
40
+ /*< public >*/
41
+
42
+ MemoryRegion iomem;
43
+ uint32_t base;
44
+} BitBandState;
45
+
46
+#define TYPE_ARMV7M "armv7m"
47
+#define ARMV7M(obj) OBJECT_CHECK(ARMv7MState, (obj), TYPE_ARMV7M)
48
+
49
+#define ARMV7M_NUM_BITBANDS 2
50
+
51
+/* ARMv7M container object.
52
+ * + Unnamed GPIO input lines: external IRQ lines for the NVIC
53
+ * + Named GPIO output SYSRESETREQ: signalled for guest AIRCR.SYSRESETREQ
54
+ * + Property "cpu-model": CPU model to instantiate
55
+ * + Property "num-irq": number of external IRQ lines
56
+ */
57
+typedef struct ARMv7MState {
58
+ /*< private >*/
59
+ SysBusDevice parent_obj;
60
+ /*< public >*/
61
+ NVICState nvic;
62
+ BitBandState bitband[ARMV7M_NUM_BITBANDS];
63
+ ARMCPU *cpu;
64
+
65
+ /* Properties */
66
+ char *cpu_model;
67
+} ARMv7MState;
68
+
69
+#endif
70
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
71
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
72
--- a/hw/arm/armv7m.c
19
--- a/hw/misc/bcm2835_cprman.c
73
+++ b/hw/arm/armv7m.c
20
+++ b/hw/misc/bcm2835_cprman.c
74
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@ static const TypeInfo cprman_pll_channel_info = {
75
*/
22
76
23
/* clock mux */
77
#include "qemu/osdep.h"
24
78
+#include "hw/arm/armv7m.h"
25
+static bool clock_mux_is_enabled(CprmanClockMuxState *mux)
79
#include "qapi/error.h"
80
#include "qemu-common.h"
81
#include "cpu.h"
82
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps bitband_ops = {
83
.endianness = DEVICE_NATIVE_ENDIAN,
84
};
85
86
-#define TYPE_BITBAND "ARM,bitband-memory"
87
-#define BITBAND(obj) OBJECT_CHECK(BitBandState, (obj), TYPE_BITBAND)
88
-
89
-typedef struct {
90
- /*< private >*/
91
- SysBusDevice parent_obj;
92
- /*< public >*/
93
-
94
- MemoryRegion iomem;
95
- uint32_t base;
96
-} BitBandState;
97
-
98
static void bitband_init(Object *obj)
99
{
100
BitBandState *s = BITBAND(obj);
101
@@ -XXX,XX +XXX,XX @@ static void armv7m_bitband_init(void)
102
103
/* Board init. */
104
105
+static const hwaddr bitband_input_addr[ARMV7M_NUM_BITBANDS] = {
106
+ 0x20000000, 0x40000000
107
+};
108
+
109
+static const hwaddr bitband_output_addr[ARMV7M_NUM_BITBANDS] = {
110
+ 0x22000000, 0x42000000
111
+};
112
+
113
+static void armv7m_instance_init(Object *obj)
114
+{
26
+{
115
+ ARMv7MState *s = ARMV7M(obj);
27
+ return FIELD_EX32(*mux->reg_ctl, CM_CLOCKx_CTL, ENABLE);
116
+ int i;
117
+
118
+ /* Can't init the cpu here, we don't yet know which model to use */
119
+
120
+ object_initialize(&s->nvic, sizeof(s->nvic), "armv7m_nvic");
121
+ qdev_set_parent_bus(DEVICE(&s->nvic), sysbus_get_default());
122
+ object_property_add_alias(obj, "num-irq",
123
+ OBJECT(&s->nvic), "num-irq", &error_abort);
124
+
125
+ for (i = 0; i < ARRAY_SIZE(s->bitband); i++) {
126
+ object_initialize(&s->bitband[i], sizeof(s->bitband[i]), TYPE_BITBAND);
127
+ qdev_set_parent_bus(DEVICE(&s->bitband[i]), sysbus_get_default());
128
+ }
129
+}
28
+}
130
+
29
+
131
+static void armv7m_realize(DeviceState *dev, Error **errp)
30
static void clock_mux_update(CprmanClockMuxState *mux)
132
+{
31
{
133
+ ARMv7MState *s = ARMV7M(dev);
32
- clock_update(mux->out, 0);
134
+ Error *err = NULL;
33
+ uint64_t freq;
135
+ int i;
34
+ uint32_t div, src = FIELD_EX32(*mux->reg_ctl, CM_CLOCKx_CTL, SRC);
136
+ char **cpustr;
35
+ bool enabled = clock_mux_is_enabled(mux);
137
+ ObjectClass *oc;
138
+ const char *typename;
139
+ CPUClass *cc;
140
+
36
+
141
+ cpustr = g_strsplit(s->cpu_model, ",", 2);
37
+ *mux->reg_ctl = FIELD_DP32(*mux->reg_ctl, CM_CLOCKx_CTL, BUSY, enabled);
142
+
38
+
143
+ oc = cpu_class_by_name(TYPE_ARM_CPU, cpustr[0]);
39
+ if (!enabled) {
144
+ if (!oc) {
40
+ clock_update(mux->out, 0);
145
+ error_setg(errp, "Unknown CPU model %s", cpustr[0]);
146
+ g_strfreev(cpustr);
147
+ return;
41
+ return;
148
+ }
42
+ }
149
+
43
+
150
+ cc = CPU_CLASS(oc);
44
+ freq = clock_get_hz(mux->srcs[src]);
151
+ typename = object_class_get_name(oc);
45
+
152
+ cc->parse_features(typename, cpustr[1], &err);
46
+ if (mux->int_bits == 0 && mux->frac_bits == 0) {
153
+ g_strfreev(cpustr);
47
+ clock_update_hz(mux->out, freq);
154
+ if (err) {
155
+ error_propagate(errp, err);
156
+ return;
48
+ return;
157
+ }
49
+ }
158
+
50
+
159
+ s->cpu = ARM_CPU(object_new(typename));
51
+ /*
160
+ if (!s->cpu) {
52
+ * The divider has an integer and a fractional part. The size of each part
161
+ error_setg(errp, "Unknown CPU model %s", s->cpu_model);
53
+ * varies with the muxes (int_bits and frac_bits). Both parts are
54
+ * concatenated, with the integer part always starting at bit 12.
55
+ *
56
+ * 31 12 11 0
57
+ * ------------------------------
58
+ * CM_DIV | | int | frac | |
59
+ * ------------------------------
60
+ * <-----> <------>
61
+ * int_bits frac_bits
62
+ */
63
+ div = extract32(*mux->reg_div,
64
+ R_CM_CLOCKx_DIV_FRAC_LENGTH - mux->frac_bits,
65
+ mux->int_bits + mux->frac_bits);
66
+
67
+ if (!div) {
68
+ clock_update(mux->out, 0);
162
+ return;
69
+ return;
163
+ }
70
+ }
164
+
71
+
165
+ object_property_set_bool(OBJECT(s->cpu), true, "realized", &err);
72
+ freq = muldiv64(freq, 1 << mux->frac_bits, div);
166
+ if (err != NULL) {
73
+
167
+ error_propagate(errp, err);
74
+ clock_update_hz(mux->out, freq);
75
}
76
77
static void clock_mux_src_update(void *opaque)
78
{
79
CprmanClockMuxState **backref = opaque;
80
CprmanClockMuxState *s = *backref;
81
+ CprmanClockMuxSource src = backref - s->backref;
82
+
83
+ if (FIELD_EX32(*s->reg_ctl, CM_CLOCKx_CTL, SRC) != src) {
168
+ return;
84
+ return;
169
+ }
85
+ }
170
+
86
171
+ /* Note that we must realize the NVIC after the CPU */
87
clock_mux_update(s);
172
+ object_property_set_bool(OBJECT(&s->nvic), true, "realized", &err);
173
+ if (err != NULL) {
174
+ error_propagate(errp, err);
175
+ return;
176
+ }
177
+
178
+ /* Alias the NVIC's input and output GPIOs as our own so the board
179
+ * code can wire them up. (We do this in realize because the
180
+ * NVIC doesn't create the input GPIO array until realize.)
181
+ */
182
+ qdev_pass_gpios(DEVICE(&s->nvic), dev, NULL);
183
+ qdev_pass_gpios(DEVICE(&s->nvic), dev, "SYSRESETREQ");
184
+
185
+ /* Wire the NVIC up to the CPU */
186
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->nvic), 0,
187
+ qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ));
188
+ s->cpu->env.nvic = &s->nvic;
189
+
190
+ for (i = 0; i < ARRAY_SIZE(s->bitband); i++) {
191
+ Object *obj = OBJECT(&s->bitband[i]);
192
+ SysBusDevice *sbd = SYS_BUS_DEVICE(&s->bitband[i]);
193
+
194
+ object_property_set_int(obj, bitband_input_addr[i], "base", &err);
195
+ if (err != NULL) {
196
+ error_propagate(errp, err);
197
+ return;
198
+ }
199
+ object_property_set_bool(obj, true, "realized", &err);
200
+ if (err != NULL) {
201
+ error_propagate(errp, err);
202
+ return;
203
+ }
204
+
205
+ sysbus_mmio_map(sbd, 0, bitband_output_addr[i]);
206
+ }
207
+}
208
+
209
+static Property armv7m_properties[] = {
210
+ DEFINE_PROP_STRING("cpu-model", ARMv7MState, cpu_model),
211
+ DEFINE_PROP_END_OF_LIST(),
212
+};
213
+
214
+static void armv7m_class_init(ObjectClass *klass, void *data)
215
+{
216
+ DeviceClass *dc = DEVICE_CLASS(klass);
217
+
218
+ dc->realize = armv7m_realize;
219
+ dc->props = armv7m_properties;
220
+}
221
+
222
+static const TypeInfo armv7m_info = {
223
+ .name = TYPE_ARMV7M,
224
+ .parent = TYPE_SYS_BUS_DEVICE,
225
+ .instance_size = sizeof(ARMv7MState),
226
+ .instance_init = armv7m_instance_init,
227
+ .class_init = armv7m_class_init,
228
+};
229
+
230
static void armv7m_reset(void *opaque)
231
{
232
ARMCPU *cpu = opaque;
233
@@ -XXX,XX +XXX,XX @@ static const TypeInfo bitband_info = {
234
static void armv7m_register_types(void)
235
{
236
type_register_static(&bitband_info);
237
+ type_register_static(&armv7m_info);
238
}
88
}
239
240
type_init(armv7m_register_types)
241
--
89
--
242
2.7.4
90
2.20.1
243
91
244
92
diff view generated by jsdifflib
New patch
1
1
From: Luc Michel <luc@lmichel.fr>
2
3
This simple mux sits between the PLL channels and the DSI0E and DSI0P
4
clock muxes. This mux selects between PLLA-DSI0 and PLLD-DSI0 channel
5
and outputs the selected signal to source number 4 of DSI0E/P clock
6
muxes. It is controlled by the cm_dsi0hsck register.
7
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Signed-off-by: Luc Michel <luc@lmichel.fr>
11
Tested-by: Guenter Roeck <linux@roeck-us.net>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
include/hw/misc/bcm2835_cprman.h | 15 +++++
15
include/hw/misc/bcm2835_cprman_internals.h | 6 ++
16
hw/misc/bcm2835_cprman.c | 74 +++++++++++++++++++++-
17
3 files changed, 94 insertions(+), 1 deletion(-)
18
19
diff --git a/include/hw/misc/bcm2835_cprman.h b/include/hw/misc/bcm2835_cprman.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/include/hw/misc/bcm2835_cprman.h
22
+++ b/include/hw/misc/bcm2835_cprman.h
23
@@ -XXX,XX +XXX,XX @@ typedef struct CprmanClockMuxState {
24
struct CprmanClockMuxState *backref[CPRMAN_NUM_CLOCK_MUX_SRC];
25
} CprmanClockMuxState;
26
27
+typedef struct CprmanDsi0HsckMuxState {
28
+ /*< private >*/
29
+ DeviceState parent_obj;
30
+
31
+ /*< public >*/
32
+ CprmanClockMux id;
33
+
34
+ uint32_t *reg_cm;
35
+
36
+ Clock *plla_in;
37
+ Clock *plld_in;
38
+ Clock *out;
39
+} CprmanDsi0HsckMuxState;
40
+
41
struct BCM2835CprmanState {
42
/*< private >*/
43
SysBusDevice parent_obj;
44
@@ -XXX,XX +XXX,XX @@ struct BCM2835CprmanState {
45
CprmanPllState plls[CPRMAN_NUM_PLL];
46
CprmanPllChannelState channels[CPRMAN_NUM_PLL_CHANNEL];
47
CprmanClockMuxState clock_muxes[CPRMAN_NUM_CLOCK_MUX];
48
+ CprmanDsi0HsckMuxState dsi0hsck_mux;
49
50
uint32_t regs[CPRMAN_NUM_REGS];
51
uint32_t xosc_freq;
52
diff --git a/include/hw/misc/bcm2835_cprman_internals.h b/include/hw/misc/bcm2835_cprman_internals.h
53
index XXXXXXX..XXXXXXX 100644
54
--- a/include/hw/misc/bcm2835_cprman_internals.h
55
+++ b/include/hw/misc/bcm2835_cprman_internals.h
56
@@ -XXX,XX +XXX,XX @@
57
#define TYPE_CPRMAN_PLL "bcm2835-cprman-pll"
58
#define TYPE_CPRMAN_PLL_CHANNEL "bcm2835-cprman-pll-channel"
59
#define TYPE_CPRMAN_CLOCK_MUX "bcm2835-cprman-clock-mux"
60
+#define TYPE_CPRMAN_DSI0HSCK_MUX "bcm2835-cprman-dsi0hsck-mux"
61
62
DECLARE_INSTANCE_CHECKER(CprmanPllState, CPRMAN_PLL,
63
TYPE_CPRMAN_PLL)
64
@@ -XXX,XX +XXX,XX @@ DECLARE_INSTANCE_CHECKER(CprmanPllChannelState, CPRMAN_PLL_CHANNEL,
65
TYPE_CPRMAN_PLL_CHANNEL)
66
DECLARE_INSTANCE_CHECKER(CprmanClockMuxState, CPRMAN_CLOCK_MUX,
67
TYPE_CPRMAN_CLOCK_MUX)
68
+DECLARE_INSTANCE_CHECKER(CprmanDsi0HsckMuxState, CPRMAN_DSI0HSCK_MUX,
69
+ TYPE_CPRMAN_DSI0HSCK_MUX)
70
71
/* Register map */
72
73
@@ -XXX,XX +XXX,XX @@ REG32(CM_LOCK, 0x114)
74
FIELD(CM_LOCK, FLOCKB, 9, 1)
75
FIELD(CM_LOCK, FLOCKA, 8, 1)
76
77
+REG32(CM_DSI0HSCK, 0x120)
78
+ FIELD(CM_DSI0HSCK, SELPLLD, 0, 1)
79
+
80
/*
81
* This field is common to all registers. Each register write value must match
82
* the CPRMAN_PASSWORD magic value in its 8 MSB.
83
diff --git a/hw/misc/bcm2835_cprman.c b/hw/misc/bcm2835_cprman.c
84
index XXXXXXX..XXXXXXX 100644
85
--- a/hw/misc/bcm2835_cprman.c
86
+++ b/hw/misc/bcm2835_cprman.c
87
@@ -XXX,XX +XXX,XX @@ static const TypeInfo cprman_clock_mux_info = {
88
};
89
90
91
+/* DSI0HSCK mux */
92
+
93
+static void dsi0hsck_mux_update(CprmanDsi0HsckMuxState *s)
94
+{
95
+ bool src_is_plld = FIELD_EX32(*s->reg_cm, CM_DSI0HSCK, SELPLLD);
96
+ Clock *src = src_is_plld ? s->plld_in : s->plla_in;
97
+
98
+ clock_update(s->out, clock_get(src));
99
+}
100
+
101
+static void dsi0hsck_mux_in_update(void *opaque)
102
+{
103
+ dsi0hsck_mux_update(CPRMAN_DSI0HSCK_MUX(opaque));
104
+}
105
+
106
+static void dsi0hsck_mux_init(Object *obj)
107
+{
108
+ CprmanDsi0HsckMuxState *s = CPRMAN_DSI0HSCK_MUX(obj);
109
+ DeviceState *dev = DEVICE(obj);
110
+
111
+ s->plla_in = qdev_init_clock_in(dev, "plla-in", dsi0hsck_mux_in_update, s);
112
+ s->plld_in = qdev_init_clock_in(dev, "plld-in", dsi0hsck_mux_in_update, s);
113
+ s->out = qdev_init_clock_out(DEVICE(s), "out");
114
+}
115
+
116
+static const VMStateDescription dsi0hsck_mux_vmstate = {
117
+ .name = TYPE_CPRMAN_DSI0HSCK_MUX,
118
+ .version_id = 1,
119
+ .minimum_version_id = 1,
120
+ .fields = (VMStateField[]) {
121
+ VMSTATE_CLOCK(plla_in, CprmanDsi0HsckMuxState),
122
+ VMSTATE_CLOCK(plld_in, CprmanDsi0HsckMuxState),
123
+ VMSTATE_END_OF_LIST()
124
+ }
125
+};
126
+
127
+static void dsi0hsck_mux_class_init(ObjectClass *klass, void *data)
128
+{
129
+ DeviceClass *dc = DEVICE_CLASS(klass);
130
+
131
+ dc->vmsd = &dsi0hsck_mux_vmstate;
132
+}
133
+
134
+static const TypeInfo cprman_dsi0hsck_mux_info = {
135
+ .name = TYPE_CPRMAN_DSI0HSCK_MUX,
136
+ .parent = TYPE_DEVICE,
137
+ .instance_size = sizeof(CprmanDsi0HsckMuxState),
138
+ .class_init = dsi0hsck_mux_class_init,
139
+ .instance_init = dsi0hsck_mux_init,
140
+};
141
+
142
+
143
/* CPRMAN "top level" model */
144
145
static uint32_t get_cm_lock(const BCM2835CprmanState *s)
146
@@ -XXX,XX +XXX,XX @@ static void cprman_write(void *opaque, hwaddr offset,
147
case R_CM_EMMC2CTL ... R_CM_EMMC2DIV:
148
update_mux_from_cm(s, idx);
149
break;
150
+
151
+ case R_CM_DSI0HSCK:
152
+ dsi0hsck_mux_update(&s->dsi0hsck_mux);
153
+ break;
154
}
155
}
156
157
@@ -XXX,XX +XXX,XX @@ static void cprman_reset(DeviceState *dev)
158
device_cold_reset(DEVICE(&s->channels[i]));
159
}
160
161
+ device_cold_reset(DEVICE(&s->dsi0hsck_mux));
162
+
163
for (i = 0; i < CPRMAN_NUM_CLOCK_MUX; i++) {
164
device_cold_reset(DEVICE(&s->clock_muxes[i]));
165
}
166
@@ -XXX,XX +XXX,XX @@ static void cprman_init(Object *obj)
167
set_pll_channel_init_info(s, &s->channels[i], i);
168
}
169
170
+ object_initialize_child(obj, "dsi0hsck-mux",
171
+ &s->dsi0hsck_mux, TYPE_CPRMAN_DSI0HSCK_MUX);
172
+ s->dsi0hsck_mux.reg_cm = &s->regs[R_CM_DSI0HSCK];
173
+
174
for (i = 0; i < CPRMAN_NUM_CLOCK_MUX; i++) {
175
char *alias;
176
177
@@ -XXX,XX +XXX,XX @@ static void connect_mux_sources(BCM2835CprmanState *s,
178
if (mapping == CPRMAN_CLOCK_SRC_FORCE_GROUND) {
179
src = s->gnd;
180
} else if (mapping == CPRMAN_CLOCK_SRC_DSI0HSCK) {
181
- src = s->gnd; /* TODO */
182
+ src = s->dsi0hsck_mux.out;
183
} else if (i < CPRMAN_CLOCK_SRC_PLLA) {
184
src = CLK_SRC_MAPPING[i];
185
} else {
186
@@ -XXX,XX +XXX,XX @@ static void cprman_realize(DeviceState *dev, Error **errp)
187
}
188
}
189
190
+ clock_set_source(s->dsi0hsck_mux.plla_in,
191
+ s->channels[CPRMAN_PLLA_CHANNEL_DSI0].out);
192
+ clock_set_source(s->dsi0hsck_mux.plld_in,
193
+ s->channels[CPRMAN_PLLD_CHANNEL_DSI0].out);
194
+
195
+ if (!qdev_realize(DEVICE(&s->dsi0hsck_mux), NULL, errp)) {
196
+ return;
197
+ }
198
+
199
for (i = 0; i < CPRMAN_NUM_CLOCK_MUX; i++) {
200
CprmanClockMuxState *clock_mux = &s->clock_muxes[i];
201
202
@@ -XXX,XX +XXX,XX @@ static void cprman_register_types(void)
203
type_register_static(&cprman_pll_info);
204
type_register_static(&cprman_pll_channel_info);
205
type_register_static(&cprman_clock_mux_info);
206
+ type_register_static(&cprman_dsi0hsck_mux_info);
207
}
208
209
type_init(cprman_register_types);
210
--
211
2.20.1
212
213
diff view generated by jsdifflib
New patch
1
1
From: Luc Michel <luc@lmichel.fr>
2
3
Those reset values have been extracted from a Raspberry Pi 3 model B
4
v1.2, using the 2020-08-20 version of raspios. The dump was done using
5
the debugfs interface of the CPRMAN driver in Linux (under
6
'/sys/kernel/debug/clk'). Each exposed clock tree stage (PLLs, channels
7
and muxes) can be observed by reading the 'regdump' file (e.g.
8
'plla/regdump').
9
10
Those values are set by the Raspberry Pi firmware at boot time (Linux
11
expects them to be set when it boots up).
12
13
Some stages are not exposed by the Linux driver (e.g. the PLL B). For
14
those, the reset values are unknown and left to 0 which implies a
15
disabled output.
16
17
Once booted in QEMU, the final clock tree is very similar to the one
18
visible on real hardware. The differences come from some unimplemented
19
devices for which the driver simply disable the corresponding clock.
20
21
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
22
Signed-off-by: Luc Michel <luc@lmichel.fr>
23
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
24
Tested-by: Guenter Roeck <linux@roeck-us.net>
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
---
27
include/hw/misc/bcm2835_cprman_internals.h | 269 +++++++++++++++++++++
28
hw/misc/bcm2835_cprman.c | 31 +++
29
2 files changed, 300 insertions(+)
30
31
diff --git a/include/hw/misc/bcm2835_cprman_internals.h b/include/hw/misc/bcm2835_cprman_internals.h
32
index XXXXXXX..XXXXXXX 100644
33
--- a/include/hw/misc/bcm2835_cprman_internals.h
34
+++ b/include/hw/misc/bcm2835_cprman_internals.h
35
@@ -XXX,XX +XXX,XX @@ static inline void set_clock_mux_init_info(BCM2835CprmanState *s,
36
mux->frac_bits = CLOCK_MUX_INIT_INFO[id].frac_bits;
37
}
38
39
+
40
+/*
41
+ * Object reset info
42
+ * Those values have been dumped from a Raspberry Pi 3 Model B v1.2 using the
43
+ * clk debugfs interface in Linux.
44
+ */
45
+typedef struct PLLResetInfo {
46
+ uint32_t cm;
47
+ uint32_t a2w_ctrl;
48
+ uint32_t a2w_ana[4];
49
+ uint32_t a2w_frac;
50
+} PLLResetInfo;
51
+
52
+static const PLLResetInfo PLL_RESET_INFO[] = {
53
+ [CPRMAN_PLLA] = {
54
+ .cm = 0x0000008a,
55
+ .a2w_ctrl = 0x0002103a,
56
+ .a2w_frac = 0x00098000,
57
+ .a2w_ana = { 0x00000000, 0x00144000, 0x00000000, 0x00000100 }
58
+ },
59
+
60
+ [CPRMAN_PLLC] = {
61
+ .cm = 0x00000228,
62
+ .a2w_ctrl = 0x0002103e,
63
+ .a2w_frac = 0x00080000,
64
+ .a2w_ana = { 0x00000000, 0x00144000, 0x00000000, 0x00000100 }
65
+ },
66
+
67
+ [CPRMAN_PLLD] = {
68
+ .cm = 0x0000020a,
69
+ .a2w_ctrl = 0x00021034,
70
+ .a2w_frac = 0x00015556,
71
+ .a2w_ana = { 0x00000000, 0x00144000, 0x00000000, 0x00000100 }
72
+ },
73
+
74
+ [CPRMAN_PLLH] = {
75
+ .cm = 0x00000000,
76
+ .a2w_ctrl = 0x0002102d,
77
+ .a2w_frac = 0x00000000,
78
+ .a2w_ana = { 0x00900000, 0x0000000c, 0x00000000, 0x00000000 }
79
+ },
80
+
81
+ [CPRMAN_PLLB] = {
82
+ /* unknown */
83
+ .cm = 0x00000000,
84
+ .a2w_ctrl = 0x00000000,
85
+ .a2w_frac = 0x00000000,
86
+ .a2w_ana = { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }
87
+ }
88
+};
89
+
90
+typedef struct PLLChannelResetInfo {
91
+ /*
92
+ * Even though a PLL channel has a CM register, it shares it with its
93
+ * parent PLL. The parent already takes care of the reset value.
94
+ */
95
+ uint32_t a2w_ctrl;
96
+} PLLChannelResetInfo;
97
+
98
+static const PLLChannelResetInfo PLL_CHANNEL_RESET_INFO[] = {
99
+ [CPRMAN_PLLA_CHANNEL_DSI0] = { .a2w_ctrl = 0x00000100 },
100
+ [CPRMAN_PLLA_CHANNEL_CORE] = { .a2w_ctrl = 0x00000003 },
101
+ [CPRMAN_PLLA_CHANNEL_PER] = { .a2w_ctrl = 0x00000000 }, /* unknown */
102
+ [CPRMAN_PLLA_CHANNEL_CCP2] = { .a2w_ctrl = 0x00000100 },
103
+
104
+ [CPRMAN_PLLC_CHANNEL_CORE2] = { .a2w_ctrl = 0x00000100 },
105
+ [CPRMAN_PLLC_CHANNEL_CORE1] = { .a2w_ctrl = 0x00000100 },
106
+ [CPRMAN_PLLC_CHANNEL_PER] = { .a2w_ctrl = 0x00000002 },
107
+ [CPRMAN_PLLC_CHANNEL_CORE0] = { .a2w_ctrl = 0x00000002 },
108
+
109
+ [CPRMAN_PLLD_CHANNEL_DSI0] = { .a2w_ctrl = 0x00000100 },
110
+ [CPRMAN_PLLD_CHANNEL_CORE] = { .a2w_ctrl = 0x00000004 },
111
+ [CPRMAN_PLLD_CHANNEL_PER] = { .a2w_ctrl = 0x00000004 },
112
+ [CPRMAN_PLLD_CHANNEL_DSI1] = { .a2w_ctrl = 0x00000100 },
113
+
114
+ [CPRMAN_PLLH_CHANNEL_AUX] = { .a2w_ctrl = 0x00000004 },
115
+ [CPRMAN_PLLH_CHANNEL_RCAL] = { .a2w_ctrl = 0x00000000 },
116
+ [CPRMAN_PLLH_CHANNEL_PIX] = { .a2w_ctrl = 0x00000000 },
117
+
118
+ [CPRMAN_PLLB_CHANNEL_ARM] = { .a2w_ctrl = 0x00000000 }, /* unknown */
119
+};
120
+
121
+typedef struct ClockMuxResetInfo {
122
+ uint32_t cm_ctl;
123
+ uint32_t cm_div;
124
+} ClockMuxResetInfo;
125
+
126
+static const ClockMuxResetInfo CLOCK_MUX_RESET_INFO[] = {
127
+ [CPRMAN_CLOCK_GNRIC] = {
128
+ .cm_ctl = 0, /* unknown */
129
+ .cm_div = 0
130
+ },
131
+
132
+ [CPRMAN_CLOCK_VPU] = {
133
+ .cm_ctl = 0x00000245,
134
+ .cm_div = 0x00003000,
135
+ },
136
+
137
+ [CPRMAN_CLOCK_SYS] = {
138
+ .cm_ctl = 0, /* unknown */
139
+ .cm_div = 0
140
+ },
141
+
142
+ [CPRMAN_CLOCK_PERIA] = {
143
+ .cm_ctl = 0, /* unknown */
144
+ .cm_div = 0
145
+ },
146
+
147
+ [CPRMAN_CLOCK_PERII] = {
148
+ .cm_ctl = 0, /* unknown */
149
+ .cm_div = 0
150
+ },
151
+
152
+ [CPRMAN_CLOCK_H264] = {
153
+ .cm_ctl = 0x00000244,
154
+ .cm_div = 0x00003000,
155
+ },
156
+
157
+ [CPRMAN_CLOCK_ISP] = {
158
+ .cm_ctl = 0x00000244,
159
+ .cm_div = 0x00003000,
160
+ },
161
+
162
+ [CPRMAN_CLOCK_V3D] = {
163
+ .cm_ctl = 0, /* unknown */
164
+ .cm_div = 0
165
+ },
166
+
167
+ [CPRMAN_CLOCK_CAM0] = {
168
+ .cm_ctl = 0x00000000,
169
+ .cm_div = 0x00000000,
170
+ },
171
+
172
+ [CPRMAN_CLOCK_CAM1] = {
173
+ .cm_ctl = 0x00000000,
174
+ .cm_div = 0x00000000,
175
+ },
176
+
177
+ [CPRMAN_CLOCK_CCP2] = {
178
+ .cm_ctl = 0, /* unknown */
179
+ .cm_div = 0
180
+ },
181
+
182
+ [CPRMAN_CLOCK_DSI0E] = {
183
+ .cm_ctl = 0x00000000,
184
+ .cm_div = 0x00000000,
185
+ },
186
+
187
+ [CPRMAN_CLOCK_DSI0P] = {
188
+ .cm_ctl = 0x00000000,
189
+ .cm_div = 0x00000000,
190
+ },
191
+
192
+ [CPRMAN_CLOCK_DPI] = {
193
+ .cm_ctl = 0x00000000,
194
+ .cm_div = 0x00000000,
195
+ },
196
+
197
+ [CPRMAN_CLOCK_GP0] = {
198
+ .cm_ctl = 0x00000200,
199
+ .cm_div = 0x00000000,
200
+ },
201
+
202
+ [CPRMAN_CLOCK_GP1] = {
203
+ .cm_ctl = 0x00000096,
204
+ .cm_div = 0x00014000,
205
+ },
206
+
207
+ [CPRMAN_CLOCK_GP2] = {
208
+ .cm_ctl = 0x00000291,
209
+ .cm_div = 0x00249f00,
210
+ },
211
+
212
+ [CPRMAN_CLOCK_HSM] = {
213
+ .cm_ctl = 0x00000000,
214
+ .cm_div = 0x00000000,
215
+ },
216
+
217
+ [CPRMAN_CLOCK_OTP] = {
218
+ .cm_ctl = 0x00000091,
219
+ .cm_div = 0x00004000,
220
+ },
221
+
222
+ [CPRMAN_CLOCK_PCM] = {
223
+ .cm_ctl = 0x00000200,
224
+ .cm_div = 0x00000000,
225
+ },
226
+
227
+ [CPRMAN_CLOCK_PWM] = {
228
+ .cm_ctl = 0x00000200,
229
+ .cm_div = 0x00000000,
230
+ },
231
+
232
+ [CPRMAN_CLOCK_SLIM] = {
233
+ .cm_ctl = 0x00000200,
234
+ .cm_div = 0x00000000,
235
+ },
236
+
237
+ [CPRMAN_CLOCK_SMI] = {
238
+ .cm_ctl = 0x00000000,
239
+ .cm_div = 0x00000000,
240
+ },
241
+
242
+ [CPRMAN_CLOCK_TEC] = {
243
+ .cm_ctl = 0x00000000,
244
+ .cm_div = 0x00000000,
245
+ },
246
+
247
+ [CPRMAN_CLOCK_TD0] = {
248
+ .cm_ctl = 0, /* unknown */
249
+ .cm_div = 0
250
+ },
251
+
252
+ [CPRMAN_CLOCK_TD1] = {
253
+ .cm_ctl = 0, /* unknown */
254
+ .cm_div = 0
255
+ },
256
+
257
+ [CPRMAN_CLOCK_TSENS] = {
258
+ .cm_ctl = 0x00000091,
259
+ .cm_div = 0x0000a000,
260
+ },
261
+
262
+ [CPRMAN_CLOCK_TIMER] = {
263
+ .cm_ctl = 0x00000291,
264
+ .cm_div = 0x00013333,
265
+ },
266
+
267
+ [CPRMAN_CLOCK_UART] = {
268
+ .cm_ctl = 0x00000296,
269
+ .cm_div = 0x0000a6ab,
270
+ },
271
+
272
+ [CPRMAN_CLOCK_VEC] = {
273
+ .cm_ctl = 0x00000097,
274
+ .cm_div = 0x00002000,
275
+ },
276
+
277
+ [CPRMAN_CLOCK_PULSE] = {
278
+ .cm_ctl = 0, /* unknown */
279
+ .cm_div = 0
280
+ },
281
+
282
+ [CPRMAN_CLOCK_SDC] = {
283
+ .cm_ctl = 0x00004006,
284
+ .cm_div = 0x00003000,
285
+ },
286
+
287
+ [CPRMAN_CLOCK_ARM] = {
288
+ .cm_ctl = 0, /* unknown */
289
+ .cm_div = 0
290
+ },
291
+
292
+ [CPRMAN_CLOCK_AVEO] = {
293
+ .cm_ctl = 0x00000000,
294
+ .cm_div = 0x00000000,
295
+ },
296
+
297
+ [CPRMAN_CLOCK_EMMC] = {
298
+ .cm_ctl = 0x00000295,
299
+ .cm_div = 0x00006000,
300
+ },
301
+
302
+ [CPRMAN_CLOCK_EMMC2] = {
303
+ .cm_ctl = 0, /* unknown */
304
+ .cm_div = 0
305
+ },
306
+};
307
+
308
#endif
309
diff --git a/hw/misc/bcm2835_cprman.c b/hw/misc/bcm2835_cprman.c
310
index XXXXXXX..XXXXXXX 100644
311
--- a/hw/misc/bcm2835_cprman.c
312
+++ b/hw/misc/bcm2835_cprman.c
313
@@ -XXX,XX +XXX,XX @@
314
315
/* PLL */
316
317
+static void pll_reset(DeviceState *dev)
318
+{
319
+ CprmanPllState *s = CPRMAN_PLL(dev);
320
+ const PLLResetInfo *info = &PLL_RESET_INFO[s->id];
321
+
322
+ *s->reg_cm = info->cm;
323
+ *s->reg_a2w_ctrl = info->a2w_ctrl;
324
+ memcpy(s->reg_a2w_ana, info->a2w_ana, sizeof(info->a2w_ana));
325
+ *s->reg_a2w_frac = info->a2w_frac;
326
+}
327
+
328
static bool pll_is_locked(const CprmanPllState *pll)
329
{
330
return !FIELD_EX32(*pll->reg_a2w_ctrl, A2W_PLLx_CTRL, PWRDN)
331
@@ -XXX,XX +XXX,XX @@ static void pll_class_init(ObjectClass *klass, void *data)
332
{
333
DeviceClass *dc = DEVICE_CLASS(klass);
334
335
+ dc->reset = pll_reset;
336
dc->vmsd = &pll_vmstate;
337
}
338
339
@@ -XXX,XX +XXX,XX @@ static const TypeInfo cprman_pll_info = {
340
341
/* PLL channel */
342
343
+static void pll_channel_reset(DeviceState *dev)
344
+{
345
+ CprmanPllChannelState *s = CPRMAN_PLL_CHANNEL(dev);
346
+ const PLLChannelResetInfo *info = &PLL_CHANNEL_RESET_INFO[s->id];
347
+
348
+ *s->reg_a2w_ctrl = info->a2w_ctrl;
349
+}
350
+
351
static bool pll_channel_is_enabled(CprmanPllChannelState *channel)
352
{
353
/*
354
@@ -XXX,XX +XXX,XX @@ static void pll_channel_class_init(ObjectClass *klass, void *data)
355
{
356
DeviceClass *dc = DEVICE_CLASS(klass);
357
358
+ dc->reset = pll_channel_reset;
359
dc->vmsd = &pll_channel_vmstate;
360
}
361
362
@@ -XXX,XX +XXX,XX @@ static void clock_mux_src_update(void *opaque)
363
clock_mux_update(s);
364
}
365
366
+static void clock_mux_reset(DeviceState *dev)
367
+{
368
+ CprmanClockMuxState *clock = CPRMAN_CLOCK_MUX(dev);
369
+ const ClockMuxResetInfo *info = &CLOCK_MUX_RESET_INFO[clock->id];
370
+
371
+ *clock->reg_ctl = info->cm_ctl;
372
+ *clock->reg_div = info->cm_div;
373
+}
374
+
375
static void clock_mux_init(Object *obj)
376
{
377
CprmanClockMuxState *s = CPRMAN_CLOCK_MUX(obj);
378
@@ -XXX,XX +XXX,XX @@ static void clock_mux_class_init(ObjectClass *klass, void *data)
379
{
380
DeviceClass *dc = DEVICE_CLASS(klass);
381
382
+ dc->reset = clock_mux_reset;
383
dc->vmsd = &clock_mux_vmstate;
384
}
385
386
--
387
2.20.1
388
389
diff view generated by jsdifflib
1
From: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
1
From: Luc Michel <luc@lmichel.fr>
2
2
3
To Save and Restore ICC_SRE_EL1 register introduce vmstate
3
Add a clock input to the PL011 UART so we can compute the current baud
4
subsection and load only if non-zero.
4
rate and trace it. This is intended for developers who wish to use QEMU
5
Also initialize icc_sre_el1 with to 0x7 in pre_load
5
to e.g. debug their firmware or to figure out the baud rate configured
6
function.
6
by an unknown/closed source binary.
7
7
8
Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Luc Michel <luc@lmichel.fr>
10
Reviewed-by: Eric Auger <eric.auger@redhat.com>
10
Tested-by: Guenter Roeck <linux@roeck-us.net>
11
Message-id: 1487850673-26455-3-git-send-email-vijay.kilari@gmail.com
11
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
13
---
14
include/hw/intc/arm_gicv3_common.h | 1 +
14
include/hw/char/pl011.h | 1 +
15
hw/intc/arm_gicv3_common.c | 36 ++++++++++++++++++++++++++++++++++++
15
hw/char/pl011.c | 45 +++++++++++++++++++++++++++++++++++++++++
16
2 files changed, 37 insertions(+)
16
hw/char/trace-events | 1 +
17
3 files changed, 47 insertions(+)
17
18
18
diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
19
diff --git a/include/hw/char/pl011.h b/include/hw/char/pl011.h
19
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/intc/arm_gicv3_common.h
21
--- a/include/hw/char/pl011.h
21
+++ b/include/hw/intc/arm_gicv3_common.h
22
+++ b/include/hw/char/pl011.h
22
@@ -XXX,XX +XXX,XX @@ struct GICv3CPUState {
23
@@ -XXX,XX +XXX,XX @@ struct PL011State {
23
uint8_t gicr_ipriorityr[GIC_INTERNAL];
24
int read_trigger;
24
25
CharBackend chr;
25
/* CPU interface */
26
qemu_irq irq[6];
26
+ uint64_t icc_sre_el1;
27
+ Clock *clk;
27
uint64_t icc_ctlr_el1[2];
28
const unsigned char *id;
28
uint64_t icc_pmr_el1;
29
};
29
uint64_t icc_bpr[3];
30
30
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
31
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
31
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/intc/arm_gicv3_common.c
33
--- a/hw/char/pl011.c
33
+++ b/hw/intc/arm_gicv3_common.c
34
+++ b/hw/char/pl011.c
34
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_gicv3_cpu_virt = {
35
@@ -XXX,XX +XXX,XX @@
35
}
36
#include "hw/char/pl011.h"
36
};
37
#include "hw/irq.h"
37
38
#include "hw/sysbus.h"
38
+static int icc_sre_el1_reg_pre_load(void *opaque)
39
+#include "hw/qdev-clock.h"
40
#include "migration/vmstate.h"
41
#include "chardev/char-fe.h"
42
#include "qemu/log.h"
43
@@ -XXX,XX +XXX,XX @@ static void pl011_set_read_trigger(PL011State *s)
44
s->read_trigger = 1;
45
}
46
47
+static unsigned int pl011_get_baudrate(const PL011State *s)
39
+{
48
+{
40
+ GICv3CPUState *cs = opaque;
49
+ uint64_t clk;
41
+
50
+
42
+ /*
51
+ if (s->fbrd == 0) {
43
+ * If the sre_el1 subsection is not transferred this
52
+ return 0;
44
+ * means SRE_EL1 is 0x7 (which might not be the same as
53
+ }
45
+ * our reset value).
54
+
46
+ */
55
+ clk = clock_get_hz(s->clk);
47
+ cs->icc_sre_el1 = 0x7;
56
+ return (clk / ((s->ibrd << 6) + s->fbrd)) << 2;
48
+ return 0;
49
+}
57
+}
50
+
58
+
51
+static bool icc_sre_el1_reg_needed(void *opaque)
59
+static void pl011_trace_baudrate_change(const PL011State *s)
52
+{
60
+{
53
+ GICv3CPUState *cs = opaque;
61
+ trace_pl011_baudrate_change(pl011_get_baudrate(s),
54
+
62
+ clock_get_hz(s->clk),
55
+ return cs->icc_sre_el1 != 7;
63
+ s->ibrd, s->fbrd);
56
+}
64
+}
57
+
65
+
58
+const VMStateDescription vmstate_gicv3_cpu_sre_el1 = {
66
static void pl011_write(void *opaque, hwaddr offset,
59
+ .name = "arm_gicv3_cpu/sre_el1",
67
uint64_t value, unsigned size)
68
{
69
@@ -XXX,XX +XXX,XX @@ static void pl011_write(void *opaque, hwaddr offset,
70
break;
71
case 9: /* UARTIBRD */
72
s->ibrd = value;
73
+ pl011_trace_baudrate_change(s);
74
break;
75
case 10: /* UARTFBRD */
76
s->fbrd = value;
77
+ pl011_trace_baudrate_change(s);
78
break;
79
case 11: /* UARTLCR_H */
80
/* Reset the FIFO state on FIFO enable or disable */
81
@@ -XXX,XX +XXX,XX @@ static void pl011_event(void *opaque, QEMUChrEvent event)
82
pl011_put_fifo(opaque, 0x400);
83
}
84
85
+static void pl011_clock_update(void *opaque)
86
+{
87
+ PL011State *s = PL011(opaque);
88
+
89
+ pl011_trace_baudrate_change(s);
90
+}
91
+
92
static const MemoryRegionOps pl011_ops = {
93
.read = pl011_read,
94
.write = pl011_write,
95
.endianness = DEVICE_NATIVE_ENDIAN,
96
};
97
98
+static const VMStateDescription vmstate_pl011_clock = {
99
+ .name = "pl011/clock",
60
+ .version_id = 1,
100
+ .version_id = 1,
61
+ .minimum_version_id = 1,
101
+ .minimum_version_id = 1,
62
+ .pre_load = icc_sre_el1_reg_pre_load,
63
+ .needed = icc_sre_el1_reg_needed,
64
+ .fields = (VMStateField[]) {
102
+ .fields = (VMStateField[]) {
65
+ VMSTATE_UINT64(icc_sre_el1, GICv3CPUState),
103
+ VMSTATE_CLOCK(clk, PL011State),
66
+ VMSTATE_END_OF_LIST()
104
+ VMSTATE_END_OF_LIST()
67
+ }
105
+ }
68
+};
106
+};
69
+
107
+
70
static const VMStateDescription vmstate_gicv3_cpu = {
108
static const VMStateDescription vmstate_pl011 = {
71
.name = "arm_gicv3_cpu",
109
.name = "pl011",
72
.version_id = 1,
110
.version_id = 2,
73
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_gicv3_cpu = {
111
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_pl011 = {
74
.subsections = (const VMStateDescription * []) {
112
VMSTATE_INT32(read_count, PL011State),
75
&vmstate_gicv3_cpu_virt,
113
VMSTATE_INT32(read_trigger, PL011State),
76
NULL
114
VMSTATE_END_OF_LIST()
77
+ },
115
+ },
78
+ .subsections = (const VMStateDescription * []) {
116
+ .subsections = (const VMStateDescription * []) {
79
+ &vmstate_gicv3_cpu_sre_el1,
117
+ &vmstate_pl011_clock,
80
+ NULL
118
+ NULL
81
}
119
}
82
};
120
};
83
121
122
@@ -XXX,XX +XXX,XX @@ static void pl011_init(Object *obj)
123
sysbus_init_irq(sbd, &s->irq[i]);
124
}
125
126
+ s->clk = qdev_init_clock_in(DEVICE(obj), "clk", pl011_clock_update, s);
127
+
128
s->read_trigger = 1;
129
s->ifl = 0x12;
130
s->cr = 0x300;
131
diff --git a/hw/char/trace-events b/hw/char/trace-events
132
index XXXXXXX..XXXXXXX 100644
133
--- a/hw/char/trace-events
134
+++ b/hw/char/trace-events
135
@@ -XXX,XX +XXX,XX @@ pl011_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
136
pl011_can_receive(uint32_t lcr, int read_count, int r) "LCR 0x%08x read_count %d returning %d"
137
pl011_put_fifo(uint32_t c, int read_count) "new char 0x%x read_count now %d"
138
pl011_put_fifo_full(void) "FIFO now full, RXFF set"
139
+pl011_baudrate_change(unsigned int baudrate, uint64_t clock, uint32_t ibrd, uint32_t fbrd) "new baudrate %u (clk: %" PRIu64 "hz, ibrd: %" PRIu32 ", fbrd: %" PRIu32 ")"
140
141
# cmsdk-apb-uart.c
142
cmsdk_apb_uart_read(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB UART read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
84
--
143
--
85
2.7.4
144
2.20.1
86
145
87
146
diff view generated by jsdifflib
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
From: Luc Michel <luc@lmichel.fr>
2
2
3
The linux-headers/asm-arm/unistd.h file has been split in three
3
Connect the 'uart-out' clock from the CPRMAN to the PL011 instance.
4
sub-files, copy them along. However, building them requires
5
setting ARCH rather than SRCARCH.
6
4
7
SRCARCH defaults to $(ARCH) anyway; to avoid future occurrence of
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
the same problem use ARCH for all architectures where SRCARCH=ARCH.
6
Signed-off-by: Luc Michel <luc@lmichel.fr>
9
Currently these are all except x86, sparc, sh and tile.
7
Tested-by: Guenter Roeck <linux@roeck-us.net>
10
8
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
12
Message-id: 20170221122920.16245-2-pbonzini@redhat.com
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
10
---
15
scripts/update-linux-headers.sh | 13 ++++++++++++-
11
hw/arm/bcm2835_peripherals.c | 2 ++
16
1 file changed, 12 insertions(+), 1 deletion(-)
12
1 file changed, 2 insertions(+)
17
13
18
diff --git a/scripts/update-linux-headers.sh b/scripts/update-linux-headers.sh
14
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
19
index XXXXXXX..XXXXXXX 100755
15
index XXXXXXX..XXXXXXX 100644
20
--- a/scripts/update-linux-headers.sh
16
--- a/hw/arm/bcm2835_peripherals.c
21
+++ b/scripts/update-linux-headers.sh
17
+++ b/hw/arm/bcm2835_peripherals.c
22
@@ -XXX,XX +XXX,XX @@ for arch in $ARCHLIST; do
18
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
23
continue
19
}
24
fi
20
memory_region_add_subregion(&s->peri_mr, CPRMAN_OFFSET,
25
21
sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->cprman), 0));
26
- make -C "$linux" INSTALL_HDR_PATH="$tmpdir" SRCARCH=$arch headers_install
22
+ qdev_connect_clock_in(DEVICE(&s->uart0), "clk",
27
+ if [ "$arch" = x86 ]; then
23
+ qdev_get_clock_out(DEVICE(&s->cprman), "uart-out"));
28
+ arch_var=SRCARCH
24
29
+ else
25
memory_region_add_subregion(&s->peri_mr, ARMCTRL_IC_OFFSET,
30
+ arch_var=ARCH
26
sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->ic), 0));
31
+ fi
32
+
33
+ make -C "$linux" INSTALL_HDR_PATH="$tmpdir" $arch_var=$arch headers_install
34
35
rm -rf "$output/linux-headers/asm-$arch"
36
mkdir -p "$output/linux-headers/asm-$arch"
37
@@ -XXX,XX +XXX,XX @@ for arch in $ARCHLIST; do
38
cp_portable "$tmpdir/include/asm/kvm_virtio.h" "$output/include/standard-headers/asm-s390/"
39
cp_portable "$tmpdir/include/asm/virtio-ccw.h" "$output/include/standard-headers/asm-s390/"
40
fi
41
+ if [ $arch = arm ]; then
42
+ cp "$tmpdir/include/asm/unistd-eabi.h" "$output/linux-headers/asm-arm/"
43
+ cp "$tmpdir/include/asm/unistd-oabi.h" "$output/linux-headers/asm-arm/"
44
+ cp "$tmpdir/include/asm/unistd-common.h" "$output/linux-headers/asm-arm/"
45
+ fi
46
if [ $arch = x86 ]; then
47
cp_portable "$tmpdir/include/asm/hyperv.h" "$output/include/standard-headers/asm-x86/"
48
cp "$tmpdir/include/asm/unistd_32.h" "$output/linux-headers/asm-x86/"
49
--
27
--
50
2.7.4
28
2.20.1
51
29
52
30
diff view generated by jsdifflib
1
From: Clement Deschamps <clement.deschamps@antfield.fr>
1
From: Shashi Mallela <shashi.mallela@linaro.org>
2
2
3
This adds the BCM2835 GPIO controller.
3
Generic watchdog device model implementation as per ARM SBSA v6.0
4
4
5
It currently implements:
5
Signed-off-by: Shashi Mallela <shashi.mallela@linaro.org>
6
- The 54 GPIOs as outputs (qemu_irq)
6
Message-id: 20201027015927.29495-2-shashi.mallela@linaro.org
7
- The SD controller selection via alternate function of GPIOs 48-53
8
9
Signed-off-by: Clement Deschamps <clement.deschamps@antfield.fr>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Message-id: 1488293711-14195-4-git-send-email-peter.maydell@linaro.org
13
Message-id: 20170224164021.9066-4-clement.deschamps@antfield.fr
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
9
---
17
hw/gpio/Makefile.objs | 1 +
10
include/hw/watchdog/sbsa_gwdt.h | 79 +++++++++
18
include/hw/gpio/bcm2835_gpio.h | 39 +++++
11
hw/watchdog/sbsa_gwdt.c | 293 ++++++++++++++++++++++++++++++++
19
hw/gpio/bcm2835_gpio.c | 353 +++++++++++++++++++++++++++++++++++++++++
12
hw/arm/Kconfig | 1 +
20
3 files changed, 393 insertions(+)
13
hw/watchdog/Kconfig | 3 +
21
create mode 100644 include/hw/gpio/bcm2835_gpio.h
14
hw/watchdog/meson.build | 1 +
22
create mode 100644 hw/gpio/bcm2835_gpio.c
15
5 files changed, 377 insertions(+)
16
create mode 100644 include/hw/watchdog/sbsa_gwdt.h
17
create mode 100644 hw/watchdog/sbsa_gwdt.c
23
18
24
diff --git a/hw/gpio/Makefile.objs b/hw/gpio/Makefile.objs
19
diff --git a/include/hw/watchdog/sbsa_gwdt.h b/include/hw/watchdog/sbsa_gwdt.h
25
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/gpio/Makefile.objs
27
+++ b/hw/gpio/Makefile.objs
28
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_GPIO_KEY) += gpio_key.o
29
30
obj-$(CONFIG_OMAP) += omap_gpio.o
31
obj-$(CONFIG_IMX) += imx_gpio.o
32
+obj-$(CONFIG_RASPI) += bcm2835_gpio.o
33
diff --git a/include/hw/gpio/bcm2835_gpio.h b/include/hw/gpio/bcm2835_gpio.h
34
new file mode 100644
20
new file mode 100644
35
index XXXXXXX..XXXXXXX
21
index XXXXXXX..XXXXXXX
36
--- /dev/null
22
--- /dev/null
37
+++ b/include/hw/gpio/bcm2835_gpio.h
23
+++ b/include/hw/watchdog/sbsa_gwdt.h
38
@@ -XXX,XX +XXX,XX @@
24
@@ -XXX,XX +XXX,XX @@
39
+/*
25
+/*
40
+ * Raspberry Pi (BCM2835) GPIO Controller
26
+ * Copyright (c) 2020 Linaro Limited
41
+ *
42
+ * Copyright (c) 2017 Antfield SAS
43
+ *
27
+ *
44
+ * Authors:
28
+ * Authors:
45
+ * Clement Deschamps <clement.deschamps@antfield.fr>
29
+ * Shashi Mallela <shashi.mallela@linaro.org>
46
+ * Luc Michel <luc.michel@antfield.fr>
30
+ *
47
+ *
31
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at your
48
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
32
+ * option) any later version. See the COPYING file in the top-level directory.
49
+ * See the COPYING file in the top-level directory.
33
+ *
50
+ */
34
+ */
51
+
35
+
52
+#ifndef BCM2835_GPIO_H
36
+#ifndef WDT_SBSA_GWDT_H
53
+#define BCM2835_GPIO_H
37
+#define WDT_SBSA_GWDT_H
54
+
38
+
55
+#include "hw/sd/sd.h"
39
+#include "qemu/bitops.h"
56
+
40
+#include "hw/sysbus.h"
57
+typedef struct BCM2835GpioState {
41
+#include "hw/irq.h"
42
+
43
+#define TYPE_WDT_SBSA "sbsa_gwdt"
44
+#define SBSA_GWDT(obj) \
45
+ OBJECT_CHECK(SBSA_GWDTState, (obj), TYPE_WDT_SBSA)
46
+#define SBSA_GWDT_CLASS(klass) \
47
+ OBJECT_CLASS_CHECK(SBSA_GWDTClass, (klass), TYPE_WDT_SBSA)
48
+#define SBSA_GWDT_GET_CLASS(obj) \
49
+ OBJECT_GET_CLASS(SBSA_GWDTClass, (obj), TYPE_WDT_SBSA)
50
+
51
+/* SBSA Generic Watchdog register definitions */
52
+/* refresh frame */
53
+#define SBSA_GWDT_WRR 0x000
54
+
55
+/* control frame */
56
+#define SBSA_GWDT_WCS 0x000
57
+#define SBSA_GWDT_WOR 0x008
58
+#define SBSA_GWDT_WORU 0x00C
59
+#define SBSA_GWDT_WCV 0x010
60
+#define SBSA_GWDT_WCVU 0x014
61
+
62
+/* Watchdog Interface Identification Register */
63
+#define SBSA_GWDT_W_IIDR 0xFCC
64
+
65
+/* Watchdog Control and Status Register Bits */
66
+#define SBSA_GWDT_WCS_EN BIT(0)
67
+#define SBSA_GWDT_WCS_WS0 BIT(1)
68
+#define SBSA_GWDT_WCS_WS1 BIT(2)
69
+
70
+#define SBSA_GWDT_WOR_MASK 0x0000FFFF
71
+
72
+/*
73
+ * Watchdog Interface Identification Register definition
74
+ * considering JEP106 code for ARM in Bits [11:0]
75
+ */
76
+#define SBSA_GWDT_ID 0x1043B
77
+
78
+/* 2 Separate memory regions for each of refresh & control register frames */
79
+#define SBSA_GWDT_RMMIO_SIZE 0x1000
80
+#define SBSA_GWDT_CMMIO_SIZE 0x1000
81
+
82
+#define SBSA_TIMER_FREQ 62500000 /* Hz */
83
+
84
+typedef struct SBSA_GWDTState {
85
+ /* <private> */
58
+ SysBusDevice parent_obj;
86
+ SysBusDevice parent_obj;
59
+
87
+
60
+ MemoryRegion iomem;
88
+ /*< public >*/
61
+
89
+ MemoryRegion rmmio;
62
+ /* SDBus selector */
90
+ MemoryRegion cmmio;
63
+ SDBus sdbus;
91
+ qemu_irq irq;
64
+ SDBus *sdbus_sdhci;
92
+
65
+ SDBus *sdbus_sdhost;
93
+ QEMUTimer *timer;
66
+
94
+
67
+ uint8_t fsel[54];
95
+ uint32_t id;
68
+ uint32_t lev0, lev1;
96
+ uint32_t wcs;
69
+ uint8_t sd_fsel;
97
+ uint32_t worl;
70
+ qemu_irq out[54];
98
+ uint32_t woru;
71
+} BCM2835GpioState;
99
+ uint32_t wcvl;
72
+
100
+ uint32_t wcvu;
73
+#define TYPE_BCM2835_GPIO "bcm2835_gpio"
101
+} SBSA_GWDTState;
74
+#define BCM2835_GPIO(obj) \
102
+
75
+ OBJECT_CHECK(BCM2835GpioState, (obj), TYPE_BCM2835_GPIO)
103
+#endif /* WDT_SBSA_GWDT_H */
76
+
104
diff --git a/hw/watchdog/sbsa_gwdt.c b/hw/watchdog/sbsa_gwdt.c
77
+#endif
78
diff --git a/hw/gpio/bcm2835_gpio.c b/hw/gpio/bcm2835_gpio.c
79
new file mode 100644
105
new file mode 100644
80
index XXXXXXX..XXXXXXX
106
index XXXXXXX..XXXXXXX
81
--- /dev/null
107
--- /dev/null
82
+++ b/hw/gpio/bcm2835_gpio.c
108
+++ b/hw/watchdog/sbsa_gwdt.c
83
@@ -XXX,XX +XXX,XX @@
109
@@ -XXX,XX +XXX,XX @@
84
+/*
110
+/*
85
+ * Raspberry Pi (BCM2835) GPIO Controller
111
+ * Generic watchdog device model for SBSA
86
+ *
112
+ *
87
+ * Copyright (c) 2017 Antfield SAS
113
+ * The watchdog device has been implemented as revision 1 variant of
114
+ * the ARM SBSA specification v6.0
115
+ * (https://developer.arm.com/documentation/den0029/d?lang=en)
116
+ *
117
+ * Copyright Linaro.org 2020
88
+ *
118
+ *
89
+ * Authors:
119
+ * Authors:
90
+ * Clement Deschamps <clement.deschamps@antfield.fr>
120
+ * Shashi Mallela <shashi.mallela@linaro.org>
91
+ * Luc Michel <luc.michel@antfield.fr>
121
+ *
92
+ *
122
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at your
93
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
123
+ * option) any later version. See the COPYING file in the top-level directory.
94
+ * See the COPYING file in the top-level directory.
124
+ *
95
+ */
125
+ */
96
+
126
+
97
+#include "qemu/osdep.h"
127
+#include "qemu/osdep.h"
128
+#include "sysemu/reset.h"
129
+#include "sysemu/watchdog.h"
130
+#include "hw/watchdog/sbsa_gwdt.h"
131
+#include "qemu/timer.h"
132
+#include "migration/vmstate.h"
98
+#include "qemu/log.h"
133
+#include "qemu/log.h"
99
+#include "qemu/timer.h"
134
+#include "qemu/module.h"
100
+#include "qapi/error.h"
135
+
101
+#include "hw/sysbus.h"
136
+static WatchdogTimerModel model = {
102
+#include "hw/sd/sd.h"
137
+ .wdt_name = TYPE_WDT_SBSA,
103
+#include "hw/gpio/bcm2835_gpio.h"
138
+ .wdt_description = "SBSA-compliant generic watchdog device",
104
+
105
+#define GPFSEL0 0x00
106
+#define GPFSEL1 0x04
107
+#define GPFSEL2 0x08
108
+#define GPFSEL3 0x0C
109
+#define GPFSEL4 0x10
110
+#define GPFSEL5 0x14
111
+#define GPSET0 0x1C
112
+#define GPSET1 0x20
113
+#define GPCLR0 0x28
114
+#define GPCLR1 0x2C
115
+#define GPLEV0 0x34
116
+#define GPLEV1 0x38
117
+#define GPEDS0 0x40
118
+#define GPEDS1 0x44
119
+#define GPREN0 0x4C
120
+#define GPREN1 0x50
121
+#define GPFEN0 0x58
122
+#define GPFEN1 0x5C
123
+#define GPHEN0 0x64
124
+#define GPHEN1 0x68
125
+#define GPLEN0 0x70
126
+#define GPLEN1 0x74
127
+#define GPAREN0 0x7C
128
+#define GPAREN1 0x80
129
+#define GPAFEN0 0x88
130
+#define GPAFEN1 0x8C
131
+#define GPPUD 0x94
132
+#define GPPUDCLK0 0x98
133
+#define GPPUDCLK1 0x9C
134
+
135
+static uint32_t gpfsel_get(BCM2835GpioState *s, uint8_t reg)
136
+{
137
+ int i;
138
+ uint32_t value = 0;
139
+ for (i = 0; i < 10; i++) {
140
+ uint32_t index = 10 * reg + i;
141
+ if (index < sizeof(s->fsel)) {
142
+ value |= (s->fsel[index] & 0x7) << (3 * i);
143
+ }
144
+ }
145
+ return value;
146
+}
147
+
148
+static void gpfsel_set(BCM2835GpioState *s, uint8_t reg, uint32_t value)
149
+{
150
+ int i;
151
+ for (i = 0; i < 10; i++) {
152
+ uint32_t index = 10 * reg + i;
153
+ if (index < sizeof(s->fsel)) {
154
+ int fsel = (value >> (3 * i)) & 0x7;
155
+ s->fsel[index] = fsel;
156
+ }
157
+ }
158
+
159
+ /* SD controller selection (48-53) */
160
+ if (s->sd_fsel != 0
161
+ && (s->fsel[48] == 0) /* SD_CLK_R */
162
+ && (s->fsel[49] == 0) /* SD_CMD_R */
163
+ && (s->fsel[50] == 0) /* SD_DATA0_R */
164
+ && (s->fsel[51] == 0) /* SD_DATA1_R */
165
+ && (s->fsel[52] == 0) /* SD_DATA2_R */
166
+ && (s->fsel[53] == 0) /* SD_DATA3_R */
167
+ ) {
168
+ /* SDHCI controller selected */
169
+ sdbus_reparent_card(s->sdbus_sdhost, s->sdbus_sdhci);
170
+ s->sd_fsel = 0;
171
+ } else if (s->sd_fsel != 4
172
+ && (s->fsel[48] == 4) /* SD_CLK_R */
173
+ && (s->fsel[49] == 4) /* SD_CMD_R */
174
+ && (s->fsel[50] == 4) /* SD_DATA0_R */
175
+ && (s->fsel[51] == 4) /* SD_DATA1_R */
176
+ && (s->fsel[52] == 4) /* SD_DATA2_R */
177
+ && (s->fsel[53] == 4) /* SD_DATA3_R */
178
+ ) {
179
+ /* SDHost controller selected */
180
+ sdbus_reparent_card(s->sdbus_sdhci, s->sdbus_sdhost);
181
+ s->sd_fsel = 4;
182
+ }
183
+}
184
+
185
+static int gpfsel_is_out(BCM2835GpioState *s, int index)
186
+{
187
+ if (index >= 0 && index < 54) {
188
+ return s->fsel[index] == 1;
189
+ }
190
+ return 0;
191
+}
192
+
193
+static void gpset(BCM2835GpioState *s,
194
+ uint32_t val, uint8_t start, uint8_t count, uint32_t *lev)
195
+{
196
+ uint32_t changes = val & ~*lev;
197
+ uint32_t cur = 1;
198
+
199
+ int i;
200
+ for (i = 0; i < count; i++) {
201
+ if ((changes & cur) && (gpfsel_is_out(s, start + i))) {
202
+ qemu_set_irq(s->out[start + i], 1);
203
+ }
204
+ cur <<= 1;
205
+ }
206
+
207
+ *lev |= val;
208
+}
209
+
210
+static void gpclr(BCM2835GpioState *s,
211
+ uint32_t val, uint8_t start, uint8_t count, uint32_t *lev)
212
+{
213
+ uint32_t changes = val & *lev;
214
+ uint32_t cur = 1;
215
+
216
+ int i;
217
+ for (i = 0; i < count; i++) {
218
+ if ((changes & cur) && (gpfsel_is_out(s, start + i))) {
219
+ qemu_set_irq(s->out[start + i], 0);
220
+ }
221
+ cur <<= 1;
222
+ }
223
+
224
+ *lev &= ~val;
225
+}
226
+
227
+static uint64_t bcm2835_gpio_read(void *opaque, hwaddr offset,
228
+ unsigned size)
229
+{
230
+ BCM2835GpioState *s = (BCM2835GpioState *)opaque;
231
+
232
+ switch (offset) {
233
+ case GPFSEL0:
234
+ case GPFSEL1:
235
+ case GPFSEL2:
236
+ case GPFSEL3:
237
+ case GPFSEL4:
238
+ case GPFSEL5:
239
+ return gpfsel_get(s, offset / 4);
240
+ case GPSET0:
241
+ case GPSET1:
242
+ /* Write Only */
243
+ return 0;
244
+ case GPCLR0:
245
+ case GPCLR1:
246
+ /* Write Only */
247
+ return 0;
248
+ case GPLEV0:
249
+ return s->lev0;
250
+ case GPLEV1:
251
+ return s->lev1;
252
+ case GPEDS0:
253
+ case GPEDS1:
254
+ case GPREN0:
255
+ case GPREN1:
256
+ case GPFEN0:
257
+ case GPFEN1:
258
+ case GPHEN0:
259
+ case GPHEN1:
260
+ case GPLEN0:
261
+ case GPLEN1:
262
+ case GPAREN0:
263
+ case GPAREN1:
264
+ case GPAFEN0:
265
+ case GPAFEN1:
266
+ case GPPUD:
267
+ case GPPUDCLK0:
268
+ case GPPUDCLK1:
269
+ /* Not implemented */
270
+ return 0;
271
+ default:
272
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
273
+ __func__, offset);
274
+ break;
275
+ }
276
+
277
+ return 0;
278
+}
279
+
280
+static void bcm2835_gpio_write(void *opaque, hwaddr offset,
281
+ uint64_t value, unsigned size)
282
+{
283
+ BCM2835GpioState *s = (BCM2835GpioState *)opaque;
284
+
285
+ switch (offset) {
286
+ case GPFSEL0:
287
+ case GPFSEL1:
288
+ case GPFSEL2:
289
+ case GPFSEL3:
290
+ case GPFSEL4:
291
+ case GPFSEL5:
292
+ gpfsel_set(s, offset / 4, value);
293
+ break;
294
+ case GPSET0:
295
+ gpset(s, value, 0, 32, &s->lev0);
296
+ break;
297
+ case GPSET1:
298
+ gpset(s, value, 32, 22, &s->lev1);
299
+ break;
300
+ case GPCLR0:
301
+ gpclr(s, value, 0, 32, &s->lev0);
302
+ break;
303
+ case GPCLR1:
304
+ gpclr(s, value, 32, 22, &s->lev1);
305
+ break;
306
+ case GPLEV0:
307
+ case GPLEV1:
308
+ /* Read Only */
309
+ break;
310
+ case GPEDS0:
311
+ case GPEDS1:
312
+ case GPREN0:
313
+ case GPREN1:
314
+ case GPFEN0:
315
+ case GPFEN1:
316
+ case GPHEN0:
317
+ case GPHEN1:
318
+ case GPLEN0:
319
+ case GPLEN1:
320
+ case GPAREN0:
321
+ case GPAREN1:
322
+ case GPAFEN0:
323
+ case GPAFEN1:
324
+ case GPPUD:
325
+ case GPPUDCLK0:
326
+ case GPPUDCLK1:
327
+ /* Not implemented */
328
+ break;
329
+ default:
330
+ goto err_out;
331
+ }
332
+ return;
333
+
334
+err_out:
335
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
336
+ __func__, offset);
337
+}
338
+
339
+static void bcm2835_gpio_reset(DeviceState *dev)
340
+{
341
+ BCM2835GpioState *s = BCM2835_GPIO(dev);
342
+
343
+ int i;
344
+ for (i = 0; i < 6; i++) {
345
+ gpfsel_set(s, i, 0);
346
+ }
347
+
348
+ s->sd_fsel = 0;
349
+
350
+ /* SDHCI is selected by default */
351
+ sdbus_reparent_card(&s->sdbus, s->sdbus_sdhci);
352
+
353
+ s->lev0 = 0;
354
+ s->lev1 = 0;
355
+}
356
+
357
+static const MemoryRegionOps bcm2835_gpio_ops = {
358
+ .read = bcm2835_gpio_read,
359
+ .write = bcm2835_gpio_write,
360
+ .endianness = DEVICE_NATIVE_ENDIAN,
361
+};
139
+};
362
+
140
+
363
+static const VMStateDescription vmstate_bcm2835_gpio = {
141
+static const VMStateDescription vmstate_sbsa_gwdt = {
364
+ .name = "bcm2835_gpio",
142
+ .name = "sbsa-gwdt",
365
+ .version_id = 1,
143
+ .version_id = 1,
366
+ .minimum_version_id = 1,
144
+ .minimum_version_id = 1,
367
+ .fields = (VMStateField[]) {
145
+ .fields = (VMStateField[]) {
368
+ VMSTATE_UINT8_ARRAY(fsel, BCM2835GpioState, 54),
146
+ VMSTATE_TIMER_PTR(timer, SBSA_GWDTState),
369
+ VMSTATE_UINT32(lev0, BCM2835GpioState),
147
+ VMSTATE_UINT32(wcs, SBSA_GWDTState),
370
+ VMSTATE_UINT32(lev1, BCM2835GpioState),
148
+ VMSTATE_UINT32(worl, SBSA_GWDTState),
371
+ VMSTATE_UINT8(sd_fsel, BCM2835GpioState),
149
+ VMSTATE_UINT32(woru, SBSA_GWDTState),
150
+ VMSTATE_UINT32(wcvl, SBSA_GWDTState),
151
+ VMSTATE_UINT32(wcvu, SBSA_GWDTState),
372
+ VMSTATE_END_OF_LIST()
152
+ VMSTATE_END_OF_LIST()
373
+ }
153
+ }
374
+};
154
+};
375
+
155
+
376
+static void bcm2835_gpio_init(Object *obj)
156
+typedef enum WdtRefreshType {
377
+{
157
+ EXPLICIT_REFRESH = 0,
378
+ BCM2835GpioState *s = BCM2835_GPIO(obj);
158
+ TIMEOUT_REFRESH = 1,
379
+ DeviceState *dev = DEVICE(obj);
159
+} WdtRefreshType;
380
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
160
+
381
+
161
+static uint64_t sbsa_gwdt_rread(void *opaque, hwaddr addr, unsigned int size)
382
+ qbus_create_inplace(&s->sdbus, sizeof(s->sdbus),
162
+{
383
+ TYPE_SD_BUS, DEVICE(s), "sd-bus");
163
+ SBSA_GWDTState *s = SBSA_GWDT(opaque);
384
+
164
+ uint32_t ret = 0;
385
+ memory_region_init_io(&s->iomem, obj,
165
+
386
+ &bcm2835_gpio_ops, s, "bcm2835_gpio", 0x1000);
166
+ switch (addr) {
387
+ sysbus_init_mmio(sbd, &s->iomem);
167
+ case SBSA_GWDT_WRR:
388
+ qdev_init_gpio_out(dev, s->out, 54);
168
+ /* watch refresh read has no effect and returns 0 */
389
+}
169
+ ret = 0;
390
+
170
+ break;
391
+static void bcm2835_gpio_realize(DeviceState *dev, Error **errp)
171
+ case SBSA_GWDT_W_IIDR:
392
+{
172
+ ret = s->id;
393
+ BCM2835GpioState *s = BCM2835_GPIO(dev);
173
+ break;
394
+ Object *obj;
174
+ default:
395
+ Error *err = NULL;
175
+ qemu_log_mask(LOG_GUEST_ERROR, "bad address in refresh frame read :"
396
+
176
+ " 0x%x\n", (int)addr);
397
+ obj = object_property_get_link(OBJECT(dev), "sdbus-sdhci", &err);
177
+ }
398
+ if (obj == NULL) {
178
+ return ret;
399
+ error_setg(errp, "%s: required sdhci link not found: %s",
179
+}
400
+ __func__, error_get_pretty(err));
180
+
401
+ return;
181
+static uint64_t sbsa_gwdt_read(void *opaque, hwaddr addr, unsigned int size)
402
+ }
182
+{
403
+ s->sdbus_sdhci = SD_BUS(obj);
183
+ SBSA_GWDTState *s = SBSA_GWDT(opaque);
404
+
184
+ uint32_t ret = 0;
405
+ obj = object_property_get_link(OBJECT(dev), "sdbus-sdhost", &err);
185
+
406
+ if (obj == NULL) {
186
+ switch (addr) {
407
+ error_setg(errp, "%s: required sdhost link not found: %s",
187
+ case SBSA_GWDT_WCS:
408
+ __func__, error_get_pretty(err));
188
+ ret = s->wcs;
409
+ return;
189
+ break;
410
+ }
190
+ case SBSA_GWDT_WOR:
411
+ s->sdbus_sdhost = SD_BUS(obj);
191
+ ret = s->worl;
412
+}
192
+ break;
413
+
193
+ case SBSA_GWDT_WORU:
414
+static void bcm2835_gpio_class_init(ObjectClass *klass, void *data)
194
+ ret = s->woru;
195
+ break;
196
+ case SBSA_GWDT_WCV:
197
+ ret = s->wcvl;
198
+ break;
199
+ case SBSA_GWDT_WCVU:
200
+ ret = s->wcvu;
201
+ break;
202
+ case SBSA_GWDT_W_IIDR:
203
+ ret = s->id;
204
+ break;
205
+ default:
206
+ qemu_log_mask(LOG_GUEST_ERROR, "bad address in control frame read :"
207
+ " 0x%x\n", (int)addr);
208
+ }
209
+ return ret;
210
+}
211
+
212
+static void sbsa_gwdt_update_timer(SBSA_GWDTState *s, WdtRefreshType rtype)
213
+{
214
+ uint64_t timeout = 0;
215
+
216
+ timer_del(s->timer);
217
+
218
+ if (s->wcs & SBSA_GWDT_WCS_EN) {
219
+ /*
220
+ * Extract the upper 16 bits from woru & 32 bits from worl
221
+ * registers to construct the 48 bit offset value
222
+ */
223
+ timeout = s->woru;
224
+ timeout <<= 32;
225
+ timeout |= s->worl;
226
+ timeout = muldiv64(timeout, NANOSECONDS_PER_SECOND, SBSA_TIMER_FREQ);
227
+ timeout += qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
228
+
229
+ if ((rtype == EXPLICIT_REFRESH) || ((rtype == TIMEOUT_REFRESH) &&
230
+ (!(s->wcs & SBSA_GWDT_WCS_WS0)))) {
231
+ /* store the current timeout value into compare registers */
232
+ s->wcvu = timeout >> 32;
233
+ s->wcvl = timeout;
234
+ }
235
+ timer_mod(s->timer, timeout);
236
+ }
237
+}
238
+
239
+static void sbsa_gwdt_rwrite(void *opaque, hwaddr offset, uint64_t data,
240
+ unsigned size) {
241
+ SBSA_GWDTState *s = SBSA_GWDT(opaque);
242
+
243
+ if (offset == SBSA_GWDT_WRR) {
244
+ s->wcs &= ~(SBSA_GWDT_WCS_WS0 | SBSA_GWDT_WCS_WS1);
245
+
246
+ sbsa_gwdt_update_timer(s, EXPLICIT_REFRESH);
247
+ } else {
248
+ qemu_log_mask(LOG_GUEST_ERROR, "bad address in refresh frame write :"
249
+ " 0x%x\n", (int)offset);
250
+ }
251
+}
252
+
253
+static void sbsa_gwdt_write(void *opaque, hwaddr offset, uint64_t data,
254
+ unsigned size) {
255
+ SBSA_GWDTState *s = SBSA_GWDT(opaque);
256
+
257
+ switch (offset) {
258
+ case SBSA_GWDT_WCS:
259
+ s->wcs = data & SBSA_GWDT_WCS_EN;
260
+ qemu_set_irq(s->irq, 0);
261
+ sbsa_gwdt_update_timer(s, EXPLICIT_REFRESH);
262
+ break;
263
+
264
+ case SBSA_GWDT_WOR:
265
+ s->worl = data;
266
+ s->wcs &= ~(SBSA_GWDT_WCS_WS0 | SBSA_GWDT_WCS_WS1);
267
+ qemu_set_irq(s->irq, 0);
268
+ sbsa_gwdt_update_timer(s, EXPLICIT_REFRESH);
269
+ break;
270
+
271
+ case SBSA_GWDT_WORU:
272
+ s->woru = data & SBSA_GWDT_WOR_MASK;
273
+ s->wcs &= ~(SBSA_GWDT_WCS_WS0 | SBSA_GWDT_WCS_WS1);
274
+ qemu_set_irq(s->irq, 0);
275
+ sbsa_gwdt_update_timer(s, EXPLICIT_REFRESH);
276
+ break;
277
+
278
+ case SBSA_GWDT_WCV:
279
+ s->wcvl = data;
280
+ break;
281
+
282
+ case SBSA_GWDT_WCVU:
283
+ s->wcvu = data;
284
+ break;
285
+
286
+ default:
287
+ qemu_log_mask(LOG_GUEST_ERROR, "bad address in control frame write :"
288
+ " 0x%x\n", (int)offset);
289
+ }
290
+ return;
291
+}
292
+
293
+static void wdt_sbsa_gwdt_reset(DeviceState *dev)
294
+{
295
+ SBSA_GWDTState *s = SBSA_GWDT(dev);
296
+
297
+ timer_del(s->timer);
298
+
299
+ s->wcs = 0;
300
+ s->wcvl = 0;
301
+ s->wcvu = 0;
302
+ s->worl = 0;
303
+ s->woru = 0;
304
+ s->id = SBSA_GWDT_ID;
305
+}
306
+
307
+static void sbsa_gwdt_timer_sysinterrupt(void *opaque)
308
+{
309
+ SBSA_GWDTState *s = SBSA_GWDT(opaque);
310
+
311
+ if (!(s->wcs & SBSA_GWDT_WCS_WS0)) {
312
+ s->wcs |= SBSA_GWDT_WCS_WS0;
313
+ sbsa_gwdt_update_timer(s, TIMEOUT_REFRESH);
314
+ qemu_set_irq(s->irq, 1);
315
+ } else {
316
+ s->wcs |= SBSA_GWDT_WCS_WS1;
317
+ qemu_log_mask(CPU_LOG_RESET, "Watchdog timer expired.\n");
318
+ /*
319
+ * Reset the watchdog only if the guest gets notified about
320
+ * expiry. watchdog_perform_action() may temporarily relinquish
321
+ * the BQL; reset before triggering the action to avoid races with
322
+ * sbsa_gwdt instructions.
323
+ */
324
+ switch (get_watchdog_action()) {
325
+ case WATCHDOG_ACTION_DEBUG:
326
+ case WATCHDOG_ACTION_NONE:
327
+ case WATCHDOG_ACTION_PAUSE:
328
+ break;
329
+ default:
330
+ wdt_sbsa_gwdt_reset(DEVICE(s));
331
+ }
332
+ watchdog_perform_action();
333
+ }
334
+}
335
+
336
+static const MemoryRegionOps sbsa_gwdt_rops = {
337
+ .read = sbsa_gwdt_rread,
338
+ .write = sbsa_gwdt_rwrite,
339
+ .endianness = DEVICE_LITTLE_ENDIAN,
340
+ .valid.min_access_size = 4,
341
+ .valid.max_access_size = 4,
342
+ .valid.unaligned = false,
343
+};
344
+
345
+static const MemoryRegionOps sbsa_gwdt_ops = {
346
+ .read = sbsa_gwdt_read,
347
+ .write = sbsa_gwdt_write,
348
+ .endianness = DEVICE_LITTLE_ENDIAN,
349
+ .valid.min_access_size = 4,
350
+ .valid.max_access_size = 4,
351
+ .valid.unaligned = false,
352
+};
353
+
354
+static void wdt_sbsa_gwdt_realize(DeviceState *dev, Error **errp)
355
+{
356
+ SBSA_GWDTState *s = SBSA_GWDT(dev);
357
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
358
+
359
+ memory_region_init_io(&s->rmmio, OBJECT(dev),
360
+ &sbsa_gwdt_rops, s,
361
+ "sbsa_gwdt.refresh",
362
+ SBSA_GWDT_RMMIO_SIZE);
363
+
364
+ memory_region_init_io(&s->cmmio, OBJECT(dev),
365
+ &sbsa_gwdt_ops, s,
366
+ "sbsa_gwdt.control",
367
+ SBSA_GWDT_CMMIO_SIZE);
368
+
369
+ sysbus_init_mmio(sbd, &s->rmmio);
370
+ sysbus_init_mmio(sbd, &s->cmmio);
371
+
372
+ sysbus_init_irq(sbd, &s->irq);
373
+
374
+ s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sbsa_gwdt_timer_sysinterrupt,
375
+ dev);
376
+}
377
+
378
+static void wdt_sbsa_gwdt_class_init(ObjectClass *klass, void *data)
415
+{
379
+{
416
+ DeviceClass *dc = DEVICE_CLASS(klass);
380
+ DeviceClass *dc = DEVICE_CLASS(klass);
417
+
381
+
418
+ dc->vmsd = &vmstate_bcm2835_gpio;
382
+ dc->realize = wdt_sbsa_gwdt_realize;
419
+ dc->realize = &bcm2835_gpio_realize;
383
+ dc->reset = wdt_sbsa_gwdt_reset;
420
+ dc->reset = &bcm2835_gpio_reset;
384
+ dc->hotpluggable = false;
421
+}
385
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
422
+
386
+ dc->vmsd = &vmstate_sbsa_gwdt;
423
+static const TypeInfo bcm2835_gpio_info = {
387
+}
424
+ .name = TYPE_BCM2835_GPIO,
388
+
425
+ .parent = TYPE_SYS_BUS_DEVICE,
389
+static const TypeInfo wdt_sbsa_gwdt_info = {
426
+ .instance_size = sizeof(BCM2835GpioState),
390
+ .class_init = wdt_sbsa_gwdt_class_init,
427
+ .instance_init = bcm2835_gpio_init,
391
+ .parent = TYPE_SYS_BUS_DEVICE,
428
+ .class_init = bcm2835_gpio_class_init,
392
+ .name = TYPE_WDT_SBSA,
393
+ .instance_size = sizeof(SBSA_GWDTState),
429
+};
394
+};
430
+
395
+
431
+static void bcm2835_gpio_register_types(void)
396
+static void wdt_sbsa_gwdt_register_types(void)
432
+{
397
+{
433
+ type_register_static(&bcm2835_gpio_info);
398
+ watchdog_add_model(&model);
434
+}
399
+ type_register_static(&wdt_sbsa_gwdt_info);
435
+
400
+}
436
+type_init(bcm2835_gpio_register_types)
401
+
402
+type_init(wdt_sbsa_gwdt_register_types)
403
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
404
index XXXXXXX..XXXXXXX 100644
405
--- a/hw/arm/Kconfig
406
+++ b/hw/arm/Kconfig
407
@@ -XXX,XX +XXX,XX @@ config SBSA_REF
408
select PL031 # RTC
409
select PL061 # GPIO
410
select USB_EHCI_SYSBUS
411
+ select WDT_SBSA
412
413
config SABRELITE
414
bool
415
diff --git a/hw/watchdog/Kconfig b/hw/watchdog/Kconfig
416
index XXXXXXX..XXXXXXX 100644
417
--- a/hw/watchdog/Kconfig
418
+++ b/hw/watchdog/Kconfig
419
@@ -XXX,XX +XXX,XX @@ config WDT_DIAG288
420
421
config WDT_IMX2
422
bool
423
+
424
+config WDT_SBSA
425
+ bool
426
diff --git a/hw/watchdog/meson.build b/hw/watchdog/meson.build
427
index XXXXXXX..XXXXXXX 100644
428
--- a/hw/watchdog/meson.build
429
+++ b/hw/watchdog/meson.build
430
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_WDT_IB700', if_true: files('wdt_ib700.c'))
431
softmmu_ss.add(when: 'CONFIG_WDT_DIAG288', if_true: files('wdt_diag288.c'))
432
softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('wdt_aspeed.c'))
433
softmmu_ss.add(when: 'CONFIG_WDT_IMX2', if_true: files('wdt_imx2.c'))
434
+softmmu_ss.add(when: 'CONFIG_WDT_SBSA', if_true: files('sbsa_gwdt.c'))
437
--
435
--
438
2.7.4
436
2.20.1
439
437
440
438
diff view generated by jsdifflib
1
Make the legacy armv7m_init() function use the newly QOMified
1
From: Shashi Mallela <shashi.mallela@linaro.org>
2
armv7m object rather than doing everything by hand.
3
2
4
We can return the armv7m object rather than the NVIC from
3
Included the newly implemented SBSA generic watchdog device model into
5
armv7m_init() because its interface to the rest of the
4
SBSA platform
6
board (GPIOs, etc) is identical.
7
5
6
Signed-off-by: Shashi Mallela <shashi.mallela@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20201027015927.29495-3-shashi.mallela@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
10
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
11
Message-id: 1487604965-23220-5-git-send-email-peter.maydell@linaro.org
12
---
10
---
13
hw/arm/armv7m.c | 49 ++++++++++++-------------------------------------
11
hw/arm/sbsa-ref.c | 23 +++++++++++++++++++++++
14
1 file changed, 12 insertions(+), 37 deletions(-)
12
1 file changed, 23 insertions(+)
15
13
16
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
14
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
17
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/armv7m.c
16
--- a/hw/arm/sbsa-ref.c
19
+++ b/hw/arm/armv7m.c
17
+++ b/hw/arm/sbsa-ref.c
20
@@ -XXX,XX +XXX,XX @@ static void bitband_init(Object *obj)
18
@@ -XXX,XX +XXX,XX @@
21
sysbus_init_mmio(dev, &s->iomem);
19
#include "hw/qdev-properties.h"
20
#include "hw/usb.h"
21
#include "hw/char/pl011.h"
22
+#include "hw/watchdog/sbsa_gwdt.h"
23
#include "net/net.h"
24
#include "qom/object.h"
25
26
@@ -XXX,XX +XXX,XX @@ enum {
27
SBSA_GIC_DIST,
28
SBSA_GIC_REDIST,
29
SBSA_SECURE_EC,
30
+ SBSA_GWDT,
31
+ SBSA_GWDT_REFRESH,
32
+ SBSA_GWDT_CONTROL,
33
SBSA_SMMU,
34
SBSA_UART,
35
SBSA_RTC,
36
@@ -XXX,XX +XXX,XX @@ static const MemMapEntry sbsa_ref_memmap[] = {
37
[SBSA_GIC_DIST] = { 0x40060000, 0x00010000 },
38
[SBSA_GIC_REDIST] = { 0x40080000, 0x04000000 },
39
[SBSA_SECURE_EC] = { 0x50000000, 0x00001000 },
40
+ [SBSA_GWDT_REFRESH] = { 0x50010000, 0x00001000 },
41
+ [SBSA_GWDT_CONTROL] = { 0x50011000, 0x00001000 },
42
[SBSA_UART] = { 0x60000000, 0x00001000 },
43
[SBSA_RTC] = { 0x60010000, 0x00001000 },
44
[SBSA_GPIO] = { 0x60020000, 0x00001000 },
45
@@ -XXX,XX +XXX,XX @@ static const int sbsa_ref_irqmap[] = {
46
[SBSA_AHCI] = 10,
47
[SBSA_EHCI] = 11,
48
[SBSA_SMMU] = 12, /* ... to 15 */
49
+ [SBSA_GWDT] = 16,
50
};
51
52
static uint64_t sbsa_ref_cpu_mp_affinity(SBSAMachineState *sms, int idx)
53
@@ -XXX,XX +XXX,XX @@ static void create_rtc(const SBSAMachineState *sms)
54
sysbus_create_simple("pl031", base, qdev_get_gpio_in(sms->gic, irq));
22
}
55
}
23
56
24
-static void armv7m_bitband_init(void)
57
+static void create_wdt(const SBSAMachineState *sms)
25
-{
58
+{
26
- DeviceState *dev;
59
+ hwaddr rbase = sbsa_ref_memmap[SBSA_GWDT_REFRESH].base;
27
-
60
+ hwaddr cbase = sbsa_ref_memmap[SBSA_GWDT_CONTROL].base;
28
- dev = qdev_create(NULL, TYPE_BITBAND);
61
+ DeviceState *dev = qdev_new(TYPE_WDT_SBSA);
29
- qdev_prop_set_uint32(dev, "base", 0x20000000);
62
+ SysBusDevice *s = SYS_BUS_DEVICE(dev);
30
- qdev_init_nofail(dev);
63
+ int irq = sbsa_ref_irqmap[SBSA_GWDT];
31
- sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0x22000000);
64
+
32
-
65
+ sysbus_realize_and_unref(s, &error_fatal);
33
- dev = qdev_create(NULL, TYPE_BITBAND);
66
+ sysbus_mmio_map(s, 0, rbase);
34
- qdev_prop_set_uint32(dev, "base", 0x40000000);
67
+ sysbus_mmio_map(s, 1, cbase);
35
- qdev_init_nofail(dev);
68
+ sysbus_connect_irq(s, 0, qdev_get_gpio_in(sms->gic, irq));
36
- sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0x42000000);
69
+}
37
-}
70
+
38
-
71
static DeviceState *gpio_key_dev;
39
/* Board init. */
72
static void sbsa_ref_powerdown_req(Notifier *n, void *opaque)
40
41
static const hwaddr bitband_input_addr[ARMV7M_NUM_BITBANDS] = {
42
@@ -XXX,XX +XXX,XX @@ static void armv7m_reset(void *opaque)
43
44
/* Init CPU and memory for a v7-M based board.
45
mem_size is in bytes.
46
- Returns the NVIC array. */
47
+ Returns the ARMv7M device. */
48
49
DeviceState *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq,
50
const char *kernel_filename, const char *cpu_model)
51
{
73
{
52
- ARMCPU *cpu;
74
@@ -XXX,XX +XXX,XX @@ static void sbsa_ref_init(MachineState *machine)
53
- CPUARMState *env;
75
54
- DeviceState *nvic;
76
create_rtc(sms);
55
+ DeviceState *armv7m;
77
56
78
+ create_wdt(sms);
57
if (cpu_model == NULL) {
58
-    cpu_model = "cortex-m3";
59
+ cpu_model = "cortex-m3";
60
}
61
- cpu = cpu_arm_init(cpu_model);
62
- if (cpu == NULL) {
63
- fprintf(stderr, "Unable to find CPU definition\n");
64
- exit(1);
65
- }
66
- env = &cpu->env;
67
-
68
- armv7m_bitband_init();
69
-
70
- nvic = qdev_create(NULL, "armv7m_nvic");
71
- qdev_prop_set_uint32(nvic, "num-irq", num_irq);
72
- env->nvic = nvic;
73
- qdev_init_nofail(nvic);
74
- sysbus_connect_irq(SYS_BUS_DEVICE(nvic), 0,
75
- qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ));
76
- armv7m_load_kernel(cpu, kernel_filename, mem_size);
77
- return nvic;
78
+
79
+
79
+ armv7m = qdev_create(NULL, "armv7m");
80
create_gpio(sms);
80
+ qdev_prop_set_uint32(armv7m, "num-irq", num_irq);
81
81
+ qdev_prop_set_string(armv7m, "cpu-model", cpu_model);
82
create_ahci(sms);
82
+ /* This will exit with an error if the user passed us a bad cpu_model */
83
+ qdev_init_nofail(armv7m);
84
+
85
+ armv7m_load_kernel(ARM_CPU(first_cpu), kernel_filename, mem_size);
86
+ return armv7m;
87
}
88
89
void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size)
90
--
83
--
91
2.7.4
84
2.20.1
92
85
93
86
diff view generated by jsdifflib
1
The NVIC is a core v7M device that exists for all v7M CPUs;
1
In ptimer_reload(), we call the callback function provided by the
2
put it under a CONFIG_ARM_V7M rather than hiding it under
2
timer device that is using the ptimer. This callback might disable
3
CONFIG_STELLARIS.
3
the ptimer. The code mostly handles this correctly, except that
4
we'll still print the warning about "Timer with delta zero,
5
disabling" if the now-disabled timer happened to be set such that it
6
would fire again immediately if it were enabled (eg because the
7
limit/reload value is zero).
4
8
5
(We'll use CONFIG_ARM_V7M for the SysTick device too
9
Suppress the spurious warning message and the unnecessary
6
when we split it out of the NVIC.)
10
repeat-deletion of the underlying timer in this case.
7
11
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
14
Message-id: 20201015151829.14656-2-peter.maydell@linaro.org
11
Message-id: 1487604965-23220-9-git-send-email-peter.maydell@linaro.org
12
---
15
---
13
hw/intc/Makefile.objs | 2 +-
16
hw/core/ptimer.c | 4 ++++
14
default-configs/arm-softmmu.mak | 2 ++
17
1 file changed, 4 insertions(+)
15
2 files changed, 3 insertions(+), 1 deletion(-)
16
18
17
diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs
19
diff --git a/hw/core/ptimer.c b/hw/core/ptimer.c
18
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/intc/Makefile.objs
21
--- a/hw/core/ptimer.c
20
+++ b/hw/intc/Makefile.objs
22
+++ b/hw/core/ptimer.c
21
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_APIC) += apic.o apic_common.o
23
@@ -XXX,XX +XXX,XX @@ static void ptimer_reload(ptimer_state *s, int delta_adjust)
22
obj-$(CONFIG_ARM_GIC_KVM) += arm_gic_kvm.o
24
}
23
obj-$(call land,$(CONFIG_ARM_GIC_KVM),$(TARGET_AARCH64)) += arm_gicv3_kvm.o
25
24
obj-$(call land,$(CONFIG_ARM_GIC_KVM),$(TARGET_AARCH64)) += arm_gicv3_its_kvm.o
26
if (delta == 0) {
25
-obj-$(CONFIG_STELLARIS) += armv7m_nvic.o
27
+ if (s->enabled == 0) {
26
+obj-$(CONFIG_ARM_V7M) += armv7m_nvic.o
28
+ /* trigger callback disabled the timer already */
27
obj-$(CONFIG_EXYNOS4) += exynos4210_gic.o exynos4210_combiner.o
29
+ return;
28
obj-$(CONFIG_GRLIB) += grlib_irqmp.o
30
+ }
29
obj-$(CONFIG_IOAPIC) += ioapic.o
31
if (!qtest_enabled()) {
30
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
32
fprintf(stderr, "Timer with delta zero, disabling\n");
31
index XXXXXXX..XXXXXXX 100644
33
}
32
--- a/default-configs/arm-softmmu.mak
33
+++ b/default-configs/arm-softmmu.mak
34
@@ -XXX,XX +XXX,XX @@ CONFIG_ARM11MPCORE=y
35
CONFIG_A9MPCORE=y
36
CONFIG_A15MPCORE=y
37
38
+CONFIG_ARM_V7M=y
39
+
40
CONFIG_ARM_GIC=y
41
CONFIG_ARM_GIC_KVM=$(CONFIG_KVM)
42
CONFIG_ARM_TIMER=y
43
--
34
--
44
2.7.4
35
2.20.1
45
36
46
37
diff view generated by jsdifflib
New patch
1
1
The armv7m systick timer is a 24-bit decrementing, wrap-on-zero,
2
clear-on-write counter. Our current implementation has various
3
bugs and dubious workarounds in it (for instance see
4
https://bugs.launchpad.net/qemu/+bug/1872237).
5
6
We have an implementation of a simple decrementing counter
7
and we put a lot of effort into making sure it handles the
8
interesting corner cases (like "spend a cycle at 0 before
9
reloading") -- ptimer.
10
11
Rewrite the systick timer to use a ptimer rather than
12
a raw QEMU timer.
13
14
Unfortunately this is a migration compatibility break,
15
which will affect all M-profile boards.
16
17
Among other bugs, this fixes
18
https://bugs.launchpad.net/qemu/+bug/1872237 :
19
now writes to SYST_CVR when the timer is enabled correctly
20
do nothing; when the timer is enabled via SYST_CSR.ENABLE,
21
the ptimer code will (because of POLICY_NO_IMMEDIATE_RELOAD)
22
arrange that after one timer tick the counter is reloaded
23
from SYST_RVR and then counts down from there, as the
24
architecture requires.
25
26
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
28
Message-id: 20201015151829.14656-3-peter.maydell@linaro.org
29
---
30
include/hw/timer/armv7m_systick.h | 3 +-
31
hw/timer/armv7m_systick.c | 124 +++++++++++++-----------------
32
2 files changed, 54 insertions(+), 73 deletions(-)
33
34
diff --git a/include/hw/timer/armv7m_systick.h b/include/hw/timer/armv7m_systick.h
35
index XXXXXXX..XXXXXXX 100644
36
--- a/include/hw/timer/armv7m_systick.h
37
+++ b/include/hw/timer/armv7m_systick.h
38
@@ -XXX,XX +XXX,XX @@
39
40
#include "hw/sysbus.h"
41
#include "qom/object.h"
42
+#include "hw/ptimer.h"
43
44
#define TYPE_SYSTICK "armv7m_systick"
45
46
@@ -XXX,XX +XXX,XX @@ struct SysTickState {
47
uint32_t control;
48
uint32_t reload;
49
int64_t tick;
50
- QEMUTimer *timer;
51
+ ptimer_state *ptimer;
52
MemoryRegion iomem;
53
qemu_irq irq;
54
};
55
diff --git a/hw/timer/armv7m_systick.c b/hw/timer/armv7m_systick.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/hw/timer/armv7m_systick.c
58
+++ b/hw/timer/armv7m_systick.c
59
@@ -XXX,XX +XXX,XX @@ static inline int64_t systick_scale(SysTickState *s)
60
}
61
}
62
63
-static void systick_reload(SysTickState *s, int reset)
64
-{
65
- /* The Cortex-M3 Devices Generic User Guide says that "When the
66
- * ENABLE bit is set to 1, the counter loads the RELOAD value from the
67
- * SYST RVR register and then counts down". So, we need to check the
68
- * ENABLE bit before reloading the value.
69
- */
70
- trace_systick_reload();
71
-
72
- if ((s->control & SYSTICK_ENABLE) == 0) {
73
- return;
74
- }
75
-
76
- if (reset) {
77
- s->tick = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
78
- }
79
- s->tick += (s->reload + 1) * systick_scale(s);
80
- timer_mod(s->timer, s->tick);
81
-}
82
-
83
static void systick_timer_tick(void *opaque)
84
{
85
SysTickState *s = (SysTickState *)opaque;
86
@@ -XXX,XX +XXX,XX @@ static void systick_timer_tick(void *opaque)
87
/* Tell the NVIC to pend the SysTick exception */
88
qemu_irq_pulse(s->irq);
89
}
90
- if (s->reload == 0) {
91
- s->control &= ~SYSTICK_ENABLE;
92
- } else {
93
- systick_reload(s, 0);
94
+ if (ptimer_get_limit(s->ptimer) == 0) {
95
+ /*
96
+ * Timer expiry with SYST_RVR zero disables the timer
97
+ * (but doesn't clear SYST_CSR.ENABLE)
98
+ */
99
+ ptimer_stop(s->ptimer);
100
}
101
}
102
103
@@ -XXX,XX +XXX,XX @@ static MemTxResult systick_read(void *opaque, hwaddr addr, uint64_t *data,
104
s->control &= ~SYSTICK_COUNTFLAG;
105
break;
106
case 0x4: /* SysTick Reload Value. */
107
- val = s->reload;
108
+ val = ptimer_get_limit(s->ptimer);
109
break;
110
case 0x8: /* SysTick Current Value. */
111
- {
112
- int64_t t;
113
-
114
- if ((s->control & SYSTICK_ENABLE) == 0) {
115
- val = 0;
116
- break;
117
- }
118
- t = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
119
- if (t >= s->tick) {
120
- val = 0;
121
- break;
122
- }
123
- val = ((s->tick - (t + 1)) / systick_scale(s)) + 1;
124
- /* The interrupt in triggered when the timer reaches zero.
125
- However the counter is not reloaded until the next clock
126
- tick. This is a hack to return zero during the first tick. */
127
- if (val > s->reload) {
128
- val = 0;
129
- }
130
+ val = ptimer_get_count(s->ptimer);
131
break;
132
- }
133
case 0xc: /* SysTick Calibration Value. */
134
val = 10000;
135
break;
136
@@ -XXX,XX +XXX,XX @@ static MemTxResult systick_write(void *opaque, hwaddr addr,
137
switch (addr) {
138
case 0x0: /* SysTick Control and Status. */
139
{
140
- uint32_t oldval = s->control;
141
+ uint32_t oldval;
142
143
+ ptimer_transaction_begin(s->ptimer);
144
+ oldval = s->control;
145
s->control &= 0xfffffff8;
146
s->control |= value & 7;
147
+
148
if ((oldval ^ value) & SYSTICK_ENABLE) {
149
- int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
150
if (value & SYSTICK_ENABLE) {
151
- if (s->tick) {
152
- s->tick += now;
153
- timer_mod(s->timer, s->tick);
154
- } else {
155
- systick_reload(s, 1);
156
- }
157
+ /*
158
+ * Always reload the period in case board code has
159
+ * changed system_clock_scale. If we ever replace that
160
+ * global with a more sensible API then we might be able
161
+ * to set the period only when it actually changes.
162
+ */
163
+ ptimer_set_period(s->ptimer, systick_scale(s));
164
+ ptimer_run(s->ptimer, 0);
165
} else {
166
- timer_del(s->timer);
167
- s->tick -= now;
168
- if (s->tick < 0) {
169
- s->tick = 0;
170
- }
171
+ ptimer_stop(s->ptimer);
172
}
173
} else if ((oldval ^ value) & SYSTICK_CLKSOURCE) {
174
- /* This is a hack. Force the timer to be reloaded
175
- when the reference clock is changed. */
176
- systick_reload(s, 1);
177
+ ptimer_set_period(s->ptimer, systick_scale(s));
178
}
179
+ ptimer_transaction_commit(s->ptimer);
180
break;
181
}
182
case 0x4: /* SysTick Reload Value. */
183
- s->reload = value;
184
+ ptimer_transaction_begin(s->ptimer);
185
+ ptimer_set_limit(s->ptimer, value & 0xffffff, 0);
186
+ ptimer_transaction_commit(s->ptimer);
187
break;
188
- case 0x8: /* SysTick Current Value. Writes reload the timer. */
189
- systick_reload(s, 1);
190
+ case 0x8: /* SysTick Current Value. */
191
+ /*
192
+ * Writing any value clears SYST_CVR to zero and clears
193
+ * SYST_CSR.COUNTFLAG. The counter will then reload from SYST_RVR
194
+ * on the next clock edge unless SYST_RVR is zero.
195
+ */
196
+ ptimer_transaction_begin(s->ptimer);
197
+ if (ptimer_get_limit(s->ptimer) == 0) {
198
+ ptimer_stop(s->ptimer);
199
+ }
200
+ ptimer_set_count(s->ptimer, 0);
201
s->control &= ~SYSTICK_COUNTFLAG;
202
+ ptimer_transaction_commit(s->ptimer);
203
break;
204
default:
205
qemu_log_mask(LOG_GUEST_ERROR,
206
@@ -XXX,XX +XXX,XX @@ static void systick_reset(DeviceState *dev)
207
*/
208
assert(system_clock_scale != 0);
209
210
+ ptimer_transaction_begin(s->ptimer);
211
s->control = 0;
212
- s->reload = 0;
213
- s->tick = 0;
214
- timer_del(s->timer);
215
+ ptimer_stop(s->ptimer);
216
+ ptimer_set_count(s->ptimer, 0);
217
+ ptimer_set_limit(s->ptimer, 0, 0);
218
+ ptimer_set_period(s->ptimer, systick_scale(s));
219
+ ptimer_transaction_commit(s->ptimer);
220
}
221
222
static void systick_instance_init(Object *obj)
223
@@ -XXX,XX +XXX,XX @@ static void systick_instance_init(Object *obj)
224
static void systick_realize(DeviceState *dev, Error **errp)
225
{
226
SysTickState *s = SYSTICK(dev);
227
- s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, systick_timer_tick, s);
228
+ s->ptimer = ptimer_init(systick_timer_tick, s,
229
+ PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD |
230
+ PTIMER_POLICY_NO_COUNTER_ROUND_DOWN |
231
+ PTIMER_POLICY_NO_IMMEDIATE_RELOAD |
232
+ PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT);
233
}
234
235
static const VMStateDescription vmstate_systick = {
236
.name = "armv7m_systick",
237
- .version_id = 1,
238
- .minimum_version_id = 1,
239
+ .version_id = 2,
240
+ .minimum_version_id = 2,
241
.fields = (VMStateField[]) {
242
VMSTATE_UINT32(control, SysTickState),
243
- VMSTATE_UINT32(reload, SysTickState),
244
VMSTATE_INT64(tick, SysTickState),
245
- VMSTATE_TIMER_PTR(timer, SysTickState),
246
+ VMSTATE_PTIMER(ptimer, SysTickState),
247
VMSTATE_END_OF_LIST()
248
}
249
};
250
--
251
2.20.1
252
253
diff view generated by jsdifflib